summaryrefslogtreecommitdiffstats
path: root/auth_mellon_config.c
diff options
context:
space:
mode:
authormanu@netbsd.org <manu@netbsd.org@a716ebb1-153a-0410-b759-cfb97c6a1b53>2011-03-17 05:20:40 +0000
committermanu@netbsd.org <manu@netbsd.org@a716ebb1-153a-0410-b759-cfb97c6a1b53>2011-03-17 05:20:40 +0000
commit000b791af8867c970bf17fb689d5d9707f54adfc (patch)
tree6d5d90bed0585254e467eb0b4478a8f120f24d89 /auth_mellon_config.c
parent99795c36c245a7d7128749cc8fc6750ffb657d84 (diff)
downloadmod_auth_mellon-000b791af8867c970bf17fb689d5d9707f54adfc.tar.gz
mod_auth_mellon-000b791af8867c970bf17fb689d5d9707f54adfc.tar.xz
mod_auth_mellon-000b791af8867c970bf17fb689d5d9707f54adfc.zip
New MellonCond directive to enable attribute filtering beyond MellonRequire
functionalities. Supports regexp, negations, and attribute name remapping though MellonSetEnv git-svn-id: https://modmellon.googlecode.com/svn/trunk@114 a716ebb1-153a-0410-b759-cfb97c6a1b53
Diffstat (limited to 'auth_mellon_config.c')
-rw-r--r--auth_mellon_config.c198
1 files changed, 182 insertions, 16 deletions
diff --git a/auth_mellon_config.c b/auth_mellon_config.c
index eba1fa4..e2323d3 100644
--- a/auth_mellon_config.c
+++ b/auth_mellon_config.c
@@ -422,6 +422,135 @@ static const char *am_set_setenv_slot(cmd_parms *cmd,
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
@@ -440,10 +569,11 @@ static const char *am_set_require_slot(cmd_parms *cmd,
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 @@ static const char *am_set_require_slot(cmd_parms *cmd,
" 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);
-
- if (r == NULL) {
- r = apr_array_make(cmd->pool, 2, sizeof(const char *));
- apr_hash_set(d->require, attribute, APR_HASH_KEY_STRING, r);
+ 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;
+
+ /*
+ * 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 @@ const command_rec auth_mellon_commands[] = {
" for the attribute. The syntax is:"
" MellonRequire <attribute> <value1> [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 <attribute> <value> [<options>]."
+ ),
AP_INIT_TAKE1(
"MellonSessionLength",
ap_set_int_slot,
@@ -795,7 +961,7 @@ void *auth_mellon_dir_config(apr_pool_t *p, char *d)
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 @@ void *auth_mellon_dir_merge(apr_pool_t *p, void *base, void *add)
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) ?