diff --git a/.mod_auth_mellon.metadata b/.mod_auth_mellon.metadata index 56de7c2..1429e6a 100644 --- a/.mod_auth_mellon.metadata +++ b/.mod_auth_mellon.metadata @@ -1,2 +1,2 @@ a0e8edcb4ecbbc2b37b98ce394ed17bee1b622a3 SOURCES/mod_auth_mellon-0.13.1.tar.gz -f1ecf8e6e809edcb5b595be206b745fe1dcfc5be SOURCES/user_guide.tar.gz +8d7826112f17649c8a0b10e44d562d72a54bdafc SOURCES/user_guide.tar.gz diff --git a/SOURCES/README.redhat.rst b/SOURCES/README.redhat.rst new file mode 100644 index 0000000..a834aae --- /dev/null +++ b/SOURCES/README.redhat.rst @@ -0,0 +1,83 @@ +Red Hat Specific mod_auth_mellon Information +============================================ + +This README contains information specific to Red Hat's distribution of +``mod_auth_mellon``. + +Diagnostic Logging +------------------ + +Diagnostic logging can be used to collect run time information to help +diagnose problems with your ``mod_auth_mellon`` deployment. Please see +the "Mellon Diagnostics" section in the Mellon User Guide for more +details. + +How to enable diagnostic logging on Red Hat systems +``````````````````````````````````````````````````` + +Diagnostic logging adds overhead to the execution of +``mod_auth_mellon``. The code to emit diagnostic logging must be +compiled into ``mod_auth_mellon`` at build time. In addition the +diagnostic log file may contain security sensitive information which +should not normally be written to a log file. If you have a +version of ``mod_auth_mellon`` which was built with diagnostics you +can disable diagnostic logging via the ``MellonDiagnosticsEnable`` +configuration directive. However given human nature the potential to +enable diagnostic logging while resolving a problem and then forget to +disable it is not a situation that should exist by default. Therefore +given the overhead consideration and the desire to avoid enabling +diagnostic logging by mistake the Red Hat ``mod_auth_mellon`` RPM's +ship with two versions of the ``mod_auth_mellon`` Apache module. + +1. The ``mod_auth_mellon`` RPM contains the normal Apache module + ``/usr/lib*/httpd/modules/mod_auth_mellon.so`` + +2. The ``mod_auth_mellon-diagnostics`` RPM contains the diagnostic + version of the Apache module + ``/usr/lib*/httpd/modules/mod_auth_mellon-diagnostics.so`` + +Because each version of the module has a different name both the +normal and diagnostic modules can be installed simultaneously without +conflict. But Apache will only load one of the two modules. Which +module is loaded is controlled by the +``/etc/httpd/conf.modules.d/10-auth_mellon.conf`` config file which +has a line in it which looks like this:: + + LoadModule auth_mellon_module modules/mod_auth_mellon.so + +To load the diagnostics version of the module you need to change the +module name so it looks like this:: + + LoadModule auth_mellon_module modules/mod_auth_mellon-diagnostics.so + +**Don't forget to change it back again when you're done debugging.** + +You'll also need to enable the collection of diagnostic information, +do this by adding this directive at the top of your Mellon conf.d +config file or inside your virtual host config (diagnostics are per +server instance):: + + MellonDiagnosticsEnable On + +.. NOTE:: + Some versions of the Mellon User Guide have a typo in the name of + this directive, it incorrectly uses ``MellonDiagnosticEnable`` + instead of ``MellonDiagnosticsEnable``. The difference is + Diagnostics is plural. + +The Apache ``error_log`` will contain a message indicating how it +processed the ``MellonDiagnosticsEnable`` directive. If you loaded the +standard module without diagnostics you'll see a message like this:: + + MellonDiagnosticsEnable has no effect because Mellon was not + compiled with diagnostics enabled, use + ./configure --enable-diagnostics at build time to turn this + feature on. + +If you've loaded the diagnostics version of the module you'll see a +message in the ``error_log`` like this:: + + mellon diagnostics enabled for virtual server *:443 + (/etc/httpd/conf.d/my_server.conf:7) + ServerName=https://my_server.example.com:443, diagnostics + filename=logs/mellon_diagnostics diff --git a/SOURCES/ac_define.patch b/SOURCES/ac_define.patch new file mode 100644 index 0000000..767284d --- /dev/null +++ b/SOURCES/ac_define.patch @@ -0,0 +1,121 @@ +commit de853e15543f6488cf71833e62f66abf2da3d628 +Author: John Dennis +Date: Thu Sep 28 16:28:55 2017 -0400 + + Add user_guide to distribution, use AC_DEFINE instead of CFLAGS + + This patch corrects a few minor autotool issues. + + The user_guide was recently added but that commit failed to include + adding the new documentation to the tarball, Makefile.in was augmented + to include the new files to the list of distribution files. + + Formerly the #defines generated by configure were passed to the + compiler on the command line in various CFLAGS values. Although that + works the more -Dxxx that configure generates the longer the compile + command becomes and it starts to get unreadable and possibly exceed + command line length. A more common practice with autotools is to + employ autoheader whereby configure generates a file typically called + config.h which then is included by the C files. The contents of + config.h contains the #defines as generated by configure. configure.ac + was updated to utilize the AC_DEFINE in lieu of adding -Dxxx to CFLAGS + and to generate and output config.h. + + Note: autogen.sh needs to be re-run to pick up these changes so that + the configure included in the tarball contains the updated version. + + Signed-off-by: John Dennis + +diff --git a/Makefile.in b/Makefile.in +index 3656bec..2934d25 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -1,4 +1,3 @@ +- + # Source files. mod_auth_mellon.c must be the first file. + SRC=mod_auth_mellon.c \ + auth_mellon_cache.c \ +@@ -10,6 +9,18 @@ SRC=mod_auth_mellon.c \ + auth_mellon_session.c \ + auth_mellon_httpclient.c + ++# Documentation files ++USER_GUIDE_FILES=\ ++ doc/user_guide/mellon_user_guide.adoc \ ++ doc/user_guide/Guardfile \ ++ doc/user_guide/README \ ++ doc/user_guide/images/chrome_SAML_Chrome_Panel.png \ ++ doc/user_guide/images/chrome_SAML_Chrome_Panel.svg \ ++ doc/user_guide/images/saml-tracer.png \ ++ doc/user_guide/images/saml-tracer.svg \ ++ doc/user_guide/images/saml-web-sso.svg ++ ++ + # Files to include when making a .tar.gz-file for distribution + DISTFILES=$(SRC) \ + auth_mellon.h \ +@@ -22,8 +33,8 @@ DISTFILES=$(SRC) \ + README \ + ECP.rst \ + COPYING \ +- NEWS +- ++ NEWS \ ++ $(USER_GUIDE_FILES) + + all: mod_auth_mellon.la + +diff --git a/auth_mellon.h b/auth_mellon.h +index c3d444a..defdf28 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -22,6 +22,8 @@ + #ifndef MOD_AUTH_MELLON_H + #define MOD_AUTH_MELLON_H + ++#include "config.h" ++ + #include + + #include +diff --git a/configure.ac b/configure.ac +index ae313e0..dcee35a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,4 +1,5 @@ + AC_INIT([mod_auth_mellon],[0.13.1],[olav.morken@uninett.no]) ++AC_CONFIG_HEADERS([config.h]) + + # We require support for C99. + AC_PROG_CC_C99 +@@ -49,7 +50,7 @@ AC_ARG_ENABLE( + [enable_diagnostics=no]) + + AS_IF([test "x$enable_diagnostics" != xno], +- [MELLON_CFLAGS="$MELLON_CFLAGS -DENABLE_DIAGNOSTICS"]) ++ [AC_DEFINE([ENABLE_DIAGNOSTICS],[],[build with diagnostics])]) + + # Replace any occurances of @APXS2@ with the value of $APXS2 in the Makefile. + AC_SUBST(APXS2) +@@ -58,13 +59,17 @@ AC_SUBST(APXS2) + PKG_CHECK_MODULES(LASSO, lasso) + saved_LIBS=$LIBS; LIBS="$LIBS $LASSO_LIBS"; + AC_CHECK_LIB(lasso, lasso_server_new_from_buffers, +- LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_lasso_server_new_from_buffers") ++ [AC_DEFINE([HAVE_lasso_server_new_from_buffers],[], ++ [lasso library exports lasso_server_new_from_buffers])]) + AC_CHECK_LIB(lasso, lasso_server_load_metadata, +- LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_lasso_server_load_metadata") ++ [AC_DEFINE([HAVE_lasso_server_load_metadata],[], ++ [lasso library exports lasso_server_load_metadata])]) + AC_CHECK_LIB(lasso, lasso_profile_set_signature_verify_hint, +- LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_lasso_profile_set_signature_verify_hint") ++ [AC_DEFINE([HAVE_lasso_profile_set_signature_verify_hint],[], ++ [lasso library exports lasso_profile_set_signature_verify_hint])]) + AC_CHECK_LIB(lasso, lasso_ecp_request_new, +- LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_ECP") ++ [AC_DEFINE([HAVE_ECP],[], ++ [lasso library supports ECP profile])]) + LIBS=$saved_LIBS; + AC_SUBST(LASSO_CFLAGS) + AC_SUBST(LASSO_LIBS) diff --git a/SOURCES/add-diagnostics.patch b/SOURCES/add-diagnostics.patch new file mode 100644 index 0000000..84c5e6f --- /dev/null +++ b/SOURCES/add-diagnostics.patch @@ -0,0 +1,2115 @@ +commit e8579f6387d9841ce619d836110050fb18117753 +Author: John Dennis +Date: Wed Jun 14 13:56:18 2017 -0400 + + Add diagnostic logging + + Field experience with Mellon has demonstrated there are many + opportunities for deployment problems. Although there are tools such + as browser plugins which can capture SAML messages it's onerous for + site personnel to install and capture the relevant information. The + problem with this approach is further compounded by the fact the + external SAML messages are not correlated to Mellon's + requests/responses. Mellon currently can dump the Lasso session and + SAML Response messages and place them in Apache environment variables, + however these do not appear in the log file. To get them into the log + you have to add custom logging to the Apache config. Another issue is + the dumps are not human readable, they are base64 encoded, anyone + looking at the logs after setting up the custom logging will have to + find the base64 text and then manually copy the text into an external + base64 decoder. At that point you'll discover the XML is not pretty + printed making human interpretation difficult. + + The Mellon debug messages written to the Apache error are often + insufficient to diagnose problems. And since the Mellon log messages + are written to the Apache error log they are interspersed with a lot + of non-Mellon message. + + Compounding the problem of writing Mellon debug messages to the Apache + error log is the fact Apache log messages have a fixed maximum length + (currently 8192) which is insufficient to completely write out such + things as SAML Assertions, metadata, etc. Apache logging also escapes + all control characters with the consequence line breaks are not + preserved and what was a nicely formatted human readable piece of text + becomes a single line with escape characters and may be truncated. + + It would be really nice if we could capture diagnostic information + with these properties: + + * All relevant data is collected in exactly one file. + + * Only information relevant to Mellon appears in the file. + + * All information is human readable (pretty printed, decrypted) with + no need to rely on other tools. + + * The diagnostic information is grouped by requests. + + * The requests can be cross correlated with other Apache logs because + they utilize the same unique request identifier. + + This patch adds diagnostic logging to a independent Mellon diagnostics + log file. Every piece of relevant information is captured, including: + + * Request information which includes: + + - Request method + - Request URL (raw and processed) + - Scheme + - Port + - Request query parameters + - Server name + - Unique request ID + - process ID, thread ID + - Request headers + + * Mellon per directory configuration + + A complete dump of the entire am_dir_cfg_rec structure keyed using + both the Mellon directive it is associated with and it's internal + name. This is emitted once on first use for a given URL. + + The per directory dump includes the pathname of each file read as + well as the file contents. This includes: + + - IdP metadata + - SP metadata + - SP cert + - SP key + - IdP public key file + - IdP CA file + + * All session management operations + + - cookie + - session lookup + - session creation + - session deletion + - cache management + - cache entry information + + * All SAML messages + + Each SAML message is decrypted, decoded and XML pretty printed in + human readable form. + + * Request pipeline operations + + What operations Mellon performs, what decisions it makes and what + data is being used to make those decisions. + + * Response + + - response status + - response headers + - Apache user name + - auth_type + - all Apache environment variables + + Diagnostics can be enabled/disabled both at compile time and run + time. Compile time inclusion of diagnostics is managed with the + ENABLE_DIAGNOSTICS preprocssor symbol. The configure script now accepts + the + + --enable-diagnostics and --disable-diagnostics + + option. Building with diagnostics is disabled by default, you must + specify --enable-diagnostics to enable the run time option of generating + diagnostics. + + The following server config directives have been added (e.g. may be + specified in the main server config area or within a + directive). If Mellon was not built with diagnostics enabled then + these config directives are no-ops and their use will generated a + warning in the log file indicating they have been ignored and to be + effective you must builld Mellon with diagnostics enabled. + + MellonDiagnosticsFile: + The name of the diagnostics file or pipe, + (default is logs/mellon_diagnostics) + + MellonDiagnosticsEnable: + Currently either On or Off but it is designed so it can take other + flags in the future to control what type of information is + reported. + + Signed-off-by: John Dennis + +diff --git a/Makefile.in b/Makefile.in +index 731919e..3656bec 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -1,8 +1,11 @@ + + # Source files. mod_auth_mellon.c must be the first file. + SRC=mod_auth_mellon.c \ +- auth_mellon_cache.c auth_mellon_config.c \ +- auth_mellon_cookie.c auth_mellon_handler.c \ ++ auth_mellon_cache.c \ ++ auth_mellon_config.c \ ++ auth_mellon_cookie.c \ ++ auth_mellon_diagnostics.c \ ++ auth_mellon_handler.c \ + auth_mellon_util.c \ + auth_mellon_session.c \ + auth_mellon_httpclient.c +@@ -25,7 +28,7 @@ DISTFILES=$(SRC) \ + all: mod_auth_mellon.la + + mod_auth_mellon.la: $(SRC) auth_mellon.h auth_mellon_compat.h +- @APXS2@ -Wc,"-std=c99 @OPENSSL_CFLAGS@ @LASSO_CFLAGS@ @CURL_CFLAGS@ @GLIB_CFLAGS@ @CFLAGS@" -Wl,"@OPENSSL_LIBS@ @LASSO_LIBS@ @CURL_LIBS@ @GLIB_LIBS@" -Wc,-Wall -Wc,-g -c $(SRC) ++ @APXS2@ -Wc,"-std=c99 @MELLON_CFLAGS@ @OPENSSL_CFLAGS@ @LASSO_CFLAGS@ @CURL_CFLAGS@ @GLIB_CFLAGS@ @CFLAGS@" -Wl,"@OPENSSL_LIBS@ @LASSO_LIBS@ @CURL_LIBS@ @GLIB_LIBS@" -Wc,-Wall -Wc,-g -c $(SRC) + + + # Building configure (for distribution) +@@ -46,6 +49,7 @@ distfile: @NAMEVER@.tar.gz + .PHONY: clean + clean: + rm -f mod_auth_mellon.la ++ rm -f $(SRC:%.c=%.o) + rm -f $(SRC:%.c=%.lo) + rm -f $(SRC:%.c=%.slo) + rm -rf .libs/ +diff --git a/README b/README +index e084ef4..8211d66 100644 +--- a/README ++++ b/README +@@ -132,6 +132,24 @@ MellonPostSize 1048576 + # Default: MellonPostCount 100 + MellonPostCount 100 + ++# MellonDiagnosticsFile If Mellon was built with diagnostic capability ++# then diagnostic is written here, it may be either a filename or a pipe. ++# If it's a filename then the resulting path is relative to the ServerRoot. ++# If the value is preceeded by the pipe character "|" it should be followed ++# by a path to a program to receive the log information on its standard input. ++# This is a server context directive, hence it may be specified in the ++# main server config area or within a directive. ++# Default: logs/mellon_diagnostics ++MellonDiagnosticsFile logs/mellon_diagnostics ++ ++# MellonDiagnosticsEnable If Mellon was built with diagnostic capability ++# then this is a list of words controlling diagnostic output. ++# Currently only On and Off are supported. ++# This is a server context directive, hence it may be specified in the ++# main server config area or within a directive. ++# Default: Off ++MellonDiagnosticsEnable Off ++ + ########################################################################### + # End of global configuration for mod_auth_mellon. + ########################################################################### +diff --git a/auth_mellon.h b/auth_mellon.h +index a6fa34c..6ce6a8e 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -85,6 +85,14 @@ + #define AM_ERROR_MISSING_PAOS_MEDIA_TYPE 3 + + ++#ifdef ENABLE_DIAGNOSTICS ++typedef enum { ++ AM_DIAG_FLAG_ENABLED = (1 << 0), ++ AM_DIAG_FLAG_DISABLE = 0, ++ AM_DIAG_FLAG_ENABLE_ALL = ~0, ++} am_diag_flags_t; ++#endif ++ + /* This is the length of the id we use (for session IDs and + * replaying POST data). + */ +@@ -100,6 +108,9 @@ + + #define am_get_req_cfg(r) (am_req_cfg_rec *)ap_get_module_config((r)->request_config, &auth_mellon_module) + ++#ifdef ENABLE_DIAGNOSTICS ++#define am_get_diag_cfg(s) (&(am_get_srv_cfg((s)))->diag_cfg) ++#endif + + typedef struct am_mod_cfg_rec { + int cache_size; +@@ -124,8 +135,20 @@ typedef struct am_mod_cfg_rec { + } am_mod_cfg_rec; + + ++#ifdef ENABLE_DIAGNOSTICS ++typedef struct am_diag_cfg_rec { ++ const char *filename; ++ apr_file_t *fd; ++ am_diag_flags_t flags; ++ apr_table_t *dir_cfg_emitted; ++} am_diag_cfg_rec; ++#endif ++ + typedef struct am_srv_cfg_rec { + am_mod_cfg_rec *mc; ++#ifdef ENABLE_DIAGNOSTICS ++ am_diag_cfg_rec diag_cfg; ++#endif + } am_srv_cfg_rec; + + typedef enum { +@@ -284,7 +307,6 @@ typedef struct am_dir_cfg_rec { + + /* List of domains we can redirect to. */ + const char * const *redirect_domains; +- + } am_dir_cfg_rec; + + /* Bitmask for PAOS service options */ +@@ -301,6 +323,9 @@ typedef struct am_req_cfg_rec { + bool ecp_authn_req; + ECPServiceOptions ecp_service_options; + #endif /* HAVE_ECP */ ++#ifdef ENABLE_DIAGNOSTICS ++ bool diag_emitted; ++#endif + } am_req_cfg_rec; + + typedef struct am_cache_storage_t { +@@ -393,6 +418,7 @@ static const int inherit_ecp_send_idplist = -1; + void *auth_mellon_dir_config(apr_pool_t *p, char *d); + void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add); + void *auth_mellon_server_config(apr_pool_t *p, server_rec *s); ++void *auth_mellon_srv_merge(apr_pool_t *p, void *base, void *add); + + + const char *am_cookie_get(request_rec *r); +@@ -503,4 +529,72 @@ int am_httpclient_post_str(request_rec *r, const char *uri, + + extern module AP_MODULE_DECLARE_DATA auth_mellon_module; + ++#ifdef ENABLE_DIAGNOSTICS ++ ++/* Initializing an apr_time_t to 0x7fffffffffffffffLL yields an ++ * iso 8601 time with 1 second precision of "294247-01-10T04:00:54Z" ++ * this is 22 characters, +1 for null terminator. */ ++#define ISO_8601_BUF_SIZE 23 ++ ++typedef struct { ++ bool req_headers_written; ++} am_diag_request_data; ++ ++const char * ++am_diag_cache_key_type_str(am_cache_key_t key_type); ++ ++const char * ++am_diag_cond_str(request_rec *r, const am_cond_t *cond); ++ ++int ++am_diag_finalize_request(request_rec *r); ++ ++const char * ++am_diag_lasso_http_method_str(LassoHttpMethod http_method); ++ ++void ++am_diag_log_cache_entry(request_rec *r, int level, am_cache_entry_t *entry, ++ const char *fmt, ...) ++ __attribute__((format(printf,4,5))); ++ ++void ++am_diag_log_file_data(request_rec *r, int level, am_file_data_t *file_data, ++ const char *fmt, ...) ++ __attribute__((format(printf,4,5))); ++ ++int ++am_diag_log_init(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s); ++ ++void ++am_diag_log_lasso_node(request_rec *r, int level, LassoNode *node, ++ const char *fmt, ...) ++ __attribute__((format(printf,4,5))); ++ ++void ++am_diag_log_profile(request_rec *r, int level, LassoProfile *profile, ++ const char *fmt, ...) ++ __attribute__((format(printf,4,5))); ++ ++void ++am_diag_printf(request_rec *r, const char *fmt, ...) ++ __attribute__((format(printf,2,3))); ++ ++void ++am_diag_rerror(const char *file, int line, int module_index, ++ int level, apr_status_t status, ++ request_rec *r, const char *fmt, ...); ++ ++char * ++am_diag_time_t_to_8601(request_rec *r, apr_time_t t); ++ ++#else /* ENABLE_DIAGNOSTICS */ ++ ++#define am_diag_log_cache_entry(...) do {} while(0) ++#define am_diag_log_file_data(...) do {} while(0) ++#define am_diag_log_lasso_node(...) do {} while(0) ++#define am_diag_log_profile(...) do {} while(0) ++#define am_diag_printf(...) do {} while(0) ++ ++#endif /* ENABLE_DIAGNOSTICS */ ++ + #endif /* MOD_AUTH_MELLON_H */ +diff --git a/auth_mellon_cache.c b/auth_mellon_cache.c +index af5c267..2115acc 100644 +--- a/auth_mellon_cache.c ++++ b/auth_mellon_cache.c +@@ -144,11 +144,17 @@ am_cache_entry_t *am_cache_lock(request_rec *r, + continue; + + if(strcmp(tablekey, key) == 0) { ++ apr_time_t now = apr_time_now(); + /* We found the entry. */ +- if(e->expires > apr_time_now()) { ++ if(e->expires > now) { + /* And it hasn't expired. */ + return e; + } ++ else { ++ am_diag_log_cache_entry(r, 0, e, ++ "found expired session, now %s\n", ++ am_diag_time_t_to_8601(r, now)); ++ } + } + } + +@@ -342,6 +348,10 @@ am_cache_entry_t *am_cache_new(request_rec *r, + * Update 't' and exit loop. + */ + t = e; ++ am_diag_log_cache_entry(r, 0, e, ++ "%s ejecting expired sessions, now %s\n", ++ __func__, ++ am_diag_time_t_to_8601(r, current_time)); + break; + } + +@@ -400,6 +410,11 @@ am_cache_entry_t *am_cache_new(request_rec *r, + return NULL; + } + ++ am_diag_printf(r, "%s created new session, id=%s at %s" ++ " cookie_token=\"%s\"\n", ++ __func__, t->key, am_diag_time_t_to_8601(r, current_time), ++ cookie_token); ++ + return t; + } + +diff --git a/auth_mellon_config.c b/auth_mellon_config.c +index c3cb5e0..66966fc 100644 +--- a/auth_mellon_config.c ++++ b/auth_mellon_config.c +@@ -78,6 +78,15 @@ static const apr_size_t post_size = 1024 * 1024; + */ + static const int post_count = 100; + ++#ifdef ENABLE_DIAGNOSTICS ++/* Default filename for mellon diagnostics log file. ++ * Relative pathname is relative to server root. */ ++static const char *default_diag_filename = "logs/mellon_diagnostics"; ++ ++/* Default state for diagnostics is off */ ++static am_diag_flags_t default_diag_flags = AM_DIAG_FLAG_DISABLE; ++#endif ++ + /* whether to merge env. vars or not + * the MellonMergeEnvVars configuration directive if you change this. + */ +@@ -470,6 +479,78 @@ static const char *am_set_module_config_int_slot(cmd_parms *cmd, + return ap_set_int_slot(cmd, am_get_mod_cfg(cmd->server), arg); + } + ++/* This function handles the MellonDiagnosticsFile configuration directive. ++ * It emits as warning in the log file if Mellon is not built with ++ * diagnostics enabled. ++ * ++ * Parameters: ++ * cmd_parms *cmd The command structure for this configuration ++ * directive. ++ * void *struct_ptr Pointer to the current directory configuration. ++ * NULL if we are not in a directory configuration. ++ * const char *arg The string argument following this configuration ++ * directive in the configuraion file. ++ * ++ * Returns: ++ * NULL on success or an error string on failure. ++ */ ++static const char *am_set_module_diag_file_slot(cmd_parms *cmd, ++ void *struct_ptr, ++ const char *arg) ++{ ++#ifdef ENABLE_DIAGNOSTICS ++ return ap_set_file_slot(cmd, am_get_diag_cfg(cmd->server), arg); ++#else ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server, ++ "%s has no effect because Mellon was not compiled with" ++ " diagnostics enabled, use ./configure --enable-diagnostics" ++ " at build time to turn this feature on.", ++ cmd->directive->directive); ++ return NULL; ++#endif ++} ++ ++/* This function handles configuration directives which sets the ++ * diagnostics flags in the module configuration. ++ * ++ * Parameters: ++ * cmd_parms *cmd The command structure for this configuration ++ * directive. ++ * void *struct_ptr Pointer to the current directory configuration. ++ * NULL if we are not in a directory configuration. ++ * const char *arg The string argument following this configuration ++ * directive in the configuraion file. ++ * ++ * Returns: ++ * NULL on success or an error string on failure. ++ */ ++static const char *am_set_module_diag_flags_slot(cmd_parms *cmd, ++ void *struct_ptr, ++ const char *arg) ++{ ++#ifdef ENABLE_DIAGNOSTICS ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(cmd->server); ++ ++ if (strcasecmp(arg, "on") == 0) { ++ diag_cfg->flags = AM_DIAG_FLAG_ENABLE_ALL; ++ } ++ else if (strcasecmp(arg, "off") == 0) { ++ diag_cfg->flags = AM_DIAG_FLAG_DISABLE; ++ } else { ++ return apr_psprintf(cmd->pool, "%s: must be one of: 'on', 'off'", ++ cmd->cmd->name); ++ } ++ return NULL; ++#else ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server, ++ "%s has no effect because Mellon was not compiled with" ++ " diagnostics enabled, use ./configure --enable-diagnostics" ++ " at build time to turn this feature on.", ++ cmd->directive->directive); ++ return NULL; ++#endif ++} ++ + /* This function handles the MellonCookieSameSite configuration directive. + * This directive can be set to "lax" or "strict" + * +@@ -684,7 +765,7 @@ static const char *am_set_setenv_no_prefix_slot(cmd_parms *cmd, + static int am_cond_flags(const char *arg) + { + int flags = AM_COND_FLAG_NULL; +- static const char const *options[] = { ++ static const char * const options[] = { + "OR", /* AM_EXPIRE_FLAG_OR */ + "NOT", /* AM_EXPIRE_FLAG_NOT */ + "REG", /* AM_EXPIRE_FLAG_REG */ +@@ -1123,6 +1204,30 @@ const command_rec auth_mellon_commands[] = { + "The maximum size of a saved POST, in bytes." + " Default value is 1048576 (1 MB)." + ), ++ AP_INIT_TAKE1( ++ "MellonDiagnosticsFile", ++ am_set_module_diag_file_slot, ++#ifdef ENABLE_DIAGNOSTICS ++ (void *)APR_OFFSETOF(am_diag_cfg_rec, filename), ++#else ++ NULL, ++#endif ++ RSRC_CONF, ++ "Diagnostics log file. [file|pipe] " ++ "If file then file is a filename, relative to the ServerRoot." ++ "If pipe then the filename is a pipe character \"|\", " ++ "followed by the path to a program to receive the log information " ++ "on its standard input. " ++ " Default value is \"logs/mellon_diagnostics\"." ++ ), ++ AP_INIT_ITERATE( ++ "MellonDiagnosticsEnable", ++ am_set_module_diag_flags_slot, ++ NULL, ++ RSRC_CONF, ++ "Diagnostics flags. [on|off] " ++ " Default value is \"off\"." ++ ), + + + /* Per-location configuration directives. */ +@@ -1855,6 +1960,13 @@ void *auth_mellon_server_config(apr_pool_t *p, server_rec *s) + + srv = apr_palloc(p, sizeof(*srv)); + ++#ifdef ENABLE_DIAGNOSTICS ++ srv->diag_cfg.filename = default_diag_filename; ++ srv->diag_cfg.fd = NULL; ++ srv->diag_cfg.flags = default_diag_flags; ++ srv->diag_cfg.dir_cfg_emitted = apr_table_make(p, 0); ++#endif ++ + /* we want to keeep our global configuration of shared memory and + * mutexes, so we try to find it in the userdata before doing anything + * else */ +@@ -1886,6 +1998,47 @@ void *auth_mellon_server_config(apr_pool_t *p, server_rec *s) + apr_pool_userdata_set(mod, key, apr_pool_cleanup_null, p); + + srv->mc = mod; ++ + return srv; + } + ++/* This function merges two am_srv_cfg_rec structures. ++ * It will try to inherit from the base where possible. ++ * ++ * Parameters: ++ * apr_pool_t *p The pool we should allocate memory from. ++ * void *base The original structure. ++ * void *add The structure we should add to base. ++ * ++ * Returns: ++ * The merged structure. ++ */ ++void *auth_mellon_srv_merge(apr_pool_t *p, void *base, void *add) ++{ ++ am_srv_cfg_rec *base_cfg = (am_srv_cfg_rec *)base; ++ am_srv_cfg_rec *new_cfg; ++ ++ new_cfg = (am_srv_cfg_rec *)apr_palloc(p, sizeof(*new_cfg)); ++ ++ new_cfg->mc = base_cfg->mc; ++ ++#ifdef ENABLE_DIAGNOSTICS ++ am_srv_cfg_rec *add_cfg = (am_srv_cfg_rec *)add; ++ new_cfg->diag_cfg.filename = (add_cfg->diag_cfg.filename != ++ default_diag_filename ? ++ add_cfg->diag_cfg.filename : ++ base_cfg->diag_cfg.filename); ++ ++ new_cfg->diag_cfg.fd = NULL; ++ ++ new_cfg->diag_cfg.flags = (add_cfg->diag_cfg.flags != ++ default_diag_flags ? ++ add_cfg->diag_cfg.flags : ++ base_cfg->diag_cfg.flags); ++ ++ new_cfg->diag_cfg.dir_cfg_emitted = apr_table_make(p, 0); ++ ++#endif ++ ++ return new_cfg; ++} +diff --git a/auth_mellon_diagnostics.c b/auth_mellon_diagnostics.c +new file mode 100644 +index 0000000..519a44f +--- /dev/null ++++ b/auth_mellon_diagnostics.c +@@ -0,0 +1,1017 @@ ++#ifdef ENABLE_DIAGNOSTICS ++ ++#include "auth_mellon.h" ++ ++#if APR_HAVE_UNISTD_H ++#include ++#endif ++#if APR_HAVE_PROCESS_H ++#include /* for getpid() on Win32 */ ++#endif ++ ++/*============================= Internal Static ==============================*/ ++ ++/*------------------ Defines ------------------*/ ++ ++#define AM_DIAG_ENABLED(diag_cfg) \ ++ (diag_cfg && diag_cfg->fd && (diag_cfg->flags & AM_DIAG_FLAG_ENABLED)) ++ ++/*------------------ Typedefs ------------------*/ ++ ++typedef struct iter_callback_data { ++ apr_file_t *diag_fd; ++ int level; ++} iter_callback_data; ++ ++/*------------------ Prototypes ------------------*/ ++ ++static const char * ++indent(int level); ++ ++static void ++write_indented_text(apr_file_t *diag_fd, int level, const char* text); ++ ++static void ++am_diag_format_line(apr_pool_t *pool, apr_file_t *diag_fd, int level, ++ const char *fmt, va_list ap); ++ ++static const char * ++am_diag_cond_flag_str(request_rec *r, am_cond_flag_t flags); ++ ++static const char * ++am_diag_enable_str(am_enable_t enable); ++ ++static const char * ++am_diag_samesite_str(am_samesite_t samesite); ++ ++static const char * ++am_diag_httpd_error_level_str(request_rec *r, int level); ++ ++static apr_size_t ++am_diag_time_t_to_8601_buf(char *buf, apr_size_t buf_size, apr_time_t t); ++ ++static int ++am_diag_open_log(server_rec *s, apr_pool_t *p); ++ ++static int ++am_table_count(void *rec, const char *key, const char *value); ++ ++static int ++log_headers(void *rec, const char *key, const char *value); ++ ++static int ++log_probe_discovery_idp(void *rec, const char *key, const char *value); ++ ++static void ++am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, ++ const char *fmt, ...) ++ __attribute__((format(printf,4,5))); ++ ++static bool ++am_diag_initialize_req(request_rec *r, am_diag_cfg_rec *diag_cfg, ++ am_req_cfg_rec *req_cfg); ++ ++/*------------------ Functions ------------------*/ ++ ++static const char * ++indent(int level) ++{ ++ static const char * const indents[] = { ++ "", /* 0 */ ++ " ", /* 1 */ ++ " ", /* 2 */ ++ " ", /* 3 */ ++ " ", /* 4 */ ++ " ", /* 5 */ ++ " ", /* 6 */ ++ " ", /* 7 */ ++ " ", /* 8 */ ++ " ", /* 9 */ ++ }; ++ int n_indents = sizeof(indents)/sizeof(indents[0]); ++ ++ if (level < 0) { ++ return ""; ++ } ++ if (level < n_indents) { ++ return indents[level]; ++ } ++ return indents[n_indents-1]; ++} ++ ++static void ++write_indented_text(apr_file_t *diag_fd, int level, const char* text) ++{ ++ const char *start, *end, *prefix; ++ size_t len, prefix_len; ++ bool crlf = false; ++ ++ if (!text) return; ++ ++ prefix = indent(level); ++ prefix_len = strlen(prefix); ++ start = end = text; ++ while (*end) { ++ /* find end of line */ ++ for (; *end && *end != '\n'; end++); ++ if (*end == '\n') { ++ /* was this a crlf sequence? */ ++ if (end > text && end[-1] == '\r') crlf = true; ++ /* advance past line ending */ ++ end += 1; ++ } ++ /* length of line including line ending */ ++ len = end - start; ++ /* write indent prefix */ ++ apr_file_write_full(diag_fd, prefix, prefix_len, NULL); ++ /* write line including line ending */ ++ apr_file_write_full(diag_fd, start, len, NULL); ++ /* begin again where we left off */ ++ start = end; ++ } ++ /* always write a trailing line ending */ ++ if (end > text && end[-1] != '\n') { ++ if (crlf) { ++ apr_file_write_full(diag_fd, "\r\n", 2, NULL); ++ } else { ++ apr_file_write_full(diag_fd, "\n", 1, NULL); ++ } ++ } ++} ++ ++static void ++am_diag_format_line(apr_pool_t *pool, apr_file_t *diag_fd, int level, ++ const char *fmt, va_list ap) ++{ ++ char * buf = NULL; ++ apr_size_t buf_len; ++ ++ if (fmt) { ++ buf = apr_pvsprintf(pool, fmt, ap); ++ buf_len = strlen(buf); ++ if (buf_len > 0) { ++ const char *prefix = indent(level); ++ apr_size_t prefix_len = strlen(prefix); ++ apr_file_write_full(diag_fd, prefix, prefix_len, NULL); ++ apr_file_write_full(diag_fd, buf, buf_len, NULL); ++ apr_file_putc('\n', diag_fd); ++ } ++ ++ } ++} ++ ++static const char * ++am_diag_cond_flag_str(request_rec *r, am_cond_flag_t flags) ++{ ++ char *str; ++ char *comma; ++ ++ str = apr_pstrcat(r->pool, ++ "[", ++ flags & AM_COND_FLAG_OR ? "OR," : "", ++ flags & AM_COND_FLAG_NOT ? "NOT," : "", ++ flags & AM_COND_FLAG_REG ? "REG," : "", ++ flags & AM_COND_FLAG_NC ? "NC," : "", ++ flags & AM_COND_FLAG_MAP ? "MAP," : "", ++ flags & AM_COND_FLAG_REF ? "REF," : "", ++ flags & AM_COND_FLAG_SUB ? "SUB," : "", ++ flags & AM_COND_FLAG_IGN ? "IGN," : "", ++ flags & AM_COND_FLAG_REQ ? "REQ," : "", ++ flags & AM_COND_FLAG_FSTR ? "FSTR," : "", ++ "]", ++ NULL); ++ ++ /* replace trailing ",]" with "]" */ ++ comma = rindex(str, ','); ++ if (comma) { ++ *comma = ']'; ++ *(comma+1) = 0; ++ } ++ return str; ++} ++ ++static const char * ++am_diag_enable_str(am_enable_t enable) ++{ ++ switch(enable) { ++ case am_enable_default: return "default"; ++ case am_enable_off: return "off"; ++ case am_enable_info: return "info"; ++ case am_enable_auth: return "auth"; ++ default: return "unknown"; ++ } ++ ++} ++ ++static const char * ++am_diag_samesite_str(am_samesite_t samesite) ++{ ++ switch(samesite) { ++ case am_samesite_default: return "default"; ++ case am_samesite_lax: return "lax"; ++ case am_samesite_strict: return "strict"; ++ default: return "unknown"; ++ } ++} ++ ++static const char * ++am_diag_httpd_error_level_str(request_rec *r, int level) ++{ ++ switch(level) { ++ case APLOG_EMERG: return "APLOG_EMERG"; ++ case APLOG_ALERT: return "APLOG_ALERT"; ++ case APLOG_CRIT: return "APLOG_CRIT"; ++ case APLOG_ERR: return "APLOG_ERR"; ++ case APLOG_WARNING: return "APLOG_WARNING"; ++ case APLOG_NOTICE: return "APLOG_NOTICE"; ++ case APLOG_INFO: return "APLOG_INFO"; ++ case APLOG_DEBUG: return "APLOG_DEBUG"; ++ case APLOG_TRACE1: return "APLOG_TRACE1"; ++ case APLOG_TRACE2: return "APLOG_TRACE2"; ++ case APLOG_TRACE3: return "APLOG_TRACE3"; ++ case APLOG_TRACE4: return "APLOG_TRACE4"; ++ case APLOG_TRACE5: return "APLOG_TRACE5"; ++ case APLOG_TRACE6: return "APLOG_TRACE6"; ++ case APLOG_TRACE7: return "APLOG_TRACE7"; ++ case APLOG_TRACE8: return "APLOG_TRACE8"; ++ default: ++ return apr_psprintf(r->pool, "APLOG_%d", level); ++ } ++} ++ ++static apr_size_t ++am_diag_time_t_to_8601_buf(char *buf, apr_size_t buf_size, apr_time_t t) ++{ ++ apr_size_t ret_size; ++ apr_time_exp_t tm; ++ const char fmt[] = "%FT%TZ"; ++ ++ apr_time_exp_gmt(&tm, t); ++ apr_strftime(buf, &ret_size, buf_size, fmt, &tm); ++ ++ /* on errror assure string is null terminated */ ++ if (ret_size == 0) buf[0] = 0; ++ return ret_size; ++} ++ ++static int ++am_diag_open_log(server_rec *s, apr_pool_t *p) ++{ ++ const char *server_name = NULL; ++ const char *server_desc = NULL; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(s); ++ ++ /* Build the ServerName as it would appear in the ServerName directive */ ++ if (s->server_scheme) { ++ server_name = apr_psprintf(p, "%s://%s", ++ s->server_scheme, s->server_hostname); ++ } else { ++ server_name = apr_psprintf(p, "%s", s->server_hostname); ++ } ++ if (s->port) { ++ server_name = apr_psprintf(p, "%s:%u", server_name, s->port); ++ } ++ ++ if (s->is_virtual) { ++ server_desc = apr_psprintf(p, "virtual server %s:%d (%s:%u)" ++ " ServerName=%s", ++ s->addrs->virthost, s->addrs->host_port, ++ s->defn_name, s->defn_line_number, ++ server_name); ++ } else { ++ server_desc = apr_psprintf(p, "main server, ServerName=%s", ++ server_name); ++ } ++ ++ if (!(diag_cfg->flags & AM_DIAG_FLAG_ENABLED)) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "mellon diagnostics disabled for %s", server_desc); ++ return 1; ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "mellon diagnostics enabled for %s, " ++ "diagnostics filename=%s", ++ server_desc, diag_cfg->filename); ++ } ++ ++ if (!diag_cfg->filename || diag_cfg->fd) ++ return 1; ++ ++ if (*diag_cfg->filename == '|') { ++ piped_log *pl; ++ const char *pname = ap_server_root_relative(p, diag_cfg->filename + 1); ++ ++ pl = ap_open_piped_log(p, pname); ++ if (pl == NULL) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, ++ "couldn't spawn mellon diagnostics log pipe %s", ++ diag_cfg->filename); ++ return 0; ++ } ++ diag_cfg->fd = ap_piped_log_write_fd(pl); ++ } ++ else { ++ const char *fname = ap_server_root_relative(p, diag_cfg->filename); ++ apr_status_t rv; ++ ++ if ((rv = apr_file_open(&diag_cfg->fd, fname, ++ APR_WRITE | APR_APPEND | APR_CREATE, ++ APR_OS_DEFAULT, p)) != APR_SUCCESS) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, ++ "could not open mellon diagnostics log file %s.", ++ fname); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static int ++am_table_count(void *rec, const char *key, const char *value) ++{ ++ int *n_items = (int *)rec; ++ ++ (*n_items)++; ++ ++ return 1; ++} ++ ++static int ++log_headers(void *rec, const char *key, const char *value) ++{ ++ iter_callback_data *iter_data = (iter_callback_data *)rec; ++ ++ apr_file_printf(iter_data->diag_fd, "%s%s: %s\n", ++ indent(iter_data->level), key, value); ++ ++ return 1; ++} ++ ++static int ++log_probe_discovery_idp(void *rec, const char *key, const char *value) ++{ ++ iter_callback_data *iter_data = (iter_callback_data *)rec; ++ ++ apr_file_printf(iter_data->diag_fd, ++ "%s%s: %s\n", indent(iter_data->level), key, value); ++ ++ return 1; ++} ++ ++static void ++am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ int i, n_items; ++ apr_hash_index_t *hash_item; ++ GList *list_item; ++ iter_callback_data iter_data; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ iter_data.diag_fd = diag_cfg->fd; ++ iter_data.level = level+1; ++ ++ va_start(ap, fmt); ++ am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap); ++ va_end(ap); ++ ++ if (!cfg) { ++ apr_file_flush(diag_cfg->fd); ++ return; ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonEnable (enable): %s\n", ++ indent(level+1), am_diag_enable_str(cfg->enable_mellon)); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonVariable (varname): %s\n", ++ indent(level+1), cfg->varname); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSecureCookie (secure): %s\n", ++ indent(level+1), cfg->secure ? "On":"Off"); /* FIXME, should be combined? */ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSecureCookie (httpd_only): %s\n", ++ indent(level+1), cfg->http_only ? "On":"Off"); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonMergeEnvVars (merge_env_vars): %s\n", ++ indent(level+1), cfg->merge_env_vars); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonEnvVarsIndexStart (env_vars_index_start): %d\n", ++ indent(level+1), cfg->env_vars_index_start); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonEnvVarsSetCount (env_vars_count_in_n): %s\n", ++ indent(level+1), cfg->env_vars_count_in_n ? "On":"Off"); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonCookieDomain (cookie_domain): %s\n", ++ indent(level+1), cfg->cookie_domain); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonCookiePath (cookie_path): %s\n", ++ indent(level+1), cfg->cookie_path); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonCookieSameSite (cookie_samesite): %s\n", ++ indent(level+1), ++ am_diag_samesite_str(cfg->cookie_samesite)); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonCond (cond): %d items\n", ++ indent(level+1), cfg->cond->nelts); ++ for (i = 0; i < cfg->cond->nelts; i++) { ++ const am_cond_t *cond = &((am_cond_t *)(cfg->cond->elts))[i]; ++ apr_file_printf(diag_cfg->fd, ++ "%s[%2d]: %s\n", ++ indent(level+2), i, am_diag_cond_str(r, cond)); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSetEnv (envattr): %u items\n", ++ indent(level+1), apr_hash_count(cfg->envattr)); ++ for (hash_item = apr_hash_first(r->pool, cfg->envattr); ++ hash_item; ++ hash_item = apr_hash_next(hash_item)) { ++ const char *key; ++ const am_envattr_conf_t *envattr_conf; ++ const char *name; ++ ++ apr_hash_this(hash_item, (void *)&key, NULL, (void *)&envattr_conf); ++ ++ if (envattr_conf->prefixed) { ++ name = apr_pstrcat(r->pool, "MELLON_", ++ envattr_conf->name, NULL); ++ } else { ++ name = envattr_conf->name; ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%s%s ==> %s\n", ++ indent(level+2), key, name); ++ } ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonUser (userattr): %s\n", ++ indent(level+1), cfg->userattr); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonIdP (idpattr): %s\n", ++ indent(level+1), cfg->idpattr); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSessionDump (dump_session): %s\n", ++ indent(level+1), cfg->dump_session ? "On":"Off"); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSamlResponseDump (dump_saml_response): %s\n", ++ indent(level+1), cfg->dump_saml_response ? "On":"Off"); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonEndpointPath (endpoint_path): %s\n", ++ indent(level+1), cfg->endpoint_path); ++ am_diag_log_file_data(r, level+1, cfg->sp_metadata_file, ++ "MellonSPMetadataFile (sp_metadata_file):"); ++ am_diag_log_file_data(r, level+1, cfg->sp_private_key_file, ++ "MellonSPPrivateKeyFile (sp_private_key_file):"); ++ am_diag_log_file_data(r, level+1, cfg->sp_cert_file, ++ "MellonSPCertFile (sp_cert_file):"); ++ am_diag_log_file_data(r, level+1, cfg->idp_public_key_file, ++ "MellonIdPPublicKeyFile (idp_public_key_file):"); ++ am_diag_log_file_data(r, level+1, cfg->idp_ca_file, ++ "MellonIdPCAFile (idp_ca_file):"); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonIdPMetadataFile (idp_metadata): %d items\n", ++ indent(level+1), cfg->idp_metadata->nelts); ++ for (i = 0; i < cfg->idp_metadata->nelts; i++) { ++ const am_metadata_t *idp_metadata; ++ idp_metadata = &(((const am_metadata_t*)cfg->idp_metadata->elts)[i]); ++ ++ am_diag_log_file_data(r, level+1, idp_metadata->metadata, ++ "[%2d] Metadata", i); ++ am_diag_log_file_data(r, level+1, idp_metadata->chain, ++ "[%2d] Chain File", i); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonIdPIgnore (idp_ignore):\n", ++ indent(level+1)); ++ for (list_item = cfg->idp_ignore, i = 0; ++ list_item; ++ list_item = g_list_next(list_item), i++) { ++ apr_file_printf(diag_cfg->fd, ++ "%s[%2d]: %s\n", ++ indent(level+2), i, (char *)list_item->data); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSPentityId (sp_entity_id): %s\n", ++ indent(level+1), cfg->sp_entity_id); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonOrganizationName (sp_org_name): %u items\n", ++ indent(level+1), apr_hash_count(cfg->sp_org_name)); ++ for (hash_item = apr_hash_first(r->pool, cfg->sp_org_name); ++ hash_item; ++ hash_item = apr_hash_next(hash_item)) { ++ const char *lang; ++ const char *value; ++ ++ apr_hash_this(hash_item, (void *)&lang, NULL, (void *)&value); ++ apr_file_printf(diag_cfg->fd, ++ "%s(lang=%s): %s\n", ++ indent(level+2), lang, value); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonOrganizationDisplayName (sp_org_display_name):" ++ " %u items\n", ++ indent(level+1), apr_hash_count(cfg->sp_org_display_name)); ++ for (hash_item = apr_hash_first(r->pool, cfg->sp_org_display_name); ++ hash_item; ++ hash_item = apr_hash_next(hash_item)) { ++ const char *lang; ++ const char *value; ++ ++ apr_hash_this(hash_item, (void *)&lang, NULL, (void *)&value); ++ apr_file_printf(diag_cfg->fd, ++ "%s(lang=%s): %s\n", ++ indent(level+2), lang, value); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonOrganizationURL (sp_org_url): %u items\n", ++ indent(level+1), apr_hash_count(cfg->sp_org_url)); ++ for (hash_item = apr_hash_first(r->pool, cfg->sp_org_url); ++ hash_item; ++ hash_item = apr_hash_next(hash_item)) { ++ const char *lang; ++ const char *value; ++ ++ apr_hash_this(hash_item, (void *)&lang, NULL, (void *)&value); ++ apr_file_printf(diag_cfg->fd, ++ "%s(lang=%s): %s\n", ++ indent(level+2), lang, value); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSessionLength (session_length): %d\n", ++ indent(level+1), cfg->session_length); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonNoCookieErrorPage (no_cookie_error_page): %s\n", ++ indent(level+1), cfg->no_cookie_error_page); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonNoSuccessErrorPage (no_success_error_page): %s\n", ++ indent(level+1), cfg->no_success_error_page); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonDefaultLoginPath (login_path): %s\n", ++ indent(level+1), cfg->login_path); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonDiscoveryURL (discovery_url): %s\n", ++ indent(level+1), cfg->discovery_url); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonProbeDiscoveryTimeout (probe_discovery_timeout):" ++ " %d\n", ++ indent(level+1), cfg->probe_discovery_timeout); ++ ++ n_items = 0; ++ apr_table_do(am_table_count, &n_items, cfg->probe_discovery_idp, NULL); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonProbeDiscoveryIdP (probe_discovery_idp):" ++ " %d items\n", ++ indent(level+1), n_items); ++ apr_table_do(log_probe_discovery_idp, &iter_data, ++ cfg->probe_discovery_idp, NULL); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonAuthnContextClassRef (authn_context_class_ref):" ++ " %d items\n", ++ indent(level+1), cfg->authn_context_class_ref->nelts); ++ for(i = 0; i < cfg->authn_context_class_ref->nelts; i++) { ++ const char *context_class; ++ ++ context_class = APR_ARRAY_IDX(cfg->authn_context_class_ref, i, char *); ++ apr_file_printf(diag_cfg->fd, ++ "%s[%2d]: %s\n", ++ indent(level+2), i, context_class); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSubjectConfirmationDataAddressCheck" ++ " (subject_confirmation_data_address_check): %s\n", ++ indent(level+1), ++ cfg->subject_confirmation_data_address_check ? "On":"Off"); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonDoNotVerifyLogoutSignature" ++ " (do_not_verify_logout_signature): %u items\n", ++ indent(level+1), ++ apr_hash_count(cfg->do_not_verify_logout_signature)); ++ ++ for (hash_item = apr_hash_first(r->pool, ++ cfg->do_not_verify_logout_signature); ++ hash_item; ++ hash_item = apr_hash_next(hash_item)) { ++ const char *entity_id; ++ ++ apr_hash_this(hash_item, (void *)&entity_id, NULL, NULL); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%s%s\n", ++ indent(level+2), entity_id); ++ } ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSendCacheControlHeader" ++ " (send_cache_control_header): %s\n", ++ indent(level+1), ++ cfg->send_cache_control_header ? "On":"Off"); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonPostReplay (post_replay): %s\n", ++ indent(level+1), cfg->post_replay ? "On":"Off"); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonECPSendIDPList (ecp_send_idplist): %s\n", ++ indent(level+1), cfg->ecp_send_idplist ? "On":"Off"); ++ ++ for (n_items = 0; cfg->redirect_domains[n_items] != NULL; n_items++); ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonRedirectDomains (redirect_domains): %d items\n", ++ indent(level+1), n_items); ++ for (i = 0; cfg->redirect_domains[i] != NULL; i++) { ++ apr_file_printf(diag_cfg->fd, ++ "%s%s\n", ++ indent(level+2), cfg->redirect_domains[i]); ++ } ++ ++ apr_file_flush(diag_cfg->fd); ++} ++ ++ ++static bool ++am_diag_initialize_req(request_rec *r, am_diag_cfg_rec *diag_cfg, ++ am_req_cfg_rec *req_cfg) ++{ ++ server_rec *s = r->server; ++ am_dir_cfg_rec *dir_cfg; ++ apr_os_thread_t tid = apr_os_thread_current(); ++ iter_callback_data iter_data; ++ int level = 0; ++ ++ if (!diag_cfg) return false; ++ if (!diag_cfg->fd) return false; ++ if (!req_cfg) return false; ++ ++ if (req_cfg->diag_emitted) return true; ++ ++ iter_data.diag_fd = diag_cfg->fd; ++ iter_data.level = level+1; ++ ++ apr_file_puts("---------------------------------- New Request" ++ " ---------------------------------\n", diag_cfg->fd); ++ apr_file_printf(diag_cfg->fd, "%s - %s\n", r->method, r->uri); ++ apr_file_printf(diag_cfg->fd, "log_id: %s\n", r->log_id); ++ apr_file_printf(diag_cfg->fd, "server: scheme=%s hostname=%s port=%d\n", ++ s->server_scheme, s->server_hostname, s->port); ++ apr_file_printf(diag_cfg->fd, "pid: %" APR_PID_T_FMT ", tid: %pT\n", ++ getpid(), &tid); ++ apr_file_printf(diag_cfg->fd, "unparsed_uri: %s\n", r->unparsed_uri); ++ apr_file_printf(diag_cfg->fd, "uri: %s\n", r->uri); ++ apr_file_printf(diag_cfg->fd, "path_info: %s\n", r->path_info); ++ apr_file_printf(diag_cfg->fd, "filename: %s\n", r->filename); ++ apr_file_printf(diag_cfg->fd, "query args: %s\n", r->args); ++ ++ apr_file_printf(diag_cfg->fd, "Request Headers:\n"); ++ apr_table_do(log_headers, &iter_data, r->headers_in, NULL); ++ ++ req_cfg->diag_emitted = true; ++ ++ ++ /* Only emit directory configuration once */ ++ if (!apr_table_get(diag_cfg->dir_cfg_emitted, r->uri)) { ++ dir_cfg = am_get_dir_cfg(r); ++ ++ am_diag_log_dir_cfg(r, level, dir_cfg, ++ "Mellon Directory Configuration for URL: %s", ++ r->uri); ++ apr_table_set(diag_cfg->dir_cfg_emitted, r->uri, "1"); ++ } ++ return true; ++} ++ ++/*=============================== Public API =================================*/ ++ ++int ++am_diag_log_init(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s) ++{ ++ for ( ; s ; s = s->next) { ++ if (!am_diag_open_log(s, p)) { ++ return HTTP_INTERNAL_SERVER_ERROR; ++ } ++ } ++ ++ return OK; ++} ++ ++int ++am_diag_finalize_request(request_rec *r) ++{ ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ int level = 0; ++ iter_callback_data iter_data; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return OK; ++ if (!req_cfg) return OK; ++ ++ if (!req_cfg->diag_emitted) return OK; ++ ++ iter_data.diag_fd = diag_cfg->fd; ++ iter_data.level = level+1; ++ ++ apr_file_puts("\n=== Response ===\n", diag_cfg->fd); ++ apr_file_printf(diag_cfg->fd, ++ "Status: %s(%d)\n", ++ r->status_line, r->status); ++ apr_file_printf(diag_cfg->fd, ++ "user: %s auth_type=%s\n", ++ r->user, r->ap_auth_type); ++ ++ apr_file_printf(diag_cfg->fd, ++ "Response Headers:\n"); ++ apr_table_do(log_headers, &iter_data, r->headers_out, NULL); ++ ++ apr_file_printf(diag_cfg->fd, ++ "Response Error Headers:\n"); ++ apr_table_do(log_headers, &iter_data, r->err_headers_out, NULL); ++ ++ apr_file_printf(diag_cfg->fd, ++ "Environment:\n"); ++ apr_table_do(log_headers, &iter_data, r->subprocess_env, NULL); ++ ++ return OK; ++} ++ ++char * ++am_diag_time_t_to_8601(request_rec *r, apr_time_t t) ++{ ++ char *buf; ++ ++ buf = apr_palloc(r->pool, ISO_8601_BUF_SIZE); ++ if (!buf) return NULL; ++ ++ am_diag_time_t_to_8601_buf(buf, ISO_8601_BUF_SIZE, t); ++ return buf; ++} ++ ++const char * ++am_diag_cond_str(request_rec *r, const am_cond_t *cond) ++{ ++ return apr_psprintf(r->pool, ++ "varname=\"%s\" flags=%s str=\"%s\" directive=\"%s\"", ++ cond->varname, am_diag_cond_flag_str(r, cond->flags), ++ cond->str, cond->directive); ++} ++ ++const char * ++am_diag_cache_key_type_str(am_cache_key_t key_type) ++{ ++ switch(key_type) { ++ case AM_CACHE_SESSION: return "session"; ++ case AM_CACHE_NAMEID : return "name id"; ++ default: return "unknown"; ++ } ++} ++ ++const char * ++am_diag_lasso_http_method_str(LassoHttpMethod http_method) ++{ ++ switch(http_method) { ++ case LASSO_HTTP_METHOD_NONE: return "LASSO_HTTP_METHOD_NONE"; ++ case LASSO_HTTP_METHOD_ANY: return "LASSO_HTTP_METHOD_ANY"; ++ case LASSO_HTTP_METHOD_IDP_INITIATED: return "LASSO_HTTP_METHOD_IDP_INITIATED"; ++ case LASSO_HTTP_METHOD_GET: return "LASSO_HTTP_METHOD_GET"; ++ case LASSO_HTTP_METHOD_POST: return "LASSO_HTTP_METHOD_POST"; ++ case LASSO_HTTP_METHOD_REDIRECT: return "LASSO_HTTP_METHOD_REDIRECT"; ++ case LASSO_HTTP_METHOD_SOAP: return "LASSO_HTTP_METHOD_SOAP"; ++ case LASSO_HTTP_METHOD_ARTIFACT_GET: return "LASSO_HTTP_METHOD_ARTIFACT_GET"; ++ case LASSO_HTTP_METHOD_ARTIFACT_POST: return "LASSO_HTTP_METHOD_ARTIFACT_POST"; ++ case LASSO_HTTP_METHOD_PAOS: return "LASSO_HTTP_METHOD_PAOS"; ++ default: return "unknown"; ++ } ++} ++ ++void ++am_diag_printf(request_rec *r, const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ char *buf; ++ apr_size_t buf_len; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ ++ va_start(ap, fmt); ++ buf = apr_pvsprintf(r->pool, fmt, ap); ++ va_end(ap); ++ buf_len = strlen(buf); ++ if (buf_len > 0) { ++ apr_file_write_full(diag_cfg->fd, buf, buf_len, NULL); ++ } ++ apr_file_flush(diag_cfg->fd); ++} ++ ++void ++am_diag_rerror(const char *file, int line, int module_index, ++ int level, apr_status_t status, ++ request_rec *r, const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ char *buf; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ buf = apr_psprintf(r->pool, "[%s %s:%d] ", ++ am_diag_httpd_error_level_str(r, level), file, line); ++ apr_file_puts(buf, diag_cfg->fd); ++ ++ va_start(ap, fmt); ++ buf = apr_pvsprintf(r->pool, fmt, ap); ++ va_end(ap); ++ apr_file_puts(buf, diag_cfg->fd); ++ ++ apr_file_puts(APR_EOL_STR, diag_cfg->fd); ++ apr_file_flush(diag_cfg->fd); ++} ++ ++void ++am_diag_log_lasso_node(request_rec *r, int level, LassoNode *node, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ gchar *xml = NULL; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ va_start(ap, fmt); ++ am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap); ++ va_end(ap); ++ ++ if (node) { ++ xml = lasso_node_debug(node, 0); ++ write_indented_text(diag_cfg->fd, level+1, xml); ++ lasso_release_string(xml); ++ } else { ++ apr_file_printf(diag_cfg->fd, "node is NULL\n"); ++ } ++ apr_file_flush(diag_cfg->fd); ++} ++ ++void ++am_diag_log_file_data(request_rec *r, int level, am_file_data_t *file_data, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ va_start(ap, fmt); ++ am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap); ++ va_end(ap); ++ ++ if (file_data) { ++ if (file_data->generated) { ++ apr_file_printf(diag_cfg->fd, ++ "%sGenerated file contents:\n", ++ indent(level+1)); ++ write_indented_text(diag_cfg->fd, ++ level+2, file_data->contents); ++ } else { ++ apr_file_printf(diag_cfg->fd, ++ "%spathname: \"%s\"\n", ++ indent(level+1), file_data->path); ++ if (!file_data->read_time) { ++ am_file_read(file_data); ++ } ++ if (file_data->rv == APR_SUCCESS) { ++ write_indented_text(diag_cfg->fd, ++ level+2, file_data->contents); ++ } else { ++ apr_file_printf(diag_cfg->fd, ++ "%s%s\n", ++ indent(level+1), file_data->strerror); ++ } ++ } ++ } else { ++ apr_file_printf(diag_cfg->fd, ++ "%sfile_data: NULL\n", ++ indent(level+1)); ++ } ++ ++ apr_file_flush(diag_cfg->fd); ++} ++ ++void ++am_diag_log_profile(request_rec *r, int level, LassoProfile *profile, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ LassoSession *session = lasso_profile_get_session(profile); ++ GList *assertions = lasso_session_get_assertions(session, NULL); ++ GList *iter = NULL; ++ int i; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ va_start(ap, fmt); ++ am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap); ++ va_end(ap); ++ ++ if (profile) { ++ apr_file_printf(diag_cfg->fd, ++ "%sProfile Type: %s\n", ++ indent(level+1), G_OBJECT_TYPE_NAME(profile)); ++ ++ for (iter = assertions, i=0; ++ iter != NULL; ++ iter = g_list_next(iter), i++) { ++ LassoSaml2Assertion *assertion = NULL; ++ ++ assertion = LASSO_SAML2_ASSERTION(iter->data); ++ if (!LASSO_IS_SAML2_ASSERTION(assertion)) { ++ apr_file_printf(diag_cfg->fd, ++ "%sObject at index %d in session assertion" ++ " list is not LassoSaml2Assertion", ++ indent(level+1), i); ++ } else { ++ am_diag_log_lasso_node(r, level+1, &assertion->parent, ++ "Assertion %d", i); ++ } ++ } ++ } else { ++ apr_file_printf(diag_cfg->fd, ++ "%sprofile is NULL\n", ++ indent(level+1)); ++ } ++ ++ apr_file_flush(diag_cfg->fd); ++} ++ ++void ++am_diag_log_cache_entry(request_rec *r, int level, am_cache_entry_t *entry, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ ++ const char *name_id = NULL; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ va_start(ap, fmt); ++ am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap); ++ va_end(ap); ++ ++ if (entry) { ++ name_id = am_cache_env_fetch_first(entry, "NAME_ID"); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%skey: %s\n", ++ indent(level+1), entry->key); ++ apr_file_printf(diag_cfg->fd, ++ "%sname_id: %s\n", ++ indent(level+1), name_id); ++ apr_file_printf(diag_cfg->fd, ++ "%sexpires: %s\n", ++ indent(level+1), ++ am_diag_time_t_to_8601(r, entry->expires)); ++ apr_file_printf(diag_cfg->fd, ++ "%saccess: %s\n", ++ indent(level+1), ++ am_diag_time_t_to_8601(r, entry->access)); ++ apr_file_printf(diag_cfg->fd, ++ "%slogged_in: %s\n", ++ indent(level+1), entry->logged_in ? "True" : "False"); ++ } else { ++ apr_file_printf(diag_cfg->fd, ++ "%sentry is NULL\n", ++ indent(level+1)); ++ } ++ apr_file_flush(diag_cfg->fd); ++} ++ ++ ++#endif /* ENABLE_DIAGNOSTICS */ +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 08b7869..0cbc0ad 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -121,6 +121,8 @@ static char *am_generate_metadata(apr_pool_t *p, request_rec *r) + char *cert = ""; + const char *sp_entity_id; + ++ am_diag_printf(r, "Generating SP metadata\n"); ++ + sp_entity_id = cfg->sp_entity_id ? cfg->sp_entity_id : url; + + if (cfg->sp_cert_file && cfg->sp_cert_file->contents) { +@@ -251,6 +253,13 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + + idp_metadata = &( ((const am_metadata_t*)cfg->idp_metadata->elts) [index] ); + ++ am_diag_log_file_data(r, 0, idp_metadata->metadata, ++ "Loading IdP Metadata"); ++ if (idp_metadata->chain) { ++ am_diag_log_file_data(r, 0, idp_metadata->chain, ++ "Loading IdP metadata chain"); ++ } ++ + #ifdef HAVE_lasso_server_load_metadata + error = lasso_server_load_metadata(cfg->server, + LASSO_PROVIDER_ROLE_IDP, +@@ -674,6 +683,9 @@ static void am_restore_lasso_profile_state(request_rec *r, + am_release_request_session(r, am_session); + } + } ++ am_diag_log_cache_entry(r, 0, am_session, "%s: Session Cache Entry", __func__); ++ ++ am_diag_log_profile(r, 0, profile, "%s: Restored Profile", __func__); + } + + /* This function handles an IdP initiated logout request. +@@ -693,6 +705,8 @@ static int am_handle_logout_request(request_rec *r, + am_cache_entry_t *session = NULL; + am_dir_cfg_rec *cfg = am_get_dir_cfg(r); + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + /* Process the logout message. Ignore missing signature. */ + res = lasso_logout_process_request_msg(logout, msg); + #ifdef HAVE_lasso_profile_set_signature_verify_hint +@@ -724,6 +738,10 @@ static int am_handle_logout_request(request_rec *r, + rc = HTTP_BAD_REQUEST; + goto exit; + } ++ ++ am_diag_printf(r, "%s name id %s\n", __func__, ++ ((LassoSaml2NameID*)logout->parent.nameIdentifier)->content); ++ + session = am_get_request_session_by_nameid(r, + ((LassoSaml2NameID*)logout->parent.nameIdentifier)->content); + if (session == NULL) { +@@ -733,6 +751,9 @@ static int am_handle_logout_request(request_rec *r, + ((LassoSaml2NameID*)logout->parent.nameIdentifier)->content); + + } ++ ++ am_diag_log_cache_entry(r, 0, session, "%s", __func__); ++ + if (session == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing logout request message." +@@ -830,6 +851,9 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + + /* Delete the session. */ + session = am_get_request_session(r); ++ ++ am_diag_log_cache_entry(r, 0, session, "%s\n", __func__); ++ + if(session != NULL) { + am_delete_request_session(r, session); + } +@@ -1482,6 +1506,9 @@ static void am_handle_session_expire(request_rec *r, am_cache_entry_t *session, + /* Find timestamp. */ + not_on_or_after = authn->SessionNotOnOrAfter; + if(not_on_or_after == NULL) { ++ am_diag_printf(r, "%s failed to find" ++ " Assertion.AuthnStatement.SessionNotOnOrAfter\n", ++ __func__); + continue; + } + +@@ -1492,6 +1519,10 @@ static void am_handle_session_expire(request_rec *r, am_cache_entry_t *session, + continue; + } + ++ am_diag_printf(r, "%s Assertion.AuthnStatement.SessionNotOnOrAfter:" ++ " %s\n", ++ __func__, am_diag_time_t_to_8601(r, t)); ++ + /* Updates the expires timestamp if this one is earlier than the + * previous timestamp. + */ +@@ -1629,6 +1660,10 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + g_free(dump); + } + /* Decode and save the attribute. */ ++ ++ am_diag_printf(r, "%s name=%s value=%s\n", ++ __func__, attribute->Name, content); ++ + ret = am_cache_env_append(session, attribute->Name, content); + if(ret != OK) { + return ret; +@@ -1725,6 +1760,9 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + int rc; + const char *idp; + ++ am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response, ++ "SAMLResponse:"); ++ + url = am_reconstruct_url(r); + chr = strchr(url, '?'); + if (! chr) { +@@ -1867,7 +1905,6 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + return HTTP_INTERNAL_SERVER_ERROR; + } + +- + /* Save the profile state. */ + rc = am_save_lasso_profile_state(r, session, LASSO_PROFILE(login), + saml_response); +@@ -1941,6 +1978,8 @@ static int am_handle_post_reply(request_rec *r) + am_dir_cfg_rec *dir_cfg = am_get_dir_cfg(r); + int i, err; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + /* Make sure that this is a POST request. */ + if(r->method_number != M_POST) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +@@ -2050,6 +2089,8 @@ static int am_handle_paos_reply(request_rec *r) + char *relay_state = NULL; + int i, err; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + /* Make sure that this is a POST request. */ + if(r->method_number != M_POST) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +@@ -2137,6 +2178,8 @@ static int am_handle_artifact_reply(request_rec *r) + char *saml_art; + char *post_data; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + /* Make sure that this is a GET request. */ + if(r->method_number != M_GET && r->method_number != M_POST) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +@@ -2408,6 +2451,8 @@ static int am_handle_repost(request_rec *r) + const char *(*post_mkform)(request_rec *, const char *); + int rc; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + if (am_cookie_get(r) == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Repost query without a session"); +@@ -2570,6 +2615,8 @@ static int am_handle_metadata(request_rec *r) + LassoServer *server; + const char *data; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + server = am_get_lasso_server(r); + if(server == NULL) + return HTTP_INTERNAL_SERVER_ERROR; +@@ -2898,6 +2945,11 @@ static int am_init_authn_request_common(request_rec *r, + static int am_set_authn_request_content(request_rec *r, LassoLogin *login) + + { ++ ++ am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->request, ++ "SAML AuthnRequest: http_method=%s", ++ am_diag_lasso_http_method_str(login->http_method)); ++ + switch (login->http_method) { + case LASSO_HTTP_METHOD_REDIRECT: + return am_set_authn_request_redirect_content(r, login); +@@ -3112,6 +3164,8 @@ static int am_handle_auth(request_rec *r) + am_dir_cfg_rec *cfg = am_get_dir_cfg(r); + const char *relay_state; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + relay_state = am_reconstruct_url(r); + + /* Check if IdP discovery is in use and no IdP was selected yet */ +@@ -3151,6 +3205,8 @@ static int am_handle_login(request_rec *r) + int is_passive; + int ret; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + return_to = am_extract_query_parameter(r->pool, r->args, "ReturnTo"); + if(return_to == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +@@ -3255,6 +3311,8 @@ static int am_handle_probe_discovery(request_rec *r) { + char *redirect_url; + int ret; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + server = am_get_lasso_server(r); + if(server == NULL) { + return HTTP_INTERNAL_SERVER_ERROR; +@@ -3488,6 +3546,8 @@ static int am_start_auth(request_rec *r) + const char *idp; + const char *login_url; + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + return_to = am_reconstruct_url(r); + + /* If this is a POST request, attempt to save it */ +@@ -3539,6 +3599,8 @@ int am_auth_mellon_user(request_rec *r) + return DECLINED; + } + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + /* Set defaut Cache-Control headers within this location */ + if (CFG_VALUE(dir, send_cache_control_header)) { + am_set_cache_control_headers(r); +@@ -3563,6 +3625,9 @@ int am_auth_mellon_user(request_rec *r) + if(session == NULL || !session->logged_in) { + /* We don't have a valid session. */ + ++ am_diag_printf(r, "%s am_enable_auth, no valid session\n", ++ __func__); ++ + if(session) { + /* Release the session. */ + am_release_request_session(r, session); +@@ -3613,9 +3678,14 @@ int am_auth_mellon_user(request_rec *r) + #endif /* HAVE_ECP */ + } + ++ am_diag_printf(r, "%s am_enable_auth, have valid session\n", ++ __func__); ++ + /* Verify that the user has access to this resource. */ + return_code = am_check_permissions(r, session); + if(return_code != OK) { ++ am_diag_printf(r, "%s failed am_check_permissions, status=%d\n", ++ __func__, return_code); + am_release_request_session(r, session); + + return return_code; +@@ -3643,11 +3713,17 @@ int am_auth_mellon_user(request_rec *r) + && session->logged_in + && am_check_permissions(r, session) == OK) { + ++ am_diag_printf(r, "%s am_enable_info, have valid session\n", ++ __func__); ++ + /* The user is authenticated and has access to the resource. + * Now we populate the environment with information about + * the user. + */ + am_cache_env_populate(r, session); ++ } else { ++ am_diag_printf(r, "%s am_enable_info, no valid session\n", ++ __func__); + } + + if(session != NULL) { +@@ -3688,6 +3764,8 @@ int am_check_uid(request_rec *r) + return DECLINED; + } + ++ am_diag_printf(r, "enter function %s\n", __func__); ++ + #ifdef HAVE_ECP + am_req_cfg_rec *req_cfg = am_get_req_cfg(r); + if (req_cfg->ecp_authn_req) { +@@ -3744,11 +3822,15 @@ int am_check_uid(request_rec *r) + + /* If we don't have a session, then we can't authorize the user. */ + if(session == NULL) { ++ am_diag_printf(r, "%s no session, return HTTP_UNAUTHORIZED\n", ++ __func__); + return HTTP_UNAUTHORIZED; + } + + /* If the user isn't logged in, then we can't authorize the user. */ + if(!session->logged_in) { ++ am_diag_printf(r, "%s session not logged in," ++ " return HTTP_UNAUTHORIZED\n", __func__); + am_release_request_session(r, session); + return HTTP_UNAUTHORIZED; + } +@@ -3756,6 +3838,8 @@ int am_check_uid(request_rec *r) + /* Verify that the user has access to this resource. */ + return_code = am_check_permissions(r, session); + if(return_code != OK) { ++ am_diag_printf(r, "%s failed am_check_permissions, status=%d\n", ++ __func__, return_code); + am_release_request_session(r, session); + return return_code; + } +diff --git a/auth_mellon_session.c b/auth_mellon_session.c +index 3eae4a0..31ae5db 100644 +--- a/auth_mellon_session.c ++++ b/auth_mellon_session.c +@@ -39,9 +39,18 @@ am_cache_entry_t *am_lock_and_validate(request_rec *r, + am_cache_key_t type, + const char *key) + { +- am_cache_entry_t *session = am_cache_lock(r, type, key); ++ am_cache_entry_t *session = NULL; ++ ++ am_diag_printf(r, "searching for session with key %s (%s) ... ", ++ key, am_diag_cache_key_type_str(type)); ++ ++ session = am_cache_lock(r, type, key); + if (session == NULL) { ++ am_diag_printf(r, "not found\n"); + return NULL; ++ } else { ++ am_diag_printf(r, "found.\n"); ++ am_diag_log_cache_entry(r, 0, session, "Session Cache Entry"); + } + + const char *cookie_token_session = am_cache_entry_get_string( +@@ -123,6 +132,10 @@ am_cache_entry_t *am_new_request_session(request_rec *r) + am_cookie_set(r, session_id); + + const char *cookie_token = am_cookie_token(r); ++ ++ am_diag_printf(r, "%s id=%s cookie_token=\"%s\"\n", ++ __func__, session_id, cookie_token); ++ + return am_cache_new(r, session_id, cookie_token); + } + +@@ -155,6 +168,8 @@ void am_release_request_session(request_rec *r, am_cache_entry_t *session) + */ + void am_delete_request_session(request_rec *r, am_cache_entry_t *session) + { ++ am_diag_log_cache_entry(r, 0, session, "delete session"); ++ + /* Delete the cookie. */ + am_cookie_delete(r); + +diff --git a/auth_mellon_util.c b/auth_mellon_util.c +index 7f8d52b..46036a9 100644 +--- a/auth_mellon_util.c ++++ b/auth_mellon_util.c +@@ -370,6 +370,10 @@ int am_check_permissions(request_rec *r, am_cache_entry_t *session) + + ce = &((am_cond_t *)(dir_cfg->cond->elts))[i]; + ++ am_diag_printf(r, "%s processing condition %d of %d: %s ", ++ __func__, i, dir_cfg->cond->nelts, ++ am_diag_cond_str(r, ce)); ++ + /* + * Rule with ignore flog? + */ +@@ -384,9 +388,11 @@ int am_check_permissions(request_rec *r, am_cache_entry_t *session) + if (!(ce->flags & AM_COND_FLAG_OR)) + skip_or = 0; + +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, +- "Skip %s, [OR] rule matched previously", +- ce->directive); ++ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ "Skip %s, [OR] rule matched previously", ++ ce->directive); ++ ++ am_diag_printf(r, "Skip, [OR] rule matched previously\n"); + continue; + } + +@@ -433,6 +439,8 @@ int am_check_permissions(request_rec *r, am_cache_entry_t *session) + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "Evaluate %s vs \"%s\"", + ce->directive, value); ++ ++ am_diag_printf(r, "evaluate value \"%s\" ", value); + + if (value == NULL) { + match = 0; /* can not happen */ +@@ -463,11 +471,16 @@ int am_check_permissions(request_rec *r, am_cache_entry_t *session) + } else { + match = !strcmp(ce->str, value); + } ++ ++ am_diag_printf(r, "match=%s, ", match ? "yes" : "no"); + } + +- if (ce->flags & AM_COND_FLAG_NOT) ++ if (ce->flags & AM_COND_FLAG_NOT) { + match = !match; + ++ am_diag_printf(r, "negating now match=%s ", match ? "yes" : "no"); ++ } ++ + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "%s: %smatch", ce->directive, + (match == 0) ? "no ": ""); +@@ -479,6 +492,9 @@ int am_check_permissions(request_rec *r, am_cache_entry_t *session) + ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, + "Client failed to match %s", + ce->directive); ++ ++ am_diag_printf(r, "failed (no OR condition)" ++ " returning HTTP_FORBIDDEN\n"); + return HTTP_FORBIDDEN; + } + +@@ -488,8 +504,12 @@ int am_check_permissions(request_rec *r, am_cache_entry_t *session) + */ + if (match && (ce->flags & AM_COND_FLAG_OR)) + skip_or = 1; ++ ++ am_diag_printf(r, "\n"); + } + ++ am_diag_printf(r, "%s succeeds\n", __func__); ++ + return OK; + } + +diff --git a/configure.ac b/configure.ac +index 5ca2c8a..ae313e0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -41,6 +41,16 @@ The executable may also be named 'apxs'. + ]) + fi + ++AC_ARG_ENABLE( ++ [diagnostics], ++ [AS_HELP_STRING([--enable-diagnostics], ++ [Build with diagnostic support])], ++ [], ++ [enable_diagnostics=no]) ++ ++AS_IF([test "x$enable_diagnostics" != xno], ++ [MELLON_CFLAGS="$MELLON_CFLAGS -DENABLE_DIAGNOSTICS"]) ++ + # Replace any occurances of @APXS2@ with the value of $APXS2 in the Makefile. + AC_SUBST(APXS2) + +@@ -74,6 +84,8 @@ PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.12]) + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) + ++AC_SUBST(MELLON_CFLAGS) ++ + # Test to see if we can include lasso/utils.h + # AC_CHECK_HEADER won't work correctly unless we specifiy the include directories + # found in the LASSO_CFLAGS. Save and restore CFLAGS and CPPFLAGS. +diff --git a/mod_auth_mellon.c b/mod_auth_mellon.c +index f632d37..74bd328 100644 +--- a/mod_auth_mellon.c ++++ b/mod_auth_mellon.c +@@ -195,6 +195,9 @@ static int am_create_request(request_rec *r) + #ifdef HAVE_ECP + req_cfg->ecp_authn_req = false; + #endif /* HAVE_ECP */ ++#ifdef ENABLE_DIAGNOSTICS ++ req_cfg->diag_emitted = false; ++#endif + + ap_set_module_config(r->request_config, &auth_mellon_module, req_cfg); + +@@ -220,6 +223,11 @@ static void register_hooks(apr_pool_t *p) + * r->handler and decide that it is the only handler for this URL. + */ + ap_hook_handler(am_handler, NULL, NULL, APR_HOOK_FIRST); ++ ++#ifdef ENABLE_DIAGNOSTICS ++ ap_hook_open_logs(am_diag_log_init,NULL,NULL,APR_HOOK_MIDDLE); ++ ap_hook_log_transaction(am_diag_finalize_request,NULL,NULL,APR_HOOK_REALLY_LAST); ++#endif + } + + +@@ -229,7 +237,7 @@ module AP_MODULE_DECLARE_DATA auth_mellon_module = + auth_mellon_dir_config, + auth_mellon_dir_merge, + auth_mellon_server_config, +- NULL, ++ auth_mellon_srv_merge, + auth_mellon_commands, + register_hooks + }; diff --git a/SOURCES/am_log_rerror.patch b/SOURCES/am_log_rerror.patch new file mode 100644 index 0000000..24c02e3 --- /dev/null +++ b/SOURCES/am_log_rerror.patch @@ -0,0 +1,1982 @@ +commit 8d49ab65a125788b70ceb8d936764dded4321012 +Author: John Dennis +Date: Wed Sep 13 18:06:12 2017 -0400 + + Replace ap_log_rerror with AM_LOG_RERROR + + If diagnostics is enabled we want error messages written to the + diagnostics log as well as the Apache error_log. AM_LOG_RERROR + replaces the use of ap_log_rerror, it invokes ap_log_rerror as + previously but then also logs the same message to the diagnostics + log. If diagnostics is not enabled it reverts to ap_log_rerror. + + Signed-off-by: John Dennis + +diff --git a/auth_mellon.h b/auth_mellon.h +index 6ce6a8e..c3d444a 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -587,6 +587,15 @@ am_diag_rerror(const char *file, int line, int module_index, + char * + am_diag_time_t_to_8601(request_rec *r, apr_time_t t); + ++/* Define AM_LOG_RERROR log to both the Apache log and diagnostics log */ ++#define AM_LOG_RERROR(...) AM_LOG_RERROR__(__VA_ARGS__) ++/* need additional step to expand macros */ ++#define AM_LOG_RERROR__(file, line, mi, level, status, r, ...) \ ++{ \ ++ ap_log_rerror(file, line, mi, level, status, r, __VA_ARGS__); \ ++ am_diag_rerror(file, line, mi, level, status, r, __VA_ARGS__); \ ++} ++ + #else /* ENABLE_DIAGNOSTICS */ + + #define am_diag_log_cache_entry(...) do {} while(0) +@@ -595,6 +604,12 @@ am_diag_time_t_to_8601(request_rec *r, apr_time_t t); + #define am_diag_log_profile(...) do {} while(0) + #define am_diag_printf(...) do {} while(0) + ++/* Define AM_LOG_RERROR log only to the Apache log */ ++#define AM_LOG_RERROR(...) AM_LOG_RERROR__(__VA_ARGS__) ++/* need additional step to expand macros */ ++#define AM_LOG_RERROR__(file, line, mi, level, status, r, ...) \ ++ap_log_rerror(file, line, mi, level, status, r, __VA_ARGS__); ++ + #endif /* ENABLE_DIAGNOSTICS */ + + #endif /* MOD_AUTH_MELLON_H */ +diff --git a/auth_mellon_cache.c b/auth_mellon_cache.c +index 2115acc..fe6c910 100644 +--- a/auth_mellon_cache.c ++++ b/auth_mellon_cache.c +@@ -109,7 +109,7 @@ am_cache_entry_t *am_cache_lock(request_rec *r, + + /* Lock the table. */ + if((rv = apr_global_mutex_lock(mod_cfg->lock)) != APR_SUCCESS) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "apr_global_mutex_lock() failed [%d]: %s", + rv, apr_strerror(rv, buffer, sizeof(buffer))); + return NULL; +@@ -309,7 +309,7 @@ am_cache_entry_t *am_cache_new(request_rec *r, + + /* Lock the table. */ + if((rv = apr_global_mutex_lock(mod_cfg->lock)) != APR_SUCCESS) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "apr_global_mutex_lock() failed [%d]: %s", + rv, apr_strerror(rv, buffer, sizeof(buffer))); + return NULL; +@@ -367,7 +367,7 @@ am_cache_entry_t *am_cache_new(request_rec *r, + age = (current_time - t->access) / 1000000; + + if(age < 3600) { +- ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_NOTICE, 0, r, + "Dropping LRU entry entry with age = %" APR_TIME_T_FMT + "s, which is less than one hour. It may be a good" + " idea to increase MellonCacheSize.", +@@ -403,7 +403,7 @@ am_cache_entry_t *am_cache_new(request_rec *r, + /* For some strange reason our cookie token is too big to fit in the + * session. This should never happen outside of absurd configurations. + */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to store cookie token in new session."); + t->key[0] = '\0'; /* Mark the entry as free. */ + apr_global_mutex_unlock(mod_cfg->lock); +@@ -572,7 +572,7 @@ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) + value = am_cache_entry_get_string(t, &t->env[i].value); + status = am_cache_entry_store_string(t, &t->user, value); + if (status != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_NOTICE, 0, r, + "Unable to store the user name because there" + " is no more space in the session. " + "Username = \"%s\".", value); +@@ -611,7 +611,7 @@ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) + (strcasecmp(varname, d->userattr) == 0)) { + status = am_cache_entry_store_string(t, &t->user, value); + if (status != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_NOTICE, 0, r, + "Unable to store the user name because there" + " is no more space in the session. " + "Username = \"%s\".", value); +@@ -679,7 +679,7 @@ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) + r->ap_auth_type = apr_pstrdup(r->pool, "Mellon"); + } else { + /* We don't have a user-"name". Log error. */ +- ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_NOTICE, 0, r, + "Didn't find the attribute \"%s\" in the attributes" + " which were received from the IdP. Cannot set a user" + " for this request without a valid user attribute.", +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 0cbc0ad..afb3195 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -239,7 +239,7 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + #endif /* ! HAVE_lasso_server_load_metadata */ + + if (cfg->idp_metadata->nelts == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error, URI \"%s\" has no IdP's defined", r->uri); + return 0; + } +@@ -273,7 +273,7 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + GList *idx; + + for (idx = loaded_idp; idx != NULL; idx = idx->next) { +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "loaded IdP \"%s\" from \"%s\".", + (char *)idx->data, idp_metadata->metadata->path); + } +@@ -296,7 +296,7 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + #endif /* HAVE_lasso_server_load_metadata */ + + if (error != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error adding metadata \"%s\" to " + "lasso server objects. Lasso error: [%i] %s", + idp_metadata->metadata->path, error, lasso_strerror(error)); +@@ -327,7 +327,7 @@ static LassoServer *am_get_lasso_server(request_rec *r) + cfg->sp_metadata_file->generated = true; + cfg->sp_metadata_file->contents = am_generate_metadata(pool, r); + #else +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing MellonSPMetadataFile option."); + apr_thread_mutex_unlock(cfg->server_mutex); + return NULL; +@@ -350,7 +350,7 @@ static LassoServer *am_get_lasso_server(request_rec *r) + cfg->sp_cert_file->path : NULL); + #endif + if (cfg->server == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error initializing lasso server object. Please" + " verify the following configuration directives:" + " MellonSPMetadataFile and MellonSPPrivateKeyFile."); +@@ -360,7 +360,7 @@ static LassoServer *am_get_lasso_server(request_rec *r) + } + + if (am_server_add_providers(cfg, r) == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error adding IdP to lasso server object. Please" + " verify the following configuration directives:" + " MellonIdPMetadataFile and" +@@ -409,7 +409,7 @@ static int am_start_disco(request_rec *r, const char *return_to) + login_url = apr_psprintf(r->pool, "%slogin?ReturnTo=%s", + endpoint, + am_urlencode(r->pool, return_to)); +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "login_url = %s", login_url); + + /* If discovery URL already has a ? we append a & */ +@@ -421,7 +421,7 @@ static int am_start_disco(request_rec *r, const char *return_to) + am_urlencode(r->pool, sp_entity_id), + am_urlencode(r->pool, login_url)); + +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "discovery_url = %s", discovery_url); + apr_table_setn(r->headers_out, "Location", discovery_url); + return HTTP_SEE_OTHER; +@@ -490,7 +490,7 @@ static const char *am_get_idp(request_rec *r) + + rc = am_urldecode((char *)idp_provider_id); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Could not urldecode IdP discovery value."); + idp_provider_id = NULL; + } else { +@@ -502,7 +502,7 @@ static const char *am_get_idp(request_rec *r) + * If we do not know about it, fall back to default. + */ + if (idp_provider_id == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "IdP discovery returned unknown or inexistant IdP"); + idp_provider_id = am_first_idp(r); + } +@@ -544,14 +544,14 @@ static int am_save_lasso_profile_state(request_rec *r, + + lasso_identity = lasso_profile_get_identity(profile); + if(lasso_identity == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "The current LassoProfile object doesn't contain a" + " LassoIdentity object."); + identity_dump = NULL; + } else { + identity_dump = lasso_identity_dump(lasso_identity); + if(identity_dump == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not create a identity dump from the" + " LassoIdentity object."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -560,14 +560,14 @@ static int am_save_lasso_profile_state(request_rec *r, + + lasso_session = lasso_profile_get_session(profile); + if(lasso_session == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "The current LassoProfile object doesn't contain a" + " LassoSession object."); + session_dump = NULL; + } else { + session_dump = lasso_session_dump(lasso_session); + if(session_dump == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not create a session dump from the" + " LassoSession object."); + if(identity_dump != NULL) { +@@ -611,7 +611,7 @@ static int am_return_logout_response(request_rec *r, + { + if (profile->msg_url && profile->msg_body) { + /* POST binding response */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error building logout response message." + " POST binding is unsupported."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -626,7 +626,7 @@ static int am_return_logout_response(request_rec *r, + ap_rputs(profile->msg_body, r); + return OK; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error building logout response message." + " There is no content to return."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -656,7 +656,7 @@ static void am_restore_lasso_profile_state(request_rec *r, + + + if(am_session == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not get auth_mellon session while attempting" + " to restore the lasso profile state."); + return; +@@ -666,7 +666,7 @@ static void am_restore_lasso_profile_state(request_rec *r, + if(identity_dump != NULL) { + rc = lasso_profile_set_identity_from_dump(profile, identity_dump); + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not restore identity from dump." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + am_release_request_session(r, am_session); +@@ -677,7 +677,7 @@ static void am_restore_lasso_profile_state(request_rec *r, + if(session_dump != NULL) { + rc = lasso_profile_set_session_from_dump(profile, session_dump); + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not restore session from dump." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + am_release_request_session(r, am_session); +@@ -722,7 +722,7 @@ static int am_handle_logout_request(request_rec *r, + } + #endif + if(res != 0 && res != LASSO_DS_ERROR_SIGNATURE_NOT_FOUND) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing logout request message." + " Lasso error: [%i] %s", res, lasso_strerror(res)); + +@@ -732,7 +732,7 @@ static int am_handle_logout_request(request_rec *r, + + /* Search session using NameID */ + if (! LASSO_IS_SAML2_NAME_ID(logout->parent.nameIdentifier)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing logout request message." + " No NameID found"); + rc = HTTP_BAD_REQUEST; +@@ -745,7 +745,7 @@ static int am_handle_logout_request(request_rec *r, + session = am_get_request_session_by_nameid(r, + ((LassoSaml2NameID*)logout->parent.nameIdentifier)->content); + if (session == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing logout request message." + " No session found for NameID %s", + ((LassoSaml2NameID*)logout->parent.nameIdentifier)->content); +@@ -755,7 +755,7 @@ static int am_handle_logout_request(request_rec *r, + am_diag_log_cache_entry(r, 0, session, "%s", __func__); + + if (session == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing logout request message." + " No session found."); + +@@ -768,7 +768,7 @@ static int am_handle_logout_request(request_rec *r, + if(res != 0 && + res != LASSO_DS_ERROR_SIGNATURE_NOT_FOUND && + res != LASSO_PROFILE_ERROR_SESSION_NOT_FOUND) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Error validating logout request." + " Lasso error: [%i] %s", res, lasso_strerror(res)); + rc = HTTP_INTERNAL_SERVER_ERROR; +@@ -787,7 +787,7 @@ static int am_handle_logout_request(request_rec *r, + /* Create response message. */ + res = lasso_logout_build_response_msg(logout); + if(res != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error building logout response message." + " Lasso error: [%i] %s", res, lasso_strerror(res)); + +@@ -839,7 +839,7 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + } + #endif + if(res != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to process logout response." + " Lasso error: [%i] %s", res, lasso_strerror(res)); + +@@ -860,7 +860,7 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + + return_to = am_extract_query_parameter(r->pool, r->args, "RelayState"); + if(return_to == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No RelayState parameter to logout response handler." + " It is possible that your IdP doesn't support the" + " RelayState parameter."); +@@ -869,7 +869,7 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + + rc = am_urldecode(return_to); + if(rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Could not urldecode RelayState value in logout" + " response."); + return HTTP_BAD_REQUEST; +@@ -884,7 +884,7 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + /* Make sure that it is a valid redirect URL. */ + rc = am_validate_redirect_url(r, return_to); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid target domain in logout response RelayState parameter."); + return rc; + } +@@ -922,14 +922,14 @@ static int am_init_logout_request(request_rec *r, LassoLogout *logout) + return_to = am_extract_query_parameter(r->pool, r->args, "ReturnTo"); + rc = am_urldecode(return_to); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Could not urldecode ReturnTo value."); + return HTTP_BAD_REQUEST; + } + + rc = am_validate_redirect_url(r, return_to); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid target domain in logout request ReturnTo parameter."); + return rc; + } +@@ -947,15 +947,15 @@ static int am_init_logout_request(request_rec *r, LassoLogout *logout) + /* Early non failing return. */ + if (res != 0) { + if(res == LASSO_PROFILE_ERROR_SESSION_NOT_FOUND) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "User attempted to initiate logout without being" + " loggged in."); + } else if (res == LASSO_LOGOUT_ERROR_UNSUPPORTED_PROFILE || res == LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "Current identity provider " ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, "Current identity provider " + "does not support single logout. Destroying local session only."); + + } else if(res != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to create logout request." + " Lasso error: [%i] %s", res, lasso_strerror(res)); + +@@ -985,7 +985,7 @@ static int am_init_logout_request(request_rec *r, LassoLogout *logout) + session, profile->remote_providerID); + if(! assertion_list || + LASSO_IS_SAML2_ASSERTION(assertion_list->data) == FALSE) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No assertions found for the current session."); + lasso_logout_destroy(logout); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1001,7 +1001,7 @@ static int am_init_logout_request(request_rec *r, LassoLogout *logout) + authnStatement = LASSO_SAML2_AUTHN_STATEMENT(assertion->AuthnStatement->data); + + if(!authnStatement) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No AuthnStatement found in the current assertion."); + lasso_logout_destroy(logout); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1022,7 +1022,7 @@ static int am_init_logout_request(request_rec *r, LassoLogout *logout) + /* Serialize the request message into a url which we can redirect to. */ + res = lasso_logout_build_request_msg(logout); + if(res != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to serialize lasso logout message." + " Lasso error: [%i] %s", res, lasso_strerror(res)); + +@@ -1077,7 +1077,7 @@ static int am_handle_logout(request_rec *r) + + logout = lasso_logout_new(server); + if(logout == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error creating lasso logout object."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -1098,7 +1098,7 @@ static int am_handle_logout(request_rec *r) + + rc = am_read_post_data(r, &post_data, NULL); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Error reading POST data."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -1121,7 +1121,7 @@ static int am_handle_logout(request_rec *r) + + } else { + /* Unknown request to the logout handler. */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No known parameters passed to the logout" + " handler. Query string was \"%s\". To initiate" + " a logout, you need to pass a \"ReturnTo\"" +@@ -1157,7 +1157,7 @@ static apr_time_t am_parse_timestamp(request_rec *r, const char *timestamp) + + /* Verify length of timestamp. */ + if(len < 20){ +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Invalid length of timestamp: \"%s\".", timestamp); + } + +@@ -1208,7 +1208,7 @@ static apr_time_t am_parse_timestamp(request_rec *r, const char *timestamp) + } + + if(expected != NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid character in timestamp at position %i." + " Expected %s, got '%c'. Full timestamp: \"%s\"", + i, expected, c, timestamp); +@@ -1217,7 +1217,7 @@ static apr_time_t am_parse_timestamp(request_rec *r, const char *timestamp) + } + + if (timestamp[len - 1] != 'Z') { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Timestamp wasn't in UTC (did not end with 'Z')." + " Full timestamp: \"%s\"", + timestamp); +@@ -1260,7 +1260,7 @@ static apr_time_t am_parse_timestamp(request_rec *r, const char *timestamp) + + rc = apr_time_exp_gmt_get(&res, &time_exp); + if(rc != APR_SUCCESS) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Error converting timestamp \"%s\".", + timestamp); + return 0; +@@ -1293,7 +1293,7 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + /* No Subject to validate. */ + return OK; + } else if (!LASSO_IS_SAML2_SUBJECT(assertion->Subject)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of Subject node."); + return HTTP_BAD_REQUEST; + } +@@ -1302,7 +1302,7 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + /* No SubjectConfirmation. */ + return OK; + } else if (!LASSO_IS_SAML2_SUBJECT_CONFIRMATION(assertion->Subject->SubjectConfirmation)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of SubjectConfirmation node."); + return HTTP_BAD_REQUEST; + } +@@ -1310,7 +1310,7 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + sc = assertion->Subject->SubjectConfirmation; + if (sc->Method == NULL || + strcmp(sc->Method, "urn:oasis:names:tc:SAML:2.0:cm:bearer")) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid Method in SubjectConfirmation."); + return HTTP_BAD_REQUEST; + } +@@ -1320,7 +1320,7 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + /* Nothing to verify. */ + return OK; + } else if (!LASSO_IS_SAML2_SUBJECT_CONFIRMATION_DATA(scd)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of SubjectConfirmationData node."); + return HTTP_BAD_REQUEST; + } +@@ -1330,12 +1330,12 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + if (scd->NotBefore) { + t = am_parse_timestamp(r, scd->NotBefore); + if (t == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid timestamp in NotBefore in SubjectConfirmationData."); + return HTTP_BAD_REQUEST; + } + if (t - 60000000 > now) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "NotBefore in SubjectConfirmationData was in the future."); + return HTTP_BAD_REQUEST; + } +@@ -1344,12 +1344,12 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + if (scd->NotOnOrAfter) { + t = am_parse_timestamp(r, scd->NotOnOrAfter); + if (t == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid timestamp in NotOnOrAfter in SubjectConfirmationData."); + return HTTP_BAD_REQUEST; + } + if (now >= t + 60000000) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "NotOnOrAfter in SubjectConfirmationData was in the past."); + return HTTP_BAD_REQUEST; + } +@@ -1357,7 +1357,7 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + + if (scd->Recipient) { + if (strcmp(scd->Recipient, url)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong Recipient in SubjectConfirmationData. Current URL is: %s, Recipient is %s", + url, scd->Recipient); + return HTTP_BAD_REQUEST; +@@ -1366,7 +1366,7 @@ static int am_validate_subject(request_rec *r, LassoSaml2Assertion *assertion, + + if (scd->Address && CFG_VALUE(cfg, subject_confirmation_data_address_check)) { + if (strcasecmp(scd->Address, am_compat_request_ip(r))) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong Address in SubjectConfirmationData." + "Current address is \"%s\", but should have been \"%s\".", + am_compat_request_ip(r), scd->Address); +@@ -1405,7 +1405,7 @@ static int am_validate_conditions(request_rec *r, + return OK; + } + if (!LASSO_IS_SAML2_CONDITIONS(conditions)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of Conditions node."); + return HTTP_BAD_REQUEST; + } +@@ -1414,7 +1414,7 @@ static int am_validate_conditions(request_rec *r, + /* This is a list of LassoSaml2ConditionAbstract - if it + * isn't empty, we have an unsupported condition. + */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unsupported condition in Assertion."); + return HTTP_BAD_REQUEST; + } +@@ -1425,12 +1425,12 @@ static int am_validate_conditions(request_rec *r, + if (conditions->NotBefore) { + t = am_parse_timestamp(r, conditions->NotBefore); + if (t == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid timestamp in NotBefore in Condition."); + return HTTP_BAD_REQUEST; + } + if (t - 60000000 > now) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "NotBefore in Condition was in the future."); + return HTTP_BAD_REQUEST; + } +@@ -1439,12 +1439,12 @@ static int am_validate_conditions(request_rec *r, + if (conditions->NotOnOrAfter) { + t = am_parse_timestamp(r, conditions->NotOnOrAfter); + if (t == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid timestamp in NotOnOrAfter in Condition."); + return HTTP_BAD_REQUEST; + } + if (now >= t + 60000000) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "NotOnOrAfter in Condition was in the past."); + return HTTP_BAD_REQUEST; + } +@@ -1454,13 +1454,13 @@ static int am_validate_conditions(request_rec *r, + i = g_list_next(i)) { + ar = i->data; + if (!LASSO_IS_SAML2_AUDIENCE_RESTRICTION(ar)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of AudienceRestriction node."); + return HTTP_BAD_REQUEST; + } + + if (ar->Audience == NULL || strcmp(ar->Audience, providerID)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid Audience in Conditions. Should be: %s", + providerID); + return HTTP_BAD_REQUEST; +@@ -1498,7 +1498,7 @@ static void am_handle_session_expire(request_rec *r, am_cache_entry_t *session, + + authn = authn_itr->data; + if (!LASSO_IS_SAML2_AUTHN_STATEMENT(authn)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of AuthnStatement node."); + continue; + } +@@ -1589,7 +1589,7 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + + atr_stmt = atr_stmt_itr->data; + if (!LASSO_IS_SAML2_ATTRIBUTE_STATEMENT(atr_stmt)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of AttributeStatement node."); + continue; + } +@@ -1601,13 +1601,13 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + + attribute = atr_itr->data; + if (!LASSO_IS_SAML2_ATTRIBUTE(attribute)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of Attribute node."); + continue; + } + + if (attribute->Name == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "SAML 2.0 attribute without name."); + continue; + } +@@ -1622,7 +1622,7 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + + value = value_itr->data; + if (!LASSO_IS_SAML2_ATTRIBUTE_VALUE(value)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of AttributeValue node."); + continue; + } +@@ -1633,7 +1633,7 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + * We assume that the list contains a single text node. + */ + if(value->any == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "AttributeValue element was empty."); + continue; + } +@@ -1644,14 +1644,14 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + any_itr = g_list_next(any_itr)) { + /* Verify that this is a LassoNode object. */ + if(!LASSO_NODE(any_itr->data)) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "AttributeValue element contained an " + " element which wasn't a Node."); + continue; + } + dump = lasso_node_dump(LASSO_NODE(any_itr->data)); + if (!dump) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "AttributeValue content dump failed."); + continue; + } +@@ -1692,7 +1692,7 @@ static int am_validate_authn_context_class_ref(request_rec *r, + return OK; + + if (! assertion->AuthnStatement) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing AuthnStatement in assertion, returning BadRequest."); + return HTTP_BAD_REQUEST; + } +@@ -1700,20 +1700,20 @@ static int am_validate_authn_context_class_ref(request_rec *r, + * sending more than one. */ + authn_statement = g_list_first(assertion->AuthnStatement)->data; + if (! authn_statement->AuthnContext) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing AuthnContext in assertion, returning BadRequest."); + return HTTP_BAD_REQUEST; + } + authn_context = authn_statement->AuthnContext; + if (! authn_context->AuthnContextClassRef) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing AuthnContextClassRef in assertion, returning Forbidden."); + return HTTP_FORBIDDEN; + } + for (i = 0; i < refs->nelts; i++) { + const char *ref = ((char **)refs->elts)[i]; + if (strcmp(ref, authn_context->AuthnContextClassRef) == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "AuthnContextClassRef (%s) matches the " + "MellonAuthnContextClassRef directive, " + "access can be granted.", +@@ -1721,7 +1721,7 @@ static int am_validate_authn_context_class_ref(request_rec *r, + return OK; + } + } +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "AuthnContextClassRef (%s) does not match the " + "MellonAuthnContextClassRef directive, returning " + "Forbidden.", +@@ -1776,7 +1776,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + dir_cfg = am_get_dir_cfg(r); + + if(LASSO_PROFILE(login)->nameIdentifier == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No acceptable name identifier found in" + " SAML 2.0 response."); + lasso_login_destroy(login); +@@ -1790,7 +1790,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + + if (response->parent.Destination) { + if (strcmp(response->parent.Destination, url)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid Destination on Response. Should be: %s", + url); + lasso_login_destroy(login); +@@ -1799,20 +1799,20 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + } + + if (g_list_length(response->Assertion) == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No Assertion in response."); + lasso_login_destroy(login); + return HTTP_BAD_REQUEST; + } + if (g_list_length(response->Assertion) > 1) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "More than one Assertion in response."); + lasso_login_destroy(login); + return HTTP_BAD_REQUEST; + } + assertion = g_list_first(response->Assertion)->data; + if (!LASSO_IS_SAML2_ASSERTION(assertion)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Wrong type of Assertion node."); + lasso_login_destroy(login); + return HTTP_BAD_REQUEST; +@@ -1840,7 +1840,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + /* This is SP-initiated login. Check that we have a cookie. */ + if(am_cookie_get(r) == NULL) { + /* Missing cookie. */ +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "User has disabled cookies, or has lost" + " the cookie before returning from the SAML2" + " login server."); +@@ -1897,7 +1897,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + + rc = lasso_login_accept_sso(login); + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to accept SSO message." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + am_release_request_session(r, session); +@@ -1930,7 +1930,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + + rc = am_urldecode(relay_state); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Could not urldecode RelayState value."); + return HTTP_BAD_REQUEST; + } +@@ -1943,7 +1943,7 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + + rc = am_validate_redirect_url(r, relay_state); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid target domain in logout response RelayState parameter."); + return rc; + } +@@ -1982,7 +1982,7 @@ static int am_handle_post_reply(request_rec *r) + + /* Make sure that this is a POST request. */ + if(r->method_number != M_POST) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Expected POST request for HTTP-POST endpoint." + " Got a %s request instead.", r->method); + +@@ -2004,7 +2004,7 @@ static int am_handle_post_reply(request_rec *r) + /* Read POST-data. */ + rc = am_read_post_data(r, &post_data, NULL); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Error reading POST data."); + return rc; + } +@@ -2013,14 +2013,14 @@ static int am_handle_post_reply(request_rec *r) + saml_response = am_extract_query_parameter(r->pool, post_data, + "SAMLResponse"); + if (saml_response == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Could not find SAMLResponse field in POST data."); + return HTTP_BAD_REQUEST; + } + + rc = am_urldecode(saml_response); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Could not urldecode SAMLResponse value."); + return rc; + } +@@ -2032,7 +2032,7 @@ static int am_handle_post_reply(request_rec *r) + + login = lasso_login_new(server); + if (login == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to initialize LassoLogin object."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -2040,7 +2040,7 @@ static int am_handle_post_reply(request_rec *r) + /* Process login responce. */ + rc = lasso_login_process_authn_response_msg(login, saml_response); + if (rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing authn response." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + +@@ -2093,7 +2093,7 @@ static int am_handle_paos_reply(request_rec *r) + + /* Make sure that this is a POST request. */ + if(r->method_number != M_POST) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Expected POST request for paosResponse endpoint." + " Got a %s request instead.", r->method); + +@@ -2115,7 +2115,7 @@ static int am_handle_paos_reply(request_rec *r) + /* Read POST-data. */ + rc = am_read_post_data(r, &post_data, NULL); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Error reading POST data."); + return rc; + } +@@ -2127,7 +2127,7 @@ static int am_handle_paos_reply(request_rec *r) + + login = lasso_login_new(server); + if (login == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to initialize LassoLogin object."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -2135,7 +2135,7 @@ static int am_handle_paos_reply(request_rec *r) + /* Process login response. */ + rc = lasso_login_process_paos_response_msg(login, post_data); + if (rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing ECP authn response." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + +@@ -2182,7 +2182,7 @@ static int am_handle_artifact_reply(request_rec *r) + + /* Make sure that this is a GET request. */ + if(r->method_number != M_GET && r->method_number != M_POST) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Expected GET or POST request for the HTTP-Artifact endpoint." + " Got a %s request instead.", r->method); + +@@ -2206,7 +2206,7 @@ static int am_handle_artifact_reply(request_rec *r) + + login = lasso_login_new(server); + if (login == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to initialize LassoLogin object."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -2217,7 +2217,7 @@ static int am_handle_artifact_reply(request_rec *r) + LASSO_HTTP_METHOD_ARTIFACT_GET); + + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to handle login response." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + lasso_login_destroy(login); +@@ -2226,14 +2226,14 @@ static int am_handle_artifact_reply(request_rec *r) + } else { + rc = am_read_post_data(r, &post_data, NULL); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Error reading POST data."); + return HTTP_BAD_REQUEST; + } + + saml_art = am_extract_query_parameter(r->pool, post_data, "SAMLart"); + if (saml_art == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, rc, r, + "Error reading POST data missing SAMLart form parameter."); + return HTTP_BAD_REQUEST; + } +@@ -2241,7 +2241,7 @@ static int am_handle_artifact_reply(request_rec *r) + + rc = lasso_login_init_request(login, saml_art, LASSO_HTTP_METHOD_ARTIFACT_POST); + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to handle login response." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + lasso_login_destroy(login); +@@ -2252,7 +2252,7 @@ static int am_handle_artifact_reply(request_rec *r) + /* Prepare SOAP request. */ + rc = lasso_login_build_request_msg(login); + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to prepare SOAP message for HTTP-Artifact" + " resolution." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); +@@ -2276,7 +2276,7 @@ static int am_handle_artifact_reply(request_rec *r) + + rc = lasso_login_process_response_msg(login, response); + if(rc != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to handle HTTP-Artifact response data." + " Lasso error: [%i] %s", rc, lasso_strerror(rc)); + lasso_login_destroy(login); +@@ -2319,7 +2319,7 @@ const char *am_post_mkform_multipart(request_rec *r, const char *post_data) + post_data = am_strip_cr(r, post_data); + + if ((boundary = am_xstrtok(r, post_data, "\n", &l1)) == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Cannot figure initial boundary"); + return NULL; + } +@@ -2349,14 +2349,14 @@ const char *am_post_mkform_multipart(request_rec *r, const char *post_data) + */ + hdr = am_get_mime_header(r, mime_part, "Content-Disposition"); + if (hdr == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No Content-Disposition header in MIME section,"); + continue; + } + + name = am_get_header_attr(r, hdr, "form-data", "name"); + if (name == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unexpected Content-Disposition header: \"%s\"", hdr); + continue; + } +@@ -2407,13 +2407,13 @@ const char *am_post_mkform_urlencoded(request_rec *r, const char *post_data) + value = empty_value; + + if (am_urldecode(name) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "urldecode(\"%s\") failed", name); + return NULL; + } + + if (am_urldecode(value) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "urldecode(\"%s\") failed", value); + return NULL; + } +@@ -2454,7 +2454,7 @@ static int am_handle_repost(request_rec *r) + am_diag_printf(r, "enter function %s\n", __func__); + + if (am_cookie_get(r) == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Repost query without a session"); + return HTTP_FORBIDDEN; + } +@@ -2462,7 +2462,7 @@ static int am_handle_repost(request_rec *r) + mod_cfg = am_get_mod_cfg(r->server); + + if (!mod_cfg->post_dir) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Repost query without MellonPostDirectory."); + return HTTP_NOT_FOUND; + } +@@ -2471,7 +2471,7 @@ static int am_handle_repost(request_rec *r) + + enctype = am_extract_query_parameter(r->pool, query, "enctype"); + if (enctype == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Bad repost query: missing enctype"); + return HTTP_BAD_REQUEST; + } +@@ -2482,7 +2482,7 @@ static int am_handle_repost(request_rec *r) + enctype = "multipart/form-data"; + post_mkform = am_post_mkform_multipart; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Bad repost query: invalid enctype \"%s\".", enctype); + return HTTP_BAD_REQUEST; + } +@@ -2490,7 +2490,7 @@ static int am_handle_repost(request_rec *r) + charset = am_extract_query_parameter(r->pool, query, "charset"); + if (charset != NULL) { + if (am_urldecode(charset) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Bad repost query: invalid charset \"%s\"", charset); + return HTTP_BAD_REQUEST; + } +@@ -2498,7 +2498,7 @@ static int am_handle_repost(request_rec *r) + /* Check that charset is sane */ + for (cp = charset; *cp; cp++) { + if (!apr_isalnum(*cp) && (*cp != '-') && (*cp != '_')) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Bad repost query: invalid charset \"%s\"", charset); + return HTTP_BAD_REQUEST; + } +@@ -2507,7 +2507,7 @@ static int am_handle_repost(request_rec *r) + + psf_id = am_extract_query_parameter(r->pool, query, "id"); + if (psf_id == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Bad repost query: missing id"); + return HTTP_BAD_REQUEST; + } +@@ -2515,7 +2515,7 @@ static int am_handle_repost(request_rec *r) + /* Check that Id is sane */ + for (cp = psf_id; *cp; cp++) { + if (!apr_isalnum(*cp)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Bad repost query: invalid id \"%s\"", psf_id); + return HTTP_BAD_REQUEST; + } +@@ -2524,25 +2524,25 @@ static int am_handle_repost(request_rec *r) + + return_url = am_extract_query_parameter(r->pool, query, "ReturnTo"); + if (return_url == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid or missing query ReturnTo parameter."); + return HTTP_BAD_REQUEST; + } + + if (am_urldecode(return_url) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Bad repost query: return"); ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, "Bad repost query: return"); + return HTTP_BAD_REQUEST; + } + + rc = am_validate_redirect_url(r, return_url); + if (rc != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid target domain in repost request ReturnTo parameter."); + return rc; + } + + if ((file_data = am_file_data_new(r->pool, NULL)) == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Bad repost query: cannot allocate file_data"); + apr_table_setn(r->headers_out, "Location", return_url); + return HTTP_SEE_OTHER; +@@ -2553,7 +2553,7 @@ static int am_handle_repost(request_rec *r) + rc = am_file_read(file_data); + if (rc != APR_SUCCESS) { + /* Unable to load repost data. Just redirect us instead. */ +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Bad repost query: %s", file_data->strerror); + apr_table_setn(r->headers_out, "Location", return_url); + return HTTP_SEE_OTHER; +@@ -2562,7 +2562,7 @@ static int am_handle_repost(request_rec *r) + } + + if ((post_form = (*post_mkform)(r, post_data)) == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "am_post_mkform() failed"); ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, "am_post_mkform() failed"); + return HTTP_INTERNAL_SERVER_ERROR; + } + +@@ -2634,7 +2634,7 @@ static int am_handle_metadata(request_rec *r) + return OK; + #else /* ! HAVE_lasso_server_new_from_buffers */ + +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "metadata publishing require lasso 2.2.2 or higher"); + return HTTP_NOT_FOUND; + #endif +@@ -2799,7 +2799,7 @@ static int am_init_authn_request_common(request_rec *r, + + login = lasso_login_new(server); + if(login == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error creating LassoLogin object from LassoServer."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -2807,7 +2807,7 @@ static int am_init_authn_request_common(request_rec *r, + + ret = lasso_login_init_authn_request(login, idp, http_method); + if(ret != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error creating login request." + " Lasso error: [%i] %s", ret, lasso_strerror(ret)); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -2815,7 +2815,7 @@ static int am_init_authn_request_common(request_rec *r, + + request = LASSO_SAMLP2_AUTHN_REQUEST(LASSO_PROFILE(login)->request); + if (request->NameIDPolicy == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error creating login request. Please verify the " + "MellonSPMetadataFile directive."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -2871,7 +2871,7 @@ static int am_init_authn_request_common(request_rec *r, + req_authn_context->AuthnContextClassRef = + g_list_append(req_authn_context->AuthnContextClassRef, + g_strdup(ref)); +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "adding AuthnContextClassRef %s to the " + "AuthnRequest", ref); + } +@@ -2898,7 +2898,7 @@ static int am_init_authn_request_common(request_rec *r, + req_cfg->ecp_service_options & + ~ECP_SERVICE_OPTION_WANT_AUTHN_SIGNED; + if (unsupported_ecp_options) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unsupported ECP service options [%s]", + am_ecp_service_options_str(r->pool, + unsupported_ecp_options)); +@@ -2924,7 +2924,7 @@ static int am_init_authn_request_common(request_rec *r, + + ret = lasso_login_build_authn_request_msg(login); + if (ret != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error building login request." + " Lasso error: [%i] %s", ret, lasso_strerror(ret)); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -2959,7 +2959,7 @@ static int am_set_authn_request_content(request_rec *r, LassoLogin *login) + return am_set_authn_request_paos_content(r, login); + default: + /* We should never get here. */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unsupported http_method."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -3097,7 +3097,7 @@ static int am_send_login_authn_request(request_rec *r, const char *idp, + /* Find our IdP. */ + provider = lasso_server_get_provider(server, idp); + if (provider == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not find metadata for the IdP \"%s\".", + idp); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -3117,7 +3117,7 @@ static int am_send_login_authn_request(request_rec *r, const char *idp, + } + if (destination_url == NULL) { + /* Both HTTP-Redirect and HTTP-POST unsupported - give up. */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Could not find a supported SingleSignOnService endpoint" + " for the IdP \"%s\".", idp); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -3209,21 +3209,21 @@ static int am_handle_login(request_rec *r) + + return_to = am_extract_query_parameter(r->pool, r->args, "ReturnTo"); + if(return_to == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing required ReturnTo parameter."); + return HTTP_BAD_REQUEST; + } + + ret = am_urldecode(return_to); + if(ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error urldecoding ReturnTo parameter."); + return ret; + } + + ret = am_validate_redirect_url(r, return_to); + if(ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid target domain in login request ReturnTo parameter."); + return ret; + } +@@ -3232,7 +3232,7 @@ static int am_handle_login(request_rec *r) + if(idp_param != NULL) { + ret = am_urldecode(idp_param); + if(ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error urldecoding IdP parameter."); + return ret; + } +@@ -3248,7 +3248,7 @@ static int am_handle_login(request_rec *r) + } else if(cfg->discovery_url) { + if(is_passive) { + /* We cannot currently do discovery with passive authentication requests. */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Discovery service with passive authentication request unsupported."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -3284,7 +3284,7 @@ static int am_probe_url(request_rec *r, const char *url, int timeout) + return error; + + if (status != HTTP_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Probe on \"%s\" returned HTTP %ld", + url, status); + return status; +@@ -3325,7 +3325,7 @@ static int am_handle_probe_discovery(request_rec *r) { + */ + timeout = cfg->probe_discovery_timeout; + if (timeout == -1) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "probe discovery handler invoked but not " + "configured. Please set MellonProbeDiscoveryTimeout."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -3337,35 +3337,35 @@ static int am_handle_probe_discovery(request_rec *r) { + */ + return_to = am_extract_query_parameter(r->pool, r->args, "return"); + if(return_to == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing required return parameter."); + return HTTP_BAD_REQUEST; + } + + ret = am_urldecode(return_to); + if (ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, ret, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, ret, r, + "Could not urldecode return value."); + return HTTP_BAD_REQUEST; + } + + ret = am_validate_redirect_url(r, return_to); + if (ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid target domain in probe discovery return parameter."); + return ret; + } + + idp_param = am_extract_query_parameter(r->pool, r->args, "returnIDParam"); + if(idp_param == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Missing required returnIDParam parameter."); + return HTTP_BAD_REQUEST; + } + + ret = am_urldecode(idp_param); + if (ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, ret, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, ret, r, + "Could not urldecode returnIDParam value."); + return HTTP_BAD_REQUEST; + } +@@ -3420,7 +3420,7 @@ static int am_handle_probe_discovery(request_rec *r) { + */ + if (disco_idp == NULL) { + if (!apr_is_empty_table(cfg->probe_discovery_idp)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "probeDiscovery failed and non empty " + "MellonProbeDiscoveryIdP was provided."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -3428,15 +3428,15 @@ static int am_handle_probe_discovery(request_rec *r) { + + disco_idp = am_first_idp(r); + if (disco_idp == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "probeDiscovery found no usable IdP."); + return HTTP_INTERNAL_SERVER_ERROR; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "probeDiscovery " ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, "probeDiscovery " + "failed, trying default IdP %s", disco_idp); + } + } else { +- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_INFO, 0, r, + "probeDiscovery using %s", disco_idp); + } + +@@ -3520,7 +3520,7 @@ int am_handler(request_rec *r) + } else if(!strcmp(endpoint, "probeDisco")) { + return am_handle_probe_discovery(r); + } else { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Endpoint \"%s\" not handled by mod_auth_mellon.", + endpoint); + +@@ -3556,7 +3556,7 @@ static int am_start_auth(request_rec *r) + if (am_save_post(r, &return_to) != OK) + return HTTP_INTERNAL_SERVER_ERROR; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "POST data dropped because we do not have a" + " MellonPostReplay is not enabled."); + } +@@ -3572,7 +3572,7 @@ static int am_start_auth(request_rec *r) + endpoint, + am_urlencode(r->pool, return_to), + am_urlencode(r->pool, idp)); +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "Redirecting to login URL: %s", login_url); + + apr_table_setn(r->headers_out, "Location", login_url); +@@ -3640,7 +3640,7 @@ int am_auth_mellon_user(request_rec *r) + ajax_header = apr_table_get(r->headers_in, "X-Request-With"); + if (ajax_header != NULL && + strcmp(ajax_header, "XMLHttpRequest") == 0) { +- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_INFO, 0, r, + "Deny unauthenticated X-Request-With XMLHttpRequest " + "(AJAX) request"); + return HTTP_FORBIDDEN; +@@ -3769,7 +3769,7 @@ int am_check_uid(request_rec *r) + #ifdef HAVE_ECP + am_req_cfg_rec *req_cfg = am_get_req_cfg(r); + if (req_cfg->ecp_authn_req) { +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "am_check_uid is performing ECP authn request flow"); + /* + * Normally when a protected resource requires authentication +diff --git a/auth_mellon_httpclient.c b/auth_mellon_httpclient.c +index ecf5c0d..67c494a 100644 +--- a/auth_mellon_httpclient.c ++++ b/auth_mellon_httpclient.c +@@ -255,7 +255,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Initialize the curl object. */ + curl = curl_easy_init(); + if(curl == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to initialize a curl object."); + return NULL; + } +@@ -264,7 +264,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Set up error reporting. */ + res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_error); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set curl error buffer: [%u]\n", res); + goto cleanup_fail; + } +@@ -272,7 +272,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Disable progress reporting. */ + res = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to disable curl progress reporting: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -281,7 +281,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Disable use of signals. */ + res = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to disable signals in curl: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -290,7 +290,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Set the timeout of the transfer. It is currently set to two minutes. */ + res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120L); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set the timeout of the curl download:" + " [%u] %s", res, curl_error); + goto cleanup_fail; +@@ -300,7 +300,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + if (cfg->idp_ca_file != NULL) { + res = curl_easy_setopt(curl, CURLOPT_CAINFO, cfg->idp_ca_file->path); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set SSL CA info %s:" + " [%u] %s", cfg->idp_ca_file->path, res, curl_error); + goto cleanup_fail; +@@ -310,7 +310,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Enable fail on http error. */ + res = curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to enable failure on http error: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -319,7 +319,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Select which uri we should download. */ + res = curl_easy_setopt(curl, CURLOPT_URL, uri); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set curl download uri to \"%s\": [%u] %s", + uri, res, curl_error); + goto cleanup_fail; +@@ -331,7 +331,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Set curl write function. */ + res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, am_hc_data_write); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set the curl write function: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -340,7 +340,7 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + /* Set the curl write function parameter. */ + res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, bh); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set the curl write function data: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -394,7 +394,7 @@ int am_httpclient_get(request_rec *r, const char *uri, + + res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)timeout); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to download data from the uri \"%s\", " + "cannot set timeout to %ld: [%u] %s", + uri, (long)timeout, res, curl_error); +@@ -403,7 +403,7 @@ int am_httpclient_get(request_rec *r, const char *uri, + + res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, (long)timeout); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to download data from the uri \"%s\", " + "cannot set connect timeout to %ld: [%u] %s", + uri, (long)timeout, res, curl_error); +@@ -413,7 +413,7 @@ int am_httpclient_get(request_rec *r, const char *uri, + /* Do the download. */ + res = curl_easy_perform(curl); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to download data from the uri \"%s\", " + "transaction aborted: [%u] %s", + uri, res, curl_error); +@@ -423,7 +423,7 @@ int am_httpclient_get(request_rec *r, const char *uri, + if (status != NULL) { + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, status); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to download data from the uri \"%s\", " + "no status report: [%u] %s", + uri, res, curl_error); +@@ -496,7 +496,7 @@ int am_httpclient_post(request_rec *r, const char *uri, + /* Enable POST request. */ + res = curl_easy_setopt(curl, CURLOPT_POST, 1L); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to enable POST request: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -505,7 +505,7 @@ int am_httpclient_post(request_rec *r, const char *uri, + /* Set POST data size. */ + res = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_length); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set the POST data length: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -514,7 +514,7 @@ int am_httpclient_post(request_rec *r, const char *uri, + /* Set POST data. */ + res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set the POST data: [%u] %s", + res, curl_error); + goto cleanup_fail; +@@ -540,7 +540,7 @@ int am_httpclient_post(request_rec *r, const char *uri, + /* Set headers. */ + res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, ctheader); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set content-type header to \"%s\": [%u] %s", + content_type, res, curl_error); + goto cleanup_fail; +@@ -550,7 +550,7 @@ int am_httpclient_post(request_rec *r, const char *uri, + /* Do the download. */ + res = curl_easy_perform(curl); + if(res != CURLE_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to download data from the uri \"%s\": [%u] %s", + uri, res, curl_error); + goto cleanup_fail; +diff --git a/auth_mellon_session.c b/auth_mellon_session.c +index 31ae5db..c7d0817 100644 +--- a/auth_mellon_session.c ++++ b/auth_mellon_session.c +@@ -57,7 +57,7 @@ am_cache_entry_t *am_lock_and_validate(request_rec *r, + session, &session->cookie_token); + const char *cookie_token_target = am_cookie_token(r); + if (strcmp(cookie_token_session, cookie_token_target)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Session cookie parameter mismatch. " + "Session created with {%s}, but current " + "request has {%s}.", +@@ -123,7 +123,7 @@ am_cache_entry_t *am_new_request_session(request_rec *r) + /* Generate session id. */ + session_id = am_generate_id(r); + if(session_id == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error creating session id."); + return NULL; + } +diff --git a/auth_mellon_util.c b/auth_mellon_util.c +index 46036a9..6538160 100644 +--- a/auth_mellon_util.c ++++ b/auth_mellon_util.c +@@ -73,7 +73,7 @@ static const char *am_request_hostname(request_rec *r) + + ret = apr_uri_parse(r->pool, url, &uri); + if (ret != APR_SUCCESS) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to parse request URL: %s", url); + return NULL; + } +@@ -82,7 +82,7 @@ static const char *am_request_hostname(request_rec *r) + /* This shouldn't happen, since the request URL is built with a hostname, + * but log a message to make any debuggin around this code easier. + */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "No hostname in request URL: %s", url); + return NULL; + } +@@ -109,7 +109,7 @@ int am_validate_redirect_url(request_rec *r, const char *url) + + ret = apr_uri_parse(r->pool, url, &uri); + if (ret != APR_SUCCESS) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid redirect URL: %s", url); + return HTTP_BAD_REQUEST; + } +@@ -118,7 +118,7 @@ int am_validate_redirect_url(request_rec *r, const char *url) + if (uri.scheme) { + if (strcasecmp(uri.scheme, "http") + && strcasecmp(uri.scheme, "https")) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Only http or https scheme allowed in redirect URL: %s (%s)", + url, uri.scheme); + return HTTP_BAD_REQUEST; +@@ -141,7 +141,7 @@ int am_validate_redirect_url(request_rec *r, const char *url) + return OK; + } + } +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Untrusted hostname (%s) in redirect URL: %s", + uri.hostname, url); + return HTTP_BAD_REQUEST; +@@ -334,7 +334,7 @@ const am_cond_t *am_cond_substitue(request_rec *r, const am_cond_t *ce, + + c->regex = ap_pregcomp(r->pool, outstr, regex_flags); + if (c->regex == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Invalid regular expression \"%s\"", outstr); + return ce; + } +@@ -586,7 +586,7 @@ int am_read_post_data(request_rec *r, char **data, apr_size_t *length) + } + + if (len >= 1024*1024) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Too large POST data payload (%lu bytes).", + (unsigned long)len); + return HTTP_BAD_REQUEST; +@@ -599,7 +599,7 @@ int am_read_post_data(request_rec *r, char **data, apr_size_t *length) + + *data = (char *)apr_palloc(r->pool, len + 1); + if (*data == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to allocate memory for %lu bytes of POST data.", + (unsigned long)len); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -627,7 +627,7 @@ int am_read_post_data(request_rec *r, char **data, apr_size_t *length) + break; + } + else if (read_length < 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to read POST data from client."); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -911,7 +911,7 @@ int am_check_url(request_rec *r, const char *url) + for (i = url; *i; i++) { + if (*i >= 0 && *i < ' ') { + /* Deny all control-characters. */ +- ap_log_rerror(APLOG_MARK, APLOG_ERR, HTTP_BAD_REQUEST, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, HTTP_BAD_REQUEST, r, + "Control character detected in URL."); + return HTTP_BAD_REQUEST; + } +@@ -938,7 +938,7 @@ int am_generate_random_bytes(request_rec *r, void *dest, apr_size_t count) + int rc; + rc = RAND_bytes((unsigned char *)dest, (int)count); + if(rc != 1) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error generating random data: %lu", + ERR_get_error()); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1247,7 +1247,7 @@ int am_postdir_cleanup(request_rec *r) + */ + rv = apr_dir_open(&postdir, mod_cfg->post_dir, r->pool); + if (rv != 0) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to open MellonPostDirectory \"%s\": %s", + mod_cfg->post_dir, + apr_strerror(rv, error_buffer, sizeof(error_buffer))); +@@ -1278,7 +1278,7 @@ int am_postdir_cleanup(request_rec *r) + (void)apr_dir_close(postdir); + + if (count >= mod_cfg->post_count) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Too many saved POST sessions. " + "Increase MellonPostCount directive."); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1382,7 +1382,7 @@ int am_save_post(request_rec *r, const char **relay_state) + + mod_cfg = am_get_mod_cfg(r->server); + if (mod_cfg->post_dir == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "MellonPostReplay enabled but MellonPostDirectory not set " + "-- cannot save post data"); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1406,7 +1406,7 @@ int am_save_post(request_rec *r, const char **relay_state) + content_type = "multipart"; + + } else { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unknown POST Content-Type \"%s\"", content_type); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -1415,7 +1415,7 @@ int am_save_post(request_rec *r, const char **relay_state) + } + + if ((psf_id = am_generate_id(r)) == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "cannot generate id"); ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, "cannot generate id"); + return HTTP_INTERNAL_SERVER_ERROR; + } + +@@ -1425,19 +1425,19 @@ int am_save_post(request_rec *r, const char **relay_state) + APR_WRITE|APR_CREATE|APR_BINARY, + APR_FPROT_UREAD|APR_FPROT_UWRITE, + r->pool) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "cannot create POST session file"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (am_read_post_data(r, &post_data, &post_data_len) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "cannot read POST data"); ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, "cannot read POST data"); + (void)apr_file_close(psf); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (post_data_len > mod_cfg->post_size) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "POST data size %" APR_SIZE_T_FMT + " exceeds maximum %" APR_SIZE_T_FMT ". " + "Increase MellonPostSize directive.", +@@ -1449,14 +1449,14 @@ int am_save_post(request_rec *r, const char **relay_state) + written = post_data_len; + if ((apr_file_write(psf, post_data, &written) != OK) || + (written != post_data_len)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "cannot write to POST session file"); + (void)apr_file_close(psf); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (apr_file_close(psf) != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "cannot close POST session file"); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -1722,7 +1722,7 @@ const char *am_get_mime_body(request_rec *r, const char *mime) + apr_size_t body_len; + + if ((body = strstr(mime, lflf)) == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "No MIME body"); ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, "No MIME body"); + return NULL; + } + +@@ -1757,7 +1757,7 @@ am_get_service_url(request_rec *r, LassoProfile *profile, char *service_name) + provider = lasso_server_get_provider(profile->server, + profile->remote_providerID); + if (LASSO_IS_PROVIDER(provider) == FALSE) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Cannot find provider service %s, no provider.", + service_name); + return NULL; +@@ -1765,7 +1765,7 @@ am_get_service_url(request_rec *r, LassoProfile *profile, char *service_name) + + url = lasso_provider_get_metadata_one(provider, service_name); + if (url == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Cannot find provider service %s from metadata.", + service_name); + return NULL; +@@ -1821,7 +1821,7 @@ static void dump_tokens(request_rec *r, apr_array_header_t *tokens) + + for (i = 0; i < tokens->nelts; i++) { + Token token = APR_ARRAY_IDX(tokens, i, Token); +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "token[%2zd] %s \"%s\" offset=%lu len=%lu ", i, + token_type_str(token.type), token.str, + token.offset, token.len); +@@ -2126,7 +2126,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + apr_size_t i; + char *error; + +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "PAOS header: \"%s\"", header); + + tokens = tokenize(r->pool, header, true, &error); +@@ -2136,7 +2136,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + #endif + + if (error) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", error); ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, "%s", error); + goto cleanup; + } + +@@ -2144,7 +2144,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + if (!is_token(tokens, 0, TOKEN_IDENTIFIER, "ver") || + !is_token(tokens, 1, TOKEN_EQUAL, NULL) || + !is_token(tokens, 2, TOKEN_DBL_QUOTE_STRING, LASSO_PAOS_HREF)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid PAOS header, " + "expected header to begin with ver=\"%s\", " + "actual header=\"%s\"", +@@ -2154,7 +2154,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + + /* Next is the service value, separated from the version by a semicolon */ + if (!is_token(tokens, 3, TOKEN_SEMICOLON, NULL)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid PAOS header, " + "expected semicolon after PAOS version " + "but found %s in header=\"%s\"", +@@ -2164,7 +2164,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + } + + if (!is_token(tokens, 4, TOKEN_DBL_QUOTE_STRING, LASSO_ECP_HREF)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid PAOS header, " + "expected service token to be \"%s\", " + "but found %s in header=\"%s\"", +@@ -2184,7 +2184,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + /* More tokens after the service value, must be options, iterate over them */ + for (i = 5; i < tokens->nelts; i++) { + if (!is_token(tokens, i, TOKEN_COMMA, NULL)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid PAOS header, " + "expected comma after PAOS service " + "but found %s in header=\"%s\"", +@@ -2194,7 +2194,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + } + + if (++i > tokens->nelts) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid PAOS header, " + "expected option after comma " + "in header=\"%s\"", +@@ -2205,7 +2205,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + Token token = APR_ARRAY_IDX(tokens, i, Token); + + if (token.type != TOKEN_DBL_QUOTE_STRING) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid PAOS header, " + "expected quoted string after comma " + "but found %s in header=\"%s\"", +@@ -2226,7 +2226,7 @@ bool am_parse_paos_header(request_rec *r, const char *header, + } else if (g_str_equal(value, LASSO_SAML2_CONDITIONS_DELEGATION)) { + options |= ECP_SERVICE_OPTION_DELEGATION; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_WARNING, 0, r, + "Unknown PAOS service option = \"%s\"", + value); + goto cleanup; +@@ -2268,7 +2268,7 @@ bool am_header_has_media_type(request_rec *r, const char *header, const char *me + char *media_range = NULL; + + if (header == NULL) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "invalid Accept header, NULL"); + goto cleanup; + } +@@ -2366,7 +2366,7 @@ int am_get_boolean_query_parameter(request_rec *r, const char *name, + if (value_str != NULL) { + ret = am_urldecode(value_str); + if (ret != OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error urldecoding \"%s\" boolean query parameter, " + "value=\"%s\"", name, value_str); + return ret; +@@ -2376,7 +2376,7 @@ int am_get_boolean_query_parameter(request_rec *r, const char *name, + } else if(!strcmp(value_str, "false")) { + *return_value = FALSE; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Invalid value for \"%s\" boolean query parameter, " + "value=\"%s\"", name, value_str); + ret = HTTP_BAD_REQUEST; +@@ -2596,7 +2596,7 @@ bool am_is_paos_request(request_rec *r, int *error_code) + if (valid_paos_header) { + is_paos = true; + } else { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "request supplied PAOS media type in Accept header " + "but omitted valid PAOS header"); + if (*error_code == 0) +@@ -2604,14 +2604,14 @@ bool am_is_paos_request(request_rec *r, int *error_code) + } + } else { + if (valid_paos_header) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "request supplied valid PAOS header " + "but omitted PAOS media type in Accept header"); + if (*error_code == 0) + *error_code = AM_ERROR_MISSING_PAOS_MEDIA_TYPE; + } + } +- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ++ AM_LOG_RERROR(APLOG_MARK, APLOG_DEBUG, 0, r, + "have_paos_media_type=%s valid_paos_header=%s is_paos=%s " + "error_code=%d ecp options=[%s]", + have_paos_media_type ? "True" : "False", diff --git a/SOURCES/cache-request_rec.patch b/SOURCES/cache-request_rec.patch new file mode 100644 index 0000000..a03fa9d --- /dev/null +++ b/SOURCES/cache-request_rec.patch @@ -0,0 +1,307 @@ +commit 119cbdd525811908738e8f5d894fe4117cf123a9 +Author: John Dennis +Date: Tue Jun 13 08:22:15 2017 -0400 + + modify cache functions to take request_rec parameter instead of server_rec + + The entire point of the cache is to persist state between requests so + conceptually it makes sense the cache functions would receive a + server_rec pointer because the cache is a server level data + structure. However most cache operations occur in the context of a + request. Passing a request_rec to a cache function has the following + advantages: + + 1) Any logging during a cache operation should be tied to the request. + + 2) Any need for temporary memory allocation is much easier to handle + with access to the request's memory pool which is cleaned up at the + end of the request as opposed to trying manage memory allocations at + the server level. + + 3) Any need for access to the server_rec is trivially easy to obtain + from the request_rec via r->server. In fact the caller of cache + functions inside requests simplyy provided the server_rec parameter + via r->server, so why not just pass the request_rec? + + These changes are in anticipation of adding enhanced logging and + diagnostics into the cache functions, they will need access to the + request_rec and it's memory pool. + + Signed-off-by: John Dennis + +diff --git a/auth_mellon.h b/auth_mellon.h +index 78a5f0d..aff658b 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -378,23 +378,23 @@ const char *am_cookie_token(request_rec *r); + + + void am_cache_init(am_mod_cfg_rec *mod_cfg); +-am_cache_entry_t *am_cache_lock(server_rec *s, ++am_cache_entry_t *am_cache_lock(request_rec *r, + am_cache_key_t type, const char *key); + const char *am_cache_entry_get_string(am_cache_entry_t *e, + am_cache_storage_t *slot); +-am_cache_entry_t *am_cache_new(server_rec *s, ++am_cache_entry_t *am_cache_new(request_rec *r, + const char *key, + const char *cookie_token); +-void am_cache_unlock(server_rec *s, am_cache_entry_t *entry); ++void am_cache_unlock(request_rec *r, am_cache_entry_t *entry); + +-void am_cache_update_expires(am_cache_entry_t *t, apr_time_t expires); ++void am_cache_update_expires(request_rec *r, am_cache_entry_t *t, apr_time_t expires); + + void am_cache_env_populate(request_rec *r, am_cache_entry_t *session); + int am_cache_env_append(am_cache_entry_t *session, + const char *var, const char *val); + const char *am_cache_env_fetch_first(am_cache_entry_t *t, + const char *var); +-void am_cache_delete(server_rec *s, am_cache_entry_t *session); ++void am_cache_delete(request_rec *r, am_cache_entry_t *session); + + int am_cache_set_lasso_state(am_cache_entry_t *session, + const char *lasso_identity, +diff --git a/auth_mellon_cache.c b/auth_mellon_cache.c +index 7d51589..af5c267 100644 +--- a/auth_mellon_cache.c ++++ b/auth_mellon_cache.c +@@ -70,14 +70,14 @@ void am_cache_init(am_mod_cfg_rec *mod_cfg) + * after you are done with it. + * + * Parameters: +- * server_rec *s The current server. ++ * request_rec *r The request we are processing. + * am_cache_key_t type AM_CACHE_SESSION or AM_CACHE_NAMEID + * const char *key The session key or user + * + * Returns: + * The session entry on success or NULL on failure. + */ +-am_cache_entry_t *am_cache_lock(server_rec *s, ++am_cache_entry_t *am_cache_lock(request_rec *r, + am_cache_key_t type, + const char *key) + { +@@ -104,14 +104,14 @@ am_cache_entry_t *am_cache_lock(server_rec *s, + break; + } + +- mod_cfg = am_get_mod_cfg(s); ++ mod_cfg = am_get_mod_cfg(r->server); + + + /* Lock the table. */ + if((rv = apr_global_mutex_lock(mod_cfg->lock)) != APR_SUCCESS) { +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "apr_global_mutex_lock() failed [%d]: %s", +- rv, apr_strerror(rv, buffer, sizeof(buffer))); ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ "apr_global_mutex_lock() failed [%d]: %s", ++ rv, apr_strerror(rv, buffer, sizeof(buffer))); + return NULL; + } + +@@ -271,7 +271,7 @@ const char *am_cache_entry_get_string(am_cache_entry_t *e, + * Remember to unlock the table with am_cache_unlock(...) afterwards. + * + * Parameters: +- * server_rec *s The current server. ++ * request_rec *r The request we are processing. + * const char *key The key of the session to allocate. + * const char *cookie_token The cookie token to tie the session to. + * +@@ -279,7 +279,7 @@ const char *am_cache_entry_get_string(am_cache_entry_t *e, + * The new session entry on success. NULL if key is a invalid session + * key. + */ +-am_cache_entry_t *am_cache_new(server_rec *s, ++am_cache_entry_t *am_cache_new(request_rec *r, + const char *key, + const char *cookie_token) + { +@@ -298,14 +298,14 @@ am_cache_entry_t *am_cache_new(server_rec *s, + } + + +- mod_cfg = am_get_mod_cfg(s); ++ mod_cfg = am_get_mod_cfg(r->server); + + + /* Lock the table. */ + if((rv = apr_global_mutex_lock(mod_cfg->lock)) != APR_SUCCESS) { +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "apr_global_mutex_lock() failed [%d]: %s", +- rv, apr_strerror(rv, buffer, sizeof(buffer))); ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ "apr_global_mutex_lock() failed [%d]: %s", ++ rv, apr_strerror(rv, buffer, sizeof(buffer))); + return NULL; + } + +@@ -357,11 +357,11 @@ am_cache_entry_t *am_cache_new(server_rec *s, + age = (current_time - t->access) / 1000000; + + if(age < 3600) { +- ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s, +- "Dropping LRU entry entry with age = %" APR_TIME_T_FMT +- "s, which is less than one hour. It may be a good" +- " idea to increase MellonCacheSize.", +- age); ++ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, ++ "Dropping LRU entry entry with age = %" APR_TIME_T_FMT ++ "s, which is less than one hour. It may be a good" ++ " idea to increase MellonCacheSize.", ++ age); + } + } + +@@ -393,8 +393,8 @@ am_cache_entry_t *am_cache_new(server_rec *s, + /* For some strange reason our cookie token is too big to fit in the + * session. This should never happen outside of absurd configurations. + */ +- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +- "Unable to store cookie token in new session."); ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ "Unable to store cookie token in new session."); + t->key[0] = '\0'; /* Mark the entry as free. */ + apr_global_mutex_unlock(mod_cfg->lock); + return NULL; +@@ -407,20 +407,20 @@ am_cache_entry_t *am_cache_new(server_rec *s, + /* This function unlocks a session entry. + * + * Parameters: +- * server_rec *s The current server. ++ * request_rec *r The request we are processing. + * am_cache_entry_t *entry The session entry. + * + * Returns: + * Nothing. + */ +-void am_cache_unlock(server_rec *s, am_cache_entry_t *entry) ++void am_cache_unlock(request_rec *r, am_cache_entry_t *entry) + { + am_mod_cfg_rec *mod_cfg; + + /* Update access time. */ + entry->access = apr_time_now(); + +- mod_cfg = am_get_mod_cfg(s); ++ mod_cfg = am_get_mod_cfg(r->server); + apr_global_mutex_unlock(mod_cfg->lock); + } + +@@ -429,13 +429,14 @@ void am_cache_unlock(server_rec *s, am_cache_entry_t *entry) + * timestamp is earlier than the previous. + * + * Parameters: ++ * request_rec *r The request we are processing. + * am_cache_entry_t *t The current session. + * apr_time_t expires The new timestamp. + * + * Returns: + * Nothing. + */ +-void am_cache_update_expires(am_cache_entry_t *t, apr_time_t expires) ++void am_cache_update_expires(request_rec *r, am_cache_entry_t *t, apr_time_t expires) + { + /* Check if we should update the expires timestamp. */ + if(t->expires == 0 || t->expires > expires) { +@@ -698,13 +699,13 @@ void am_cache_env_populate(request_rec *r, am_cache_entry_t *t) + /* This function deletes a given key from the session store. + * + * Parameters: +- * server_rec *s The current server. ++ * request_rec *r The request we are processing. + * am_cache_entry_t *cache The entry we are deleting. + * + * Returns: + * Nothing. + */ +-void am_cache_delete(server_rec *s, am_cache_entry_t *cache) ++void am_cache_delete(request_rec *r, am_cache_entry_t *cache) + { + /* We write a null-byte at the beginning of the key to + * mark this slot as unused. +@@ -712,7 +713,7 @@ void am_cache_delete(server_rec *s, am_cache_entry_t *cache) + cache->key[0] = '\0'; + + /* Unlock the entry. */ +- am_cache_unlock(s, cache); ++ am_cache_unlock(r, cache); + } + + +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 5661083..44a5ee9 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -1479,7 +1479,7 @@ static void am_handle_session_expire(request_rec *r, am_cache_entry_t *session, + /* Updates the expires timestamp if this one is earlier than the + * previous timestamp. + */ +- am_cache_update_expires(session, t); ++ am_cache_update_expires(r, session, t); + } + } + +@@ -1517,10 +1517,10 @@ static int add_attributes(am_cache_entry_t *session, request_rec *r, + /* Set expires to whatever is set by MellonSessionLength. */ + if(dir_cfg->session_length == -1) { + /* -1 means "use default. The current default is 86400 seconds. */ +- am_cache_update_expires(session, apr_time_now() ++ am_cache_update_expires(r, session, apr_time_now() + + apr_time_make(86400, 0)); + } else { +- am_cache_update_expires(session, apr_time_now() ++ am_cache_update_expires(r, session, apr_time_now() + + apr_time_make(dir_cfg->session_length, 0)); + } + +diff --git a/auth_mellon_session.c b/auth_mellon_session.c +index fca6c01..856dbb6 100644 +--- a/auth_mellon_session.c ++++ b/auth_mellon_session.c +@@ -39,7 +39,7 @@ am_cache_entry_t *am_lock_and_validate(request_rec *r, + am_cache_key_t type, + const char *key) + { +- am_cache_entry_t *session = am_cache_lock(r->server, type, key); ++ am_cache_entry_t *session = am_cache_lock(r, type, key); + if (session == NULL) { + return NULL; + } +@@ -54,7 +54,7 @@ am_cache_entry_t *am_lock_and_validate(request_rec *r, + "request has {%s}.", + cookie_token_session, + cookie_token_target); +- am_cache_unlock(r->server, session); ++ am_cache_unlock(r, session); + return NULL; + } + +@@ -124,7 +124,7 @@ am_cache_entry_t *am_new_request_session(request_rec *r) + am_cookie_set(r, session_id); + + const char *cookie_token = am_cookie_token(r); +- return am_cache_new(r->server, session_id, cookie_token); ++ return am_cache_new(r, session_id, cookie_token); + } + + +@@ -140,7 +140,7 @@ am_cache_entry_t *am_new_request_session(request_rec *r) + */ + void am_release_request_session(request_rec *r, am_cache_entry_t *session) + { +- am_cache_unlock(r->server, session); ++ am_cache_unlock(r, session); + } + + +@@ -164,5 +164,5 @@ void am_delete_request_session(request_rec *r, am_cache_entry_t *session) + } + + /* Delete session from the session store. */ +- am_cache_delete(r->server, session); ++ am_cache_delete(r, session); + } diff --git a/SOURCES/fix-conditional-diagnostics-build.patch b/SOURCES/fix-conditional-diagnostics-build.patch new file mode 100644 index 0000000..cd0de9b --- /dev/null +++ b/SOURCES/fix-conditional-diagnostics-build.patch @@ -0,0 +1,39 @@ +commit 86eb3440b260c7227f4e8d059f9b2410007fa350 +Author: John Dennis +Date: Thu Dec 7 15:17:03 2017 -0500 + + Fix conditional build of auth_mellon_diagnostics.c + + Commit de853e15 introduced using config.h to define optional build + parameters instead of putting them on the compile command + line. Unfortunately that broke the compilation of + auth_mellon_diagostics.c. + + We used to have this: + + ifdef ENABLE_DIAGNOSTICS + include "auth_mellon.h" + + but the flag ENABLE_DIAGNOSTICS is now defined by including + auth_mellon.h (which includes config.h) hence it would be impossible + for the ENABLE_DIAGNOSTICS to be defined during compilation. + + The solution is simple, just reverse the order of the two lines such + that the defines are seen before the #ifdef conditional. + + Signed-off-by: John Dennis + +diff --git a/auth_mellon_diagnostics.c b/auth_mellon_diagnostics.c +index 519a44f..289a878 100644 +--- a/auth_mellon_diagnostics.c ++++ b/auth_mellon_diagnostics.c +@@ -1,7 +1,7 @@ +-#ifdef ENABLE_DIAGNOSTICS +- + #include "auth_mellon.h" + ++#ifdef ENABLE_DIAGNOSTICS ++ + #if APR_HAVE_UNISTD_H + #include + #endif diff --git a/SOURCES/log-status-response.patch b/SOURCES/log-status-response.patch new file mode 100644 index 0000000..4f01d2c --- /dev/null +++ b/SOURCES/log-status-response.patch @@ -0,0 +1,317 @@ +commit 582f283c49c754a07aee6eea0fbcd4b188f23236 +Author: John Dennis +Date: Wed Feb 7 09:45:18 2018 -0500 + + Log SAML status response information + + Knowing if a SAML operation failed and the reason why is essential to + diagnose problems. The SAML Status Response is always included in all + SAML responses. In addition to the major reason why a transaction + failed it may also include extra expository information giving + additional details. Unfortunately we never logged any of the status + response information when a failure occurred. This patch adds code to + log the status response information. + + In addition the patch adds diagnostic logging of received POST data. + + Signed-off-by: John Dennis + +diff --git a/auth_mellon.h b/auth_mellon.h +index a10bc4c..289db0c 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -511,6 +511,9 @@ char *am_ecp_service_options_str(apr_pool_t *pool, ECPServiceOptions options); + bool am_is_paos_request(request_rec *r, int *error_code); + #endif /* HAVE_ECP */ + ++char * ++am_saml_response_status_str(request_rec *r, LassoNode *node); ++ + int am_auth_mellon_user(request_rec *r); + int am_check_uid(request_rec *r); + int am_handler(request_rec *r); +@@ -577,6 +580,11 @@ am_diag_log_lasso_node(request_rec *r, int level, LassoNode *node, + const char *fmt, ...) + __attribute__((format(printf,4,5))); + ++void ++am_diag_log_saml_status_response(request_rec *r, int level, LassoNode *node, ++ const char *fmt, ...) ++ __attribute__((format(printf,4,5))); ++ + void + am_diag_log_profile(request_rec *r, int level, LassoProfile *profile, + const char *fmt, ...) +@@ -608,6 +616,7 @@ am_diag_time_t_to_8601(request_rec *r, apr_time_t t); + #define am_diag_log_cache_entry(...) do {} while(0) + #define am_diag_log_file_data(...) do {} while(0) + #define am_diag_log_lasso_node(...) do {} while(0) ++#define am_diag_log_saml_status_response(...) do {} while(0) + #define am_diag_log_profile(...) do {} while(0) + #define am_diag_printf(...) do {} while(0) + +diff --git a/auth_mellon_diagnostics.c b/auth_mellon_diagnostics.c +index 289a878..89fbc62 100644 +--- a/auth_mellon_diagnostics.c ++++ b/auth_mellon_diagnostics.c +@@ -867,7 +867,9 @@ am_diag_log_lasso_node(request_rec *r, int level, LassoNode *node, + write_indented_text(diag_cfg->fd, level+1, xml); + lasso_release_string(xml); + } else { +- apr_file_printf(diag_cfg->fd, "node is NULL\n"); ++ apr_file_printf(diag_cfg->fd, ++ "%snode is NULL\n", ++ indent(level+1)); + } + apr_file_flush(diag_cfg->fd); + } +@@ -919,6 +921,99 @@ am_diag_log_file_data(request_rec *r, int level, am_file_data_t *file_data, + apr_file_flush(diag_cfg->fd); + } + ++void ++am_diag_log_saml_status_response(request_rec *r, int level, LassoNode *node, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ am_diag_cfg_rec *diag_cfg = am_get_diag_cfg(r->server); ++ am_req_cfg_rec *req_cfg = am_get_req_cfg(r); ++ ++ LassoSamlp2StatusResponse *response = (LassoSamlp2StatusResponse*)node; ++ LassoSamlp2Status *status = NULL; ++ const char *status_code1 = NULL; ++ const char *status_code2 = NULL; ++ ++ if (!AM_DIAG_ENABLED(diag_cfg)) return; ++ if (!am_diag_initialize_req(r, diag_cfg, req_cfg)) return; ++ ++ va_start(ap, fmt); ++ am_diag_format_line(r->pool, diag_cfg->fd, level, fmt, ap); ++ va_end(ap); ++ ++ if (response == NULL) { ++ apr_file_printf(diag_cfg->fd, ++ "%sresponse is NULL\n", indent(level+1)); ++ return; ++ } ++ ++ ++ if (!LASSO_IS_SAMLP2_STATUS_RESPONSE(response)) { ++ apr_file_printf(diag_cfg->fd, ++ "%sERROR, expected LassoSamlp2StatusResponse " ++ "but got %s\n", ++ indent(level+1), ++ lasso_node_get_name((LassoNode*)response)); ++ return; ++ } ++ ++ status = response->Status; ++ if (status == NULL || ++ !LASSO_IS_SAMLP2_STATUS(status) || ++ status->StatusCode == NULL || ++ status->StatusCode->Value == NULL) { ++ apr_file_printf(diag_cfg->fd, ++ "%sStatus missing\n", ++ indent(level+1)); ++ return; ++ } ++ ++ status_code1 = status->StatusCode->Value; ++ if (status->StatusCode->StatusCode) { ++ status_code2 = status->StatusCode->StatusCode->Value; ++ } ++ ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sID: %s\n", ++ indent(level+1), response->ID); ++ apr_file_printf(diag_cfg->fd, ++ "%sInResponseTo: %s\n", ++ indent(level+1), response->InResponseTo); ++ apr_file_printf(diag_cfg->fd, ++ "%sVersion: %s\n", ++ indent(level+1), response->Version); ++ apr_file_printf(diag_cfg->fd, ++ "%sIssueInstant: %s\n", ++ indent(level+1), response->IssueInstant); ++ apr_file_printf(diag_cfg->fd, ++ "%sConsent: %s\n", ++ indent(level+1), response->Consent); ++ apr_file_printf(diag_cfg->fd, ++ "%sIssuer: %s\n", ++ indent(level+1), response->Issuer->content); ++ apr_file_printf(diag_cfg->fd, ++ "%sDestination: %s\n", ++ indent(level+1), response->Destination); ++ ++ apr_file_printf(diag_cfg->fd, ++ "%sStatus:\n", indent(level+1)); ++ apr_file_printf(diag_cfg->fd, ++ "%sTop Level Status code: %s\n", ++ indent(level+2), status_code1); ++ apr_file_printf(diag_cfg->fd, ++ "%s2nd Level Status code: %s\n", ++ indent(level+2), status_code2); ++ apr_file_printf(diag_cfg->fd, ++ "%sStatus Message: %s\n", ++ indent(level+2), status->StatusMessage); ++ am_diag_log_lasso_node(r, level+2, (LassoNode*)status->StatusDetail, ++ "Status Detail:"); ++ ++ return; ++ ++} ++ + void + am_diag_log_profile(request_rec *r, int level, LassoProfile *profile, + const char *fmt, ...) +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 030abe7..5058744 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -826,6 +826,8 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + am_dir_cfg_rec *cfg = am_get_dir_cfg(r); + + res = lasso_logout_process_response_msg(logout, r->args); ++ am_diag_log_lasso_node(r, 0, LASSO_PROFILE(logout)->response, ++ "SAML Response (%s):", __func__); + #ifdef HAVE_lasso_profile_set_signature_verify_hint + if(res != 0 && res != LASSO_DS_ERROR_SIGNATURE_NOT_FOUND && + logout->parent.remote_providerID != NULL) { +@@ -841,7 +843,10 @@ static int am_handle_logout_response(request_rec *r, LassoLogout *logout) + if(res != 0) { + AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Unable to process logout response." +- " Lasso error: [%i] %s", res, lasso_strerror(res)); ++ " Lasso error: [%i] %s, SAML Response: %s", ++ res, lasso_strerror(res), ++ am_saml_response_status_str(r, ++ LASSO_PROFILE(logout)->response)); + + lasso_logout_destroy(logout); + return HTTP_BAD_REQUEST; +@@ -1760,9 +1765,6 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, + int rc; + const char *idp; + +- am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response, +- "SAMLResponse:"); +- + url = am_reconstruct_url(r); + chr = strchr(url, '?'); + if (! chr) { +@@ -2039,10 +2041,15 @@ static int am_handle_post_reply(request_rec *r) + + /* Process login responce. */ + rc = lasso_login_process_authn_response_msg(login, saml_response); ++ am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response, ++ "SAML Response (%s):", __func__); + if (rc != 0) { + AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing authn response." +- " Lasso error: [%i] %s", rc, lasso_strerror(rc)); ++ " Lasso error: [%i] %s, SAML Response: %s", ++ rc, lasso_strerror(rc), ++ am_saml_response_status_str(r, ++ LASSO_PROFILE(login)->response)); + + lasso_login_destroy(login); + err = HTTP_BAD_REQUEST; +@@ -2134,10 +2141,15 @@ static int am_handle_paos_reply(request_rec *r) + + /* Process login response. */ + rc = lasso_login_process_paos_response_msg(login, post_data); ++ am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response, ++ "SAML Response (%s):", __func__); + if (rc != 0) { + AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Error processing ECP authn response." +- " Lasso error: [%i] %s", rc, lasso_strerror(rc)); ++ " Lasso error: [%i] %s, SAML Response: %s", ++ rc, lasso_strerror(rc), ++ am_saml_response_status_str(r, ++ LASSO_PROFILE(login)->response)); + + lasso_login_destroy(login); + err = HTTP_BAD_REQUEST; +@@ -2275,10 +2287,16 @@ static int am_handle_artifact_reply(request_rec *r) + } + + rc = lasso_login_process_response_msg(login, response); ++ am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->response, ++ "SAML Response (%s):", __func__); + if(rc != 0) { + AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to handle HTTP-Artifact response data." +- " Lasso error: [%i] %s", rc, lasso_strerror(rc)); ++ " Lasso error: [%i] %s, SAML Response: %s", ++ rc, lasso_strerror(rc), ++ am_saml_response_status_str(r, ++ LASSO_PROFILE(login)->response)); ++ + lasso_login_destroy(login); + return HTTP_INTERNAL_SERVER_ERROR; + } +@@ -2947,8 +2965,9 @@ static int am_set_authn_request_content(request_rec *r, LassoLogin *login) + { + + am_diag_log_lasso_node(r, 0, LASSO_PROFILE(login)->request, +- "SAML AuthnRequest: http_method=%s", +- am_diag_lasso_http_method_str(login->http_method)); ++ "SAML AuthnRequest: http_method=%s URL=%s", ++ am_diag_lasso_http_method_str(login->http_method), ++ LASSO_PROFILE(login)->msg_url); + + switch (login->http_method) { + case LASSO_HTTP_METHOD_REDIRECT: +diff --git a/auth_mellon_util.c b/auth_mellon_util.c +index 6538160..1fd3d4b 100644 +--- a/auth_mellon_util.c ++++ b/auth_mellon_util.c +@@ -636,6 +636,7 @@ int am_read_post_data(request_rec *r, char **data, apr_size_t *length) + bytes_left -= read_length; + } + ++ am_diag_printf(r, "POST data: %s\n", *data); + return OK; + } + +@@ -2630,3 +2631,38 @@ bool am_is_paos_request(request_rec *r, int *error_code) + return is_paos; + } + #endif /* HAVE_ECP */ ++ ++char * ++am_saml_response_status_str(request_rec *r, LassoNode *node) ++{ ++ LassoSamlp2StatusResponse *response = (LassoSamlp2StatusResponse*)node; ++ LassoSamlp2Status *status = NULL; ++ const char *status_code1 = NULL; ++ const char *status_code2 = NULL; ++ ++ if (!LASSO_IS_SAMLP2_STATUS_RESPONSE(response)) { ++ return apr_psprintf(r->pool, ++ "error, expected LassoSamlp2StatusResponse " ++ "but got %s", ++ lasso_node_get_name((LassoNode*)response)); ++ } ++ ++ status = response->Status; ++ if (status == NULL || ++ !LASSO_IS_SAMLP2_STATUS(status) || ++ status->StatusCode == NULL || ++ status->StatusCode->Value == NULL) { ++ return apr_psprintf(r->pool, "Status missing"); ++ ++ } ++ ++ status_code1 = status->StatusCode->Value; ++ if (status->StatusCode->StatusCode) { ++ status_code2 = status->StatusCode->StatusCode->Value; ++ } ++ ++ return apr_psprintf(r->pool, ++ "StatusCode1=\"%s\", StatusCode2=\"%s\", " ++ "StatusMessage=\"%s\"", ++ status_code1, status_code2, status->StatusMessage); ++} diff --git a/SOURCES/signature-algorithm.patch b/SOURCES/signature-algorithm.patch new file mode 100644 index 0000000..1d9bf49 --- /dev/null +++ b/SOURCES/signature-algorithm.patch @@ -0,0 +1,365 @@ +Note: this patch has been sligtly modified from the origianal +commit to change the default signature algorithm back to sha1 + +commit 9b17e5c1078a9be90de1e9d03079b34ca4056e96 +Author: John Dennis +Date: Thu Jan 11 13:05:26 2018 -0500 + + Add MellonSignatureMethod to control signature algorithm + + Previously there was no way to control the signature algorithm used + when Mellon signed it's SAML messages. It simply defaulted to whatever + the default was in the LassoServer server object. Currently the lasso + default is LASSO_SIGNATURE_METHOD_RSA_SHA1. Some IdP's require a + different or more secure method (e.g. ADFS). This patch allows + controlling the signature method on a per directory basis via the + MellonSignatureMethod configuration directive. + + It currently supports the following configuration values which map to + these Lasso enumerated constants (provided these definition exist in + Lasso): + + rsa-sha1: LASSO_SIGNATURE_METHOD_RSA_SHA1 + rsa-sha256: LASSO_SIGNATURE_METHOD_RSA_SHA256 + rsa-sha384: LASSO_SIGNATURE_METHOD_RSA_SHA384 + rsa-sha512: LASSO_SIGNATURE_METHOD_RSA_SHA512 + + configure.ac was modified to test for the existence of the above + Lasso definitions, support is only compiled into Mellon if they + are defined at build time. + + The patch also includes a few corrections in the diagnostics code + where it failed to use CFG_VALUE. Also fixed the diagnostics code when + an unknown value was encounted to print what that unknown value was. + + Signed-off-by: John Dennis + +diff --git a/README b/README +index 2660e9a..0a91dc5 100644 +--- a/README ++++ b/README +@@ -583,6 +583,18 @@ MellonDiagnosticsEnable Off + # MellonRedirectDomains [self] + MellonRedirectDomains [self] + ++ # This option controls the signature method used to sign SAML ++ # messages generated by Mellon, it may be one of the following ++ # (depending if feature was supported when Mellon was built): ++ # ++ # rsa-sha1 ++ # rsa-sha256 ++ # rsa-sha384 ++ # rsa-sha512 ++ # ++ # Default: rsa-sha1 ++ # MellonSignatureMethod ++ + + + +diff --git a/auth_mellon.h b/auth_mellon.h +index a10bc4c..3b23537 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -239,6 +239,7 @@ typedef struct am_dir_cfg_rec { + apr_hash_t *envattr; + const char *userattr; + const char *idpattr; ++ LassoSignatureMethod signature_method; + int dump_session; + int dump_saml_response; + +@@ -416,6 +417,14 @@ static const int inherit_post_replay = -1; + static const int default_ecp_send_idplist = 0; + static const int inherit_ecp_send_idplist = -1; + ++/* Algorithm to use when signing Mellon SAML messages */ ++static const LassoSignatureMethod default_signature_method = ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA256 ++ LASSO_SIGNATURE_METHOD_RSA_SHA1; ++#else ++ LASSO_SIGNATURE_METHOD_RSA_SHA1; ++#endif ++static const int inherit_signature_method = -1; + + void *auth_mellon_dir_config(apr_pool_t *p, char *d); + void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add); +diff --git a/auth_mellon_config.c b/auth_mellon_config.c +index 66966fc..396ff1e 100644 +--- a/auth_mellon_config.c ++++ b/auth_mellon_config.c +@@ -105,6 +105,7 @@ static const int default_env_vars_count_in_n = -1; + /* The default list of trusted redirect domains. */ + static const char * const default_redirect_domains[] = { "[self]", NULL }; + ++ + /* This function handles configuration directives which set a + * multivalued string slot in the module configuration (the destination + * strucure is a hash). +@@ -1139,6 +1140,63 @@ static const char *am_set_redirect_domains(cmd_parms *cmd, + return NULL; + } + ++/* This function handles the MellonSignatureMethod configuration directive. ++ * This directive can be set to one of: ++ * ++ * Parameters: ++ * cmd_parms *cmd The command structure for this configuration ++ * directive. ++ * void *struct_ptr Pointer to the current directory configuration. ++ * const char *arg The string argument following this configuration ++ * directive in the configuraion file. ++ * ++ * Returns: ++ * NULL on success or an error string if the argument is wrong. ++ */ ++static const char *am_set_signature_method_slot(cmd_parms *cmd, ++ void *struct_ptr, ++ const char *arg) ++{ ++ am_dir_cfg_rec *d = (am_dir_cfg_rec *)struct_ptr; ++ char *valid_methods = "rsa-sha1" ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA256 ++ " rsa-sha256" ++#endif ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA384 ++ " rsa-sha384" ++#endif ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA512 ++ " rsa-sha512" ++#endif ++ ; ++ ++ if (!strcasecmp(arg, "rsa-sha1")) { ++ d->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA1; ++ } ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA256 ++ else if (!strcasecmp(arg, "rsa-sha256")) { ++ d->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA256; ++ } ++#endif ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA384 ++ else if (!strcasecmp(arg, "rsa-sha384")) { ++ d->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA384; ++ } ++#endif ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA512 ++ else if (!strcasecmp(arg, "rsa-sha512")) { ++ d->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA512; ++ } ++#endif ++ else { ++ return apr_psprintf(cmd->pool, ++ "%s: Invalid method \"%s\", must be one of: %s", ++ cmd->cmd->name, arg, valid_methods); ++ } ++ ++ return NULL; ++} ++ + /* This array contains all the configuration directive which are handled + * by auth_mellon. + */ +@@ -1587,6 +1645,13 @@ const command_rec auth_mellon_commands[] = { + OR_AUTHCFG, + "List of domains we can redirect to." + ), ++ AP_INIT_TAKE1( ++ "MellonSignatureMethod", ++ am_set_signature_method_slot, ++ NULL, ++ OR_AUTHCFG, ++ "Signature method used to sign SAML messages sent by Mellon" ++ ), + {NULL} + }; + +@@ -1651,6 +1716,7 @@ void *auth_mellon_dir_config(apr_pool_t *p, char *d) + dir->envattr = apr_hash_make(p); + dir->userattr = default_user_attribute; + dir->idpattr = NULL; ++ dir->signature_method = inherit_signature_method; + dir->dump_session = default_dump_session; + dir->dump_saml_response = default_dump_saml_response; + +@@ -1810,6 +1876,8 @@ void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add) + add_cfg->idpattr : + base_cfg->idpattr); + ++ new_cfg->signature_method = CFG_MERGE(add_cfg, base_cfg, signature_method); ++ + new_cfg->dump_session = (add_cfg->dump_session != default_dump_session ? + add_cfg->dump_session : + base_cfg->dump_session); +diff --git a/auth_mellon_diagnostics.c b/auth_mellon_diagnostics.c +index 289a878..8919b7d 100644 +--- a/auth_mellon_diagnostics.c ++++ b/auth_mellon_diagnostics.c +@@ -39,14 +39,17 @@ static const char * + am_diag_cond_flag_str(request_rec *r, am_cond_flag_t flags); + + static const char * +-am_diag_enable_str(am_enable_t enable); ++am_diag_enable_str(request_rec *r, am_enable_t enable); + + static const char * +-am_diag_samesite_str(am_samesite_t samesite); ++am_diag_samesite_str(request_rec *r, am_samesite_t samesite); + + static const char * + am_diag_httpd_error_level_str(request_rec *r, int level); + ++static const char * ++am_diag_signature_method_str(request_rec *r, ++ LassoSignatureMethod signature_method); + static apr_size_t + am_diag_time_t_to_8601_buf(char *buf, apr_size_t buf_size, apr_time_t t); + +@@ -191,26 +194,28 @@ am_diag_cond_flag_str(request_rec *r, am_cond_flag_t flags) + } + + static const char * +-am_diag_enable_str(am_enable_t enable) ++am_diag_enable_str(request_rec *r, am_enable_t enable) + { + switch(enable) { + case am_enable_default: return "default"; + case am_enable_off: return "off"; + case am_enable_info: return "info"; + case am_enable_auth: return "auth"; +- default: return "unknown"; ++ default: ++ return apr_psprintf(r->pool, "unknown (%d)", enable); + } + + } + + static const char * +-am_diag_samesite_str(am_samesite_t samesite) ++am_diag_samesite_str(request_rec *r, am_samesite_t samesite) + { + switch(samesite) { + case am_samesite_default: return "default"; + case am_samesite_lax: return "lax"; + case am_samesite_strict: return "strict"; +- default: return "unknown"; ++ default: ++ return apr_psprintf(r->pool, "unknown (%d)", samesite); + } + } + +@@ -239,6 +244,26 @@ am_diag_httpd_error_level_str(request_rec *r, int level) + } + } + ++static const char * ++am_diag_signature_method_str(request_rec *r, ++ LassoSignatureMethod signature_method) ++{ ++ switch(signature_method) { ++ case LASSO_SIGNATURE_METHOD_RSA_SHA1: return "rsa-sha1"; ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA256 ++ case LASSO_SIGNATURE_METHOD_RSA_SHA256: return "rsa-sha256"; ++#endif ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA384 ++ case LASSO_SIGNATURE_METHOD_RSA_SHA384: return "rsa-sha384"; ++#endif ++#if HAVE_DECL_LASSO_SIGNATURE_METHOD_RSA_SHA512 ++ case LASSO_SIGNATURE_METHOD_RSA_SHA512: return "rsa-sha512"; ++#endif ++ default: ++ return apr_psprintf(r->pool, "unknown (%d)", signature_method); ++ } ++} ++ + static apr_size_t + am_diag_time_t_to_8601_buf(char *buf, apr_size_t buf_size, apr_time_t t) + { +@@ -388,7 +413,7 @@ am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, + + apr_file_printf(diag_cfg->fd, + "%sMellonEnable (enable): %s\n", +- indent(level+1), am_diag_enable_str(cfg->enable_mellon)); ++ indent(level+1), am_diag_enable_str(r, cfg->enable_mellon)); + apr_file_printf(diag_cfg->fd, + "%sMellonVariable (varname): %s\n", + indent(level+1), cfg->varname); +@@ -416,7 +441,7 @@ am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, + apr_file_printf(diag_cfg->fd, + "%sMellonCookieSameSite (cookie_samesite): %s\n", + indent(level+1), +- am_diag_samesite_str(cfg->cookie_samesite)); ++ am_diag_samesite_str(r, cfg->cookie_samesite)); + + apr_file_printf(diag_cfg->fd, + "%sMellonCond (cond): %d items\n", +@@ -597,7 +622,7 @@ am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, + "%sMellonSubjectConfirmationDataAddressCheck" + " (subject_confirmation_data_address_check): %s\n", + indent(level+1), +- cfg->subject_confirmation_data_address_check ? "On":"Off"); ++ CFG_VALUE(cfg, subject_confirmation_data_address_check) ? "On":"Off"); + + apr_file_printf(diag_cfg->fd, + "%sMellonDoNotVerifyLogoutSignature" +@@ -622,13 +647,13 @@ am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, + "%sMellonSendCacheControlHeader" + " (send_cache_control_header): %s\n", + indent(level+1), +- cfg->send_cache_control_header ? "On":"Off"); ++ CFG_VALUE(cfg, send_cache_control_header) ? "On":"Off"); + apr_file_printf(diag_cfg->fd, + "%sMellonPostReplay (post_replay): %s\n", +- indent(level+1), cfg->post_replay ? "On":"Off"); ++ indent(level+1), CFG_VALUE(cfg, post_replay) ? "On":"Off"); + apr_file_printf(diag_cfg->fd, + "%sMellonECPSendIDPList (ecp_send_idplist): %s\n", +- indent(level+1), cfg->ecp_send_idplist ? "On":"Off"); ++ indent(level+1), CFG_VALUE(cfg, ecp_send_idplist) ? "On":"Off"); + + for (n_items = 0; cfg->redirect_domains[n_items] != NULL; n_items++); + apr_file_printf(diag_cfg->fd, +@@ -640,6 +665,11 @@ am_diag_log_dir_cfg(request_rec *r, int level, am_dir_cfg_rec *cfg, + indent(level+2), cfg->redirect_domains[i]); + } + ++ apr_file_printf(diag_cfg->fd, ++ "%sMellonSignatureMethod (signature_method): %s\n", ++ indent(level+1), ++ am_diag_signature_method_str(r, CFG_VALUE(cfg, signature_method))); ++ + apr_file_flush(diag_cfg->fd); + } + +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 030abe7..3f15c0a 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -372,6 +372,8 @@ static LassoServer *am_get_lasso_server(request_rec *r) + apr_thread_mutex_unlock(cfg->server_mutex); + return NULL; + } ++ ++ cfg->server->signature_method = CFG_VALUE(cfg, signature_method); + } + + apr_thread_mutex_unlock(cfg->server_mutex); +diff --git a/configure.ac b/configure.ac +index dcee35a..3ab7176 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -102,6 +102,14 @@ AC_CHECK_HEADER([lasso/utils.h], LASSO_CFLAGS="$LASSO_CFLAGS -DHAVE_LASSO_UTILS_ + CFLAGS=$saved_CFLAGS + CPPFLAGS=$saved_CPPFLAGS + ++# Determine what definitions exist in Lasso ++saved_CFLAGS=$CFLAGS ++CFLAGS="$CFLAGS $pkg_cv_LASSO_CFLAGS" ++AC_CHECK_DECLS([LASSO_SIGNATURE_METHOD_RSA_SHA256, ++ LASSO_SIGNATURE_METHOD_RSA_SHA384, ++ LASSO_SIGNATURE_METHOD_RSA_SHA512, ++ ], [], [], [#include ]) ++CFLAGS=$saved_CFLAGS + + # Create Makefile from Makefile.in + AC_CONFIG_FILES([Makefile]) diff --git a/SOURCES/track-file-info.patch b/SOURCES/track-file-info.patch new file mode 100644 index 0000000..d23d239 --- /dev/null +++ b/SOURCES/track-file-info.patch @@ -0,0 +1,744 @@ +commit 6d2ee845c030a3b3cadd2897ed2e5ce279c1a266 +Author: John Dennis +Date: Tue Aug 8 10:00:30 2017 -0400 + + Track file information + + File information was handled inconsistently. Some configuration + directives which specified a file path replaced the file path with the + contents of the file. This made it impossible to report where the data + was read from. Other file configuration simply recorded the path. The + directives which immediately read the file contents would generate a + configuration error if the file wasn't readable, but those directives + which simply recorded the file path didn't check on the validity of + the path and relied on Lasso to report an error, however these errors + come significantly after configuration parsing because they are + evaluated in a lazy fashion on first use. The Lasso error reporting + can sometimes be cryptic making it difficult to realize the problem is + due to a improperly specified path in a configuration directive. + + We want to be able to log the file pathnames where various files are + read from for diagnostic logging purposes. + + This patch introduces a new struct am_file_data_t that encapsulates + all information concerning a file including it's pathname, it's stat + information, optionally it's content, when it was read, etc. as well + as maintaing error codes and an error description. + + All file specifications and operations now use this mechanism for + consistency. + + Signed-off-by: John Dennis + +diff --git a/auth_mellon.h b/auth_mellon.h +index aff658b..a6fa34c 100644 +--- a/auth_mellon.h ++++ b/auth_mellon.h +@@ -159,6 +159,30 @@ typedef enum { + + extern const char *am_cond_options[]; + ++/* ++ * am_file_data_t is used to maintain information about a file: ++ * ++ * * The filesystem pathname ++ * * Stat information about the file (e.g. type, size, times, etc.) ++ * * If and when the file was stat'ed or read ++ * * Error code of failed operation and error string description ++ * * Contents of the file ++ * * Flag indicating if contents were generated instead of being read ++ * from a file. ++ */ ++typedef struct am_file_data_t { ++ apr_pool_t *pool; /* allocation pool */ ++ const char *path; /* filesystem pathname, NULL for generated file */ ++ apr_time_t stat_time; /* when stat was performed, zero indicates never */ ++ apr_finfo_t finfo; /* stat data */ ++ char *contents; /* file contents */ ++ apr_time_t read_time; /* when contents was read, zero indicates never */ ++ apr_status_t rv; /* most recent result value */ ++ const char *strerror; /* if rv is error then this is error description */ ++ bool generated; /* true if contents generated instead of being ++ read from path */ ++} am_file_data_t; ++ + typedef struct { + const char *varname; + int flags; +@@ -168,8 +192,8 @@ typedef struct { + } am_cond_t; + + typedef struct am_metadata { +- const char *file; /* Metadata file with one or many IdP */ +- const char *chain; /* Validating chain */ ++ am_file_data_t *metadata; /* Metadata file with one or many IdP */ ++ am_file_data_t *chain; /* Validating chain */ + } am_metadata_t; + + typedef struct am_dir_cfg_rec { +@@ -201,12 +225,12 @@ typedef struct am_dir_cfg_rec { + const char *endpoint_path; + + /* Lasso configuration variables. */ +- const char *sp_metadata_file; +- const char *sp_private_key_file; +- const char *sp_cert_file; ++ am_file_data_t *sp_metadata_file; ++ am_file_data_t *sp_private_key_file; ++ am_file_data_t *sp_cert_file; + apr_array_header_t *idp_metadata; +- const char *idp_public_key_file; +- const char *idp_ca_file; ++ am_file_data_t *idp_public_key_file; ++ am_file_data_t *idp_ca_file; + GList *idp_ignore; + + /* metadata autogeneration helper */ +@@ -424,7 +448,11 @@ char *am_urlencode(apr_pool_t *pool, const char *str); + int am_urldecode(char *data); + int am_check_url(request_rec *r, const char *url); + char *am_generate_id(request_rec *r); +-char *am_getfile(apr_pool_t *conf, server_rec *s, const char *file); ++am_file_data_t *am_file_data_new(apr_pool_t *pool, const char *path); ++am_file_data_t *am_file_data_copy(apr_pool_t *pool, ++ am_file_data_t *src_file_data); ++apr_status_t am_file_read(am_file_data_t *file_data); ++apr_status_t am_file_stat(am_file_data_t *file_data); + char *am_get_endpoint_url(request_rec *r); + int am_postdir_cleanup(request_rec *s); + char *am_htmlencode(request_rec *r, const char *str); +diff --git a/auth_mellon_config.c b/auth_mellon_config.c +index 3dfab67..c3cb5e0 100644 +--- a/auth_mellon_config.c ++++ b/auth_mellon_config.c +@@ -176,9 +176,8 @@ static const char *am_set_table_string_slot(cmd_parms *cmd, + return NULL; + } + +-/* This function handles configuration directives which set a file +- * slot in the module configuration. If lasso is recent enough, it +- * attempts to read the file immediatly. ++/* This function handles configuration directives which set a file slot ++ * in the module configuration. The file contents are immediately read. + * + * Parameters: + * cmd_parms *cmd The command structure for this configuration +@@ -192,12 +191,15 @@ static const char *am_set_table_string_slot(cmd_parms *cmd, + * Returns: + * NULL on success or an error string on failure. + */ +-static const char *am_set_filestring_slot(cmd_parms *cmd, ++static const char *am_set_file_contents_slot(cmd_parms *cmd, + void *struct_ptr, + const char *arg) + { +- const char *data; + const char *path; ++ apr_status_t rv; ++ am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr; ++ int offset; ++ am_file_data_t **p_file_data, *file_data; + + path = ap_server_root_relative(cmd->pool, arg); + if (!path) { +@@ -205,29 +207,64 @@ static const char *am_set_filestring_slot(cmd_parms *cmd, + ": Invalid file path ", arg, NULL); + } + +-#ifdef HAVE_lasso_server_new_from_buffers +- data = am_getfile(cmd->pool, cmd->server, path); +- if (!data) { +- return apr_pstrcat(cmd->pool, cmd->cmd->name, +- ": Cannot read file ", path, NULL); ++ offset = (int)(long)cmd->info; ++ p_file_data = (am_file_data_t **)((char *)cfg + offset); ++ *p_file_data = am_file_data_new(cmd->pool, path); ++ file_data = *p_file_data; ++ rv = am_file_read(file_data); ++ if (rv != APR_SUCCESS) { ++ return file_data->strerror; + } +-#else +- apr_finfo_t finfo; ++ ++ return NULL; ++} ++ ++/* This function handles configuration directives which set a file ++ * pathname in the module configuration. The file is checked for ++ * existence. ++ * ++ * Parameters: ++ * cmd_parms *cmd The command structure for this configuration ++ * directive. ++ * void *struct_ptr Pointer to the current directory configuration. ++ * NULL if we are not in a directory configuration. ++ * This value isn't used by this function. ++ * const char *arg The string argument following this configuration ++ * directive in the configuraion file. ++ * ++ * Returns: ++ * NULL on success or an error string on failure. ++ */ ++static const char *am_set_file_pathname_slot(cmd_parms *cmd, ++ void *struct_ptr, ++ const char *arg) ++{ ++ const char *path; + apr_status_t rv; +- char error[64]; ++ am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr; ++ int offset; ++ am_file_data_t **p_file_data, *file_data; + +- rv = apr_stat(&finfo, path, APR_FINFO_SIZE, cmd->pool); +- if(rv != 0) { +- apr_strerror(rv, error, sizeof(error)); +- return apr_psprintf(cmd->pool, +- "%s - Cannot read file \"%s\" [%d] \"%s\"", +- cmd->cmd->name, path, rv, error); ++ path = ap_server_root_relative(cmd->pool, arg); ++ if (!path) { ++ return apr_pstrcat(cmd->pool, cmd->cmd->name, ++ ": Invalid file_data path ", arg, NULL); + } + +- data = path; +-#endif ++ offset = (int)(long)cmd->info; ++ p_file_data = (am_file_data_t **)((char *)cfg + offset); ++ *p_file_data = am_file_data_new(cmd->pool, path); ++ file_data = *p_file_data; ++ rv = am_file_stat(file_data); ++ if (rv != APR_SUCCESS) { ++ return file_data->strerror; ++ } ++ if (file_data->finfo.filetype != APR_REG) { ++ return apr_psprintf(cmd->pool, "file \"%s\" is not a regular file", ++ file_data->path); ++ } + +- return ap_set_string_slot(cmd, struct_ptr, data); ++ return NULL; + } + + +@@ -305,6 +342,8 @@ static const char *am_set_idp_string_slot(cmd_parms *cmd, + server_rec *s = cmd->server; + apr_pool_t *pconf = s->process->pconf; + am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr; ++ am_file_data_t *idp_file_data = NULL; ++ am_file_data_t *chain_file_data = NULL; + + #ifndef HAVE_lasso_server_load_metadata + if (chain != NULL) +@@ -313,9 +352,23 @@ static const char *am_set_idp_string_slot(cmd_parms *cmd, + "lasso_server_load_metadata()", cmd->cmd->name); + #endif /* HAVE_lasso_server_load_metadata */ + ++ idp_file_data = am_file_data_new(pconf, metadata); ++ if (am_file_stat(idp_file_data) != APR_SUCCESS) { ++ return idp_file_data->strerror; ++ } ++ ++ if (chain) { ++ chain_file_data = am_file_data_new(pconf, chain); ++ if (am_file_stat(chain_file_data) != APR_SUCCESS) { ++ return chain_file_data->strerror; ++ } ++ } else { ++ chain_file_data = NULL; ++ } ++ + am_metadata_t *idp_metadata = apr_array_push(cfg->idp_metadata); +- idp_metadata->file = apr_pstrdup(pconf, metadata); +- idp_metadata->chain = apr_pstrdup(pconf, chain); ++ idp_metadata->metadata = idp_file_data; ++ idp_metadata->chain = chain_file_data; + + return NULL; + } +@@ -1230,21 +1283,21 @@ const command_rec auth_mellon_commands[] = { + ), + AP_INIT_TAKE1( + "MellonSPMetadataFile", +- am_set_filestring_slot, ++ am_set_file_contents_slot, + (void *)APR_OFFSETOF(am_dir_cfg_rec, sp_metadata_file), + OR_AUTHCFG, + "Full path to xml file with metadata for the SP." + ), + AP_INIT_TAKE1( + "MellonSPPrivateKeyFile", +- am_set_filestring_slot, ++ am_set_file_contents_slot, + (void *)APR_OFFSETOF(am_dir_cfg_rec, sp_private_key_file), + OR_AUTHCFG, + "Full path to pem file with the private key for the SP." + ), + AP_INIT_TAKE1( + "MellonSPCertFile", +- am_set_filestring_slot, ++ am_set_file_contents_slot, + (void *)APR_OFFSETOF(am_dir_cfg_rec, sp_cert_file), + OR_AUTHCFG, + "Full path to pem file with certificate for the SP." +@@ -1267,14 +1320,14 @@ const command_rec auth_mellon_commands[] = { + ), + AP_INIT_TAKE1( + "MellonIdPPublicKeyFile", +- ap_set_file_slot, ++ am_set_file_pathname_slot, + (void *)APR_OFFSETOF(am_dir_cfg_rec, idp_public_key_file), + OR_AUTHCFG, + "Full path to pem file with the public key for the IdP." + ), + AP_INIT_TAKE1( + "MellonIdPCAFile", +- ap_set_file_slot, ++ am_set_file_pathname_slot, + (void *)APR_OFFSETOF(am_dir_cfg_rec, idp_ca_file), + OR_AUTHCFG, + "Full path to pem file with CA chain for the IdP." +@@ -1679,7 +1732,6 @@ void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add) + add_cfg->no_success_error_page : + base_cfg->no_success_error_page); + +- + new_cfg->sp_metadata_file = (add_cfg->sp_metadata_file ? + add_cfg->sp_metadata_file : + base_cfg->sp_metadata_file); +diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c +index 2004752..08b7869 100644 +--- a/auth_mellon_handler.c ++++ b/auth_mellon_handler.c +@@ -32,13 +32,6 @@ APLOG_USE_MODULE(auth_mellon); + * the ECP.rst file. + */ + +-#ifdef HAVE_lasso_server_new_from_buffers +-# define SERVER_NEW lasso_server_new_from_buffers +-#else /* HAVE_lasso_server_new_from_buffers */ +-# define SERVER_NEW lasso_server_new +-#endif /* HAVE_lasso_server_new_from_buffers */ +- +- + + #ifdef HAVE_lasso_server_new_from_buffers + /* This function generates optional metadata for a given element +@@ -130,7 +123,7 @@ static char *am_generate_metadata(apr_pool_t *p, request_rec *r) + + sp_entity_id = cfg->sp_entity_id ? cfg->sp_entity_id : url; + +- if (cfg->sp_cert_file) { ++ if (cfg->sp_cert_file && cfg->sp_cert_file->contents) { + char *sp_cert_file; + char *cp; + char *bp; +@@ -141,7 +134,7 @@ static char *am_generate_metadata(apr_pool_t *p, request_rec *r) + * Try to remove leading and trailing garbage, as it can + * wreak havoc XML parser if it contains [<>&] + */ +- sp_cert_file = apr_pstrdup(p, cfg->sp_cert_file); ++ sp_cert_file = apr_pstrdup(p, cfg->sp_cert_file->contents); + + cp = strstr(sp_cert_file, begin); + if (cp != NULL) +@@ -237,7 +230,8 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + const char *idp_public_key_file; + + if (cfg->idp_metadata->nelts == 1) +- idp_public_key_file = cfg->idp_public_key_file; ++ idp_public_key_file = cfg->idp_public_key_file ? ++ cfg->idp_public_key_file->path : NULL; + else + idp_public_key_file = NULL; + #endif /* ! HAVE_lasso_server_load_metadata */ +@@ -260,8 +254,9 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + #ifdef HAVE_lasso_server_load_metadata + error = lasso_server_load_metadata(cfg->server, + LASSO_PROVIDER_ROLE_IDP, +- idp_metadata->file, +- idp_metadata->chain, ++ idp_metadata->metadata->path, ++ idp_metadata->chain ? ++ idp_metadata->chain->path : NULL, + cfg->idp_ignore, + &loaded_idp, + LASSO_SERVER_LOAD_METADATA_FLAG_DEFAULT); +@@ -271,7 +266,7 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + for (idx = loaded_idp; idx != NULL; idx = idx->next) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "loaded IdP \"%s\" from \"%s\".", +- (char *)idx->data, idp_metadata->file); ++ (char *)idx->data, idp_metadata->metadata->path); + } + } + +@@ -285,16 +280,17 @@ static guint am_server_add_providers(am_dir_cfg_rec *cfg, request_rec *r) + #else /* HAVE_lasso_server_load_metadata */ + error = lasso_server_add_provider(cfg->server, + LASSO_PROVIDER_ROLE_IDP, +- idp_metadata->file, ++ idp_metadata->metadata->path, + idp_public_key_file, +- cfg->idp_ca_file); ++ cfg->idp_ca_file ? ++ cfg->idp_ca_file->path : NULL); + #endif /* HAVE_lasso_server_load_metadata */ + + if (error != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Error adding metadata \"%s\" to " + "lasso server objects. Lasso error: [%i] %s", +- idp_metadata->file, error, lasso_strerror(error)); ++ idp_metadata->metadata->path, error, lasso_strerror(error)); + } + } + +@@ -317,7 +313,10 @@ static LassoServer *am_get_lasso_server(request_rec *r) + * Try to generate missing metadata + */ + apr_pool_t *pool = r->server->process->pconf; +- cfg->sp_metadata_file = am_generate_metadata(pool, r); ++ cfg->sp_metadata_file = am_file_data_new(pool, NULL); ++ cfg->sp_metadata_file->rv = APR_SUCCESS; ++ cfg->sp_metadata_file->generated = true; ++ cfg->sp_metadata_file->contents = am_generate_metadata(pool, r); + #else + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Missing MellonSPMetadataFile option."); +@@ -326,11 +325,22 @@ static LassoServer *am_get_lasso_server(request_rec *r) + #endif /* HAVE_lasso_server_new_from_buffers */ + } + +- cfg->server = SERVER_NEW(cfg->sp_metadata_file, +- cfg->sp_private_key_file, +- NULL, +- cfg->sp_cert_file); +- if(cfg->server == NULL) { ++#ifdef HAVE_lasso_server_new_from_buffers ++ cfg->server = lasso_server_new_from_buffers(cfg->sp_metadata_file->contents, ++ cfg->sp_private_key_file ? ++ cfg->sp_private_key_file->contents : NULL, ++ NULL, ++ cfg->sp_cert_file ? ++ cfg->sp_cert_file->contents : NULL); ++#else ++ cfg->server = lasso_server_new(cfg->sp_metadata_file->path, ++ cfg->sp_private_key_file ? ++ cfg->sp_private_key_file->path : NULL, ++ NULL, ++ cfg->sp_cert_file ? ++ cfg->sp_cert_file->path : NULL); ++#endif ++ if (cfg->server == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Error initializing lasso server object. Please" + " verify the following configuration directives:" +@@ -2390,8 +2400,8 @@ static int am_handle_repost(request_rec *r) + char *charset; + char *psf_id; + char *cp; +- char *psf_filename; +- char *post_data; ++ am_file_data_t *file_data; ++ const char *post_data; + const char *post_form; + char *output; + char *return_url; +@@ -2486,14 +2496,24 @@ static int am_handle_repost(request_rec *r) + return rc; + } + +- psf_filename = apr_psprintf(r->pool, "%s/%s", mod_cfg->post_dir, psf_id); +- post_data = am_getfile(r->pool, r->server, psf_filename); +- if (post_data == NULL) { ++ if ((file_data = am_file_data_new(r->pool, NULL)) == NULL) { ++ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, ++ "Bad repost query: cannot allocate file_data"); ++ apr_table_setn(r->headers_out, "Location", return_url); ++ return HTTP_SEE_OTHER; ++ } ++ ++ file_data->path = apr_psprintf(file_data->pool, "%s/%s", ++ mod_cfg->post_dir, psf_id); ++ rc = am_file_read(file_data); ++ if (rc != APR_SUCCESS) { + /* Unable to load repost data. Just redirect us instead. */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, +- "Bad repost query: cannot find \"%s\"", psf_filename); ++ "Bad repost query: %s", file_data->strerror); + apr_table_setn(r->headers_out, "Location", return_url); + return HTTP_SEE_OTHER; ++ } else { ++ post_data = file_data->contents; + } + + if ((post_form = (*post_mkform)(r, post_data)) == NULL) { +@@ -2556,7 +2576,7 @@ static int am_handle_metadata(request_rec *r) + + cfg = cfg->inherit_server_from; + +- data = cfg->sp_metadata_file; ++ data = cfg->sp_metadata_file ? cfg->sp_metadata_file->contents : NULL; + if (data == NULL) + return HTTP_INTERNAL_SERVER_ERROR; + +diff --git a/auth_mellon_httpclient.c b/auth_mellon_httpclient.c +index d9688df..ecf5c0d 100644 +--- a/auth_mellon_httpclient.c ++++ b/auth_mellon_httpclient.c +@@ -298,11 +298,11 @@ static CURL *am_httpclient_init_curl(request_rec *r, const char *uri, + + /* If we have a CA configured, try to use it */ + if (cfg->idp_ca_file != NULL) { +- res = curl_easy_setopt(curl, CURLOPT_CAINFO, cfg->idp_ca_file); ++ res = curl_easy_setopt(curl, CURLOPT_CAINFO, cfg->idp_ca_file->path); + if(res != CURLE_OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Failed to set SSL CA info %s:" +- " [%u] %s", cfg->idp_ca_file, res, curl_error); ++ " [%u] %s", cfg->idp_ca_file->path, res, curl_error); + goto cleanup_fail; + } + } +diff --git a/auth_mellon_session.c b/auth_mellon_session.c +index 856dbb6..3eae4a0 100644 +--- a/auth_mellon_session.c ++++ b/auth_mellon_session.c +@@ -119,7 +119,6 @@ am_cache_entry_t *am_new_request_session(request_rec *r) + return NULL; + } + +- + /* Set session id. */ + am_cookie_set(r, session_id); + +diff --git a/auth_mellon_util.c b/auth_mellon_util.c +index 19bfb41..7f8d52b 100644 +--- a/auth_mellon_util.c ++++ b/auth_mellon_util.c +@@ -1022,57 +1022,179 @@ const char *am_filepath_dirname(apr_pool_t *p, const char *path) + } + + /* +- * malloc a buffer and fill it with a given file ++ * Allocate and initialize a am_file_data_t + * + * Parameters: +- * apr_pool_t *conf The configuration pool. Valid as long as this +- * server_rec *s The server record for the current server. +- * const char *file The file path ++ * apr_pool_t *pool Allocation pool. ++ * const char *path If non-NULL initialize file_data->path to copy of path + * + * Returns: +- * char * The file content ++ * Newly allocated & initialized file_data_t + */ +-char *am_getfile(apr_pool_t *conf, server_rec *s, const char *file) ++am_file_data_t *am_file_data_new(apr_pool_t *pool, const char *path) ++{ ++ am_file_data_t *file_data = NULL; ++ ++ if ((file_data = apr_pcalloc(pool, sizeof(am_file_data_t))) == NULL) { ++ return NULL; ++ } ++ ++ file_data->pool = pool; ++ file_data->rv = APR_EINIT; ++ if (path) { ++ file_data->path = apr_pstrdup(file_data->pool, path); ++ } ++ ++ return file_data; ++} ++ ++/* ++ * Allocate a new am_file_data_t and copy ++ * ++ * Parameters: ++ * apr_pool_t *pool Allocation pool. ++ * am_file_data_t *src_file_data The src being copied. ++ * ++ * Returns: ++ * Newly allocated & initialized from src_file_data ++ */ ++am_file_data_t *am_file_data_copy(apr_pool_t *pool, ++ am_file_data_t *src_file_data) ++{ ++ am_file_data_t *dst_file_data = NULL; ++ ++ if ((dst_file_data = am_file_data_new(pool, src_file_data->path)) == NULL) { ++ return NULL; ++ } ++ ++ dst_file_data->path = apr_pstrdup(pool, src_file_data->path); ++ dst_file_data->stat_time = src_file_data->stat_time; ++ dst_file_data->finfo = src_file_data->finfo; ++ dst_file_data->contents = apr_pstrdup(pool, src_file_data->contents); ++ dst_file_data->read_time = src_file_data->read_time; ++ dst_file_data->rv = src_file_data->rv; ++ dst_file_data->strerror = apr_pstrdup(pool, src_file_data->strerror); ++ dst_file_data->generated = src_file_data->generated; ++ ++ return dst_file_data; ++} ++ ++/* ++ * Peform a stat on a file to get it's properties ++ * ++ * A stat is performed on the file. If there was an error the ++ * result value is left in file_data->rv and an error description ++ * string is formatted and left in file_data->strerror and function ++ * returns the rv value. If the stat was successful the stat ++ * information is left in file_data->finfo and APR_SUCCESS ++ * set set as file_data->rv and returned as the function result. ++ * ++ * The file_data->stat_time indicates if and when the stat was ++ * performed, a zero time value indicates the operation has not yet ++ * been performed. ++ * ++ * Parameters: ++ * am_file_data_t *file_data Struct containing file information ++ * ++ * Returns: ++ * APR status code, same value as file_data->rv ++ */ ++apr_status_t am_file_stat(am_file_data_t *file_data) ++{ ++ char buffer[512]; ++ ++ if (file_data == NULL) { ++ return APR_EINVAL; ++ } ++ ++ file_data->strerror = NULL; ++ ++ file_data->stat_time = apr_time_now(); ++ file_data->rv = apr_stat(&file_data->finfo, file_data->path, ++ APR_FINFO_SIZE, file_data->pool); ++ if (file_data->rv != APR_SUCCESS) { ++ file_data->strerror = ++ apr_psprintf(file_data->pool, ++ "apr_stat: Error opening \"%s\" [%d] \"%s\"", ++ file_data->path, file_data->rv, ++ apr_strerror(file_data->rv, buffer, sizeof(buffer))); ++ } ++ ++ return file_data->rv; ++} ++ ++/* ++ * Read file into dynamically allocated buffer ++ * ++ * First a stat is performed on the file. If there was an error the ++ * result value is left in file_data->rv and an error description ++ * string is formatted and left in file_data->strerror and function ++ * returns the rv value. If the stat was successful the stat ++ * information is left in file_data->finfo. ++ * ++ * A buffer is dynamically allocated and the contents of the file is ++ * read into file_data->contents. If there was an error the result ++ * value is left in file_data->rv and an error description string is ++ * formatted and left in file_data->strerror and the function returns ++ * the rv value. ++ * ++ * The file_data->stat_time and file_data->read_time indicate if and ++ * when those operations were performed, a zero time value indicates ++ * the operation has not yet been performed. ++ * ++ * Parameters: ++ * am_file_data_t *file_data Struct containing file information ++ * ++ * Returns: ++ * APR status code, same value as file_data->rv ++ */ ++apr_status_t am_file_read(am_file_data_t *file_data) + { +- apr_status_t rv; + char buffer[512]; +- apr_finfo_t finfo; +- char *data; + apr_file_t *fd; + apr_size_t nbytes; + +- if (file == NULL) +- return NULL; ++ if (file_data == NULL) { ++ return APR_EINVAL; ++ } ++ file_data->rv = APR_SUCCESS; ++ file_data->strerror = NULL; + +- if ((rv = apr_file_open(&fd, file, APR_READ, 0, conf)) != 0) { +- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, +- "apr_file_open: Error opening \"%s\" [%d] \"%s\"", +- file, rv, apr_strerror(rv, buffer, sizeof(buffer))); +- return NULL; ++ am_file_stat(file_data); ++ if (file_data->rv != APR_SUCCESS) { ++ return file_data->rv; + } + +- if ((rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fd)) != 0) { +- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, +- "apr_file_info_get: Error opening \"%s\" [%d] \"%s\"", +- file, rv, apr_strerror(rv, buffer, sizeof(buffer))); +- (void)apr_file_close(fd); +- return NULL; ++ if ((file_data->rv = apr_file_open(&fd, file_data->path, ++ APR_READ, 0, file_data->pool)) != 0) { ++ file_data->strerror = ++ apr_psprintf(file_data->pool, ++ "apr_file_open: Error opening \"%s\" [%d] \"%s\"", ++ file_data->path, file_data->rv, ++ apr_strerror(file_data->rv, buffer, sizeof(buffer))); ++ return file_data->rv; + } + +- nbytes = finfo.size; +- data = (char *)apr_palloc(conf, nbytes + 1); ++ file_data->read_time = apr_time_now(); ++ nbytes = file_data->finfo.size; ++ file_data->contents = (char *)apr_palloc(file_data->pool, nbytes + 1); ++ ++ file_data->rv = apr_file_read_full(fd, file_data->contents, nbytes, NULL); ++ if (file_data->rv != 0) { ++ file_data->strerror = ++ apr_psprintf(file_data->pool, ++ "apr_file_read_full: Error reading \"%s\" [%d] \"%s\"", ++ file_data->path, file_data->rv, ++ apr_strerror(file_data->rv, buffer, sizeof(buffer))); ++ (void)apr_file_close(fd); ++ return file_data->rv; + +- rv = apr_file_read_full(fd, data, nbytes, NULL); +- if (rv != 0) { +- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, +- "apr_file_read_full: Error reading \"%s\" [%d] \"%s\"", +- file, rv, apr_strerror(rv, buffer, sizeof(buffer))); + } +- data[nbytes] = '\0'; ++ file_data->contents[nbytes] = '\0'; + + (void)apr_file_close(fd); + +- return data; ++ return file_data->rv; + } + + /* +diff --git a/mod_auth_mellon.c b/mod_auth_mellon.c +index 3d44460..f632d37 100644 +--- a/mod_auth_mellon.c ++++ b/mod_auth_mellon.c +@@ -220,7 +220,6 @@ static void register_hooks(apr_pool_t *p) + * r->handler and decide that it is the only handler for this URL. + */ + ap_hook_handler(am_handler, NULL, NULL, APR_HOOK_FIRST); +- return; + } + + diff --git a/SOURCES/update_log_invalid_dst.patch b/SOURCES/update_log_invalid_dst.patch index 17c328d..44c1108 100644 --- a/SOURCES/update_log_invalid_dst.patch +++ b/SOURCES/update_log_invalid_dst.patch @@ -11,7 +11,7 @@ index afb3195..030abe7 100644 @@ -1461,8 +1461,8 @@ static int am_validate_conditions(request_rec *r, if (ar->Audience == NULL || strcmp(ar->Audience, providerID)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, - "Invalid Audience in Conditions. Should be: %s", - providerID); + "Invalid Audience in Conditions. Should be '%s', but was '%s'", @@ -22,7 +22,7 @@ index afb3195..030abe7 100644 @@ -1791,8 +1791,8 @@ static int am_handle_reply_common(request_rec *r, LassoLogin *login, if (response->parent.Destination) { if (strcmp(response->parent.Destination, url)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + AM_LOG_RERROR(APLOG_MARK, APLOG_ERR, 0, r, - "Invalid Destination on Response. Should be: %s", - url); + "Invalid Destination on Response. Should be '%s', but was '%s'", diff --git a/SPECS/mod_auth_mellon.spec b/SPECS/mod_auth_mellon.spec index c9ab7bb..0123165 100644 --- a/SPECS/mod_auth_mellon.spec +++ b/SPECS/mod_auth_mellon.spec @@ -1,7 +1,7 @@ Summary: A SAML 2.0 authentication module for the Apache Httpd Server Name: mod_auth_mellon Version: 0.13.1 -Release: 1%{?dist} +Release: 3%{?dist} Group: System Environment/Daemons Source0: https://github.com/UNINETT/mod_auth_mellon/releases/download/v%{version}/%{name}-%{version}.tar.gz Source1: auth_mellon.conf @@ -9,6 +9,7 @@ Source2: 10-auth_mellon.conf Source3: mod_auth_mellon.conf Source4: mellon_create_metadata.sh Source5: user_guide.tar.gz +Source6: README.redhat.rst License: GPLv2+ BuildRequires: curl-devel @@ -17,6 +18,7 @@ BuildRequires: httpd-devel BuildRequires: lasso-devel >= 2.5.0 BuildRequires: openssl-devel BuildRequires: xmlsec1-devel +BuildRequires: automake Requires: httpd-mmn = %{_httpd_mmn} Requires: lasso >= 2.5.0 Url: https://github.com/UNINETT/mod_auth_mellon @@ -25,8 +27,16 @@ Patch1: log_typo.patch Patch2: post_segfault.patch Patch3: lasso_error_check.patch Patch4: mellon_user_case_insensitive.patch -Patch5: log_no_idp.patch -Patch6: update_log_invalid_dst.patch +Patch5: cache-request_rec.patch +Patch6: log_no_idp.patch +Patch7: track-file-info.patch +Patch8: add-diagnostics.patch +Patch9: am_log_rerror.patch +Patch10: update_log_invalid_dst.patch +Patch11: log-status-response.patch +Patch12: ac_define.patch +Patch13: fix-conditional-diagnostics-build.patch +Patch14: signature-algorithm.patch %description The mod_auth_mellon module is an authentication service that implements the @@ -41,16 +51,32 @@ received in assertions generated by a IdP server. %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 %build export APXS=%{_httpd_apxs} +./autogen.sh +%configure --enable-diagnostics +make clean +make %{?_smp_mflags} +cp .libs/%{name}.so %{name}-diagnostics.so + %configure +make clean make %{?_smp_mflags} %install # install module mkdir -p %{buildroot}%{_httpd_moddir} install -m 755 .libs/%{name}.so %{buildroot}%{_httpd_moddir} +install -m 755 %{name}-diagnostics.so %{buildroot}%{_httpd_moddir} # install module configuration mkdir -p %{buildroot}%{_httpd_confdir} @@ -66,10 +92,29 @@ mkdir -p %{buildroot}/run/%{name} mkdir -p %{buildroot}/%{_libexecdir}/%{name} install -m 755 %{SOURCE4} %{buildroot}/%{_libexecdir}/%{name} -# install user guide +#install documentation mkdir -p %{buildroot}/%{_pkgdocdir} + +# install Red Hat README +install %{SOURCE6} %{buildroot}/%{_pkgdocdir} + +# install user guide tar -C %{buildroot}/%{_pkgdocdir} -xf %{SOURCE5} +%package diagnostics +Summary: Build of mod_auth_mellon with diagnostic logging +Requires: %{name} = %{version}-%{release} + +%description diagnostics +Build of mod_auth_mellon with diagnostic logging. To use this +diagnostic version of mod_auth_mellon edit: +%{_httpd_moddir}/%(basename %{SOURCE2}) +changing "mod_auth_mellon.so" to "mod_auth_mellon-diagnostics.so". +Don't forget to return the loaded module to "mod_auth_mellon.so" +after you've completed your diagnostic debugging. + +%files diagnostics +%{_httpd_moddir}/%{name}-diagnostics.so %files %defattr(-,root,root) @@ -79,6 +124,7 @@ tar -C %{buildroot}/%{_pkgdocdir} -xf %{SOURCE5} %license COPYING %endif %doc README NEWS ECP.rst +%doc %{_pkgdocdir}/README.redhat.rst %doc %{_pkgdocdir}/user_guide %config(noreplace) %{_httpd_modconfdir}/10-auth_mellon.conf %config(noreplace) %{_httpd_confdir}/auth_mellon.conf @@ -88,6 +134,15 @@ tar -C %{buildroot}/%{_pkgdocdir} -xf %{SOURCE5} %dir /run/%{name}/ %changelog +* Thu Apr 19 2018 John Dennis - 0.13.1-3 +- Resolves: rhbz#1553854 Add diagnostic logging +- Add README.redhat.rst doc, explains how to enable diagnostic logging + +* Thu Mar 29 2018 John Dennis - 0.13.1-2 +- Resolves: rhbz#1553854 Add diagnostic logging +- Add MellonSignatureMethod config option to set signature method used + to sign SAML messages sent by Mellon. Defaults to original sha1. + * Fri Oct 20 2017 John Dennis - 0.13.1-1 - Resolves: rhbz#1481332 Upgrade to current upstream 0.13.1 - Adds the following upstream bug fixes on top of 0.13.1: