summaryrefslogtreecommitdiff
path: root/module/mod_auth_singleid.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/mod_auth_singleid.c')
-rw-r--r--module/mod_auth_singleid.c1333
1 files changed, 202 insertions, 1131 deletions
diff --git a/module/mod_auth_singleid.c b/module/mod_auth_singleid.c
index 6085fec..3b6304a 100644
--- a/module/mod_auth_singleid.c
+++ b/module/mod_auth_singleid.c
@@ -36,10 +36,6 @@
*
*/
-
-#include "consumer.h"
-#include "storage.h"
-
#include <ap_config.h>
#include <httpd.h>
@@ -49,6 +45,7 @@
#include <http_protocol.h>
#include <http_request.h>
#include <mpm.h>
+#include <mod_ssl.h>
#include <apr_base64.h>
#include <apr_file_io.h>
@@ -57,8 +54,6 @@
#include <apr_sha1.h>
#include <apr_strings.h>
-#include <ctype.h>
-
/* Apache defines these */
#undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME
@@ -67,6 +62,9 @@
#undef PACKAGE_VERSION
#include "config.h"
+#include "mod_auth_singleid.h"
+
+#include <ctype.h>
#include <unistd.h>
extern module AP_MODULE_DECLARE_DATA auth_singleid_module;
@@ -74,23 +72,24 @@ extern module AP_MODULE_DECLARE_DATA auth_singleid_module;
/*
* Per directory configuration.
*/
-typedef struct singleid_context {
+typedef struct sid_context {
const char *trust_root;
- const char *identity;
- void *shared_block;
-} singleid_context_t;
+ const char *identifier;
+ sid_storage_t *store;
+} sid_context_t;
-#define SINGLEID_AUTHTYPE "SINGLEID"
+#define SID_AUTHTYPE "SingleID"
/* -------------------------------------------------------------------------------
- * SHARED MEMORY
+ * SHARED MEMORY and LOCKING
*/
static apr_global_mutex_t *shared_lock = NULL;
static const char *shared_lock_name = NULL;
+static size_t shared_size = 64 * 1024;
static int
-shared_initialize (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+shared_initialize (apr_pool_t *p, server_rec *s)
{
apr_file_t *file = NULL;
const char *tmpdir;
@@ -167,6 +166,9 @@ shared_create (apr_pool_t* p, size_t size)
void *addr;
int rc;
+ if (!shared_lock)
+ return NULL;
+
/* Get the temp directory */
rc = apr_temp_dir_get (&tmpdir, p);
if (rc != APR_SUCCESS) {
@@ -216,939 +218,100 @@ shared_create (apr_pool_t* p, size_t size)
return NULL;
}
-/* -------------------------------------------------------------------------------------------------
- * COMMON STORAGE
- */
-
-typedef struct storage_context {
- void* shared;
- size_t size;
-} storage_context_t;
-
-/* -------------------------------------------------------------------------------------------------
- * OPENID CONSUMER
- */
-
-#if 0
-static void* storage_shared = NULL;
-static size_t storage_size = NULL;
-#endif
-
-#if 0
-
-static int
-shared_get_if_changed (httpauth_context_t *ctx, int version, httpauth_shared_t *shared)
+void
+sid_shared_lock (void)
{
- httpauth_shared_t *block;
- int ret = 0;
-
- if (!ctx->shared_block || !shared_lock)
- return 0;
-
apr_global_mutex_lock (shared_lock);
-
- block = ctx->shared_block;
- if (block->version != version) {
- ret = 1;
- if (shared)
- memcpy (shared, block, sizeof (*shared));
- }
-
- apr_global_mutex_unlock (shared_lock);
-
- return ret;
}
-static void
-shared_set_if_changed (httpauth_context_t *ctx, httpauth_shared_t *shared)
+void
+sid_shared_unlock (void)
{
- httpauth_shared_t *block;
-
- if (!ctx->shared_block || !shared_lock)
- return;
-
- apr_global_mutex_lock (shared_lock);
-
- block = ctx->shared_block;
- if (memcmp (shared, block, sizeof (*shared)) != 0) {
-
- /* Increment the version beyond all */
- if (block->version > shared->version)
- shared->version = block->version;
- ++shared->version;
-
- /* And write it out */
- memcpy (block, shared, sizeof (*shared));
- }
-
apr_global_mutex_unlock (shared_lock);
}
-#endif
/* -------------------------------------------------------------------------------
- * Per Directory Config and Context Code
+ * CONFIGURATION
*/
static void*
dir_config_creator (apr_pool_t* p, char* dir)
{
-#if 0
- httpauth_context_t* ctx;
- httpauth_shared_t shared;
- const char *tmpdir;
- char *filename;
- apr_file_t *file;
- apr_mmap_t *map;
- void *addr;
- int rc;
+ sid_context_t* ctx;
+ void *shared;
- ctx = (httpauth_context_t*)apr_pcalloc(p, sizeof(*ctx));
+ ctx = (sid_context_t*)apr_pcalloc(p, sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
- ctx->socket = -1;
- ctx->types = 0xFFFFFFFF;
- ctx->child_pool = p;
- ctx->needed_groups = NULL;
- ctx->alloced_groups = 0;
- ctx->shared_version = 0;
- ctx->retries = 1;
+ ctx->identifier = NULL;
+ ctx->store = NULL;
+ ctx->trust_root = NULL;
if (!dir)
return ctx;
- /* Get the temp directory */
- rc = apr_temp_dir_get (&tmpdir, p);
- if (rc != APR_SUCCESS)
- ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
- "httpauth: couldn't get temporary directory");
-
- /* Create the shared file */
- if (rc == APR_SUCCESS) {
- filename = apr_pstrcat (p, tmpdir, "/", "mod-httpauth.board.XXXXXX", NULL);
- rc = apr_file_mktemp (&file, filename, 0, p);
- if (rc != APR_SUCCESS)
- ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
- "httpauth: couldn't create temporary file: %s", filename);
- }
-
- /* Write a shared block to file */
- if (rc == APR_SUCCESS) {
- memset (&shared, 0, sizeof (shared));
- rc = apr_file_write_full (file, &shared, sizeof (shared), NULL);
- if (rc != APR_SUCCESS)
- ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
- "httpauth: couldn't write to temporary file: %s", filename);
- }
-
- /* Map the shared file into memory */
- if (rc == APR_SUCCESS) {
- rc = apr_mmap_create (&map, file, 0, sizeof (shared),
- APR_MMAP_READ | APR_MMAP_WRITE, p);
- if (rc != APR_SUCCESS)
- ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
- "httpauth: couldn't map temporary file: %s", filename);
- }
-
- /* Get the actual address of the mapping */
- if (rc == APR_SUCCESS) {
- rc = apr_mmap_offset (&addr, map, 0);
- if (rc != APR_SUCCESS)
- ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
- "httpauth: couldn't get shared memory");
- }
-
- if (rc == APR_SUCCESS)
- ctx->shared_block = addr;
+ shared = shared_create (p, shared_size);
+ ctx->store = sid_storage_initialize (shared, shared_size);
return ctx;
-#endif
- return NULL;
}
-#if 0
-static const char* set_socket(cmd_parms* cmd, void* config, const char* val)
+static const char*
+set_identifier (cmd_parms* cmd, void* config, const char* val)
{
- struct sockaddr_any sany;
-
- if (sock_any_pton_n (val, &sany, 1, DEFAULT_PORT | SANY_OPT_NORESOLV) == -1)
- return "Invalid socket name or ip in HttpAuthSocket";
-
- ((httpauth_context_t*)config)->socketname = val;
+ sid_context_t *ctx = config;
+ ctx->identifier = apr_pstrdup (cmd->pool, val);
return NULL;
}
-static const char* set_handler(cmd_parms* cmd, void* config, const char* val)
-{
- httpauth_context_t* conf = (httpauth_context_t*)config;
- conf->handler = val;
- return NULL;
-}
-
-static const char* set_types(cmd_parms* cmd, void* config, const char* val)
-{
- httpauth_context_t* conf = (httpauth_context_t*)config;
- int type = 0;
-
- if(strcasecmp(val, AUTH_PREFIX_BASIC) == 0)
- type = AUTH_TYPE_BASIC;
- else if(strcasecmp(val, AUTH_PREFIX_DIGEST) == 0)
- type = AUTH_TYPE_DIGEST;
- else if(strcasecmp(val, AUTH_PREFIX_NTLM) == 0)
- type = AUTH_TYPE_NTLM;
- else if(strcasecmp(val, "any"))
- type = AUTH_TYPE_ANY;
- else
- return "Invalid type in HttpAuthTypes";
-
- if(conf->types == 0xFFFFFFFF)
- conf->types = type;
- else
- conf->types |= type;
-
- return NULL;
-}
-
-static const char* set_domain(cmd_parms* cmd, void* config, const char* val)
+static const char*
+set_trust_root (cmd_parms* cmd, void* config, const char* val)
{
- httpauth_context_t* conf = (httpauth_context_t*)config;
- conf->domain = trim_space(apr_pstrdup(cmd->pool, val));
- return NULL;
+ sid_context_t *ctx = config;
+ if (!ap_is_url (val))
+ return "Not a valid URL in SingleTrustRoot";
+ ctx->trust_root = apr_pstrdup (cmd->pool, val);
+ return NULL;
}
-#endif
-static const command_rec command_table[] =
-{
-#if 0
- AP_INIT_RAW_ARGS( "HttpAuthSocket", set_socket, NULL, OR_AUTHCFG,
- "The socket that httpauthd is listening on" ),
- AP_INIT_TAKE1( "HttpAuthHandler", set_handler, NULL, OR_AUTHCFG,
- "The handler that httpauthd should use to authenticate" ),
- AP_INIT_ITERATE( "HttpAuthTypes", set_types, NULL, OR_AUTHCFG,
- "The types of authentiction allowed (Basic, Digest, NTLM ...)" ),
- AP_INIT_RAW_ARGS( "HttpAuthDigestDomain", set_domain, NULL, OR_AUTHCFG,
- "The domain for which digest authentication is relevant" ),
-#endif
- { 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" ),
+ AP_INIT_TAKE1( "SingleTrustRoot", set_trust_root, NULL, OR_AUTHCFG,
+ "The OpenID Trust Root of this site."),
+ { NULL }
};
-#if 0
-
-/* -------------------------------------------------------------------------------
- * Socket handling code
+/* -------------------------------------------------------------------------------------------
+ * COOKIE SESSIONS
*/
-static apr_status_t cleanup_socket(void *fdv)
-{
- close((int)(long)fdv);
- return OK;
-}
-
-void disconnect_socket(httpauth_context_t* ctx, server_rec* s)
-{
- if(ctx->socket != -1)
- {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
- "httpauth: disconnecting from daemon");
-
- apr_pool_cleanup_kill(ctx->child_pool, (void*)(long)ctx->socket,
- cleanup_socket);
- close(ctx->socket);
- ctx->socket = -1;
-
- /* Make sure we send our list of groups to daemon again */
- if (ctx->needed_groups)
- ctx->needed_groups[0] = 0;
- }
-}
-
-void read_junk(httpauth_context_t* ctx, request_rec* r)
-{
- char buf[16];
- const char* t;
- int said = 0;
- int l;
-
- if(ctx->socket == -1)
- return;
-
- /* Make it non blocking */
- fcntl(ctx->socket, F_SETFL, fcntl(ctx->socket, F_GETFL, 0) | O_NONBLOCK);
-
- for(;;)
- {
- l = read(ctx->socket, buf, sizeof(buf) - 1);
- if(l <= 0)
- break;
-
- buf[l] = 0;
- t = trim_start(buf);
-
- if(!said && *t)
- {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
- "httpauth: received junk data from daemon");
- said = 1;
- }
- }
-
- fcntl(ctx->socket, F_SETFL, fcntl(ctx->socket, F_GETFL, 0) & ~O_NONBLOCK);
-}
-
-int read_line(httpauth_context_t* ctx, request_rec* r, char** line)
-{
- int l;
- int al = 256;
- char* t;
- const char* e;
-
- e = t = NULL;
- *line = NULL;
-
- for(;;)
- {
- if(!*line || t + 2 == e)
- {
- char* n;
- int d;
-
- n = (char*)apr_palloc(r->pool, al * 2);
-
- if(*line)
- memcpy(n, *line, al);
-
- al *= 2;
-
- /* The difference */
- d = t - *line;
-
- *line = n;
- t = n + d;
- e = n + al;
- }
-
- l = read(ctx->socket, (void*)t, sizeof(char));
-
- /* We got a character */
- if(l == 1)
- {
- /* Skip junky CRLFs */
- if(*t == '\r')
- {
- *t = ' ';
- continue;
- }
-
- /* End of line */
- else if(*t == '\n')
- {
- t++;
- break;
- }
-
- t++;
- }
-
- /* If it's the end of file then return that */
- else if(l == 0)
- {
- /* Disconnect from socket quietly so we can reconnect later */
- disconnect_socket(ctx, r->server);
- return -1;
- }
-
- /* Transient errors */
- else if(l == -1 && errno == EAGAIN)
- continue;
-
- /* Fatal errors */
- else if(l == -1)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(errno), r,
- "httpauth: couldn't read data from daemon");
- return -1;
- }
- }
-
- *t = 0;
- return 0;
-}
-
-int
-read_response (httpauth_context_t *ctx, request_rec *r,
- int *code, int *ccode, char **details,
- int return_errors)
-{
- int c, ret = -1;
- char *line;
- char *t;
- char *t2;
-
- if (read_line (ctx, r, &line) == -1)
- return -1;
-
- line = trim_space (line);
-
- ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: received response line from daemon: %s", line);
-
- /* Get response code */
- t = ap_getword_nc (r->pool, &line, ' ');
- c = strtol (t, &t2, 10);
- if (*t2 || c < 100 || c > 999) {
- ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: invalid code: %s", t);
- goto finally;
- }
-
- if (code)
- *code = c;
-
- if (c >= 400 && !return_errors) {
- ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: received error from httpauthd: %d %s", c, line);
- goto finally;
- }
-
- /* Get the second response code if we're a 200 */
- if (c == 200) {
- t = ap_getword_nc (r->pool, &line, ' ');
- c = strtol (t, &t2, 10);
- if (*t2 || c < 100 || c > 999) {
- ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: invalid code: %s", t);
- goto finally;
- }
-
- if (ccode)
- *ccode = c;
- }
-
- if (details)
- *details = trim_space (line);
-
- ret = 0;
-
-finally:
- if (ret < 0 && ctx->socket >= 0) {
- disconnect_socket (ctx, r->server);
- ++ctx->address_seed;
- }
-
- return ret;
-}
-
-static int
-read_process_headers(httpauth_context_t* ctx, int ccode,
- request_rec* r, char **groups)
-{
- char* line;
- const char* name;
- apr_table_t* headers;
- int c = 0;
-
- if(ccode > 299)
- headers = r->err_headers_out;
- else
- headers = r->headers_out;
-
- for(;;)
- {
- if(read_line(ctx, r, &line) == -1)
- return -1;
-
- /* If that's it then break */
- if(!*line)
- break;
-
- if(apr_isspace(*line))
- {
- line = (char*)trim_start(line);
-
- /* End of headers */
- if(!*line)
- break;
-
- if(c > 0)
- {
- /*
- * TODO: We really should be supporting headers split
- * across lines. But httpauthd doesn't currently produce
- * headers like that, so we don't need to care about it.
- */
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
- "httpauth: protocol error: server sent us an split header, which we don't support.");
- }
- else
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: invalid headers.");
- }
- }
-
- name = ap_getword_nc(r->pool, &line, ':');
- if(!name || !*name)
- break;
-
- /*
- * If that was the end of the line, then it's an
- * invalid header :(
- */
- if(!*line)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol header: invalid headers");
- return -1;
- }
-
- line = trim_space(line);
-
- if(strcasecmp(name, "WWW-Authenticate") == 0)
- {
- if(strncasecmp(line, AUTH_PREFIX_BASIC, strlen(AUTH_PREFIX_BASIC)) == 0 &&
- !(ctx->types & AUTH_TYPE_BASIC))
- continue;
-
- else if(strncasecmp(line, AUTH_PREFIX_DIGEST, strlen(AUTH_PREFIX_DIGEST)) == 0 &&
- !(ctx->types & AUTH_TYPE_DIGEST))
- continue;
-
- /* Only allow unknown if we don't have it */
- else if(!(ctx->types & AUTH_TYPE_ANY))
- continue;
-
- /* Fix up when we're a proxy */
- if(r->proxyreq == PROXYREQ_PROXY)
- name = "Proxy-Authenticate";
- }
-
- else if(strcasecmp(name, "Authentication-Info") == 0)
- {
- if(r->proxyreq == PROXYREQ_PROXY)
- name = "Proxy-Authentication-Info";
- }
-
- else if (strcasecmp(name, "X-HttpAuth-Groups") == 0)
- {
- if (groups && line)
- *groups = line;
- }
-
- c++;
- apr_table_addn(headers, name, line);
- }
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: received %d headers from daemon", c);
-
- return 0;
-}
-
-int write_data(httpauth_context_t* ctx, server_rec* s, const char* data)
-{
- int r;
-
- if(ctx->socket == -1)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
- "httpauth: Socket to httpauthd daemon closed. Can't write data.");
- return -1;
- }
-
- while(*data != 0)
- {
- r = write(ctx->socket, data, strlen(data));
-
- if(r > 0)
- data += r;
-
- else if(r == -1)
- {
- if(errno == EAGAIN)
- continue;
-
- /* The other end closed. no message */
- if(errno == EPIPE)
- disconnect_socket(ctx, s);
-
- else
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(errno), s,
- "httpauth: Couldn't write data to daemon");
-
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
-try_connect_socket (httpauth_context_t *ctx, struct sockaddr_any *sany,
- request_rec *r)
-{
- char peername[256];
- int rc;
-
- if (sock_any_ntop (sany, peername, sizeof (peername), 0) < 0)
- strcpy (peername, "[unknown]");
-
- ctx->socket = socket (SANY_TYPE (*sany), SOCK_STREAM, 0);
- if(ctx->socket == -1) {
- ap_log_rerror (APLOG_MARK, APLOG_CRIT, APR_FROM_OS_ERROR (errno), r,
- "httpauth: Can't create socket");
- return -1;
- }
-
- if (connect (ctx->socket, &SANY_ADDR (*sany), SANY_LEN(*sany)) != 0) {
- rc = APR_FROM_OS_ERROR (errno);
- ap_log_rerror (APLOG_MARK, APLOG_CRIT, rc, r,
- "httpauth: Can't connect to httpauthd at: %s", peername);
- close (ctx->socket);
- ctx->socket = -1;
- return -1;
- }
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: connected to daemon: %s", peername);
-
- return 0;
-}
-
-static int
-connect_socket(httpauth_context_t* ctx, request_rec* r)
-{
- httpauth_shared_t shared;
- struct sockaddr_any sany[16];
- int i, which, count = 0;
- int rc = -1;
-
- disconnect_socket(ctx, r->server);
- memset (&shared, 0, sizeof (shared));
-
- /* Find out what everyone else is connected to */
- if (shared_get_if_changed (ctx, ctx->shared_version, &shared) && shared.version > 0) {
- ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: trying shared address...");
- rc = try_connect_socket (ctx, &shared.address, r);
- }
-
- /* Now try to connect to all the other addresses */
- if (rc < 0) {
- ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: resolving daemon address(s)");
-
- count = sock_any_pton_n (ctx->socketname, sany, 16, DEFAULT_PORT);
- if (count < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
- "httpauth: Invalid socket name or ip: %s", ctx->socketname);
- rc = -1;
- }
-
- /* We know how many addresses we have to retry with */
- if (count > 0)
- ctx->retries = count;
-
- for (i = 0; i != count; ++i) {
- which = (i + ctx->address_seed) % count;
- rc = try_connect_socket (ctx, &sany[which], r);
-
- /* Successful, then let others know we're connected here */
- if (rc >= 0) {
- memcpy (&shared.address, &sany[which], sizeof (shared.address));
- break;
- }
- }
- }
-
- /* Yay, successful */
- if (rc >= 0) {
- shared_set_if_changed (ctx, &shared);
- ctx->shared_version = shared.version;
- apr_pool_cleanup_register(ctx->child_pool, (void*)(long)ctx->socket,
- cleanup_socket, cleanup_socket);
- errno = 0;
- }
-
- return rc;
-}
-
-int connect_httpauth(httpauth_context_t* ctx, request_rec* r)
-{
- int ret = -1;
- int code;
- char* details;
- const char* t;
-
- if(connect_socket(ctx, r) == -1)
- goto finally;
-
- if(read_response(ctx, r, &code, NULL, &details, 0) == -1)
- goto finally;
-
- if(code != 100)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error (Expected 100, got %d)", code);
- goto finally;
- }
-
- /* Check theversion number */
- details = trim_space(details);
-
- if(strcmp(details, "HTTPAUTH/1.0") != 0)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: Daemon speaking incompatible protocol version: %s", details);
- goto finally;
- }
-
- /* Send our handler */
- if(ctx->handler)
- {
- t = apr_pstrcat(r->pool, "SET Handler ", ctx->handler, "\n", NULL);
-
- if(write_data(ctx, r->server, t) == -1)
- goto finally;
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: sent handler to daemon: %s", t);
-
- if(read_response(ctx, r, &code, NULL, NULL, 0) == -1)
- goto finally;
-
- if(code != 202)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: couldn't send handler to daemon (Expected 202, got %d)", code);
- goto finally;
- }
- }
-
- /* Send any setup info we have */
- if(ctx->domain)
- {
- t = apr_pstrcat(r->pool, "SET Domain ", ctx->domain, "\n", NULL);
-
- if(write_data(ctx, r->server, t) == -1)
- goto finally;
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: sent domains to daemon: %s", t);
-
- if(read_response(ctx, r, &code, NULL, NULL, 0) == -1)
- goto finally;
-
- if(code != 202)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: couldn't send domain to daemon (Expected 202, got %d)", code);
- goto finally;
- }
- }
-
- /* We're cool! */
- ret = 0;
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "httpauth: handshake with daemon completed");
-
-finally:
- if(ret == -1 && ctx->socket >= 0) {
- disconnect_socket(ctx, r->server);
- ++ctx->address_seed;
- }
-
- return ret;
-}
-
-/* Make sure our connection identifier is unique */
-static apr_status_t connection_gone (void *data)
-{
- conn_current = NULL;
- conn_seen++;
- return APR_SUCCESS;
-}
-
-int write_request(httpauth_context_t* ctx, request_rec* r)
-{
- char pidid[40];
- char connid[40];
- int i, c = 0;
- const char* t;
- const apr_array_header_t* hdrs_arr;
- const apr_table_entry_t* elts;
-
- /* When the connection goes away, call our handler */
- if(conn_current != r->connection)
- {
- conn_current = r->connection;
- apr_pool_cleanup_register(r->connection->pool, r,
- connection_gone, apr_pool_cleanup_null);
- }
-
- /* A unique per connection id */
- snprintf(connid, sizeof(connid), "0x%X-%X-%X",
- (unsigned int)r->connection, conn_seen, (unsigned int)r->connection->id);
- connid[sizeof(connid) - 1] = 0;
- snprintf(pidid, sizeof(pidid), "%d", (unsigned int)getpid());
- pidid[sizeof(pidid) - 1] = 0;
- t = apr_pstrcat(r->pool, pidid, ":", connid, NULL);
-
- /* Send the request header to httpauthd */
- t = apr_pstrcat(r->pool, "AUTH ", t, " ", r->method,
- " ", r->unparsed_uri, "\n", NULL);
-
- if(write_data(ctx, r->server, t) == -1)
- return -1;
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: sent auth request to daemon: %s", t);
-
- /* Now send the headers to httpauthd */
-
- hdrs_arr = apr_table_elts(r->headers_in);
- elts = (const apr_table_entry_t*)hdrs_arr->elts;
-
- for(i = 0; i < hdrs_arr->nelts; i++)
- {
- if(!elts[i].val)
- continue;
-
- /* Filter out headers we don't want */
- if(strcasecmp(elts[i].key, r->proxyreq == PROXYREQ_PROXY ?
- "Proxy-Authorization" : "Authorization") == 0)
- {
- t = trim_start(elts[i].val);
-
- if(strncasecmp(t, AUTH_PREFIX_BASIC, strlen(AUTH_PREFIX_BASIC)) == 0 &&
- !(ctx->types & AUTH_TYPE_BASIC))
- continue;
-
- else if(strncasecmp(t, AUTH_PREFIX_DIGEST, strlen(AUTH_PREFIX_DIGEST)) == 0 &&
- !(ctx->types & AUTH_TYPE_DIGEST))
- continue;
-
- else if(strncasecmp(t, AUTH_PREFIX_NTLM, strlen(AUTH_PREFIX_NTLM)) == 0 &&
- !(ctx->types & AUTH_TYPE_NTLM))
- continue;
-
- /* Only allow unknown if we don't have it */
- else if(!(ctx->types & AUTH_TYPE_ANY))
- continue;
-
- /* Extra blank line when at end */
- t = apr_pstrcat(r->pool, "Authorization: ", elts[i].val, "\n", NULL);
-
- if(write_data(ctx, r->server, t) == -1)
- return HTTP_INTERNAL_SERVER_ERROR;
-
- c++;
- }
- }
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: sent %d headers to daemon", c);
-
- return write_data(ctx, r->server, "\n");
-}
-
-static int
-write_needed_groups(httpauth_context_t *ctx, request_rec *r)
-{
- const apr_array_header_t *reqs_arr = ap_requires(r);
- require_line *reqs;
- const char *groups = NULL;
- const char *text;
- char *word;
- register int x;
- int m = r->method_number;
- int code, len;
-
- if(reqs_arr) {
- reqs = (require_line*)reqs_arr->elts;
- for (x = 0; x < reqs_arr->nelts; x++) {
- if (!(reqs[x].method_mask & (AP_METHOD_BIT << m)))
- continue;
-
- text = reqs[x].requirement;
- word = ap_getword_white (r->pool, &text);
-
- /* Append all groups to the string */
- if (strcmp (word, "group") == 0 && text && text[0]) {
- if (!groups)
- groups = text;
- else
- groups = apr_pstrcat (r->pool, text, " ", groups, NULL);
- }
- }
- }
-
- /* No groups, no need to send */
- if (!groups && !ctx->needed_groups)
- return 0;
-
- if (!groups)
- groups = "";
-
- /* Equal groups, no need to send */
- if (ctx->needed_groups && strcmp (groups, ctx->needed_groups) == 0)
- return 0;
-
- /* Groups changed, send to daemon */
- text = apr_pstrcat (r->pool, "SET Groups ", groups, "\n", NULL);
-
- if (write_data (ctx, r->server, text) < 0)
- return -1;
-
- ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: sent groups to daemon: %s", text);
-
- if (read_response (ctx, r, &code, NULL, NULL, 1) < 0)
- return -1;
-
- if (code != 202) {
- ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: couldn't send groups to daemon (Expected 202, got %d)", code);
- /* Older versions of the daemon did not support the 'SET Groups' command */
- if (code != 400)
- return -1;
- }
+typedef struct sid_session {
+ char *identifier;
+ time_t expiry;
+} sid_session_t;
- /* Save away the groups for next time */
- len = strlen (groups);
- if (len >= ctx->alloced_groups) {
- if (len < 512)
- len = 512;
- ctx->needed_groups = (char*)apr_pcalloc (ctx->child_pool, len * 2);
- ctx->alloced_groups = len * 2;
- }
- strcpy (ctx->needed_groups, groups);
- return 0;
-}
+/* Secret used to sign session cookies */
+static unsigned char session_secret[40];
-static httpauth_request_t*
-setup_request_hreq (request_rec *r, char *user, char *groups)
+static apr_status_t
+session_initialize (apr_pool_t *p, server_rec *s)
{
- httpauth_request_t* hreq;
+ apr_status_t status;
- hreq = (httpauth_request_t*)apr_pcalloc (r->pool, sizeof (*hreq));
- hreq->user = r->user;
- hreq->groups = groups;
-
- if (groups)
- apr_table_setn (r->subprocess_env, "HTTPAUTH_GROUPS", groups);
- else
- apr_table_unset (r->subprocess_env, "HTTPAUTH_GROUPS");
+#if APR_HAS_RANDOM
+ status = apr_generate_random_bytes (session_secret, sizeof (session_secret));
+#else
+#error APR random number support is missing; you probably need to install the truerand library.
+#endif
- ap_set_module_config (r->request_config, &httpauth_module, hreq);
+ if (status != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_CRIT, status, s,
+ "auth-singleid: couldn't generate random secret");
- return hreq;
+ return status;
}
-#endif
-
-typedef struct session_info {
- char *identifier;
- time_t expiry;
-} session_info_t;
-
static const char*
session_cookie_value (request_rec *r, const char *name)
{
@@ -1192,7 +355,7 @@ session_create_sig (apr_pool_t *p, const char *value)
apr_sha1_ctx_t ctx;
apr_sha1_init (&ctx);
- apr_sha1_update (&ctx, session_secret, strlen (session_secret));
+ apr_sha1_update (&ctx, (const char*)session_secret, sizeof (session_secret));
apr_sha1_update (&ctx, "\0", 1);
apr_sha1_update (&ctx, value, strlen (value));
apr_sha1_final (digest, &ctx);
@@ -1209,10 +372,10 @@ session_validate_sig (apr_pool_t *p, const char *sig, const char *value)
return strcmp (sig, valid) == 0;
}
-static session_info_t*
+static sid_session_t*
session_load_info (request_rec *r)
{
- session_info_t *sess;
+ sid_session_t *sess;
const char *value;
char *token, *sig, *end;
char *identifier;
@@ -1246,7 +409,7 @@ session_load_info (request_rec *r)
if (!ap_is_url (identifier))
return NULL;
- sess = apr_pcalloc (r->pool, sizeof (session_info_t));
+ sess = apr_pcalloc (r->pool, sizeof (sid_session_t));
sess->expiry = expiry;
sess->identifier = identifier;
@@ -1254,7 +417,7 @@ session_load_info (request_rec *r)
}
static void
-session_send_info (request_rec *r, session_info_t *sess)
+session_send_info (request_rec *r, sid_session_t *sess)
{
char *cookie, *sig, *value;
@@ -1267,53 +430,152 @@ session_send_info (request_rec *r, session_info_t *sess)
apr_table_addn (r->headers_out, "Set-Cookie", cookie);
}
-static session_info_t*
-session_copy_info (apr_pool_t *p, session_info_t *sess)
+static sid_session_t*
+session_copy_info (apr_pool_t *p, sid_session_t *sess)
{
- session_info_t *copy = apr_palloc (p, sizeof (*sess));
+ sid_session_t *copy = apr_palloc (p, sizeof (*sess));
copy->expiry = sess->expiry;
copy->identifier = apr_pstrdup (p, sess->identifier);
return copy;
}
+/* ---------------------------------------------------------------------------------------
+ * REQUEST ABSTRACTIONS
+ */
+
+struct sid_request {
+ int result;
+ request_rec *rec;
+};
+
+
+void
+sid_request_log_error (sid_request_t *req, const char *message, const char *detail)
+{
+ ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, req->rec,
+ "%s%s%s", message,
+ detail ? ": " : "",
+ detail ? detail : "");
+
+}
+
+const char*
+sid_request_qs (sid_request_t *req)
+{
+ return req->rec->args;
+}
+
+const char*
+sid_request_url (sid_request_t *req)
+{
+ /* function to determine if a connection is using https */
+ static APR_OPTIONAL_FN_TYPE(ssl_is_https) *using_https = NULL;
+ static int using_https_inited = 0;
+
+ const char *scheme;
+ const char *host;
+ const char *uri;
+ apr_port_t port;
+ int is_ssl;
+
+ if (!using_https_inited) {
+ using_https = APR_RETRIEVE_OPTIONAL_FN (ssl_is_https);
+ using_https_inited = 1;
+ }
+
+ is_ssl = using_https && using_https (req->rec->connection);
+ host = req->rec->hostname ? req->rec->hostname : ap_get_server_name (req->rec);
+ scheme = is_ssl ? "https" : "http";
+ port = ap_get_server_port (req->rec);
+ uri = req->rec->uri ? req->rec->uri : "";
+
+ /* Default ports? */
+ if ((port == 80 && !is_ssl) || (port == 443 && is_ssl))
+ return apr_psprintf (req->rec->pool, "%s://%s%s", scheme, host, uri);
+ else
+ return apr_psprintf (req->rec->pool, "%s://%s:%d%s", scheme, host, port, uri);
+}
+
+void
+sid_request_respond (sid_request_t *req, int code, const char *reason,
+ const char *header, ...)
+{
+ const char *value;
+ va_list va;
+
+ if (reason)
+ req->rec->status_line = apr_pstrdup (req->rec->pool, reason);
+
+ va_start(va, header);
+ while (header) {
+ value = va_arg (va, const char*);
+ apr_table_set (req->rec->err_headers_out, header, value);
+ header = va_arg (va, const char*);
+ }
+ va_end(va);
+
+ req->result = code;
+}
+
static void
-set_request_authenticated (request_rec *r, session_info_t *sess)
+set_request_authenticated (request_rec *r, sid_session_t *sess)
{
r->user = sess->identifier;
- r->ap_auth_type = SINGLEID_AUTHTYPE;
+ r->ap_auth_type = SID_AUTHTYPE;
ap_set_module_config (r->request_config, &auth_singleid_module, sess);
}
+void
+sid_request_authenticated (sid_request_t *req, const char *identifier)
+{
+ sid_session_t *sess;
+
+ sess = apr_pcalloc (req->rec->pool, sizeof (sid_session_t));
+ sess->identifier = apr_pstrdup (req->rec->pool, identifier);
+ sess->expiry = time (NULL) + 86400;
+
+ set_request_authenticated (req->rec, sess);
+ session_send_info (req->rec, sess);
+}
+
+/* ---------------------------------------------------------------------------------------
+ * MAIN HOOKS
+ */
+
+static int
+hook_initialize (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+{
+ int rc;
+
+ rc = shared_initialize (p, s);
+ if (rc != OK)
+ return rc;
+
+ return session_initialize (p, s);
+}
+
+static void
+hook_child (apr_pool_t *p, server_rec *s)
+{
+ shared_child (p, s);
+}
+
static int
hook_authenticate (request_rec* r)
{
- session_info_t *sess;
-#if 0
- httpauth_context_t* ctx;
- httpauth_request_t* hreq;
-#endif
+ sid_session_t *sess;
+ sid_context_t *ctx;
+ sid_request_t req;
const char* authtype;
-#if 0
- int code = 0;
- int ccode = 0;
- char *groups = NULL;
- char* details = NULL;
-#endif
request_rec* mainreq;
-#if 0
- int retried = 0;
-#endif
/* Make sure it's for us */
- if (!(authtype = ap_auth_type (r)) || strcasecmp (SINGLEID_AUTHTYPE, authtype) != 0)
+ if (!(authtype = ap_auth_type (r)) || strcasecmp (SID_AUTHTYPE, authtype) != 0)
return DECLINED;
-#if 0
- ctx = (httpauth_context_t*)ap_get_module_config(r->per_dir_config, &httpauth_module);
-
- if(!ctx->socketname || !ctx->handler)
+ ctx = (sid_context_t*)ap_get_module_config(r->per_dir_config, &auth_singleid_module);
+ if(ctx->identifier == NULL)
return DECLINED;
-#endif
mainreq = r;
@@ -1340,214 +602,23 @@ hook_authenticate (request_rec* r)
return OK;
}
+ req.result = OK;
+ req.rec = r;
- /* Otherwise start a new openid authentication */
- return DECLINED;
-
-#if 0
- /*
- * Check if we're in sync with the other processes,
- * and connected to the same daemon
- */
- if (ctx->socket != -1 && shared_get_if_changed (ctx, ctx->shared_version, NULL)) {
- ap_log_rerror (APLOG_MARK, APLOG_INFO, 0, r,
- "httpauth: syncing connection with other processes");
- disconnect_socket (ctx, r->server);
- }
-
-/* For jumping to when a connection has been closed */
-retry:
-
- if (ctx->socket == -1) {
- if (connect_httpauth (ctx, r) == -1) {
-
- if (ctx->socket == -1 && retried < ctx->retries) {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
- "httpauth: trying to connect to daemon again");
- ++retried;
- goto retry;
- }
-
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- /* Make sure we're starting on a clean slate */
- read_junk (ctx, r);
-
-
-
- /* Send off a request, along with groups, and read response */
- if (write_needed_groups (ctx, r) == -1 ||
- write_request (ctx, r) == -1 ||
- read_response (ctx, r, &code, &ccode, &details, 0) == -1) {
-
- /*
- * If our connection was closed by httpauthd then this
- * is where we get the error. Just do one retry to
- * try and reconnect. This happens often when restarting
- * httpauthd.
- */
-
- if (ctx->socket == -1 && retried < ctx->retries) {
- ap_log_rerror (APLOG_MARK, APLOG_WARNING, 0, r,
- "httpauth: reconnecting to to httpauthd");
- ++retried;
- goto retry;
- }
-
- ap_log_rerror (APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(errno), r,
- "httpauth: couldn't send request to httpauthd");
-
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if(code != 200)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: unexpected code while authenticating: %d", code);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* Copy over other headers */
- if(read_process_headers(ctx, ccode, r, &groups) == -1)
- return HTTP_INTERNAL_SERVER_ERROR;
-
- if (ccode == 200) {
- ap_log_rerror (APLOG_MARK, APLOG_INFO, 0, r,
- "httpauth: successful authentication for user: %s", details);
-
- r->user = apr_pstrdup (r->pool, details);
- r->ap_auth_type = HTTPAUTH_AUTHTYPE;
-
- /* Mark request as successfully authenticated */
- hreq = setup_request_hreq (r, details, groups);
- return OK;
- }
-
- return ccode;
-#endif
-}
-
-
-#if 0
-
-static const char*
-find_word_quoted (const char *all, const char *word)
-{
- const char *at;
- char before, after;
- size_t len = strlen (word);
-
- at = all;
- for (;;) {
- at = strstr (at, word);
- if (!at)
- return NULL;
-
- before = (at == all) ? 0 : *(at - 1);
- after = *(at + len);
-
- /* Beginning and end of a space delimited word */
- if ((!before || isspace (before)) &&
- (!after || isspace (after))) {
- return at;
- }
-
- /* Beginning and end of a quoted word */
- if ((before == '"' || before == '\'') && after == before)
- return at;
-
- at += len;
- }
-}
-
-static int
-httpauth_access(request_rec *r)
-{
- httpauth_context_t *ctx;
- httpauth_request_t *hreq;
- const char* authtype;
- char *user = r->user;
- int m = r->method_number;
- int method_restricted = 0;
- register int x;
- const char *text, *word;
- const apr_array_header_t *reqs_arr = ap_requires (r);
- require_line *reqs;
-
- /* Make sure it's for us */
- if (!(authtype = ap_auth_type (r)) || strcasecmp (HTTPAUTH_AUTHTYPE, authtype) != 0)
- return DECLINED;
-
- if (!reqs_arr)
- return OK;
-
- /* Dig out our configuration */
- ctx = ap_get_module_config (r->per_dir_config, &httpauth_module);
- hreq = ap_get_module_config (r->request_config, &httpauth_module);
- reqs = (require_line *)reqs_arr->elts;
-
- for (x = 0; x < reqs_arr->nelts; x++) {
- if (!(reqs[x].method_mask & (AP_METHOD_BIT << m)))
- continue;
+ /* Do the OpenID magic */
+ sid_consumer_authenticate (&req, ctx->store, ctx->trust_root, ctx->identifier);
- method_restricted = 1;
-
- text = reqs[x].requirement;
- word = ap_getword_white(r->pool, &text);
-
- /* Any valid user */
- if (strcmp (word, "valid-user") == 0) {
- return OK;
-
- /* Specific listed users */
- } else if (strcmp (word, "user") == 0) {
- while (text[0]) {
- word = ap_getword_conf (r->pool, &text);
- if (strcmp (user, word) == 0) {
- return OK;
- }
- }
-
- /* Specific groups */
- } else if (strcmp (word, "group") == 0) {
- if (hreq && hreq->groups) {
- while (text[0]) {
- word = ap_getword_conf (r->pool, &text);
- if (find_word_quoted (hreq->groups, word))
- return OK;
- }
- }
-
- /* What is this? */
- } else {
- ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
- "access to %s failed, reason: unknown require "
- "directive:\"%s\"", r->uri, reqs[x].requirement);
- }
- }
-
- if (!method_restricted)
- return OK;
-
- ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
- "access to %s failed, reason: user %s not allowed access",
- r->uri, user);
- return HTTP_UNAUTHORIZED;
+ return req.result;
}
-#endif
static void
register_hooks(apr_pool_t *p)
{
ap_log_perror (APLOG_MARK, APLOG_ERR, 0, p, "mod_auth_singleid registering hooks");
-#if 0
- ap_hook_post_config (httpauth_initialize, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_child_init (httpauth_child, NULL, NULL, APR_HOOK_MIDDLE);
+
+ ap_hook_post_config (hook_initialize, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init (hook_child, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_check_user_id (hook_authenticate, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_auth_checker (httpauth_access, NULL, NULL, APR_HOOK_MIDDLE);
-#endif
}
module AP_MODULE_DECLARE_DATA auth_singleid_module = {