summaryrefslogtreecommitdiff
path: root/module/mod_auth_singleid.c
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2009-07-07 20:05:29 +0000
committerStef Walter <stef@memberwebs.com>2009-07-07 20:05:29 +0000
commit2989ee8b72ddb3995e5a4686c988385d05493365 (patch)
tree566819988818d2478a556394d2a7243d8f1a8b1f /module/mod_auth_singleid.c
parent2622d0eb7d32ae035d9c04d92de4e61588b1950e (diff)
Implement simple AX attribute exchange.
* Does not yet handle setting attributes from the cookie.
Diffstat (limited to 'module/mod_auth_singleid.c')
-rw-r--r--module/mod_auth_singleid.c130
1 files changed, 124 insertions, 6 deletions
diff --git a/module/mod_auth_singleid.c b/module/mod_auth_singleid.c
index 2e46586..d2e53e8 100644
--- a/module/mod_auth_singleid.c
+++ b/module/mod_auth_singleid.c
@@ -73,6 +73,7 @@
extern module AP_MODULE_DECLARE_DATA auth_singleid_module;
#define VALID_NAME "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-."
+#define VALID_ALIAS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
enum {
NONE = 0,
@@ -90,11 +91,36 @@ typedef struct sid_context {
int user_match;
ap_regex_t *converter;
sid_storage_t *store;
+ sid_attribute_t *attributes;
} sid_context_t;
#define SID_AUTHTYPE "SingleID"
/* -------------------------------------------------------------------------------
+ * UTILITY
+ */
+
+static void
+strupcase(char *str)
+{
+ while (*str) {
+ *str = apr_toupper(*str);
+ ++str;
+ }
+}
+
+static char*
+safe_get_token (apr_pool_t *pool, const char **line, int accept_white)
+{
+ /* HACK: ap_get_token() endless loop if string starts with delim */
+ const char *orig = *line;
+ char *result = ap_get_token (pool, line, accept_white);
+ if (orig == *line && orig[0])
+ (*line)++;
+ return result;
+}
+
+/* -------------------------------------------------------------------------------
* SHARED MEMORY and LOCKING
*/
@@ -344,6 +370,67 @@ set_cookie_name (cmd_parms *cmd, void *config, const char *val)
return NULL;
}
+static const char*
+set_attribute (cmd_parms *cmd, void *config, const char *val)
+{
+ sid_context_t *ctx = config;
+ sid_attribute_t attr, *at;
+ const char *flag;
+ char *end;
+
+ memset (&attr, 0, sizeof (attr));
+ attr.count = 1;
+
+ /* First word is the alias */
+ attr.alias = ap_getword_conf (cmd->pool, &val);
+ if (!attr.alias || strspn (attr.alias, VALID_ALIAS) != strlen (attr.alias))
+ return "Invalid attribute alias";
+
+ /* Check if we already have this alias */
+ for (at = ctx->attributes; at; at = at->next) {
+ if (strcasecmp (at->alias, attr.alias) == 0)
+ return "Duplicate attribute alias";
+ }
+
+ /* Next word is the url */
+ attr.url = ap_getword_conf (cmd->pool, &val);
+ if (!attr.url || !ap_is_url (attr.url))
+ return "Invalid attribute URL";
+
+ /* Now come all the various flags */
+ for (;;) {
+ flag = ap_getword_conf (cmd->pool, &val);
+ if (!flag || !flag[0])
+ break;
+
+ if (strcasecmp (flag, "required") == 0) {
+ attr.required = 1;
+
+ } else if (strcasecmp (flag, "unlimited") == 0) {
+ attr.count = 0;
+
+ } else {
+ attr.count = strtol (flag, &end, 10);
+ if (*end != '\0') {
+ if (attr.count != 0)
+ return "Invalid attribute count";
+ else
+ return "Unrecognized value or flag";
+ }
+ if (attr.count <= 0)
+ return "Attribute count must a number greater than zero or 'unlimited'";
+ }
+ }
+
+ /* Instantiate the copy */
+ attr.next = ctx->attributes;
+ at = apr_pcalloc (cmd->pool, sizeof (attr));
+ memcpy (at, &attr, sizeof (attr));
+ ctx->attributes = at;
+
+ return NULL;
+}
+
static const command_rec command_table[] = {
AP_INIT_TAKE1 ("SingleIdentifier", set_identifier, NULL, OR_AUTHCFG,
"The OpenID identifier we should perform ID selection on when authenticating" ),
@@ -355,6 +442,8 @@ static const command_rec command_table[] = {
"Set the cookie name used once user has logged in via OpenID"),
AP_INIT_RAW_ARGS ("SingleUserMatch", set_user_match, NULL, OR_AUTHCFG,
"How to convert an OpenID identifier into a user name" ),
+ AP_INIT_RAW_ARGS ("SingleAttribute", set_attribute, NULL, OR_AUTHCFG,
+ "Specify an attribute exchange url and alias."),
{ NULL }
};
@@ -399,8 +488,11 @@ session_cookie_value (request_rec *r, const char *name)
if (cookies == NULL)
return NULL;
+ while (cookies[0] == ',' || cookies[0] == ';')
+ ++cookies;
+
while (*cookies) {
- pair = ap_get_token (r->pool, &cookies, 1);
+ pair = safe_get_token (r->pool, &cookies, 1);
if (!pair)
break;
if (pair[0] == '$')
@@ -463,16 +555,16 @@ session_load_info (sid_context_t *ctx, request_rec *r)
if (!value)
return NULL;
- sig = ap_get_token (r->pool, &value, 0);
+ sig = safe_get_token (r->pool, &value, 0);
if (!session_validate_sig (r->pool, sig, value))
return NULL;
/* The version of the session info, only 1 supported for now */
- token = ap_get_token (r->pool, &value, 0);
+ token = safe_get_token (r->pool, &value, 0);
if (strcmp (token, "1") != 0)
return NULL;
- token = ap_get_token (r->pool, &value, 0);
+ token = safe_get_token (r->pool, &value, 0);
expiry = strtol (token, &end, 10);
if (*end != '\0')
return NULL;
@@ -482,7 +574,7 @@ session_load_info (sid_context_t *ctx, request_rec *r)
return NULL;
/* The identifier */
- identifier = ap_get_token (r->pool, &value, 0);
+ identifier = safe_get_token (r->pool, &value, 0);
len = strlen (identifier);
if (identifier[0] == '"' && identifier[len - 1] == '"') {
identifier[len - 1] = 0;
@@ -652,6 +744,31 @@ sid_request_authenticated (sid_request_t *req, const char *identifier)
session_send_info (ctx, req->rec, sess);
}
+void
+sid_request_attribute_values (sid_request_t *req, sid_attribute_t *attr, const char **values)
+{
+ const char **val;
+ char buf[64];
+ char *name;
+ int i = 0;
+
+ /* Setup all the values */
+ for (i = 0, val = values; *val; ++val, ++i) {
+ snprintf (buf, sizeof (buf), "AX_VALUE_%s_%d", attr->alias, i);
+ name = apr_pstrdup (req->rec->pool, buf);
+ strupcase (name);
+ apr_table_setn (req->rec->subprocess_env, name,
+ apr_pstrdup (req->rec->pool, *val));
+ }
+
+ /* Put in the count */
+ snprintf (buf, sizeof (buf), "AX_COUNT_%s", attr->alias);
+ name = apr_pstrdup (req->rec->pool, buf);
+ strupcase (name);
+ snprintf (buf, sizeof (buf), "%d", i);
+ apr_table_set (req->rec->subprocess_env, name, apr_pstrdup (req->rec->pool, buf));
+}
+
/* ---------------------------------------------------------------------------------------
* MAIN HOOKS
*/
@@ -720,7 +837,8 @@ hook_authenticate (request_rec* r)
req.rec = r;
/* Do the OpenID magic */
- sid_consumer_authenticate (&req, ctx->store, ctx->trust_root, ctx->identifier);
+ sid_consumer_authenticate (&req, ctx->store, ctx->trust_root,
+ ctx->identifier, ctx->attributes);
return req.result;
}