summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--module/Makefile.am5
-rw-r--r--module/consumer.cc198
-rw-r--r--module/consumer.h18
-rw-r--r--module/mod_auth_singleid.c1333
-rw-r--r--module/mod_auth_singleid.h81
-rw-r--r--module/request.h16
-rw-r--r--module/storage.c156
-rw-r--r--module/storage.h34
8 files changed, 516 insertions, 1325 deletions
diff --git a/module/Makefile.am b/module/Makefile.am
index f2b92ca..cb4d829 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -6,8 +6,9 @@ AM_LDFLAGS = ${OPKELE_LIBS}
libmodauthsingleid_la_SOURCES = \
mod_auth_singleid.c \
- consumer.cc consumer.h \
- storage.c storage.h
+ mod_auth_singleid.h \
+ storage.c \
+ consumer.cc
install-exec-local:
@APXS@ -i -a -n 'auth_singleid' mod_auth_singleid.la
diff --git a/module/consumer.cc b/module/consumer.cc
index 15eadc8..91ab773 100644
--- a/module/consumer.cc
+++ b/module/consumer.cc
@@ -1,35 +1,77 @@
-#include "consumer.h"
+#include "mod_auth_singleid.h"
+
+#include <opkele/association.h>
+#include <opkele/exception.h>
+#include <opkele/types.h>
+#include <opkele/prequeue_rp.h>
+#include <opkele/util.h>
using opkele::assoc_t;
using opkele::association;
-using opkele::endpoint_t;
+using opkele::bad_input;
+using opkele::dumb_RP;
+using opkele::exception;
+using opkele::failed_discovery;
using opkele::failed_lookup;
-using opkele::params;
+using opkele::failed_xri_resolution;
+using opkele::no_endpoint;
+using opkele::openid_endpoint_t;
+using opkele::openid_message_t;
+using opkele::params_t;
using opkele::prequeue_RP;
using opkele::secret_t;
using std::string;
using std::vector;
+class LockShared
+{
+public:
+ LockShared()
+ { sid_shared_lock (); }
+ ~LockShared()
+ { sid_shared_unlock (); }
+};
+
+class AdaptorFix :
+ public params_t
+{
+public:
+ AdaptorFix(params_t& params)
+ { _params = params; };
+ virtual bool has_field(const string& n) const
+ { return _params.has_param("openid." + n); }
+ virtual const string& get_field(const string& n) const
+ { return _params.get_param("openid." + n); }
+private:
+ params_t _params;
+};
+
+
class Consumer :
public prequeue_RP
{
private: // types
- vector<endpoint_t> endpoints;
+ typedef vector<openid_endpoint_t> endpoints;
public: // interface
- Consumer(const char *url, singleid_board_t *board)
- : _url(url), _board(board)
+ Consumer(const char *url, sid_storage_t *store)
+ : _url(url), _store(store), _index(0)
{ }
public: // overrides
- virtual void begin_queueing() const
- { _endpoints.clear(); }
+ virtual void begin_queueing()
+ { _endpoints.clear(); _index = 0; }
virtual void queue_endpoint(const openid_endpoint_t& oep)
- { _endpoints.push(oep); }
+ { _endpoints.push_back(oep); }
+
+ virtual const openid_endpoint_t& get_endpoint() const;
+
+ virtual void next_endpoint()
+ { _index++; }
virtual void set_normalized_id(const string& nid)
{ _normalized = nid; }
@@ -37,7 +79,7 @@ public: // overrides
virtual const string get_normalized_id() const
{ return _normalized; }
- virtual const string get_this_url()
+ virtual const string get_this_url() const
{ return _url; }
virtual assoc_t store_assoc(const string& server, const string& handle,
@@ -48,25 +90,37 @@ public: // overrides
virtual assoc_t retrieve_assoc(const string& server, const string& handle);
- virtual assoc_t invalidate_assoc(const string& server, const string& handle);
+ virtual void invalidate_assoc(const string& server, const string& handle);
virtual void check_nonce(const string& server, const string& nonce);
private: // data
- singleid_board_t _board;
+ sid_storage_t *_store;
endpoints _endpoints;
string _normalized;
string _url;
+ endpoints::size_type _index;
};
+const openid_endpoint_t&
+Consumer::get_endpoint() const
+{
+ if (_index >= _endpoints.size())
+ throw no_endpoint("no more endpoints");
+ return _endpoints[_index];
+}
+
assoc_t
Consumer::store_assoc(const string& server, const string& handle,
const string& type, const secret_t& secret,
int expires_in)
{
- singleid_assoc_t data;
+ sid_assoc_t data;
int res;
+ if (!_store)
+ throw dumb_RP("no storage initialized");
+
data.server = server.c_str();
data.handle = handle.c_str();
data.type = type.c_str();
@@ -76,27 +130,32 @@ Consumer::store_assoc(const string& server, const string& handle,
{
LockShared lock; /* scoped lock */
- res = singleid_board_store_assoc (_board, &data);
+ res = sid_storage_store_assoc (_store, &data);
}
if (!res)
- throw dump_RP("association data was too large to fit in shared storage");
+ throw dumb_RP("association data was too large to fit in shared storage");
- return assoc_t(new association(server, handle, type, secret, expires_on, false));
+ return assoc_t(new association(server, handle, type, secret, expires_in, false));
}
assoc_t
Consumer::find_assoc(const string& server)
{
- singleid_assoc_t data = { 0, };
- association assoc = NULL;
+ sid_assoc_t data = { 0, };
+ association *assoc = NULL;
+
+ if (!_store)
+ throw dumb_RP("no storage initialized");
{
LockShared lock;
- if (singleid_board_find_assoc (_board, server.c_str(), NULL, &data))
+ if (sid_storage_find_assoc (_store, server.c_str(), NULL, &data)) {
+ secret_t secret;
+ secret.assign(data.secret, data.secret + data.n_secret);
assoc = new association(data.server, data.handle, data.type,
- secret_t(data.secret, data.secret + data.n_secret),
- data.expires, false);
+ secret, data.expires, false);
+ }
}
if (!assoc)
@@ -108,15 +167,20 @@ Consumer::find_assoc(const string& server)
assoc_t
Consumer::retrieve_assoc(const string& server, const string& handle)
{
- singleid_assoc_t data = { 0, };
- association assoc = NULL;
+ sid_assoc_t data = { 0, };
+ association *assoc = NULL;
+
+ if (!_store)
+ throw dumb_RP("no storage initialized");
{
LockShared lock;
- if (singleid_board_find_assoc (_board, server.c_str(), handle.c_str(), &data))
+ if (sid_storage_find_assoc (_store, server.c_str(), handle.c_str(), &data)) {
+ secret_t secret;
+ secret.assign(data.secret, data.secret + data.n_secret);
assoc = new association(data.server, data.handle, data.type,
- secret_t(data.secret, data.secret + data.n_secret),
- data.expires, false);
+ secret, data.expires, false);
+ }
}
if (!assoc)
@@ -125,19 +189,24 @@ Consumer::retrieve_assoc(const string& server, const string& handle)
return assoc_t(assoc);
}
-assoc_t
+void
Consumer::invalidate_assoc(const string& server, const string& handle)
{
+ if (!_store)
+ throw dumb_RP("no storage initialized");
+
LockShared lock;
- singleid_board_invalidate_assoc (_board, server.c_str(), handle.c_str());
+ sid_storage_invalidate_assoc (_store, server.c_str(), handle.c_str());
}
-
void
Consumer::check_nonce(const string& server, const string& nonce)
{
+ if (!_store)
+ throw dumb_RP("no storage initialized");
+
LockShared lock;
- singleid_board_check_nonce (_board, server.c_str(), nonce.c_str());
+ sid_storage_check_nonce (_store, server.c_str(), nonce.c_str());
}
/* -----------------------------------------------------------------------
@@ -145,17 +214,13 @@ Consumer::check_nonce(const string& server, const string& nonce)
*/
static void
-filter_openid_params (params_t &params, params_t &extensions)
+filter_openid_params (params_t &params)
{
for (params_t::iterator it = params.begin(); it != params.end(); ) {
const string& name = it->first;
if (name.find ("openid.") == 0) {
- /* Extension params have at least a second dot */
- if (name.find ('.', sizeof ("openid.")))
- extensions.insert(*it);
-
/* We erase an increment together, must use post-increment operator */
- it->erase(it++);
+ params.erase (it++);
} else {
/* Did not match, just go to next element */
++it;
@@ -164,7 +229,32 @@ filter_openid_params (params_t &params, params_t &extensions)
}
static void
-start_auth (sid_request_t *req, Consumer &consumer, params_t &params,
+parse_query_string (const char *qs, params_t &params)
+{
+ string pair, key, value;
+ const char *at;
+
+ while (qs && *qs) {
+ at = strchr (qs, '&');
+ if (at == NULL)
+ at = qs + strlen (qs);
+ pair = string(qs, at);
+ string::size_type loc = pair.find('=', 0);
+ if (loc != string::npos) {
+ key = pair.substr (0, loc);
+ value = pair.substr (loc + 1);
+ } else {
+ key = pair;
+ value = "";
+ }
+
+ params[opkele::util::url_decode(key)] = opkele::util::url_decode(value);
+ qs = at;
+ }
+}
+
+static void
+begin_auth (sid_request_t *req, Consumer &consumer, params_t &params,
const string& trust_root, const string &identity)
{
/* Remove all openid params, and stash away extensions */
@@ -172,32 +262,43 @@ start_auth (sid_request_t *req, Consumer &consumer, params_t &params,
string return_to = params.append_query (consumer.get_this_url(), "");
params_t result;
+ string redirect;
try {
openid_message_t cm;
consumer.initiate (identity);
- result = consumer.checkid_ (cm, opkele::mode_checkid_setup, return_to, trust_root);
- output = result.append_query (consumer.get_endpoint().uri);
+ consumer.checkid_ (cm, opkele::mode_checkid_setup, return_to, trust_root);
+ redirect = cm.append_query (consumer.get_endpoint().uri);
} catch (failed_xri_resolution &ex) {
- sid_request_respond (xxx, xxx, xxx);
+ sid_request_respond (req, 503, "Invalid Identifier", NULL, NULL);
+ sid_request_log_error (req, "failed xri resolution while while discovering identity provider",
+ ex.what ());
return;
} catch (failed_discovery &ex) {
- sid_request_respond (xxx, xxx, xxx);
+ sid_request_respond (req, 503, "Invalid Identifier", NULL, NULL);
+ sid_request_log_error (req, "failed discovery while while discovering identity provider",
+ ex.what ());
return;
} catch (bad_input &ex) {
- sid_request_respond (xxx, xxx, xxx);
+ sid_request_respond (req, 503, "Invalid Identifier", NULL, NULL);
+ sid_request_log_error (req, "bad input while while discovering identity provider",
+ ex.what());
return;
} catch (exception &ex) {
- sid_request_respond (xxx, xxx, xxx);
- xxx log xxx;
+ sid_request_respond (req, 500, NULL, NULL, NULL);
+ sid_request_log_error (req, "error while while discovering identity provider",
+ ex.what());
return;
}
- sid_request_respond (xxx, xxx, xxx);
+ sid_request_respond (req, 307, "Moved Temporarily", NULL,
+ "Location", redirect.c_str(),
+ "Cache-Control", "no-cache",
+ NULL);
}
static void
@@ -208,14 +309,15 @@ complete_auth (sid_request_t *req, Consumer &consumer, params_t &params)
string identity = consumer.get_claimed_id();
sid_request_authenticated (req, identity.c_str());
} catch (exception &ex) {
- sid_request_respond (xxx, xxx, xxx);
+ sid_request_respond (req, 500, NULL, NULL, NULL);
+ sid_request_log_error (req, "error while completing authentication: %s", ex.what());
}
}
static void
cancelled_auth (sid_request_t *req, Consumer &consumer, params_t &params)
{
- sid_request_respond (xxx, xxx, xxx);
+ sid_request_respond (req, 401, "Authentication Required", NULL, NULL);
}
void
@@ -239,6 +341,4 @@ sid_consumer_authenticate(sid_request_t *req, sid_storage_t *store,
cancelled_auth (req, consumer, params);
else
begin_auth (req, consumer, params, trust_root, identity);
-
- consumer.close();
}
diff --git a/module/consumer.h b/module/consumer.h
deleted file mode 100644
index 5cea9f8..0000000
--- a/module/consumer.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef CONSUMER_H_
-#define CONSUMER_H_
-
-#include "request.h"
-#include "storage.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void sid_consumer_authenticate (sid_request_t *req, sid_storage_t *store,
- const char *trust_root, const char *identity);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* CONSUMER_H_ */
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 = {
diff --git a/module/mod_auth_singleid.h b/module/mod_auth_singleid.h
new file mode 100644
index 0000000..68b5490
--- /dev/null
+++ b/module/mod_auth_singleid.h
@@ -0,0 +1,81 @@
+#ifndef MOD_AUTH_SINGLEID_H_
+#define MOD_AUTH_SINGLEID_H_
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void sid_shared_lock (void);
+
+void sid_shared_unlock (void);
+
+typedef struct sid_request sid_request_t;
+
+void sid_request_log_error (sid_request_t *req,
+ const char *message,
+ const char *detail);
+
+const char* sid_request_qs (sid_request_t *req);
+
+const char* sid_request_url (sid_request_t *req);
+
+void sid_request_respond (sid_request_t *req,
+ int code,
+ const char *reason,
+ const char *header,
+ ...);
+
+void sid_request_authenticated (sid_request_t *req,
+ const char *identifier);
+
+/* -----------------------------------------------------------------------------------
+ * STORAGE: Actually, communications white-board between processes/threads.
+ */
+
+typedef struct sid_storage sid_storage_t;
+
+typedef struct sid_assoc {
+ const char *server;
+ const char *handle;
+ const char *type;
+ const unsigned char *secret;
+ size_t n_secret;
+ time_t expires;
+} sid_assoc_t;
+
+sid_storage_t* sid_storage_initialize (void *memory,
+ size_t n_memory);
+
+int sid_storage_check_nonce (sid_storage_t *storage,
+ const char *server,
+ const char *nonce);
+
+int sid_storage_store_assoc (sid_storage_t *storage,
+ const sid_assoc_t *assoc);
+
+int sid_storage_find_assoc (sid_storage_t *storage,
+ const char *server,
+ const char *handle,
+ sid_assoc_t *assoc);
+
+void sid_storage_invalidate_assoc (sid_storage_t *storage,
+ const char *server,
+ const char *handle);
+
+/* -----------------------------------------------------------------------------------
+ * OPENID CONSUMER
+ */
+
+void sid_consumer_authenticate (sid_request_t *req,
+ sid_storage_t *store,
+ const char *trust_root,
+ const char *identity);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MOD_AUTH_SINGLEID_H_ */
diff --git a/module/request.h b/module/request.h
deleted file mode 100644
index 6c63a25..0000000
--- a/module/request.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef REQUEST_H_
-#define REQUEST_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-typedef void sid_request_t;
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* REQUEST_H_ */
diff --git a/module/storage.c b/module/storage.c
index 3cb9cdd..cb1085d 100644
--- a/module/storage.c
+++ b/module/storage.c
@@ -1,8 +1,15 @@
+#include "mod_auth_singleid.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <apr_sha1.h>
+
/* Yes, this looks backwards. */
-typedef char nonce_t[40];
+typedef char sid_nonce_t[40];
-struct singleid_board {
+struct sid_storage {
/* The association with our server */
char server[256];
@@ -13,7 +20,7 @@ struct singleid_board {
time_t expires;
/* Book keeping for the records */
- nonce_t *records;
+ sid_nonce_t *records;
size_t first;
size_t total;
size_t count;
@@ -21,78 +28,78 @@ struct singleid_board {
};
int
-singleid_board_store_assoc (singleid_board_t *board, const singleid_assoc_t *assoc)
+sid_storage_store_assoc (sid_storage_t *store, const sid_assoc_t *assoc)
{
- assert (board);
+ assert (store);
assert (assoc);
/* Check that we have enough space to store this information */
- if ((assoc->server && strlen (assoc->server) > sizeof (board->server)) ||
- (assoc->handle && strlen (assoc->handle) > sizeof (board->handle)) ||
- (assoc->n_secret && assoc->n_secret > sizeof (board->secret)) ||
- (assoc->type && strlen (assoc->type) > sizeof (board->type)))
+ if ((assoc->server && strlen (assoc->server) > sizeof (store->server)) ||
+ (assoc->handle && strlen (assoc->handle) > sizeof (store->handle)) ||
+ (assoc->n_secret && assoc->n_secret > sizeof (store->secret)) ||
+ (assoc->type && strlen (assoc->type) > sizeof (store->type)))
return 0;
- strcpy (board->server, assoc->server ? assoc->server : "");
- strcpy (board->handle, assoc->handle ? assoc->handle : "");
- memcpy (board->secret, assoc->secret, assoc->n_secret);
- strcpy (board->type, assoc->type ? assoc->type : "");
- board->expires = assoc->expires;
+ strcpy (store->server, assoc->server ? assoc->server : "");
+ strcpy (store->handle, assoc->handle ? assoc->handle : "");
+ memcpy (store->secret, assoc->secret, assoc->n_secret);
+ strcpy (store->type, assoc->type ? assoc->type : "");
+ store->expires = assoc->expires;
return 1;
}
int
-singleid_board_find_assoc (singleid_board_t *board, const char *server,
- const char *handle, singleid_assoc_t *assoc)
+sid_storage_find_assoc (sid_storage_t *store, const char *server,
+ const char *handle, sid_assoc_t *assoc)
{
- assert (board);
+ assert (store);
assert (assoc);
- if (server && (strlen (server) > sizeof (board->server) ||
- strcmp (server, board->server) != 0))
+ if (server && (strlen (server) > sizeof (store->server) ||
+ strcmp (server, store->server) != 0))
return 0;
- if (handle && (strlen (handle) > sizeof (board->handle) ||
- strcmp (handle, board->handle) != 0))
+ if (handle && (strlen (handle) > sizeof (store->handle) ||
+ strcmp (handle, store->handle) != 0))
return 0;
- assoc->server = board->server;
- assoc->handle = board->handle;
- assoc->type = board->type;
- assoc->secret = board->secret;
- assoc->n_secret = board->n_secret;
- assoc->expires = board->expires;
+ assoc->server = store->server;
+ assoc->handle = store->handle;
+ assoc->type = store->type;
+ assoc->secret = store->secret;
+ assoc->n_secret = store->n_secret;
+ assoc->expires = store->expires;
return 1;
}
void
-singleid_board_invalidate_assoc (singleid_board_t *board, const char *server,
+sid_storage_invalidate_assoc (sid_storage_t *store, const char *server,
const char *handle)
{
- singleid_assoc_t dummy;
- assert (board);
-
- if (singleid_board_find_assoc (board, server, handle, &dummy)) {
- board->server[0] = 0;
- board->handle[0] = 0;
- board->type[0] = 0;
- memset (board->secret, 0, sizeof (board->secret));
- board->n_secret = 0;
- board->expires = 0;
- board->secret[0] = 0;
+ sid_assoc_t dummy;
+ assert (store);
+
+ if (sid_storage_find_assoc (store, server, handle, &dummy)) {
+ store->server[0] = 0;
+ store->handle[0] = 0;
+ store->type[0] = 0;
+ memset (store->secret, 0, sizeof (store->secret));
+ store->n_secret = 0;
+ store->expires = 0;
+ store->secret[0] = 0;
}
}
#define nonce_compare(a, b) \
- memcmp (a, b, sizeof (nonce_t))
+ memcmp (a, b, sizeof (sid_nonce_t))
static void
-nonce_put (nonce_t rec, const char *nonce)
+nonce_put (sid_nonce_t rec, const char *nonce)
{
size_t len = strlen (nonce);
char *dst = (char*)rec;
- /* If it's short enough, then just board. Fast */
+ /* If it's short enough, then just store. Fast */
if (len < sizeof (rec)) {
memcpy (dst, nonce, len);
memset (dst + len, 0, sizeof (rec) - len);
@@ -101,7 +108,7 @@ nonce_put (nonce_t rec, const char *nonce)
} else {
apr_sha1_ctx_t ctx;
- assert (sizeof (nonce_t) == APR_SHA1_DIGESTSIZE + 20);
+ assert (sizeof (sid_nonce_t) == APR_SHA1_DIGESTSIZE + 20);
assert (len > 20);
/* The date prefix we just copy in */
@@ -110,65 +117,64 @@ nonce_put (nonce_t rec, const char *nonce)
/* Hash the rest into the buffer */
apr_sha1_init (&ctx);
apr_sha1_update (&ctx, nonce + 20, len - 20);
- apr_sha1_final (dst + 20, &ctx);
+ apr_sha1_final ((unsigned char*)dst + 20, &ctx);
}
}
static void
-insert_nonce_record (singleid_board_t *board, nonce_t rec, size_t at)
+insert_nonce_record (sid_storage_t *store, sid_nonce_t rec, size_t at)
{
- nonce_t *records = board->records;
- size_t from, to, num;
+ sid_nonce_t *records = store->records;
- assert (board->total > 2);
- assert (at < board->total);
- assert (at != board->first);
+ assert (store->total > 2);
+ assert (at < store->total);
+ assert (at != store->first);
/* Insertion right after latest, either ancient, more likely top */
- if (at == board->first + 1 % board->total) {
+ if (at == store->first + 1 % store->total) {
/* We can just copy in at this point */
/* Our ring has empty space in it, so always push forwards, but only until first */
- } else if (!board->wrapped) {
- memmove (records + at + 1, records + at, sizeof (rec) * (board->first - at));
- board->first += 1;
+ } else if (!store->wrapped) {
+ memmove (records + at + 1, records + at, sizeof (rec) * (store->first - at));
+ store->first += 1;
/* Move data backwards to make space */
- } else if (board->first < at) {
- memmove (records + board->first + 2, records + board->first + 1,
- sizeof (rec) * (at - board->first));
+ } else if (store->first < at) {
+ memmove (records + store->first + 2, records + store->first + 1,
+ sizeof (rec) * (at - store->first));
/* Move data forwards to make space simply */
} else {
- memmove (records + at + 1, records + at, sizeof (rec) * (board->first - at - 1));
+ memmove (records + at + 1, records + at, sizeof (rec) * (store->first - at - 1));
}
memcpy (records[at], rec, sizeof (rec));
- ++board->count;
+ ++store->count;
/* Track whether we have a full ring or not. */
- if (!board->wrapped && board->count > board->total)
- board->wrapped = 1;
+ if (!store->wrapped && store->count > store->total)
+ store->wrapped = 1;
}
int
-singleid_board_check_nonce (singleid_board_t *board, const char *nonce)
+sid_storage_check_nonce (sid_storage_t *store, const char *server, const char *nonce)
{
- nonce_t *records;
- nonce_t rec;
+ sid_nonce_t *records;
+ sid_nonce_t rec;
size_t at, lower, upper, mid;
int res;
- assert (board);
+ assert (store);
assert (nonce);
- assert (board->records);
- assert (board->first < board->total);
+ assert (store->records);
+ assert (store->first < store->total);
nonce_put (rec, nonce);
- records = board->records;
+ records = store->records;
/* Best case scenario, new nonce is higher than our latest one */
- res = nonce_compare (rec, records[top]);
+ res = nonce_compare (rec, records[store->first]);
/* Was the last nonce */
if (res == 0) {
@@ -176,16 +182,16 @@ singleid_board_check_nonce (singleid_board_t *board, const char *nonce)
/* Newer than anything, push on top */
} else if (res < 0) {
- at = (board->first + 1) % board->total;
- insert_nonce_record (board, rec, at);
- board->first = at;
+ at = (store->first + 1) % store->total;
+ insert_nonce_record (store, rec, at);
+ store->first = at;
return 0;
}
/* Do a binary search for the item */
- for (lower = 0, upper = board->total; lower < upper; ) {
+ for (lower = 0, upper = store->total; lower < upper; ) {
mid = lower + ((upper - lower) / 2); // Note: not (low + high) / 2 !!
- at = at + board->first % board->total;
+ at = at + store->first % store->total;
res = nonce_compare (rec, records[at]);
if (res == 0)
return 1; /* Have the nonce */
@@ -195,6 +201,6 @@ singleid_board_check_nonce (singleid_board_t *board, const char *nonce)
upper = mid;
}
- insert_nonce_record (board, rec, at);
+ insert_nonce_record (store, rec, at);
return 0; /* Didn't find nonce */
}
diff --git a/module/storage.h b/module/storage.h
deleted file mode 100644
index 4c73da6..0000000
--- a/module/storage.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef BOARD_H_
-#define BOARD_H_
-
-#include <stdlib.h>
-
-/* Communications white-board between processes/threads */
-
-typedef struct sid_storage sid_storage_t;
-
-typedef struct sid_assoc {
- const char *server;
- const char *handle;
- const char *type;
- const unsigned char *secret;
- const size_t n_secret;
- time_t expires;
-} sid_assoc_t;
-
-int singleid_board_check_nonce (sid_storage_t *storage,
- const char *nonce);
-
-int singleid_board_store_assoc (sid_storage_t *storage,
- const sid_assoc_t *assoc);
-
-int singleid_board_find_assoc (sid_storage_t *storage,
- const char *server,
- const char *handle,
- sid_assoc_t *assoc);
-
-void singleid_board_invalidate_assoc (sid_storage_t *storage,
- const char *server,
- const char *handle);
-
-#endif /* BOARD_H_ */