From b8c0859d81464063a0d0195cafa4c865a91255ad Mon Sep 17 00:00:00 2001 From: manu Date: Tue, 6 Dec 2011 09:58:00 +0000 Subject: Update to mod_auth_mellon 0.4.0 plus upstream patch: * Honour MellonProbeDiscoveryIdP order when sending probes * Allow MellonUser variable to be translated through MellonSetEnv * A /mellon/probeDisco endpoint replaces the builtin:get-metadata IdP dicovery URL scheme * New MellonCond directive to enable attribute filtering beyond MellonRequire functionalities. * New MellonIdPMetadataGlob directive to load mulitple IdP metadata using a glob(3) pattern. * Support for running behind reverse proxy. * MellonCookieDomain and MellonCookiePath options to configure cookie settings. * Support for loading federation metadata files. * Several bugfixes. --- www/ap2-auth-mellon/Makefile | 12 +- www/ap2-auth-mellon/distinfo | 15 +- www/ap2-auth-mellon/patches/patch-ac | 515 ---------------------------------- www/ap2-auth-mellon/patches/patch-ae | 523 ----------------------------------- www/ap2-auth-mellon/patches/patch-af | 65 ----- www/ap2-auth-mellon/patches/patch-ag | 149 ---------- www/ap2-auth-mellon/patches/patch-ah | 91 ------ www/ap2-auth-mellon/patches/patch-ai | 310 +++++++++++++++++++++ 8 files changed, 322 insertions(+), 1358 deletions(-) delete mode 100644 www/ap2-auth-mellon/patches/patch-ac delete mode 100644 www/ap2-auth-mellon/patches/patch-ae delete mode 100644 www/ap2-auth-mellon/patches/patch-af delete mode 100644 www/ap2-auth-mellon/patches/patch-ag delete mode 100644 www/ap2-auth-mellon/patches/patch-ah create mode 100644 www/ap2-auth-mellon/patches/patch-ai (limited to 'www/ap2-auth-mellon') diff --git a/www/ap2-auth-mellon/Makefile b/www/ap2-auth-mellon/Makefile index 13be9bf71f2..32c31470e54 100644 --- a/www/ap2-auth-mellon/Makefile +++ b/www/ap2-auth-mellon/Makefile @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.17 2011/05/07 05:15:21 manu Exp $ +# $NetBSD: Makefile,v 1.18 2011/12/06 09:58:01 manu Exp $ # PKGNAME= ${APACHE_PKG_PREFIX}-${DISTNAME:S/mod_//:S/_/-/} -DISTNAME= mod_auth_mellon-0.3.0 -PKGREVISION= 3 +DISTNAME= mod_auth_mellon-0.4.0 +PKGREVISION= 1 CATEGORIES= www security MASTER_SITES= http://modmellon.googlecode.com/files/ @@ -17,6 +17,7 @@ PKG_DESTDIR_SUPPORT= user-destdir GNU_CONFIGURE= YES USE_LIBTOOL= YES USE_TOOLS+= pkg-config +CFLAGS+= -DLASSO_SERVER_LOAD_METADATA_FLAG_DEFAULT=0 APACHE_MODULE= YES APACHE_MODULE_NAME= auth_mellon_module @@ -25,10 +26,10 @@ PKG_APACHE_ACCEPTED= apache22 BUILDLINK_API_DEPENDS.apache+= apache>=2.0.47 SUBST_CLASSES+= pthflags -SUBST_MESSAGES= Convert -pthread flag to apxs style +SUBST_MESSAGES= Remove -pthread flag SUBST_STAGE.pthflags= post-configure SUBST_FILES.pthflags= Makefile -SUBST_SED.pthflags= -e 's| -pthread | ${"${PTHREAD_CFLAGS:M-pthread}":?-Wc,-pthread:} ${"${PTHREAD_LDFLAGS:M-pthread}":?-Wl,-pthread:} |g' +SUBST_SED.pthflags= -e 's| -pthread | |g' INSTALLATION_DIRS+= lib/httpd @@ -39,6 +40,7 @@ do-install: -n auth_mellon mod_auth_mellon.la .include "../../security/lasso/buildlink3.mk" +.include "../../mk/pthread.buildlink3.mk" .include "../../www/curl/buildlink3.mk" .include "../../mk/bsd.pkg.mk" diff --git a/www/ap2-auth-mellon/distinfo b/www/ap2-auth-mellon/distinfo index fa24e895579..8a636760523 100644 --- a/www/ap2-auth-mellon/distinfo +++ b/www/ap2-auth-mellon/distinfo @@ -1,11 +1,6 @@ -$NetBSD: distinfo,v 1.10 2011/05/07 05:15:21 manu Exp $ +$NetBSD: distinfo,v 1.11 2011/12/06 09:58:01 manu Exp $ -SHA1 (mod_auth_mellon-0.3.0.tar.gz) = 658dda51652f491552f2ecc84572ed7750f914ff -RMD160 (mod_auth_mellon-0.3.0.tar.gz) = 69237b1ec266018a86e7134a4662b491af3c261e -Size (mod_auth_mellon-0.3.0.tar.gz) = 92252 bytes -SHA1 (patch-ac) = 7976528d9c77b8e30accf60edc958db53ac5e8fb -SHA1 (patch-ad) = a1bebae20bfbb99bd71d68de19901eaef6c52dbd -SHA1 (patch-ae) = d51040b6d827940a2c3cf8928dee175efa946e37 -SHA1 (patch-af) = 0803665a14df8582ac20d950a070f73d794b08ea -SHA1 (patch-ag) = c1ef8704268d99b01d1e96fc2da9be74a7726b9d -SHA1 (patch-ah) = 6287c038aee79e66539dda12ff447dfd5d9529bf +SHA1 (mod_auth_mellon-0.4.0.tar.gz) = d09f7bbefe32c2eaa624612584eab1ea8e89820a +RMD160 (mod_auth_mellon-0.4.0.tar.gz) = 92ef003ae22c43ef81d22f5027486244e76e3d3f +Size (mod_auth_mellon-0.4.0.tar.gz) = 103708 bytes +SHA1 (patch-ai) = a7a4f729301bff79cb39d441f9fa48993cdc2899 diff --git a/www/ap2-auth-mellon/patches/patch-ac b/www/ap2-auth-mellon/patches/patch-ac deleted file mode 100644 index 91a7d3d5b22..00000000000 --- a/www/ap2-auth-mellon/patches/patch-ac +++ /dev/null @@ -1,515 +0,0 @@ -$NetBSD: patch-ac,v 1.1 2011/04/04 08:46:42 manu Exp $ - -Add MellonCond directive (pulled up from upstream) - -Index: auth_mellon_util.c -=================================================================== ---- auth_mellon_util.c (revision 113) -+++ auth_mellon_util.c (working copy) -@@ -51,7 +51,7 @@ - - - /* This function checks if the user has access according -- * to the MellonRequire directives. -+ * to the MellonRequire and MellonCond directives. - * - * Parameters: - * request_rec *r The current request. -@@ -63,51 +63,105 @@ - int am_check_permissions(request_rec *r, am_cache_entry_t *session) - { - am_dir_cfg_rec *dir_cfg; -- apr_hash_index_t *idx; -- const char *key; -- apr_array_header_t *rlist; - int i, j; -- int rlist_ok; -- const char **re; -+ int skip_or = 0; - - dir_cfg = am_get_dir_cfg(r); - -- /* Iterate over all require-directives. */ -- for(idx = apr_hash_first(r->pool, dir_cfg->require); -- idx != NULL; -- idx = apr_hash_next(idx)) { -+ /* Iterate over all cond-directives */ -+ for (i = 0; i < dir_cfg->cond->nelts; i++) { -+ am_cond_t *ce; -+ const char *value = NULL; -+ int match = 0; - -- /* Get current require directive. key will be the name -- * of the attribute, and rlist is a list of all allowed values. -+ ce = &((am_cond_t *)(dir_cfg->cond->elts))[i]; -+ -+ /* -+ * Rule with ignore flog? - */ -- apr_hash_this(idx, (const void **)&key, NULL, (void **)&rlist); -+ if (ce->flags & AM_COND_FLAG_IGN) -+ continue; - -- /* Reset status to 0 before search. */ -- rlist_ok = 0; -+ /* -+ * We matched a [OR] rule, skip the next rules -+ * until we have one without [OR]. -+ */ -+ if (skip_or) { -+ if (!(ce->flags & AM_COND_FLAG_OR)) -+ skip_or = 0; - -- re = (const char **)rlist->elts; -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, -+ "Skip %s, [OR] rule matched previously", -+ ce->directive); -+ continue; -+ } -+ -+ /* -+ * look for a match on each value for this attribute, -+ * stop on first match. -+ */ -+ for (j = 0; (j < session->size) && !match; j++) { -+ const char *varname = NULL; - -- /* rlist is an array of all the valid values for this attribute. */ -- for(i = 0; i < rlist->nelts && !rlist_ok; i++) { -+ /* -+ * if MAP flag is set, check for remapped -+ * attribute name with mellonSetEnv -+ */ -+ if (ce->flags & AM_COND_FLAG_MAP) -+ varname = apr_hash_get(dir_cfg->envattr, -+ session->env[j].varname, -+ APR_HASH_KEY_STRING); - -- /* Search for a matching attribute in the session data. */ -- for(j = 0; j < session->size && !rlist_ok; j++) { -- if(strcmp(session->env[j].varname, key) == 0 && -- strcmp(session->env[j].value, re[i]) == 0) { -- /* We found a attribute with the correct name -- * and value. -- */ -- rlist_ok = 1; -- } -+ /* -+ * Otherwise or if not found, use the attribute name -+ * sent by the IdP. -+ */ -+ if (varname == NULL) -+ varname = session->env[j].varname; -+ -+ if (strcmp(varname, ce->varname) != 0) -+ continue; -+ -+ value = session->env[j].value; -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, -+ "Evaluate %s vs \"%s\"", -+ ce->directive, value); -+ -+ if (value == NULL) { -+ match = 0; /* can not happen */ -+ } else if (ce->flags & AM_COND_FLAG_REG) { -+ match = !ap_regexec(ce->regex, value, 0, NULL, 0); -+ } else if (ce->flags & AM_COND_FLAG_NC) { -+ match = !strcasecmp(ce->str, value); -+ } else { -+ match = !strcmp(ce->str, value); - } - } - -- if(!rlist_ok) { -- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, -- "Client failed to match required attribute \"%s\".", -- key); -+ if (ce->flags & AM_COND_FLAG_NOT) -+ match = !match; -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, -+ "%s: %smatch", ce->directive, -+ (match == 0) ? "no ": ""); -+ -+ /* -+ * If no match, we stop here, except if it is an [OR] condition -+ */ -+ if (!match & !(ce->flags & AM_COND_FLAG_OR)) { -+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, -+ "Client failed to match %s", -+ ce->directive); - return HTTP_FORBIDDEN; - } -+ -+ /* -+ * Match on [OR] condition means we skip until a rule -+ * without [OR], -+ */ -+ if (match && (ce->flags & AM_COND_FLAG_OR)) -+ skip_or = 1; - } - - return OK; -Index: README -=================================================================== ---- README (revision 113) -+++ README (working copy) -@@ -152,9 +152,9 @@ - # "auth": We will populate the environment with information about - # the user if he is authorized. If he is authenticated - # (logged in), but not authorized (according to the -- # MellonRequire directives, then we will return a 403 -- # Forbidden error. If he isn't authenticated then we will -- # redirect him to the login page of the IdP. -+ # MellonRequire and MellonCond directives, then we will -+ # return a 403 Forbidden error. If he isn't authenticated -+ # then we will redirect him to the login page of the IdP. - # - # Default: MellonEnable "off" - MellonEnable "auth" -@@ -221,14 +221,45 @@ - # Note that the attribute name is the name we received from the - # IdP. - # -- # If you don't list any MellonRequire directives, then any user -- # authenticated by the IdP will have access to this service. If -- # you list several MellonRequire directives, then all of them -- # will have to match. -+ # If you don't list any MellonRequire directives (and any -+ # MellonCond directives, see below), then any user authenticated -+ # by the IdP will have access to this service. If you list several -+ # MellonRequire directives, then all of them will have to match. -+ # If you use multiple MellonRequire directive on the same -+ # attribute, the last overrides the previous ones. - # - # Default: None set. - MellonRequire "eduPersonAffiliation" "student" "employee" - -+ # MellonCond provides the same function as MellonRequire, with -+ # extra functionnality (MellonRequire is retained for backward -+ # compatibility). The syntax is -+ # 'MellonCond []' -+ # -+ # is an optional, comma-separated list of option -+ # encloseed with brackets. Here is an example: [NOT,NC] -+ # The valid options are: -+ # OR If this MellonCond evaluted to false, then the -+ # next one will be checked. If it evalutes to true, -+ # then the overall check succeeds. -+ # NOT This MellonCond evaluates to true if the attribute -+ # does not match the value. -+ # REG Value to check is a regular expression. -+ # NC Perform case insensitive match. -+ # MAP Attempt to search an attribute with name remapped by -+ # MellonSetEnv. Fallback to non remapped name if not -+ # found. -+ # -+ # It is allowed to have multiple MellonCond on the same -+ # attribute, and to mix MellonCond and MellonRequire. -+ # Note that this can create tricky situations, since the OR -+ # option has effect on a following MellonRequire directive. -+ # -+ # Default: none set -+ # MellonCond "mail" "@example\.net$" [OR,REG] -+ # MellonCond "mail" "@example\.com$" [OR,REG] -+ # MellonCond "uid" "superuser" -+ - # MellonEndpointPath selects which directory mod_auth_mellon - # should assume contains the SAML 2.0 endpoints. Any request to - # this directory will be handled by mod_auth_mellon. -Index: auth_mellon.h -=================================================================== ---- auth_mellon.h (revision 113) -+++ auth_mellon.h (working copy) -@@ -124,6 +124,30 @@ - am_decoder_feide, - } am_decoder_t; - -+typedef enum { -+ AM_COND_FLAG_NULL = 0x00, /* No flags */ -+ AM_COND_FLAG_OR = 0x01, /* Or with next condition */ -+ AM_COND_FLAG_NOT = 0x02, /* Negate this condition */ -+ AM_COND_FLAG_REG = 0x04, /* Condition is regex */ -+ AM_COND_FLAG_NC = 0x08, /* Case insensitive match */ -+ AM_COND_FLAG_MAP = 0x10, /* Try to use attribute name from MellonSetEnv */ -+ AM_COND_FLAG_IGN = 0x20, /* Condition is to be ignored */ -+ AM_COND_FLAG_REQ = 0x40, /* Condition was configure using MellonRequire */ -+} am_cond_flag_t; -+ -+/* Not counting AM_COND_FLAG_NULL */ -+#define AM_COND_FLAG_COUNT 7 -+ -+extern const char *am_cond_options[]; -+ -+typedef struct { -+ const char *varname; -+ int flags; -+ const char *str; -+ ap_regex_t *regex; -+ const char *directive; -+} am_cond_t; -+ - typedef struct am_dir_cfg_rec { - /* enable_mellon is used to enable auth_mellon for a location. - */ -@@ -136,7 +160,7 @@ - - const char *varname; - int secure; -- apr_hash_t *require; -+ apr_array_header_t *cond; - apr_hash_t *envattr; - const char *userattr; - const char *idpattr; -Index: auth_mellon_config.c -=================================================================== ---- auth_mellon_config.c (revision 113) -+++ auth_mellon_config.c (working copy) -@@ -422,7 +422,136 @@ - return NULL; - } - -+/* This function decodes MellonCond flags, such as [NOT,REG] -+ * -+ * Parameters: -+ * const char *arg Pointer to the flags string -+ * -+ * Returns: -+ * flags, or -1 on error -+ */ -+const char *am_cond_options[] = { -+ "OR", /* AM_EXPIRE_FLAG_OR */ -+ "NOT", /* AM_EXPIRE_FLAG_NOT */ -+ "REG", /* AM_EXPIRE_FLAG_REG */ -+ "NC", /* AM_EXPIRE_FLAG_NC */ -+ "MAP", /* AM_EXPIRE_FLAG_MAP */ -+ "IGN", /* AM_EXPIRE_FLAG_IGN */ -+ "REQ", /* AM_EXPIRE_FLAG_REQ */ -+}; - -+static int am_cond_flags(const char *arg) -+{ -+ int flags = AM_COND_FLAG_NULL; -+ -+ /* Skip inital [ */ -+ if (arg[0] == '[') -+ arg++; -+ else -+ return -1; -+ -+ do { -+ apr_size_t i; -+ -+ for (i = 0; i < AM_COND_FLAG_COUNT; i++) { -+ apr_size_t optlen = strlen(am_cond_options[i]); -+ -+ if (strncmp(arg, am_cond_options[i], optlen) == 0) { -+ /* Make sure we have a separator next */ -+ if (arg[optlen] && !strchr("]\t ,", (int)arg[optlen])) -+ return -1; -+ -+ flags |= (1 << i); -+ arg += optlen; -+ break; -+ } -+ -+ /* no match */ -+ if (i == AM_COND_FLAG_COUNT) -+ return -1; -+ -+ /* skip spaces, tabs and commas */ -+ arg += strspn(arg, " \t,"); -+ -+ /* Garbage after ] is ignored */ -+ if (*arg == ']') -+ return flags; -+ } -+ } while (*arg); -+ -+ /* Missing trailing ] */ -+ return -1; -+} -+ -+/* This function handles the MellonCond configuration directive, which -+ * allows the user to restrict access based on attributes received from -+ * the IdP. -+ * -+ * Parameters: -+ * cmd_parms *cmd The command structure for the MellonCond -+ * configuration directive. -+ * void *struct_ptr Pointer to the current directory configuration. -+ * const char *attribute Pointer to the attribute name -+ * const char *value Pointer to the attribute value or regex -+ * const char *options Pointer to options -+ * -+ * Returns: -+ * NULL on success or an error string on failure. -+ */ -+static const char *am_set_cond_slot(cmd_parms *cmd, -+ void *struct_ptr, -+ const char *attribute, -+ const char *value, -+ const char *options) -+{ -+ am_dir_cfg_rec *d = struct_ptr; -+ am_cond_t *element; -+ -+ if (*attribute == '\0' || *value == '\0') -+ return apr_pstrcat(cmd->pool, cmd->cmd->name, -+ " takes two or three arguments", NULL); -+ -+ element = (am_cond_t *)apr_array_push(d->cond); -+ element->varname = attribute; -+ element->flags = AM_COND_FLAG_NULL; -+ element->str = NULL; -+ element->regex = NULL; -+ element->directive = apr_pstrcat(cmd->pool, cmd->directive->directive, -+ " ", cmd->directive->args, NULL); -+ -+ /* Handle optional flags */ -+ if (*options != '\0') { -+ int flags; -+ -+ flags = am_cond_flags(options); -+ if (flags == -1) -+ return apr_psprintf(cmd->pool, "%s - invalid flags %s", -+ cmd->cmd->name, options); -+ -+ element->flags = flags; -+ } -+ -+ if (element->flags & AM_COND_FLAG_REG) { -+ int regex_flags = AP_REG_EXTENDED|AP_REG_NOSUB; -+ -+ if (element->flags & AM_COND_FLAG_NC) -+ regex_flags |= AP_REG_ICASE; -+ -+ element->regex = ap_pregcomp(cmd->pool, value, regex_flags); -+ if (element->regex == NULL) -+ return apr_psprintf(cmd->pool, "%s - invalid regex %s", -+ cmd->cmd->name, value); -+ } -+ -+ /* -+ * We keep the string also for regex, so that we can -+ * print it for debug purpose. -+ */ -+ element->str = value; -+ -+ return NULL; -+} -+ - /* This function handles the MellonRequire configuration directive, which - * allows the user to restrict access based on attributes received from - * the IdP. -@@ -440,10 +569,11 @@ - void *struct_ptr, - const char *arg) - { -- apr_array_header_t *r; - am_dir_cfg_rec *d = struct_ptr; - char *attribute, *value; -- const char **element; -+ int i; -+ am_cond_t *element; -+ am_cond_t *first_element; - - attribute = ap_getword_conf(cmd->pool, &arg); - value = ap_getword_conf(cmd->pool, &arg); -@@ -453,20 +583,47 @@ - " takes at least two arguments", NULL); - } - -+ /* -+ * MellonRequire overwrites previous conditions on this attribute -+ * We just tag the am_cond_t with the ignore flag, as it is -+ * easier (and probably faster) than to really remove it. -+ */ -+ for (i = 0; i < d->cond->nelts; i++) { -+ am_cond_t *ce = &((am_cond_t *)(d->cond->elts))[i]; -+ -+ if ((strcmp(ce->varname, attribute) == 0) && -+ (ce->flags & AM_COND_FLAG_REQ)) -+ ce->flags |= AM_COND_FLAG_IGN; -+ } -+ -+ first_element = NULL; - do { -- r = (apr_array_header_t *)apr_hash_get(d->require, attribute, -- APR_HASH_KEY_STRING); -+ element = (am_cond_t *)apr_array_push(d->cond); -+ element->varname = attribute; -+ element->flags = AM_COND_FLAG_OR|AM_COND_FLAG_REQ; -+ element->str = value; -+ element->regex = NULL; - -- if (r == NULL) { -- r = apr_array_make(cmd->pool, 2, sizeof(const char *)); -- apr_hash_set(d->require, attribute, APR_HASH_KEY_STRING, r); -+ /* -+ * When multiple values are given, we track the first one -+ * in order to retreive the directive -+ */ -+ if (first_element == NULL) { -+ element->directive = apr_pstrcat(cmd->pool, -+ cmd->directive->directive, " ", -+ cmd->directive->args, NULL); -+ first_element = element; -+ } else { -+ element->directive = first_element->directive; - } - -- element = (const char **)apr_array_push(r); -- *element = value; -- - } while (*(value = ap_getword_conf(cmd->pool, &arg)) != '\0'); - -+ /* -+ * Remove OR flag on last element -+ */ -+ element->flags &= ~AM_COND_FLAG_OR; -+ - return NULL; - } - -@@ -650,6 +807,15 @@ - " for the attribute. The syntax is:" - " MellonRequire [value2....]." - ), -+ AP_INIT_TAKE23( -+ "MellonCond", -+ am_set_cond_slot, -+ NULL, -+ OR_AUTHCFG, -+ "Attribute requirements for authorization. Allows you to restrict" -+ " access based on attributes received from the IdP. The syntax is:" -+ " MellonRequire []." -+ ), - AP_INIT_TAKE1( - "MellonSessionLength", - ap_set_int_slot, -@@ -795,7 +961,7 @@ - - dir->varname = default_cookie_name; - dir->secure = default_secure_cookie; -- dir->require = apr_hash_make(p); -+ dir->cond = apr_array_make(p, 0, sizeof(am_cond_t)); - dir->envattr = apr_hash_make(p); - dir->userattr = default_user_attribute; - dir->idpattr = NULL; -@@ -871,10 +1037,10 @@ - base_cfg->secure); - - -- new_cfg->require = apr_hash_copy(p, -- (apr_hash_count(add_cfg->require) > 0) ? -- add_cfg->require : -- base_cfg->require); -+ new_cfg->cond = apr_array_copy(p, -+ (!apr_is_empty_array(add_cfg->cond)) ? -+ add_cfg->cond : -+ base_cfg->cond); - - new_cfg->envattr = apr_hash_copy(p, - (apr_hash_count(add_cfg->envattr) > 0) ? diff --git a/www/ap2-auth-mellon/patches/patch-ae b/www/ap2-auth-mellon/patches/patch-ae deleted file mode 100644 index a1f5ba5667f..00000000000 --- a/www/ap2-auth-mellon/patches/patch-ae +++ /dev/null @@ -1,523 +0,0 @@ -$NetBSD: patch-ae,v 1.1 2011/04/04 08:46:42 manu Exp $ - -Replace buildtin: diescovery URL by the discoProbe endpoint (pulled from -upstream) - -Index: auth_mellon_handler.c -=================================================================== ---- auth_mellon_handler.c (revision 112) -+++ auth_mellon_handler.c (working copy) -@@ -226,34 +226,7 @@ - return provider_id; - } - --/* This returns built-in IdP discovery timeout -- * -- * Parameters: -- * request_rec *r The request we received. -- * -- * Returns: -- * the timeout, -1 if not enabled. -- */ --static long am_builtin_discovery_timeout(request_rec *r) --{ -- am_dir_cfg_rec *cfg = am_get_dir_cfg(r); -- const char *builtin = "builtin:get-metadata"; -- const char *timeout = "?timeout="; -- const char *cp; -- const long default_timeout = 1L; - -- if ((cfg->discovery_url == NULL) || -- (strncmp(cfg->discovery_url, builtin, strlen(builtin)) != 0)) -- return -1; -- -- cp = cfg->discovery_url + strlen(builtin); -- if (strncmp(cp, timeout, strlen(timeout)) != 0) -- return default_timeout; -- -- cp += strlen(timeout); -- return atoi(cp); --} -- - /* This function selects an IdP and returns its provider_id - * - * Parameters: -@@ -267,8 +240,6 @@ - am_dir_cfg_rec *cfg = am_get_dir_cfg(r); - const char *idp_provider_id; - const char *idp_metadata_file; -- apr_hash_index_t *index; -- long timeout; - - /* - * If we have a single IdP, return that one. -@@ -308,47 +279,6 @@ - return idp_provider_id; - } - -- /* -- * If built-in IdP discovery is not configured, return default. -- */ -- timeout = am_builtin_discovery_timeout(r); -- if (timeout == -1) -- return am_first_idp(r); -- -- /* -- * Otherwise, proceed with built-in IdP discovery: -- * send probes for all configures IdP to check availability. -- * The first to answer is chosen. On error, use default. -- */ -- for (index = apr_hash_first(r->pool, cfg->idp_metadata_files); -- index; -- index = apr_hash_next(index)) { -- void *buffer; -- apr_size_t len; -- apr_ssize_t slen; -- long status; -- -- apr_hash_this(index, -- (const void **)&idp_provider_id, -- &slen, -- (void *)&idp_metadata_file); -- -- status = 0; -- if (am_httpclient_get(r, idp_provider_id, &buffer, &len, -- timeout, &status) != OK) -- continue; -- -- if (status != HTTP_OK) { -- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -- "Cannot probe %s: IdP returned HTTP %ld", -- idp_provider_id, status); -- continue; -- } -- -- /* We got some succes */ -- return idp_provider_id; -- } -- - /* - * No IdP answered, use default - * Perhaps we should redirect to an error page instead. -@@ -2506,7 +2436,6 @@ - - /* Check if IdP discovery is in use and no IdP was selected yet */ - if ((cfg->discovery_url != NULL) && -- (am_builtin_discovery_timeout(r) == -1) && /* no built-in discovery */ - (am_extract_query_parameter(r->pool, r->args, "IdP") == NULL)) { - char *discovery_url; - char *return_url; -@@ -2536,8 +2465,7 @@ - /* If IdP discovery is in use and we have an IdP selected, - * set the relay_state - */ -- if ((cfg->discovery_url != NULL) && -- (am_builtin_discovery_timeout(r) == -1)) { /* no built-in discovery */ -+ if (cfg->discovery_url != NULL) { - char *return_url; - - return_url = am_extract_query_parameter(r->pool, r->args, "ReturnTo"); -@@ -2615,7 +2543,151 @@ - return am_send_authn_request(r, idp, return_to, is_passive); - } - -+/* This function handles requests to the probe discovery handler -+ * -+ * Parameters: -+ * request_rec *r The request. -+ * -+ * Returns: -+ * OK on success, or an error if any of the steps fail. -+ */ -+static int am_handle_probe_discovery(request_rec *r) { -+ am_dir_cfg_rec *cfg = am_get_dir_cfg(r); -+ const char *idp = NULL; -+ int timeout; -+ apr_hash_index_t *index; -+ char *return_to; -+ char *idp_param; -+ char *redirect_url; -+ int ret; - -+ /* -+ * If built-in IdP discovery is not configured, return error. -+ * For now we only have the get-metadata metadata method, so this -+ * information is not saved in configuration nor it is checked here. -+ */ -+ timeout = cfg->probe_discovery_timeout; -+ if (timeout == -1) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "probe discovery handler invoked but not " -+ "configured. Plase set MellonProbeDiscoveryTimeout."); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ -+ /* -+ * Check for mandatory arguments early to avoid sending -+ * probles for nothing. -+ */ -+ return_to = am_extract_query_parameter(r->pool, r->args, "return"); -+ if(return_to == NULL) { -+ ap_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, -+ "Could not urldecode return value."); -+ return HTTP_BAD_REQUEST; -+ } -+ -+ idp_param = am_extract_query_parameter(r->pool, r->args, "returnIDParam"); -+ if(idp_param == NULL) { -+ ap_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, -+ "Could not urldecode returnIDParam value."); -+ return HTTP_BAD_REQUEST; -+ } -+ -+ /* -+ * Proceed with built-in IdP discovery. -+ * -+ * Send probes for all configured IdP to check availability. -+ * The first to answer is chosen, but the list of usable -+ * IdP can be restricted in configuration. -+ */ -+ for (index = apr_hash_first(r->pool, cfg->idp_metadata_files); -+ index; -+ index = apr_hash_next(index)) { -+ void *dontcare; -+ const char *ping_url; -+ apr_size_t len; -+ apr_ssize_t slen; -+ long status; -+ -+ apr_hash_this(index, (const void **)&idp, -+ &slen, (void *)&dontcare); -+ ping_url = idp; -+ -+ /* -+ * If a list of IdP was given for probe discovery, -+ * skip any IdP that does not match. -+ */ -+ if (apr_hash_count(cfg->probe_discovery_idp) != 0) { -+ char *value = apr_hash_get(cfg->probe_discovery_idp, -+ idp, APR_HASH_KEY_STRING); -+ -+ if (value == NULL) { -+ /* idp not in list, try the next one */ -+ idp = NULL; -+ continue; -+ } else { -+ /* idp in list, use the value as the ping url */ -+ ping_url = value; -+ } -+ } -+ -+ status = 0; -+ if (am_httpclient_get(r, ping_url, &dontcare, &len, -+ timeout, &status) != OK) -+ continue; -+ -+ if (status != HTTP_OK) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "Cannot probe %s: \"%s\" returned HTTP %ld", -+ idp, ping_url, status); -+ continue; -+ } -+ -+ /* We got some succes */ -+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, -+ "probeDiscovery using %s", idp); -+ break; -+ } -+ -+ /* -+ * On failure, try default -+ */ -+ if (idp == NULL) { -+ idp = am_first_idp(r); -+ if (idp == NULL) { -+ ap_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 " -+ "failed, trying default IdP %s", idp); -+ } -+ } -+ -+ redirect_url = apr_psprintf(r->pool, "%s%s%s=%s", return_to, -+ strchr(return_to, '?') ? "&" : "?", -+ am_urlencode(r->pool, idp_param), -+ am_urlencode(r->pool, idp)); -+ -+ apr_table_setn(r->headers_out, "Location", redirect_url); -+ -+ return HTTP_SEE_OTHER; -+} -+ -+ - /* This function takes a request for an endpoint and passes it on to the - * correct handler function. - * -@@ -2656,6 +2728,8 @@ - return am_handle_logout(r); - } else if(!strcmp(endpoint, "login")) { - return am_handle_login(r); -+ } else if(!strcmp(endpoint, "probeDisco")) { -+ return am_handle_probe_discovery(r); - } else { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Endpoint \"%s\" not handled by mod_auth_mellon.", -Index: auth_mellon.h -=================================================================== ---- auth_mellon.h (revision 112) -+++ auth_mellon.h (working copy) -@@ -174,6 +174,8 @@ - - /* IdP discovery service */ - const char *discovery_url; -+ int probe_discovery_timeout; -+ apr_hash_t *probe_discovery_idp; - - /* Mutex to prevent us from creating several lasso server objects. */ - apr_thread_mutex_t *server_mutex; -Index: README -=================================================================== ---- README (revision 112) -+++ README (working copy) -@@ -321,8 +321,17 @@ - # The IdP discovery must redirect the user to the return URL, - # with retueniDParam set to the selected IdP providerID. - # -- # Alternatively, a simple built-in IdP discovery can be used, -- # by specifying "builtin:get-metadata?timeout=1" -+ # The builtin:get-metadata discovery URL is not supported anymore -+ # starting with 0.3.1. See MellonProbeDiscoveryTimeout for -+ # a replacement. -+ # -+ # Default: None set. -+ MellonDiscoveryURL "http://www.example.net/idp-discovery" -+ -+ # MellonProbeDiscoveryTimeout sets the timeout of the -+ # IdP probe discovery service, which is available on the -+ # probeDisco endoint. -+ # - # This will cause the SP to send HTTP GET requests on the - # configured IdP PorviderID URL. Theses URL should be used to - # publish metadata, though this is not mandatory. If the IdP -@@ -330,9 +339,17 @@ - # If the PorviderID URL requires SSL, MellonIdPCAFile is used - # as a trusted CA bundle. - # -- # Default: None set. -- MellonDiscoveryURL "http://www.example.net/idp-discovery" -+ # Default: unset, which means the feature is disabled -+ # MellonProbeDiscoveryTimeout 1 - -+ # MellonProbeDiscoveryIdP can be used to restrict the -+ # list of IdP queried by the IdP probe discovery service. -+ # -+ # Default unset, which means that all configured IdP are -+ # queried. -+ # MellonProbeDiscoveryIdP http://idp1.example.com/saml/metadata -+ # MellonProbeDiscoveryIdP http://idp2.example.net/saml/metadata -+ - # This option will make the SAML authentication assertion - # available in the MELLON_SAML_RESPONSE environement - # variable. This assertion holds a verifiable signature -@@ -476,7 +493,39 @@ - This will return the user to "https://www.example.org/logged_out.html" - after the logout operation has completed. - -+=========================================================================== -+ Probe IdP discovery -+=========================================================================== - -+mod_auth_mellon has an IdP probe discovery service that sends HTTP GET -+to IdP and picks the first that answers. This can be used as a poor -+man's failover setup that redirects to your organisation internal IdP. -+Here is a sample configuration: -+ -+ MellonEndpointPath "/saml" -+ (...) -+ MellonDiscoveryUrl "/saml/probeDisco" -+ MellonProbeDiscoveryTimeout 1 -+ -+The SP will sends HTTP GET to each configured IdP providerId URL until -+it gets an HTTP 200 response within the 1 second timeout. It will then -+proceed with that IdP. -+ -+If you are in a federation, then your IdP login page will need to provide -+an IdP selection feature aimed at users from other institutions (after -+such a choice, the user would be redirected to the SP's /saml/login -+endpoint, with ReturnTo and IdP set appropriately). In such a setup, -+you will want to configure external IdP in mod_auth_mellon, but not -+use them for IdP probe discovery. The MellonProbeDiscoveryIdP -+directive can be used to limit the usable IdP for probe discovery: -+ -+ MellonEndpointPath "/saml" -+ (...) -+ MellonDiscoveryUrl "/saml/probeDisco" -+ MellonProbeDiscoveryTimeout 1 -+ MellonProbeDiscoveryIdP "https://idp1.example.net/saml/metadata" -+ MellonProbeDiscoveryIdP "https://idp2.example.net/saml/metadata" -+ - =========================================================================== - Contributors - =========================================================================== -Index: auth_mellon_config.c -=================================================================== ---- auth_mellon_config.c (revision 112) -+++ auth_mellon_config.c (working copy) -@@ -76,6 +76,47 @@ - */ - static const int post_count = 100; - -+/* This function handles configuration directives which set a -+ * multivalued string slot in the module configuration (the destination -+ * strucure is a hash). -+ * -+ * 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 *key The string argument following this configuration -+ * directive in the configuraion file. -+ * const char *value Optional value to be stored in the hash. -+ * -+ * Returns: -+ * NULL on success or an error string on failure. -+ */ -+static const char *am_set_hash_string_slot(cmd_parms *cmd, -+ void *struct_ptr, -+ const char *key, -+ const char *value) -+{ -+ server_rec *s = cmd->server; -+ apr_pool_t *pconf = s->process->pconf; -+ am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr; -+ int offset; -+ apr_hash_t **hash; -+ -+ /* -+ * If no value is given, we just store the key in the hash. -+ */ -+ if (value == NULL || *value == '\0') -+ value = key; -+ -+ offset = (int)(long)cmd->info; -+ hash = (apr_hash_t **)((char *)cfg + offset); -+ apr_hash_set(*hash, apr_pstrdup(pconf, key), APR_HASH_KEY_STRING, value); -+ -+ 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. -@@ -133,10 +174,10 @@ - * NULL on success or an error string on failure. - * - */ --static const char *am_get_proovider_id(apr_pool_t *p, -- server_rec *s, -- const char *file, -- const char **provider) -+static const char *am_get_provider_id(apr_pool_t *p, -+ server_rec *s, -+ const char *file, -+ const char **provider) - { - char *data; - apr_xml_parser *xp; -@@ -195,7 +236,7 @@ - * Returns: - * NULL on success or an error string on failure. - */ --static const char *ap_set_idp_string_slot(cmd_parms *cmd, -+static const char *am_set_idp_string_slot(cmd_parms *cmd, - void *struct_ptr, - const char *arg) - { -@@ -205,8 +246,8 @@ - const char *error; - const char *provider_id; - -- if ((error = am_get_proovider_id(cmd->pool, s, -- arg, &provider_id)) != NULL) -+ if ((error = am_get_provider_id(cmd->pool, s, -+ arg, &provider_id)) != NULL) - return apr_psprintf(cmd->pool, "%s - %s", cmd->cmd->name, error); - - apr_hash_set(cfg->idp_metadata_files, -@@ -649,8 +690,8 @@ - ), - AP_INIT_TAKE1( - "MellonIdPMetadataFile", -- ap_set_idp_string_slot, -- NULL, -+ am_set_idp_string_slot, -+ NULL, - OR_AUTHCFG, - "Full path to xml metadata file for the IdP." - ), -@@ -705,6 +746,21 @@ - "The URL of IdP discovery service. Default is unset." - ), - AP_INIT_TAKE1( -+ "MellonProbeDiscoveryTimeout", -+ ap_set_int_slot, -+ (void *)APR_OFFSETOF(am_dir_cfg_rec, probe_discovery_timeout), -+ OR_AUTHCFG, -+ "The timeout of IdP probe discovery service. " -+ "Default is 1s" -+ ), -+ AP_INIT_TAKE12( -+ "MellonProbeDiscoveryIdP", -+ am_set_hash_string_slot, -+ (void *)APR_OFFSETOF(am_dir_cfg_rec, probe_discovery_idp), -+ OR_AUTHCFG, -+ "An IdP that can be used for IdP probe discovery." -+ ), -+ AP_INIT_TAKE1( - "MellonEndpointPath", - am_set_endpoint_path, - NULL, -@@ -760,6 +816,8 @@ - dir->idp_ca_file = NULL; - dir->login_path = default_login_path; - dir->discovery_url = NULL; -+ dir->probe_discovery_timeout = -1; /* -1 means no probe discovery */ -+ dir->probe_discovery_idp = apr_hash_make(p); - - dir->sp_org_name = apr_hash_make(p); - dir->sp_org_display_name = apr_hash_make(p); -@@ -903,6 +961,16 @@ - add_cfg->discovery_url : - base_cfg->discovery_url); - -+ new_cfg->probe_discovery_timeout = -+ (add_cfg->probe_discovery_timeout != -1 ? -+ add_cfg->probe_discovery_timeout : -+ base_cfg->probe_discovery_timeout); -+ -+ new_cfg->probe_discovery_idp = apr_hash_copy(p, -+ (apr_hash_count(add_cfg->probe_discovery_idp) > 0) ? -+ add_cfg->probe_discovery_idp : -+ base_cfg->probe_discovery_idp); -+ - apr_thread_mutex_create(&new_cfg->server_mutex, - APR_THREAD_MUTEX_DEFAULT, p); - new_cfg->server = NULL; diff --git a/www/ap2-auth-mellon/patches/patch-af b/www/ap2-auth-mellon/patches/patch-af deleted file mode 100644 index 59bbf9caefb..00000000000 --- a/www/ap2-auth-mellon/patches/patch-af +++ /dev/null @@ -1,65 +0,0 @@ -$NetBSD: patch-af,v 1.1 2011/04/04 08:46:42 manu Exp $ - -Make remapped attribute usable for MellonUser - ---- auth_mellon_cache.c.orig 2011-02-28 17:12:42.000000000 +0100 -+++ auth_mellon_cache.c 2011-02-28 17:59:02.000000000 +0100 -@@ -367,21 +367,8 @@ - } - } - } - -- if(t->user[0] != '\0') { -- /* We have a user-"name". Set r->user and r->ap_auth_type. */ -- r->user = apr_pstrdup(r->pool, t->user); -- 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, -- "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.", -- d->userattr); -- } -- - /* Allocate a set of counters for duplicate variables in the list. */ - counters = apr_hash_make(r->pool); - - /* Populate the subprocess environment with the attributes we -@@ -398,8 +385,13 @@ - } - - value = t->env[i].value; - -+ /* -+ * If we find a variable remapping to MellonUser, use it. -+ */ -+ if ((t->user[0] == '\0') && (strcmp(varname, d->userattr) == 0)) -+ strcpy(t->user, value); - - /* Find the number of times this variable has been set. */ - count = apr_hash_get(counters, varname, APR_HASH_KEY_STRING); - if(count == NULL) { -@@ -425,8 +417,22 @@ - /* Increase the count. */ - ++(*count); - } - -+ if(t->user[0] != '\0') { -+ /* We have a user-"name". Set r->user and r->ap_auth_type. */ -+ r->user = apr_pstrdup(r->pool, t->user); -+ 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, -+ "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.", -+ d->userattr); -+ } -+ -+ - /* Populate with the session? */ - if (d->dump_session) { - char *session; - int srclen, dstlen; diff --git a/www/ap2-auth-mellon/patches/patch-ag b/www/ap2-auth-mellon/patches/patch-ag deleted file mode 100644 index 8790d1f82f8..00000000000 --- a/www/ap2-auth-mellon/patches/patch-ag +++ /dev/null @@ -1,149 +0,0 @@ -$NetBSD: patch-ag,v 1.1 2011/04/04 08:46:42 manu Exp $ - -Add the MellonIdPMetadataGlob directive (pulled from upstream) - -Index: auth_mellon_util.c -=================================================================== ---- auth_mellon_util.c (revision 116) -+++ auth_mellon_util.c (working copy) -@@ -838,6 +838,31 @@ - return ret; - } - -+/* This returns the directroy part of a path, a la dirname(3) -+ * -+ * Parameters: -+ * apr_pool_t p Pool to allocate memory from -+ * const char *path Path to extract directory from -+ * -+ * Returns: -+ * The directory part of path -+ */ -+const char *am_filepath_dirname(apr_pool_t *p, const char *path) -+{ -+ char *cp; -+ -+ /* -+ * Try Unix and then Windows style. Borrowed from -+ * apr_match_glob(), it seems it cannot be made more -+ * portable. -+ */ -+ if (((cp = strrchr(path, (int)'/')) == NULL) && -+ ((cp = strrchr(path, (int)'\\')) == NULL)) -+ return "."; -+ -+ return apr_pstrndup(p, path, cp - path); -+} -+ - /* - * malloc a buffer and fill it with a given file - * -Index: auth_mellon.h -=================================================================== ---- auth_mellon.h (revision 116) -+++ auth_mellon.h (working copy) -@@ -52,6 +52,7 @@ - #include "apr_file_io.h" - #include "apr_xml.h" - #include "apr_lib.h" -+#include "apr_fnmatch.h" - - #include "ap_config.h" - #include "httpd.h" -@@ -296,6 +297,7 @@ - int am_postdir_cleanup(request_rec *s); - char *am_htmlencode(request_rec *r, const char *str); - int am_save_post(request_rec *r, const char **relay_state); -+const char *am_filepath_dirname(apr_pool_t *p, const char *path); - const char *am_strip_cr(request_rec *r, const char *str); - const char *am_add_cr(request_rec *r, const char *str); - const char *am_xstrtok(request_rec *r, const char *str, -Index: README -=================================================================== ---- README (revision 116) -+++ README (working copy) -@@ -349,6 +349,11 @@ - # Default: None set. - MellonIdPMetadataFile /etc/apache2/mellon/idp-metadata.xml - -+ # MellonIdPMetadataGlob is a glob(3) pattern enabled alternative -+ # to MellonIdPMetadataFile. -+ # Default: None set. -+ #MellonIdPMetadataGlob /etc/apache2/mellon/*-metadata.xml -+ - # MellonIdpPublicKeyFile is the full path of the public key of the - # IdP. This parameter is optional if the public key is embedded - # in the IdP's metadata file, or if a certificate authority is -Index: auth_mellon_config.c -=================================================================== ---- auth_mellon_config.c (revision 116) -+++ auth_mellon_config.c (working copy) -@@ -222,6 +222,54 @@ - return NULL; - } - -+/* This function handles configuration directives which use -+ * a glob pattern -+ * -+ * 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_glob_fn(cmd_parms *cmd, -+ void *struct_ptr, -+ const char *arg) -+{ -+ const char *(*take_argv)(cmd_parms *, void *, const char *); -+ apr_array_header_t *files; -+ const char *error; -+ const char *directory; -+ int i; -+ -+ take_argv = cmd->info; -+ directory = am_filepath_dirname(cmd->pool, arg); -+ -+ if (arg == NULL || *arg == '\0') -+ return apr_psprintf(cmd->pool, "%s takes one argument", cmd->cmd->name); -+ -+ if (apr_match_glob(arg, &files, cmd->pool) != 0) -+ return take_argv(cmd, struct_ptr, arg); -+ -+ for (i = 0; i < files->nelts; i++) { -+ const char *path; -+ -+ path = apr_pstrcat(cmd->pool, directory, "/", -+ ((const char **)(files->elts))[i], NULL); -+ -+ error = take_argv(cmd, struct_ptr, path); -+ -+ if (error != NULL) -+ return error; -+ } -+ -+ return NULL; -+} -+ - /* This function handles configuration directives which set an - * idp related slot in the module configuration. - * -@@ -872,6 +920,13 @@ - "Full path to xml metadata file for the IdP." - ), - AP_INIT_TAKE1( -+ "MellonIdPMetadataGlob", -+ am_set_glob_fn, -+ am_set_idp_string_slot, -+ OR_AUTHCFG, -+ "Full path to xml metadata files for the IdP, with glob(3) patterns." -+ ), -+ AP_INIT_TAKE1( - "MellonIdPPublicKeyFile", - ap_set_string_slot, - (void *)APR_OFFSETOF(am_dir_cfg_rec, idp_public_key_file), diff --git a/www/ap2-auth-mellon/patches/patch-ah b/www/ap2-auth-mellon/patches/patch-ah deleted file mode 100644 index 03e62cd2e0e..00000000000 --- a/www/ap2-auth-mellon/patches/patch-ah +++ /dev/null @@ -1,91 +0,0 @@ -$NetBSD: patch-ah,v 1.1 2011/05/07 05:15:21 manu Exp $ - -Unbreak SP initiated SLO with lasso >= 2.3.5 - ---- auth_mellon_handler.c.orig 2011-05-07 06:31:46.000000000 +0200 -+++ auth_mellon_handler.c 2011-05-07 06:57:03.000000000 +0200 -@@ -774,8 +774,9 @@ - gint res; - char *redirect_to; - LassoProfile *profile; - LassoSession *session; -+ GList *assertion_list; - LassoNode *assertion_n; - LassoSaml2Assertion *assertion; - LassoSaml2AuthnStatement *authnStatement; - LassoSamlp2LogoutRequest *request; -@@ -822,42 +823,46 @@ - return HTTP_INTERNAL_SERVER_ERROR; - } - - -- /* We need to set the SessionIndex in the LogoutRequest to the -- * SessionIndex we received during the login operation. -- */ -- - profile = LASSO_PROFILE(logout); -- session = lasso_profile_get_session(profile); - -- /* We currently only look at the first assertion in the list -- * lasso_session_get_assertions returns. -+ /* We need to set the SessionIndex in the LogoutRequest to the SessionIndex -+ * we received during the login operation. This is not needed since release -+ * 2.3.0. - */ -- assertion_n = lasso_session_get_assertions( -- session, profile->remote_providerID)->data; -- if(LASSO_IS_SAML2_ASSERTION(assertion_n) == FALSE) { -- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -- "No assertions found for the current session."); -- lasso_logout_destroy(logout); -- return HTTP_INTERNAL_SERVER_ERROR; -- } -- -- assertion = LASSO_SAML2_ASSERTION(assertion_n); -+ if (lasso_check_version(2, 3, 0, LASSO_CHECK_VERSION_NUMERIC) == 0) { -+ session = lasso_profile_get_session(profile); -+ assertion_list = lasso_session_get_assertions( -+ session, profile->remote_providerID); -+ if(! assertion_list || -+ LASSO_IS_SAML2_ASSERTION(assertion_list->data) == FALSE) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "No assertions found for the current session."); -+ lasso_logout_destroy(logout); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ /* We currently only look at the first assertion in the list -+ * lasso_session_get_assertions returns. -+ */ -+ assertion_n = assertion_list->data; - -- /* We assume that the first authnStatement contains the data we want. */ -- authnStatement = LASSO_SAML2_AUTHN_STATEMENT(assertion->AuthnStatement->data); -+ assertion = LASSO_SAML2_ASSERTION(assertion_n); - -- if(!authnStatement) { -- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -- "No AuthnStatement found in the current assertion."); -- lasso_logout_destroy(logout); -- return HTTP_INTERNAL_SERVER_ERROR; -- } -+ /* We assume that the first authnStatement contains the data we want. */ -+ authnStatement = LASSO_SAML2_AUTHN_STATEMENT(assertion->AuthnStatement->data); - -- if(authnStatement->SessionIndex) { -- request = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request); -- request->SessionIndex = g_strdup(authnStatement->SessionIndex); -+ if(!authnStatement) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "No AuthnStatement found in the current assertion."); -+ lasso_logout_destroy(logout); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ -+ if(authnStatement->SessionIndex) { -+ request = LASSO_SAMLP2_LOGOUT_REQUEST(profile->request); -+ request->SessionIndex = g_strdup(authnStatement->SessionIndex); -+ } - } - - - /* Set the RelayState parameter to the return url (if we have one). */ diff --git a/www/ap2-auth-mellon/patches/patch-ai b/www/ap2-auth-mellon/patches/patch-ai new file mode 100644 index 00000000000..2c89561d992 --- /dev/null +++ b/www/ap2-auth-mellon/patches/patch-ai @@ -0,0 +1,310 @@ +$NetBSD: patch-ai,v 1.1 2011/12/06 09:58:01 manu Exp $ + +Honour MellonProbeDiscoveryIdP order when sending probes (from upstream) + +--- auth_mellon.h.orig 2011-05-18 12:39:00.000000000 +0200 ++++ auth_mellon.h 2011-12-06 09:54:08.000000000 +0100 +@@ -209,9 +209,9 @@ + + /* IdP discovery service */ + const char *discovery_url; + int probe_discovery_timeout; +- apr_hash_t *probe_discovery_idp; ++ apr_table_t *probe_discovery_idp; + + /* The configuration record we "inherit" the lasso server object from. */ + struct am_dir_cfg_rec *inherit_server_from; + /* Mutex to prevent us from creating several lasso server objects. */ +--- auth_mellon_config.c.orig 2011-05-18 12:39:00.000000000 +0200 ++++ auth_mellon_config.c 2011-12-06 09:54:08.000000000 +0100 +@@ -76,8 +76,9 @@ + * the MellonPostCount configuration directive if you change this. + */ + static const int post_count = 100; + ++#if unused + /* This function handles configuration directives which set a + * multivalued string slot in the module configuration (the destination + * strucure is a hash). + * +@@ -85,9 +86,8 @@ + * 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 *key The string argument following this configuration + * directive in the configuraion file. + * const char *value Optional value to be stored in the hash. + * +@@ -116,8 +116,49 @@ + apr_hash_set(*hash, apr_pstrdup(pconf, key), APR_HASH_KEY_STRING, value); + + return NULL; + } ++#endif /* unused */ ++ ++/* This function handles configuration directives which set a ++ * multivalued string slot in the module configuration (the destination ++ * strucure is a table). ++ * ++ * 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 *key The string argument following this configuration ++ * directive in the configuraion file. ++ * const char *value Optional value to be stored in the hash. ++ * ++ * Returns: ++ * NULL on success or an error string on failure. ++ */ ++static const char *am_set_table_string_slot(cmd_parms *cmd, ++ void *struct_ptr, ++ const char *key, ++ const char *value) ++{ ++ server_rec *s = cmd->server; ++ apr_pool_t *pconf = s->process->pconf; ++ am_dir_cfg_rec *cfg = (am_dir_cfg_rec *)struct_ptr; ++ int offset; ++ apr_table_t **table; ++ ++ /* ++ * If no value is given, we just store the key in the hash. ++ */ ++ if (value == NULL || *value == '\0') ++ value = key; ++ ++ offset = (int)(long)cmd->info; ++ table = (apr_table_t **)((char *)cfg + offset); ++ apr_table_set(*table, apr_pstrdup(pconf, key), value); ++ ++ 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. +@@ -1008,9 +1049,9 @@ + "Default is 1s" + ), + AP_INIT_TAKE12( + "MellonProbeDiscoveryIdP", +- am_set_hash_string_slot, ++ am_set_table_string_slot, + (void *)APR_OFFSETOF(am_dir_cfg_rec, probe_discovery_idp), + OR_AUTHCFG, + "An IdP that can be used for IdP probe discovery." + ), +@@ -1097,9 +1138,9 @@ + dir->idp_ignore = NULL; + dir->login_path = default_login_path; + dir->discovery_url = NULL; + dir->probe_discovery_timeout = -1; /* -1 means no probe discovery */ +- dir->probe_discovery_idp = apr_hash_make(p); ++ dir->probe_discovery_idp = apr_table_make(p, 0); + + dir->sp_org_name = apr_hash_make(p); + dir->sp_org_display_name = apr_hash_make(p); + dir->sp_org_url = apr_hash_make(p); +@@ -1292,12 +1333,12 @@ + (add_cfg->probe_discovery_timeout != -1 ? + add_cfg->probe_discovery_timeout : + base_cfg->probe_discovery_timeout); + +- new_cfg->probe_discovery_idp = apr_hash_copy(p, +- (apr_hash_count(add_cfg->probe_discovery_idp) > 0) ? +- add_cfg->probe_discovery_idp : +- base_cfg->probe_discovery_idp); ++ new_cfg->probe_discovery_idp = apr_table_copy(p, ++ (!apr_is_empty_table(add_cfg->probe_discovery_idp)) ? ++ add_cfg->probe_discovery_idp : ++ base_cfg->probe_discovery_idp); + + + if (cfg_can_inherit_lasso_server(add_cfg)) { + new_cfg->inherit_server_from = base_cfg->inherit_server_from; +--- auth_mellon_handler.c.orig 2011-05-18 12:39:00.000000000 +0200 ++++ auth_mellon_handler.c 2011-12-06 10:40:20.000000000 +0100 +@@ -2572,8 +2572,40 @@ + + return am_send_authn_request(r, idp, return_to, is_passive); + } + ++/* This function probes an URL (HTTP GET) ++ * ++ * Parameters: ++ * request_rec *r The request. ++ * const char *url The URL ++ * int timeout Timeout in seconds ++ * ++ * Returns: ++ * OK on success, or an error if any of the steps fail. ++ */ ++static int am_probe_url(request_rec *r, const char *url, int timeout) ++{ ++ void *dontcare; ++ apr_size_t len; ++ long status; ++ int error; ++ ++ status = 0; ++ if ((error = am_httpclient_get(r, url, &dontcare, &len, ++ timeout, &status)) != OK) ++ return error; ++ ++ if (status != HTTP_OK) { ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ++ "Probe on \"%s\" returned HTTP %ld", ++ url, status); ++ return status; ++ } ++ ++ return OK; ++} ++ + /* This function handles requests to the probe discovery handler + * + * Parameters: + * request_rec *r The request. +@@ -2583,11 +2615,10 @@ + */ + static int am_handle_probe_discovery(request_rec *r) { + am_dir_cfg_rec *cfg = am_get_dir_cfg(r); + LassoServer *server; +- const char *idp = NULL; ++ const char *disco_idp = NULL; + int timeout; +- GHashTableIter iter; + char *return_to; + char *idp_param; + char *redirect_url; + int ret; +@@ -2644,82 +2675,77 @@ + + /* + * Proceed with built-in IdP discovery. + * +- * Send probes for all configured IdP to check availability. +- * The first to answer is chosen, but the list of usable +- * IdP can be restricted in configuration. ++ * First try sending probes to IdP configured for discovery. ++ * Second send probes for all configured IdP ++ * The first to answer is chosen. ++ * If none answer, use the first configured IdP + */ +- g_hash_table_iter_init(&iter, server->providers); +- while (g_hash_table_iter_next(&iter, (void**)&idp, NULL)) { +- void *dontcare; +- const char *ping_url; +- apr_size_t len; +- long status; +- +- ping_url = idp; +- +- /* +- * If a list of IdP was given for probe discovery, +- * skip any IdP that does not match. +- */ +- if (apr_hash_count(cfg->probe_discovery_idp) != 0) { +- char *value = apr_hash_get(cfg->probe_discovery_idp, +- idp, APR_HASH_KEY_STRING); +- +- if (value == NULL) { +- /* idp not in list, try the next one */ +- continue; +- } else { +- /* idp in list, use the value as the ping url */ +- ping_url = value; ++ if (!apr_is_empty_table(cfg->probe_discovery_idp)) { ++ const apr_array_header_t *header; ++ apr_table_entry_t *elts; ++ const char *url; ++ const char *idp; ++ int i; ++ ++ header = apr_table_elts(cfg->probe_discovery_idp); ++ elts = (apr_table_entry_t *)header->elts; ++ ++ for (i = 0; i < header->nelts; i++) { ++ idp = elts[i].key; ++ url = elts[i].val; ++ ++ if (am_probe_url(r, url, timeout) == OK) { ++ disco_idp = idp; ++ break; + } + } +- +- status = 0; +- if (am_httpclient_get(r, ping_url, &dontcare, &len, +- timeout, &status) != OK) +- continue; +- +- if (status != HTTP_OK) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, +- "Cannot probe %s: \"%s\" returned HTTP %ld", +- idp, ping_url, status); +- continue; ++ } else { ++ GList *iter; ++ GList *idp_list; ++ const char *idp; ++ ++ idp_list = g_hash_table_get_keys(server->providers); ++ for (iter = idp_list; iter != NULL; iter = iter->next) { ++ idp = iter->data; ++ ++ if (am_probe_url(r, idp, timeout) == OK) { ++ disco_idp = idp; ++ break; ++ } + } +- +- /* We got some succes */ +- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, +- "probeDiscovery using %s", idp); +- break; ++ g_list_free(idp_list); + } + + /* + * On failure, try default + */ +- if (idp == NULL) { +- idp = am_first_idp(r); +- if (idp == NULL) { ++ if (disco_idp == NULL) { ++ disco_idp = am_first_idp(r); ++ if (disco_idp == NULL) { + ap_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 " +- "failed, trying default IdP %s", idp); ++ "failed, trying default IdP %s", disco_idp); + } ++ } else { ++ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, ++ "probeDiscovery using %s", disco_idp); + } + + redirect_url = apr_psprintf(r->pool, "%s%s%s=%s", return_to, + strchr(return_to, '?') ? "&" : "?", + am_urlencode(r->pool, idp_param), +- am_urlencode(r->pool, idp)); ++ am_urlencode(r->pool, disco_idp)); + + apr_table_setn(r->headers_out, "Location", redirect_url); + + return HTTP_SEE_OTHER; + } + +- + /* This function takes a request for an endpoint and passes it on to the + * correct handler function. + * + * Parameters: -- cgit v1.2.3