summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2004-08-09 18:35:56 +0000
committerStef Walter <stef@memberwebs.com>2004-08-09 18:35:56 +0000
commit670eba73c474230e31d688e9568fcd540b4e3b39 (patch)
tree624502f0713a9c6f3b0520416134b405f150f356 /daemon
parentb0e50bbeb12e6247dd52dfd9e44c62f558c8a3a0 (diff)
- added request parameter to ha_message...
- combined ha_request and ha_response
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/basic.c48
-rw-r--r--daemon/basic.h6
-rw-r--r--daemon/bd.c171
-rw-r--r--daemon/bd.h10
-rw-r--r--daemon/digest.c822
-rw-r--r--daemon/digest.h32
-rw-r--r--daemon/httpauthd.c2021
-rw-r--r--daemon/httpauthd.h137
-rw-r--r--daemon/ldap.c200
-rw-r--r--daemon/misc.c835
-rw-r--r--daemon/ntlm.c1156
-rw-r--r--daemon/simple.c82
-rw-r--r--daemon/usuals.h6
14 files changed, 2763 insertions, 2765 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 5ad8665..c669f04 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -1,7 +1,7 @@
sbin_PROGRAMS = httpauthd
-httpauthd_SOURCES = httpauthd.c httpauthd.h usuals.h compat.h compat.c \
+httpauthd_SOURCES = httpauthd.c httpauthd.h usuals.h compat.h compat.c bd.h bd.c\
buffer.c misc.c basic.h basic.c ntlm.c hash.c hash.h ntlmssp.h ntlmssp.c \
md5.c md5.h sha1.c sha1.h digest.h digest.c ldap.c defaults.h simple.c \
../common/sock_any.c ../common/sock_any.h ../common/stringx.c\
diff --git a/daemon/basic.c b/daemon/basic.c
index fc0a096..6b41a36 100644
--- a/daemon/basic.c
+++ b/daemon/basic.c
@@ -6,39 +6,39 @@
int basic_parse(const char* header, ha_buffer_t* buf, basic_header_t* rec)
{
- char* t;
- ASSERT(header && buf && rec);
+ char* t;
+ ASSERT(header && buf && rec);
- memset(rec, 0, sizeof(*rec));
+ memset(rec, 0, sizeof(*rec));
- /*
- * Authorization header is in this format:
- *
- * "Basic " B64(user ":" password)
- */
+ /*
+ * Authorization header is in this format:
+ *
+ * "Basic " B64(user ":" password)
+ */
- header = trim_start(header);
- header = (const char*)ha_bufdec64(buf, header, NULL);
+ header = trim_start(header);
+ header = (const char*)ha_bufdec64(buf, header, NULL);
- if(!header)
- return ha_buferr(buf) ? HA_CRITERROR : HA_FALSE;
+ if(!header)
+ return ha_buferr(buf) ? HA_CRITERROR : HA_FALSE;
- /* We have a cache key at this point so hash it */
- md5_string(rec->key, header);
+ /* We have a cache key at this point so hash it */
+ md5_string(rec->key, header);
- /* Parse the user. We need it in any case */
- t = strchr(header, ':');
- if(t != NULL)
- {
- /* Break the string in half */
- *t = 0;
+ /* Parse the user. We need it in any case */
+ t = strchr(header, ':');
+ if(t != NULL)
+ {
+ /* Break the string in half */
+ *t = 0;
- rec->user = header;
- rec->password = t + 1;
- }
+ rec->user = header;
+ rec->password = t + 1;
+ }
- return HA_OK;
+ return HA_OK;
}
diff --git a/daemon/basic.h b/daemon/basic.h
index c28dc1e..775a3a7 100644
--- a/daemon/basic.h
+++ b/daemon/basic.h
@@ -6,9 +6,9 @@
typedef struct basic_header
{
- const char* user;
- const char* password;
- unsigned char key[MD5_LEN];
+ const char* user;
+ const char* password;
+ unsigned char key[MD5_LEN];
}
basic_header_t;
diff --git a/daemon/bd.c b/daemon/bd.c
index 916c453..6cd7b6b 100644
--- a/daemon/bd.c
+++ b/daemon/bd.c
@@ -25,8 +25,8 @@ static unsigned char g_digest_secret[DIGEST_SECRET_LEN];
static void free_hash_object(void* arg, void* val)
{
- if(val && val != BASIC_ESTABLISHED)
- free(val);
+ if(val && val != BASIC_ESTABLISHED)
+ free(val);
}
static digest_record_t* get_cached_digest(bd_context_t* ctx, ha_context_t* c,
@@ -92,7 +92,7 @@ static int save_cached_digest(bd_context_t* ctx, ha_context_t* c,
if(!r)
{
- ha_messagex(LOG_CRIT, "out of memory");
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
return HA_CRITERROR;
}
@@ -120,22 +120,21 @@ static int add_cached_basic(bd_context_t* ctx, ha_context_t* c,
if(!r)
{
- ha_messagex(LOG_CRIT, "out of memory");
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
return HA_CRITERROR;
}
return HA_OK;
}
-static int do_basic_response(bd_context_t* ctx, const char* header,
- const ha_request_t* req, ha_response_t* resp)
+static int do_basic_response(ha_request_t* rq, bd_context_t* ctx, const char* header)
{
basic_header_t basic;
int ret = HA_FALSE;
- ASSERT(header && resp && req);
+ ASSERT(header && rq);
- if((ret = basic_parse(header, req->buf, &basic)) < 0)
+ if((ret = basic_parse(header, rq->buf, &basic)) < 0)
return ret;
/* Past this point we don't return directly */
@@ -143,7 +142,7 @@ static int do_basic_response(bd_context_t* ctx, const char* header,
/* Check and see if this connection is in the cache */
if(have_cached_basic(ctx, basic.key))
{
- ha_messagex(LOG_NOTICE, "bd: validated basic user against cache: %s",
+ ha_messagex(rq, LOG_NOTICE, "validated basic user against cache: %s",
basic.user);
ret = HA_OK;
goto finally;
@@ -153,42 +152,41 @@ static int do_basic_response(bd_context_t* ctx, const char* header,
if(!basic.user || !basic.user[0] ||
!basic.password || !basic.password[0])
{
- ha_messagex(LOG_NOTICE, "bd: no valid basic auth info");
+ ha_messagex(rq, LOG_NOTICE, "no valid basic auth info");
ret = HA_FALSE;
goto finally;
}
ASSERT(ctx->f_validate_basic);
- ret = ctx->f_validate_basic(req, basic.user, basic.password);
+ ret = ctx->f_validate_basic(rq, basic.user, basic.password);
finally:
if(ret == HA_OK)
{
- resp->code = HA_SERVER_OK;
- resp->detail = basic.user;
+ rq->resp_code = HA_SERVER_OK;
+ rq->resp_detail = basic.user;
/* We put this connection into the successful connections */
- ret = add_cached_basic(ctx, req->context, basic.key);
+ ret = add_cached_basic(ctx, rq->context, basic.key);
}
return ret;
}
-static int do_digest_challenge(bd_context_t* ctx, const ha_request_t* req,
- ha_response_t* resp, int stale)
+static int do_digest_challenge(ha_request_t* rq, bd_context_t* ctx, int stale)
{
unsigned char nonce[DIGEST_NONCE_LEN];
const char* nonce_str;
const char* header;
- ASSERT(ctx && resp && req);
+ ASSERT(ctx && rq);
#ifdef _DEBUG
- if(req->context->digest_debugnonce)
+ if(rq->context->digest_debugnonce)
{
- nonce_str = req->context->digest_debugnonce;
- ha_messagex(LOG_WARNING, "bd: using debug nonce. security non-existant.");
+ nonce_str = rq->context->digest_debugnonce;
+ ha_messagex(rq, LOG_WARNING, "using debug nonce. security non-existant.");
}
else
#endif
@@ -196,28 +194,27 @@ static int do_digest_challenge(bd_context_t* ctx, const ha_request_t* req,
unsigned char nonce[DIGEST_NONCE_LEN];
digest_makenonce(nonce, g_digest_secret, NULL);
- nonce_str = ha_bufenchex(req->buf, nonce, DIGEST_NONCE_LEN);
+ nonce_str = ha_bufenchex(rq->buf, nonce, DIGEST_NONCE_LEN);
if(!nonce_str)
- return HA_CRITERROR;
+ return HA_CRITERROR;
}
/* Now generate a message to send */
- header = digest_challenge(req->buf, nonce_str, req->context->realm,
- req->digest_domain, stale);
+ header = digest_challenge(rq->buf, nonce_str, rq->context->realm,
+ rq->digest_domain, stale);
if(!header)
return HA_CRITERROR;
/* And append it nicely */
- resp->code = HA_SERVER_DECLINE;
- ha_addheader(resp, "WWW-Authenticate", header);
+ rq->resp_code = HA_SERVER_DECLINE;
+ ha_addheader(rq, "WWW-Authenticate", header);
- ha_messagex(LOG_DEBUG, "bd: created digest challenge with nonce: %s", nonce_str);
+ ha_messagex(rq, LOG_DEBUG, "created digest challenge with nonce: %s", nonce_str);
return HA_OK;
}
-static int do_digest_response(bd_context_t* ctx, const char* header,
- const ha_request_t* req, ha_response_t* resp)
+static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* header)
{
unsigned char nonce[DIGEST_NONCE_LEN];
digest_header_t dg;
@@ -228,26 +225,26 @@ static int do_digest_response(bd_context_t* ctx, const char* header,
int stale = 0;
int r;
- ASSERT(ctx && header && req && resp);
+ ASSERT(ctx && header && rq);
/* We use this below to send a default response */
- resp->code = -1;
+ rq->resp_code = -1;
- if((r = digest_parse(header, req->buf, &dg, nonce)) < 0)
+ if((r = digest_parse(header, rq->buf, &dg, nonce)) < 0)
return r;
#ifdef _DEBUG
- if(req->context->digest_debugnonce)
+ if(rq->context->digest_debugnonce)
{
- if(dg.nonce && strcmp(dg.nonce, req->context->digest_debugnonce) != 0)
+ if(dg.nonce && strcmp(dg.nonce, rq->context->digest_debugnonce) != 0)
{
ret = HA_FALSE;
- ha_messagex(LOG_WARNING, "bd: digest response contains invalid nonce");
+ ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce");
goto finally;
}
/* Do a rough hash into the real nonce, for use as a key */
- md5_string(nonce, req->context->digest_debugnonce);
+ md5_string(nonce, rq->context->digest_debugnonce);
/* Debug nonce's never expire */
expiry = time(NULL);
@@ -259,18 +256,18 @@ static int do_digest_response(bd_context_t* ctx, const char* header,
if(r != HA_OK)
{
if(r == HA_FALSE)
- ha_messagex(LOG_WARNING, "bd: digest response contains invalid nonce");
+ ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce");
goto finally;
}
}
- rec = get_cached_digest(ctx, req->context, nonce);
+ rec = get_cached_digest(ctx, rq->context, nonce);
/* Check to see if we're stale */
- if((expiry + req->context->cache_timeout) <= time(NULL))
+ if((expiry + rq->context->cache_timeout) <= time(NULL))
{
- ha_messagex(LOG_INFO, "bd: nonce expired, sending stale challenge: %s",
+ ha_messagex(rq, LOG_INFO, "nonce expired, sending stale challenge: %s",
dg.username);
stale = 1;
@@ -279,7 +276,7 @@ static int do_digest_response(bd_context_t* ctx, const char* header,
if(!rec)
{
- ha_messagex(LOG_INFO, "bd: no record in cache, creating one: %s", dg.username);
+ ha_messagex(rq, LOG_INFO, "no record in cache, creating one: %s", dg.username);
/*
* If we're valid but don't have a record in the
@@ -294,7 +291,7 @@ static int do_digest_response(bd_context_t* ctx, const char* header,
}
ASSERT(ctx->f_complete_digest);
- r = ctx->f_complete_digest(req, dg.username, rec->ha1);
+ r = ctx->f_complete_digest(rq, dg.username, rec->ha1);
if(r != HA_OK)
{
ret = r;
@@ -308,32 +305,32 @@ static int do_digest_response(bd_context_t* ctx, const char* header,
rec->nc++;
}
- ret = digest_check(&dg, rec, req->context, req->buf,
- req->args[AUTH_ARG_METHOD], req->args[AUTH_ARG_URI]);
+ ret = digest_check(&dg, rec, rq->context, rq->buf,
+ rq->req_args[AUTH_ARG_METHOD], rq->req_args[AUTH_ARG_URI]);
if(ret == HA_BADREQ)
{
ret = HA_FALSE;
- resp->code = HA_SERVER_BADREQ;
+ rq->resp_code = HA_SERVER_BADREQ;
}
else if(ret == HA_OK)
{
- resp->code = HA_SERVER_OK;
- resp->detail = dg.username;
+ rq->resp_code = HA_SERVER_OK;
+ rq->resp_detail = dg.username;
/* Figure out if we need a new nonce */
- if((expiry + (req->context->cache_timeout -
- (req->context->cache_timeout / 8))) < time(NULL))
+ if((expiry + (rq->context->cache_timeout -
+ (rq->context->cache_timeout / 8))) < time(NULL))
{
- ha_messagex(LOG_INFO, "bd: nonce almost expired, creating new one: %s",
+ ha_messagex(rq, LOG_INFO, "nonce almost expired, creating new one: %s",
dg.username);
digest_makenonce(nonce, g_digest_secret, NULL);
stale = 1;
}
- t = digest_respond(req->buf, &dg, rec, stale ? nonce : NULL);
+ t = digest_respond(rq->buf, &dg, rec, stale ? nonce : NULL);
if(!t)
{
ret = HA_CRITERROR;
@@ -341,12 +338,12 @@ static int do_digest_response(bd_context_t* ctx, const char* header,
}
if(t[0])
- ha_addheader(resp, "Authentication-Info", t);
+ ha_addheader(rq, "Authentication-Info", t);
- ha_messagex(LOG_NOTICE, "bd: validated digest user: %s", dg.username);
+ ha_messagex(rq, LOG_NOTICE, "validated digest user: %s", dg.username);
/* Put the connection into the cache */
- if((r = save_cached_digest(ctx, req->context, rec)) < 0)
+ if((r = save_cached_digest(ctx, rq->context, rec)) < 0)
ret = r;
rec = NULL;
@@ -359,8 +356,8 @@ finally:
free(rec);
/* If nobody above responded then challenge the client again */
- if(resp->code == -1)
- return do_digest_challenge(ctx, req, resp, stale);
+ if(rq->resp_code == -1)
+ return do_digest_challenge(rq, ctx, stale);
return ret;
}
@@ -375,7 +372,7 @@ int bd_init(ha_context_t* context)
/* Global initialization */
if(!context)
{
- ha_messagex(LOG_DEBUG, "bd: generating secret");
+ ha_messagex(NULL, LOG_DEBUG, "generating secret");
return ha_genrandom(g_digest_secret, DIGEST_SECRET_LEN);
}
@@ -390,15 +387,15 @@ int bd_init(ha_context_t* context)
/* Make sure there are some types of authentication we can do */
if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_DIGEST)))
{
- ha_messagex(LOG_ERR, "bd: module configured, but does not implement any "
- "configured authentication type.");
+ ha_messagex(NULL, LOG_ERR, "module configured, but does not implement any "
+ "configured authentication type.");
return HA_FAILED;
}
/* The cache for digest records and basic */
if(!(ctx->cache = hsh_create(MD5_LEN)))
{
- ha_messagex(LOG_CRIT, "out of memory");
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
return HA_CRITERROR;
}
@@ -406,7 +403,7 @@ int bd_init(ha_context_t* context)
htc.arg = NULL;
hsh_set_table_calls(ctx->cache, &htc);
- ha_messagex(LOG_INFO, "ldap: initialized handler");
+ ha_messagex(NULL, LOG_INFO, "initialized handler");
}
return HA_OK;
@@ -428,54 +425,54 @@ void bd_destroy(ha_context_t* context)
if(ctx->cache)
hsh_free(ctx->cache);
- ha_messagex(LOG_INFO, "bd: uninitialized handler");
+ ha_messagex(NULL, LOG_INFO, "uninitialized handler");
}
-int bd_process(const ha_request_t* req, ha_response_t* resp)
+int bd_process(ha_request_t* rq)
{
- bd_context_t* ctx = (bd_context_t*)req->context->ctx_data;
+ bd_context_t* ctx = (bd_context_t*)rq->context->ctx_data;
time_t t = time(NULL);
const char* header = NULL;
int ret, r;
- ASSERT(req && resp);
- ASSERT(req->args[AUTH_ARG_METHOD]);
- ASSERT(req->args[AUTH_ARG_URI]);
+ ASSERT(rq);
+ ASSERT(rq->req_args[AUTH_ARG_METHOD]);
+ ASSERT(rq->req_args[AUTH_ARG_URI]);
ha_lock(NULL);
/* Purge out stale connection stuff. */
- r = hsh_purge(ctx->cache, t - req->context->cache_timeout);
+ r = hsh_purge(ctx->cache, t - rq->context->cache_timeout);
ha_unlock(NULL);
if(r > 0)
- ha_messagex(LOG_DEBUG, "ldap: purged cache records: %d", r);
+ ha_messagex(rq, LOG_DEBUG, "purged cache records: %d", r);
/* We use this below to detect whether to send a default response */
- resp->code = -1;
+ rq->resp_code = -1;
/* Check the headers and see if we got a response thingy */
- if(req->context->allowed_types & HA_TYPE_DIGEST)
+ if(rq->context->allowed_types & HA_TYPE_DIGEST)
{
- header = ha_getheader(req, "Authorization", HA_PREFIX_DIGEST);
+ header = ha_getheader(rq, "Authorization", HA_PREFIX_DIGEST);
if(header)
{
- ha_messagex(LOG_DEBUG, "ldap: processing digest auth header");
- ret = do_digest_response(ctx, header, req, resp);
+ ha_messagex(rq, LOG_DEBUG, "processing digest auth header");
+ ret = do_digest_response(rq, ctx, header);
if(ret < 0)
return ret;
}
}
/* Or a basic authentication */
- if(!header && req->context->allowed_types & HA_TYPE_BASIC)
+ if(!header && rq->context->allowed_types & HA_TYPE_BASIC)
{
- header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC);
+ header = ha_getheader(rq, "Authorization", HA_PREFIX_BASIC);
if(header)
{
- ha_messagex(LOG_DEBUG, "bd: processing basic auth header");
- ret = do_basic_response(ctx, header, req, resp);
+ ha_messagex(rq, LOG_DEBUG, "processing basic auth header");
+ ret = do_basic_response(rq, ctx, header);
if(ret < 0)
return ret;
}
@@ -483,24 +480,24 @@ int bd_process(const ha_request_t* req, ha_response_t* resp)
/* Send a default response if that's what we need */
- if(resp->code == -1)
+ if(rq->resp_code == -1)
{
- resp->code = HA_SERVER_DECLINE;
+ rq->resp_code = HA_SERVER_DECLINE;
- if(req->context->allowed_types & HA_TYPE_BASIC)
+ if(rq->context->allowed_types & HA_TYPE_BASIC)
{
- ha_bufmcat(req->buf, "BASIC realm=\"", req->context->realm , "\"", NULL);
+ ha_bufmcat(rq->buf, "BASIC realm=\"", rq->context->realm , "\"", NULL);
- if(ha_buferr(req->buf))
+ if(ha_buferr(rq->buf))
return HA_CRITERROR;
- ha_addheader(resp, "WWW-Authenticate", ha_bufdata(req->buf));
- ha_messagex(LOG_DEBUG, "bd: sent basic auth request");
+ ha_addheader(rq, "WWW-Authenticate", ha_bufdata(rq->buf));
+ ha_messagex(rq, LOG_DEBUG, "sent basic auth request");
}
- if(req->context->allowed_types & HA_TYPE_DIGEST)
+ if(rq->context->allowed_types & HA_TYPE_DIGEST)
{
- ret = do_digest_challenge(ctx, req, resp, 0);
+ ret = do_digest_challenge(rq, ctx, 0);
if(ret < 0)
return ret;
}
diff --git a/daemon/bd.h b/daemon/bd.h
index 450c8e1..272e09a 100644
--- a/daemon/bd.h
+++ b/daemon/bd.h
@@ -17,8 +17,8 @@
* HA_OK: completed successfully
* HA_FAILED: error retrieving hash (should have logged error)
*/
-typedef int (*bd_complete_digest)(const ha_request_t* req,
- const char* user, unsigned char* ha1);
+typedef int (*bd_complete_digest)(ha_request_t* rq,
+ const char* user, unsigned char* ha1);
/*
* A callback for validating a given user's password.
@@ -28,8 +28,8 @@ typedef int (*bd_complete_digest)(const ha_request_t* req,
* HA_FALSE: invalid password
* HA_FAILED: error validating (should have logged error)
*/
-typedef int (*bd_validate_basic)(const ha_request_t* req,
- const char* user, const char* password);
+typedef int (*bd_validate_basic)(ha_request_t* rq,
+ const char* user, const char* password);
/* ----------------------------------------------------------------------------------
* Base Context
@@ -66,6 +66,6 @@ void bd_destroy(ha_context_t* context);
* The base/digest processer for requests. Call this from your
* 'derived' handler process function.
*/
-int bd_process(const ha_request_t* req, ha_response_t* resp);
+int bd_process(ha_request_t* rq);
#endif /* BD_H */
diff --git a/daemon/digest.c b/daemon/digest.c
index 405a661..099bf31 100644
--- a/daemon/digest.c
+++ b/daemon/digest.c
@@ -12,103 +12,103 @@ static unsigned int g_digest_unique = 0;
typedef struct internal_nonce
{
- unsigned char hash[MD5_LEN];
- time_t tm;
- unsigned int unique;
+ unsigned char hash[MD5_LEN];
+ time_t tm;
+ unsigned int unique;
}
internal_nonce_t;
void digest_makenonce(unsigned char* nonce, unsigned char* secret, unsigned char* old)
{
- internal_nonce_t in;
- md5_ctx_t md5;
-
- ASSERT(nonce && secret);
- ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN);
-
- if(old)
- {
- internal_nonce_t* nold = (internal_nonce_t*)old;
- in.tm = nold->tm;
- in.unique = nold->unique;
- }
- else
- {
- in.tm = time(NULL);
- ha_lock(NULL);
- in.unique = g_digest_unique++;
- ha_unlock(NULL);
- }
-
- md5_init(&md5);
- md5_update(&md5, secret, DIGEST_SECRET_LEN);
- md5_update(&md5, &(in.tm), sizeof(in.tm));
- md5_update(&md5, &(in.unique), sizeof(in.unique));
- md5_final(in.hash, &md5);
-
- memcpy(nonce, &in, DIGEST_NONCE_LEN);
+ internal_nonce_t in;
+ md5_ctx_t md5;
+
+ ASSERT(nonce && secret);
+ ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN);
+
+ if(old)
+ {
+ internal_nonce_t* nold = (internal_nonce_t*)old;
+ in.tm = nold->tm;
+ in.unique = nold->unique;
+ }
+ else
+ {
+ in.tm = time(NULL);
+ ha_lock(NULL);
+ in.unique = g_digest_unique++;
+ ha_unlock(NULL);
+ }
+
+ md5_init(&md5);
+ md5_update(&md5, secret, DIGEST_SECRET_LEN);
+ md5_update(&md5, &(in.tm), sizeof(in.tm));
+ md5_update(&md5, &(in.unique), sizeof(in.unique));
+ md5_final(in.hash, &md5);
+
+ memcpy(nonce, &in, DIGEST_NONCE_LEN);
}
int digest_checknonce(unsigned char* nonce, unsigned char* secret, time_t* tm)
{
- internal_nonce_t in;
+ internal_nonce_t in;
- ASSERT(nonce && secret);
- ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN);
+ ASSERT(nonce && secret);
+ ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN);
- digest_makenonce((unsigned char*)&in, secret, nonce);
+ digest_makenonce((unsigned char*)&in, secret, nonce);
- if(memcmp((unsigned char*)&in, nonce, DIGEST_SECRET_LEN) == 0)
- {
- if(tm)
- *tm = in.tm;
+ if(memcmp((unsigned char*)&in, nonce, DIGEST_SECRET_LEN) == 0)
+ {
+ if(tm)
+ *tm = in.tm;
- return HA_OK;
- }
+ return HA_OK;
+ }
- return HA_FALSE;
+ return HA_FALSE;
}
digest_record_t* digest_makerec(unsigned char* nonce, const char* user)
{
- digest_record_t* rec = (digest_record_t*)malloc(sizeof(*rec));
+ digest_record_t* rec = (digest_record_t*)malloc(sizeof(*rec));
- ASSERT(nonce && user);
+ ASSERT(nonce && user);
- if(!rec)
- {
- ha_messagex(LOG_CRIT, "out of memory");
- return NULL;
- }
+ if(!rec)
+ {
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
+ return NULL;
+ }
- memset(rec, 0, sizeof(*rec));
- memcpy(rec->nonce, nonce, DIGEST_NONCE_LEN);
+ memset(rec, 0, sizeof(*rec));
+ memcpy(rec->nonce, nonce, DIGEST_NONCE_LEN);
- md5_string(rec->userhash, user);
- return rec;
+ md5_string(rec->userhash, user);
+ return rec;
}
const char* digest_challenge(ha_buffer_t* buf, const char* nonce_str,
const char* realm, const char* domains, int stale)
{
- ASSERT(buf && realm && nonce_str);
+ ASSERT(buf && realm && nonce_str);
- ha_bufmcat(buf, HA_PREFIX_DIGEST, " realm=\"", realm, "\", nonce=\"",
- nonce_str, "\", qop=\"auth\", algorithm=\"MD5\"", NULL);
+ ha_bufmcat(buf, HA_PREFIX_DIGEST, " realm=\"", realm, "\", nonce=\"",
+ nonce_str, "\", qop=\"auth\", algorithm=\"MD5\"", NULL);
- if(domains)
- {
- ha_bufjoin(buf);
- ha_bufmcat(buf, ", domain=\"", domains, "\"", NULL);
- }
+ if(domains)
+ {
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, ", domain=\"", domains, "\"", NULL);
+ }
- if(stale)
- {
- ha_bufjoin(buf);
- ha_bufcat(buf, ", stale=true");
- }
+ if(stale)
+ {
+ ha_bufjoin(buf);
+ ha_bufcat(buf, ", stale=true");
+ }
- return ha_bufdata(buf);
+ return ha_bufdata(buf);
}
/*
@@ -130,316 +130,396 @@ const char* digest_challenge(ha_buffer_t* buf, const char* nonce_str,
int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec,
unsigned char* nonce)
{
- char next;
- char* key;
- char* value;
-
- ASSERT(header && buf && rec);
-
- header = ha_bufcpy(buf, header);
-
- if(!header)
- return HA_CRITERROR;
-
- memset(rec, 0, sizeof(*rec));
-
- while(header[0])
- {
- /* find key */
- header = (char*)trim_start(header);
- key = header;
+ char next;
+ char* key;
+ char* value;
- while(header[0] && header[0] != '=' && header[0] != ',' &&
- !isspace(header[0]))
- header++;
+ ASSERT(header && buf && rec);
- /* null terminate and move on */
- next = header[0];
- header[0] = '\0';
- header++;
+ header = ha_bufcpy(buf, header);
- if(!next)
- break;
-
- if(isspace(header[0]))
- {
- header = (char*)trim_start(header);
- next = header[0];
- }
+ if(!header)
+ return HA_CRITERROR;
- /* find value */
+ memset(rec, 0, sizeof(*rec));
- if(next == '=')
+ while(header[0])
{
- header = (char*)trim_start(header);
+ /* find key */
+ header = (char*)trim_start(header);
+ key = header;
- if(header[0] == '\"') /* quoted string */
- {
- header++;
- value = header;
-
- while(header[0] && header[0] != '\"')
- header++;
+ while(header[0] && header[0] != '=' && header[0] != ',' &&
+ !isspace(header[0]))
+ header++;
+ /* null terminate and move on */
next = header[0];
- header[0] = 0;
+ header[0] = '\0';
header++;
- }
- else /* token */
- {
- value = header;
+ if(!next)
+ break;
+
+ if(isspace(header[0]))
+ {
+ header = (char*)trim_start(header);
+ next = header[0];
+ }
- while(header[0] && header[0] != ',' && !isspace(header[0]))
- header++;
+ /* find value */
- next = header[0];
- header[0] = 0;
- header++;
- }
-
- if(next != ',')
- {
- while(header[0] && header[0] != ',')
- header++;
-
- if(header[0])
- header++;
- }
-
- if(!strcasecmp(key, "username"))
- rec->username = value;
- else if(!strcasecmp(key, "realm"))
- rec->realm = value;
- else if (!strcasecmp(key, "nonce"))
- rec->nonce = value;
- else if (!strcasecmp(key, "uri"))
- rec->uri = value;
- else if (!strcasecmp(key, "response"))
- rec->digest = value;
- else if (!strcasecmp(key, "algorithm"))
- rec->algorithm = value;
- else if (!strcasecmp(key, "cnonce"))
- rec->cnonce = value;
- else if (!strcasecmp(key, "opaque"))
- rec->opaque = value;
- else if (!strcasecmp(key, "qop"))
- rec->qop = value;
- else if (!strcasecmp(key, "nc"))
- rec->nc = value;
+ if(next == '=')
+ {
+ header = (char*)trim_start(header);
+
+ if(header[0] == '\"') /* quoted string */
+ {
+ header++;
+ value = header;
+
+ while(header[0] && header[0] != '\"')
+ header++;
+
+ next = header[0];
+ header[0] = 0;
+ header++;
+ }
+
+ else /* token */
+ {
+ value = header;
+
+ while(header[0] && header[0] != ',' && !isspace(header[0]))
+ header++;
+
+ next = header[0];
+ header[0] = 0;
+ header++;
+ }
+
+ if(next != ',')
+ {
+ while(header[0] && header[0] != ',')
+ header++;
+
+ if(header[0])
+ header++;
+ }
+
+ if(!strcasecmp(key, "username"))
+ rec->username = value;
+ else if(!strcasecmp(key, "realm"))
+ rec->realm = value;
+ else if (!strcasecmp(key, "nonce"))
+ rec->nonce = value;
+ else if (!strcasecmp(key, "uri"))
+ rec->uri = value;
+ else if (!strcasecmp(key, "response"))
+ rec->digest = value;
+ else if (!strcasecmp(key, "algorithm"))
+ rec->algorithm = value;
+ else if (!strcasecmp(key, "cnonce"))
+ rec->cnonce = value;
+ else if (!strcasecmp(key, "opaque"))
+ rec->opaque = value;
+ else if (!strcasecmp(key, "qop"))
+ rec->qop = value;
+ else if (!strcasecmp(key, "nc"))
+ rec->nc = value;
+ }
}
- }
- if(nonce)
- {
- memset(nonce, 0, DIGEST_NONCE_LEN);
-
- if(rec->nonce)
+ if(nonce)
{
- size_t len = DIGEST_NONCE_LEN;
- void* d = ha_bufdechex(buf, rec->nonce, &len);
+ memset(nonce, 0, DIGEST_NONCE_LEN);
+
+ if(rec->nonce)
+ {
+ size_t len = DIGEST_NONCE_LEN;
+ void* d = ha_bufdechex(buf, rec->nonce, &len);
- if(d && len == DIGEST_NONCE_LEN)
- memcpy(nonce, d, DIGEST_NONCE_LEN);
+ if(d && len == DIGEST_NONCE_LEN)
+ memcpy(nonce, d, DIGEST_NONCE_LEN);
+ }
}
- }
- return HA_OK;
+ return HA_OK;
}
int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_t* ctx,
ha_buffer_t* buf, const char* method, const char* uri)
{
- unsigned char hash[MD5_LEN];
- md5_ctx_t md5;
- const char* digest;
- const char* t;
-
- ASSERT(ctx && method && buf && dg && rec);
-
- /* TODO: Many of these should somehow communicate BAD REQ back to the client */
-
- /* Check for digest */
- if(!dg->digest || !dg->digest[0])
- {
- ha_messagex(LOG_WARNING, "digest response missing digest");
- return HA_BADREQ;
- }
-
- /* Username */
- if(!dg->username || !dg->username[0])
- {
- ha_messagex(LOG_WARNING, "digest response missing username");
- return HA_BADREQ;
- }
-
- if(md5_strcmp(rec->userhash, dg->username) != 0)
- {
- ha_messagex(LOG_ERR, "digest response contains invalid username");
- return HA_FALSE;
- }
-
- /* The realm */
- if(!dg->realm)
- {
- ha_messagex(LOG_WARNING, "digest response contains missing realm");
- return HA_BADREQ;
- }
-
- if(strcmp(dg->realm, ctx->realm) != 0)
- {
- ha_messagex(LOG_ERR, "digest response contains invalid realm: %s", dg->realm);
- return HA_FALSE;
- }
+ unsigned char hash[MD5_LEN];
+ md5_ctx_t md5;
+ const char* digest;
+ const char* t;
- /* Components in the new RFC */
- if(dg->qop)
- {
- /*
- * We only support 'auth' qop. We don't have access to the data
- * and wouldn't be able to support anything else.
- */
- if(strcmp(dg->qop, "auth") != 0)
+ ASSERT(ctx && method && buf && dg && rec);
+
+ /* TODO: This stuff should probably go into bd.c */
+
+ /* Check for digest */
+ if(!dg->digest || !dg->digest[0])
{
- ha_messagex(LOG_WARNING, "digest response contains unknown or unsupported qop: '%s'",
- dg->qop ? dg->qop : "");
- return HA_BADREQ;
+ ha_messagex(NULL, LOG_WARNING, "digest response missing digest");
+ return HA_BADREQ;
}
- /* The cnonce */
- if(!dg->cnonce || !dg->cnonce[0])
+ /* Username */
+ if(!dg->username || !dg->username[0])
{
- ha_messagex(LOG_WARNING, "digest response is missing cnonce value");
- return HA_BADREQ;
+ ha_messagex(NULL, LOG_WARNING, "digest response missing username");
+ return HA_BADREQ;
+ }
+
+ if(md5_strcmp(rec->userhash, dg->username) != 0)
+ {
+ ha_messagex(NULL, LOG_ERR, "digest response contains invalid username");
+ return HA_FALSE;
}
- if(!ctx->digest_ignorenc)
+ /* The realm */
+ if(!dg->realm)
{
- /* The nonce count */
- if(!dg->nc || !dg->nc[0])
- {
- ha_messagex(LOG_WARNING, "digest response is missing nc value");
+ ha_messagex(NULL, LOG_WARNING, "digest response contains missing realm");
return HA_BADREQ;
- }
+ }
- /* Validate the nc */
- else
- {
- char* e;
- long nc = strtol(dg->nc, &e, 16);
+ if(strcmp(dg->realm, ctx->realm) != 0)
+ {
+ ha_messagex(NULL, LOG_ERR, "digest response contains invalid realm: %s", dg->realm);
+ return HA_FALSE;
+ }
- if(*e)
+ /* Components in the new RFC */
+ if(dg->qop)
+ {
+ /*
+ * We only support 'auth' qop. We don't have access to the data
+ * and wouldn't be able to support anything else.
+ */
+ if(strcmp(dg->qop, "auth") != 0)
{
- ha_messagex(LOG_ERR, "digest response has invalid nc value: %s", dg->nc);
- return HA_BADREQ;
+ ha_messagex(NULL, LOG_WARNING, "digest response contains unknown or unsupported qop: '%s'",
+ dg->qop ? dg->qop : "");
+ return HA_BADREQ;
}
- /* If we didn't a nc then save it away */
- if(!*e && rec->nc == 0)
- rec->nc = nc;
+ /* The cnonce */
+ if(!dg->cnonce || !dg->cnonce[0])
+ {
+ ha_messagex(NULL, LOG_WARNING, "digest response is missing cnonce value");
+ return HA_BADREQ;
+ }
- if(*e || nc != rec->nc)
+ if(!ctx->digest_ignorenc)
{
- ha_messagex(LOG_WARNING, "digest response has wrong nc value. "
- "possible replay attack: %s", dg->nc);
- return HA_FALSE;
+ /* The nonce count */
+ if(!dg->nc || !dg->nc[0])
+ {
+ ha_messagex(NULL, LOG_WARNING, "digest response is missing nc value");
+ return HA_BADREQ;
+ }
+
+ /* Validate the nc */
+ else
+ {
+ char* e;
+ long nc = strtol(dg->nc, &e, 16);
+
+ if(*e)
+ {
+ ha_messagex(NULL, LOG_ERR, "digest response has invalid nc value: %s", dg->nc);
+ return HA_BADREQ;
+ }
+
+ /* If we didn't a nc then save it away */
+ if(!*e && rec->nc == 0)
+ rec->nc = nc;
+
+ if(*e || nc != rec->nc)
+ {
+ ha_messagex(NULL, LOG_WARNING, "digest response has wrong nc value. "
+ "possible replay attack: %s", dg->nc);
+ return HA_FALSE;
+ }
+ }
}
- }
}
- }
-
- /* The algorithm */
- if(dg->algorithm && strcasecmp(dg->algorithm, "MD5") != 0)
- {
- ha_messagex(LOG_WARNING, "digest response contains unknown or unsupported algorithm: '%s'",
- dg->algorithm ? dg->algorithm : "");
- return HA_BADREQ;
- }
-
- /* Request URI */
- if(!dg->uri)
- {
- ha_messagex(LOG_WARNING, "digest response is missing uri");
- return HA_BADREQ;
- }
-
- if(!ctx->digest_ignoreuri && strcmp(dg->uri, uri) != 0)
- {
- ha_uri_t d_uri;
- ha_uri_t s_uri;
-
- if(ha_uriparse(buf, dg->uri, &d_uri) < 0)
+
+ /* The algorithm */
+ if(dg->algorithm && strcasecmp(dg->algorithm, "MD5") != 0)
{
- if(ha_buferr(buf))
- return HA_CRITERROR;
+ ha_messagex(NULL, LOG_WARNING, "digest response contains unknown or unsupported algorithm: '%s'",
+ dg->algorithm ? dg->algorithm : "");
+ return HA_BADREQ;
+ }
- ha_messagex(LOG_WARNING, "digest response constains invalid uri: %s", dg->uri);
- return HA_BADREQ;
+ /* Request URI */
+ if(!dg->uri)
+ {
+ ha_messagex(NULL, LOG_WARNING, "digest response is missing uri");
+ return HA_BADREQ;
}
- if(ha_uriparse(buf, uri, &s_uri) < 0)
+ if(!ctx->digest_ignoreuri && strcmp(dg->uri, uri) != 0)
{
- if(ha_buferr(buf))
+ ha_uri_t d_uri;
+ ha_uri_t s_uri;
+
+ if(ha_uriparse(buf, dg->uri, &d_uri) < 0)
+ {
+ if(ha_buferr(buf))
+ return HA_CRITERROR;
+
+ ha_messagex(NULL, LOG_WARNING, "digest response constains invalid uri: %s", dg->uri);
+ return HA_BADREQ;
+ }
+
+ if(ha_uriparse(buf, uri, &s_uri) < 0)
+ {
+ if(ha_buferr(buf))
+ return HA_CRITERROR;
+
+ ha_messagex(NULL, LOG_ERR, "server sent us an invalid uri");
+ return HA_BADREQ;
+ }
+
+ if(ha_uricmp(&d_uri, &s_uri) != 0)
+ {
+ ha_messagex(NULL, LOG_ERR, "digest response contains wrong uri: %s "
+ "(should be %s)", dg->uri, uri);
+ return HA_FALSE;
+ }
+ }
+
+ /*
+ * nonce: should have already been validated by the caller who
+ * found this nice rec structure to pass us.
+ *
+ * opaque: We also don't use opaque. The caller should have validated it
+ * if it's used there.
+ */
+
+ /*
+ * Now we validate the digest response
+ */
+
+ /* Encode ha1 */
+ t = ha_bufenchex(buf, rec->ha1, MD5_LEN);
+
+ if(t == NULL)
+ return HA_CRITERROR;
+
+ /* Encode ha2 */
+ md5_init(&md5);
+ md5_update(&md5, method, strlen(method));
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, dg->uri, strlen(dg->uri));
+ md5_final(hash, &md5);
+
+ ha_bufenchex(buf, hash, MD5_LEN);
+
+ if(!ha_bufdata(buf))
return HA_CRITERROR;
- ha_messagex(LOG_ERR, "server sent us an invalid uri");
- return HA_BADREQ;
+
+ /* Old style digest (RFC 2069) */
+ if(!dg->qop)
+ {
+ md5_init(&md5);
+ md5_update(&md5, t, MD5_LEN * 2); /* ha1 */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha1 */
+ md5_final(hash, &md5);
+ }
+
+ /* New style 'auth' digest (RFC 2617) */
+ else
+ {
+ md5_init(&md5);
+ md5_update(&md5, t, MD5_LEN * 2); /* ha1 */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, dg->nc, strlen(dg->nc)); /* nc */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, dg->cnonce, strlen(dg->cnonce)); /* cnonce */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, dg->qop, strlen(dg->qop)); /* qop */
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha2 */
+ md5_final(hash, &md5);
}
- if(ha_uricmp(&d_uri, &s_uri) != 0)
+ /* Encode the digest */
+ digest = ha_bufenchex(buf, hash, MD5_LEN);
+
+ if(digest == NULL)
+ return HA_CRITERROR;
+
+ if(strcasecmp(dg->digest, digest) != 0)
{
- ha_messagex(LOG_ERR, "digest response contains wrong uri: %s "
- "(should be %s)", dg->uri, uri);
- return HA_FALSE;
+ ha_messagex(NULL, LOG_WARNING, "digest authentication failed for user: %s", dg->username);
+ return HA_FALSE;
}
- }
- /*
- * nonce: should have already been validated by the caller who
- * found this nice rec structure to pass us.
- *
- * opaque: We also don't use opaque. The caller should have validated it
- * if it's used there.
- */
+ return HA_OK;
+}
- /*
- * Now we validate the digest response
- */
+const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg,
+ digest_record_t* rec, unsigned char* next)
+{
+ unsigned char hash[MD5_LEN];
+ md5_ctx_t md5;
+ const char* nextnonce = NULL;
+ const char* t;
- /* Encode ha1 */
- t = ha_bufenchex(buf, rec->ha1, MD5_LEN);
+ ASSERT(buf && dg && rec);
- if(t == NULL)
- return HA_CRITERROR;
+ /* This makes a new buffer */
+ ha_bufcpy(buf, "");
- /* Encode ha2 */
- md5_init(&md5);
- md5_update(&md5, method, strlen(method));
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->uri, strlen(dg->uri));
- md5_final(hash, &md5);
+ if(next)
+ {
+ nextnonce = ha_bufenc64(buf, next, DIGEST_NONCE_LEN);
- ha_bufenchex(buf, hash, MD5_LEN);
+ if(nextnonce == NULL)
+ return NULL;
+ }
- if(!ha_bufdata(buf))
- return HA_CRITERROR;
+ /* For older clients RFC 2069 */
+ if(!dg->qop)
+ {
+ if(nextnonce)
+ ha_bufmcat(buf, "nextnonce=\"", nextnonce, "\"", NULL);
+
+ return ha_bufdata(buf);
+ }
+
+ /* Otherwise we do the whole song and dance */
+ /* Encode ha1 */
+ t = ha_bufenchex(buf, rec->ha1, MD5_LEN);
- /* Old style digest (RFC 2069) */
- if(!dg->qop)
- {
+ if(t == NULL)
+ return NULL;
+
+ /* Encode ha2 */
md5_init(&md5);
- md5_update(&md5, t, MD5_LEN * 2); /* ha1 */
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */
md5_update(&md5, ":", 1);
- md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha1 */
+ md5_update(&md5, dg->uri, strlen(dg->uri));
md5_final(hash, &md5);
- }
- /* New style 'auth' digest (RFC 2617) */
- else
- {
+ ha_bufenchex(buf, hash, MD5_LEN);
+
+ if(!ha_bufdata(buf))
+ return NULL;
+
+ /* New style 'auth' digest (RFC 2617) */
md5_init(&md5);
md5_update(&md5, t, MD5_LEN * 2); /* ha1 */
md5_update(&md5, ":", 1);
@@ -453,119 +533,39 @@ int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_t*
md5_update(&md5, ":", 1);
md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha2 */
md5_final(hash, &md5);
- }
- /* Encode the digest */
- digest = ha_bufenchex(buf, hash, MD5_LEN);
+ /* Encode the digest */
+ t = ha_bufenchex(buf, hash, MD5_LEN);
- if(digest == NULL)
- return HA_CRITERROR;
+ if(t == NULL)
+ return NULL;
- if(strcasecmp(dg->digest, digest) != 0)
- {
- ha_messagex(LOG_WARNING, "digest authentication failed for user: %s", dg->username);
- return HA_FALSE;
- }
-
- return HA_OK;
-}
-
-const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg,
- digest_record_t* rec, unsigned char* next)
-{
- unsigned char hash[MD5_LEN];
- md5_ctx_t md5;
- const char* nextnonce = NULL;
- const char* t;
-
- ASSERT(buf && dg && rec);
+ ha_bufmcat(buf, "rspauth=\"", t, "\"",
+ ", qop=", dg->qop,
+ ", nc=", dg->nc,
+ ", cnonce=\"", dg->cnonce, "\"", NULL);
- /* This makes a new buffer */
- ha_bufcpy(buf, "");
-
- if(next)
- {
- nextnonce = ha_bufenc64(buf, next, DIGEST_NONCE_LEN);
-
- if(nextnonce == NULL)
- return NULL;
- }
-
- /* For older clients RFC 2069 */
- if(!dg->qop)
- {
if(nextnonce)
- ha_bufmcat(buf, "nextnonce=\"", nextnonce, "\"", NULL);
+ {
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, ", nextnonce=\"", nextnonce, "\"", NULL);
+ }
return ha_bufdata(buf);
- }
-
- /* Otherwise we do the whole song and dance */
-
- /* Encode ha1 */
- t = ha_bufenchex(buf, rec->ha1, MD5_LEN);
-
- if(t == NULL)
- return NULL;
-
- /* Encode ha2 */
- md5_init(&md5);
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->uri, strlen(dg->uri));
- md5_final(hash, &md5);
-
- ha_bufenchex(buf, hash, MD5_LEN);
-
- if(!ha_bufdata(buf))
- return NULL;
-
- /* New style 'auth' digest (RFC 2617) */
- md5_init(&md5);
- md5_update(&md5, t, MD5_LEN * 2); /* ha1 */
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->nc, strlen(dg->nc)); /* nc */
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->cnonce, strlen(dg->cnonce)); /* cnonce */
- md5_update(&md5, ":", 1);
- md5_update(&md5, dg->qop, strlen(dg->qop)); /* qop */
- md5_update(&md5, ":", 1);
- md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha2 */
- md5_final(hash, &md5);
-
- /* Encode the digest */
- t = ha_bufenchex(buf, hash, MD5_LEN);
-
- if(t == NULL)
- return NULL;
-
- ha_bufmcat(buf, "rspauth=\"", t, "\"",
- ", qop=", dg->qop,
- ", nc=", dg->nc,
- ", cnonce=\"", dg->cnonce, "\"", NULL);
-
- if(nextnonce)
- {
- ha_bufjoin(buf);
- ha_bufmcat(buf, ", nextnonce=\"", nextnonce, "\"", NULL);
- }
-
- return ha_bufdata(buf);
}
void digest_makeha1(unsigned char* digest, const char* user,
const char* realm, const char* password)
{
- md5_ctx_t md5;
+ md5_ctx_t md5;
- ASSERT(digest && user && realm && password);
+ ASSERT(digest && user && realm && password);
- md5_init(&md5);
- md5_update(&md5, user, strlen(user));
- md5_update(&md5, ":", 1);
- md5_update(&md5, realm, strlen(realm));
- md5_update(&md5, ":", 1);
- md5_update(&md5, password, strlen(password));
- md5_final(digest, &md5);
+ md5_init(&md5);
+ md5_update(&md5, user, strlen(user));
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, realm, strlen(realm));
+ md5_update(&md5, ":", 1);
+ md5_update(&md5, password, strlen(password));
+ md5_final(digest, &md5);
}
diff --git a/daemon/digest.h b/daemon/digest.h
index 8b3ecdf..f763133 100644
--- a/daemon/digest.h
+++ b/daemon/digest.h
@@ -10,28 +10,28 @@
/* Parsed Digest response from the client */
typedef struct digest_header
{
- const char* scheme;
- const char* realm;
- const char* username;
- const char* nonce;
- const char* uri;
- const char* method;
- const char* digest;
- const char* algorithm;
- const char* cnonce;
- const char* opaque;
- const char* qop;
- const char* nc;
+ const char* scheme;
+ const char* realm;
+ const char* username;
+ const char* nonce;
+ const char* uri;
+ const char* method;
+ const char* digest;
+ const char* algorithm;
+ const char* cnonce;
+ const char* opaque;
+ const char* qop;
+ const char* nc;
}
digest_header_t;
/* Kept by the server for validating the client */
typedef struct digest_record
{
- unsigned char nonce[DIGEST_NONCE_LEN];
- unsigned char userhash[MD5_LEN];
- unsigned char ha1[MD5_LEN];
- unsigned int nc;
+ unsigned char nonce[DIGEST_NONCE_LEN];
+ unsigned char userhash[MD5_LEN];
+ unsigned char ha1[MD5_LEN];
+ unsigned int nc;
}
digest_record_t;
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c
index c238a1a..17ed15c 100644
--- a/daemon/httpauthd.c
+++ b/daemon/httpauthd.c
@@ -36,15 +36,15 @@ extern ha_handler_t ntlm_handler;
/* This is the list of all available handlers */
ha_handler_t* g_handlerlist[] =
{
- &simple_handler,
- &ldap_handler,
- &ntlm_handler
+ &simple_handler,
+ &ldap_handler,
+ &ntlm_handler
};
typedef struct httpauth_loaded
{
- ha_context_t ctx;
- struct httpauth_loaded* next;
+ ha_context_t ctx;
+ struct httpauth_loaded* next;
}
httpauth_loaded_t;
@@ -58,34 +58,34 @@ httpauth_loaded_t* g_handlers = NULL;
/* A command definition. Used in parsing */
typedef struct httpauth_command
{
- const char* name;
- int code;
- int word_args; /* Arguments to be parsed as words */
- int rest_arg; /* Parse remainder as one arg? */
- const char** headers; /* Headers needed/allowed */
+ const char* name;
+ int code;
+ int word_args; /* Arguments to be parsed as words */
+ int rest_arg; /* Parse remainder as one arg? */
+ const char** headers; /* Headers needed/allowed */
}
httpauth_command_t;
/* The various valid headers for the auth command */
const char* kAuthHeaders[] =
{
- "Authorization",
- NULL
+ "Authorization",
+ NULL
};
/* The command definitions */
const httpauth_command_t kCommands[] =
{
- { "auth", REQTYPE_AUTH, 3, 0, kAuthHeaders },
- { "set", REQTYPE_SET, 1, 1, NULL },
- { "quit", REQTYPE_QUIT, 0, 0, NULL },
- { NULL, -1, 0, 0, NULL }
+ { "auth", REQTYPE_AUTH, 3, 0, kAuthHeaders },
+ { "set", REQTYPE_SET, 1, 1, NULL },
+ { "quit", REQTYPE_QUIT, 0, 0, NULL },
+ { NULL, -1, 0, 0, NULL }
};
typedef struct httpauth_thread
{
- pthread_t tid;
- int fd;
+ pthread_t tid;
+ int fd;
}
httpauth_thread_t;
@@ -126,9 +126,8 @@ static int usage();
static void writepid(const char* pid);
static void* httpauth_thread(void* arg);
static int httpauth_processor(int ifd, int ofd);
-static int httpauth_respond(int ofd, int scode, int ccode, const char* msg);
-static int process_auth(ha_request_t* req, ha_response_t* resp,
- ha_buffer_t* outb);
+static int httpauth_respond(ha_request_t* rq, int ofd, int scode, int ccode, const char* msg);
+static int process_auth(ha_request_t* rq);
static int config_parse(const char* file, ha_buffer_t* buf);
static void on_quit(int signal);
@@ -138,990 +137,984 @@ static void on_quit(int signal);
int main(int argc, char* argv[])
{
- const char* conf = DEFAULT_CONFIG;
- const char* pidfile = NULL;
- httpauth_thread_t* threads = NULL;
- httpauth_loaded_t* h;
- char peername[MAXPATHLEN];
- struct sockaddr_any sany;
- int daemonize = 1;
- ha_buffer_t cbuf;
- int r, i, sock;
- int ch = 0;
-
- /* Keep note of the main thread */
- g_mainthread = pthread_self();
-
- /* Create the main mutex */
- if(pthread_mutexattr_init(&g_mutexattr) != 0 ||
- pthread_mutexattr_settype(&g_mutexattr, HA_MUTEX_TYPE) ||
- pthread_mutex_init(&g_mutex, &g_mutexattr) != 0)
- errx(1, "threading problem. can't create mutex");
-
- /* Parse the arguments nicely */
+ const char* conf = DEFAULT_CONFIG;
+ const char* pidfile = NULL;
+ httpauth_thread_t* threads = NULL;
+ httpauth_loaded_t* h;
+ char peername[MAXPATHLEN];
+ struct sockaddr_any sany;
+ int daemonize = 1;
+ ha_buffer_t cbuf;
+ int r, i, sock;
+ int ch = 0;
+
+ /* Keep note of the main thread */
+ g_mainthread = pthread_self();
+
+ /* Create the main mutex */
+ if(pthread_mutexattr_init(&g_mutexattr) != 0 ||
+ pthread_mutexattr_settype(&g_mutexattr, HA_MUTEX_TYPE) ||
+ pthread_mutex_init(&g_mutex, &g_mutexattr) != 0)
+ errx(1, "threading problem. can't create mutex");
+
+ /* Parse the arguments nicely */
while((ch = getopt(argc, argv, "d:f:p:X")) != -1)
{
switch(ch)
{
/* Don't daemonize */
- case 'd':
- {
- char* t;
-
- daemonize = 0;
- g_debuglevel = strtol(optarg, &t, 10);
- if(*t || g_debuglevel > 4)
- errx(1, "invalid debug log level");
- g_debuglevel += LOG_ERR;
- }
- break;
-
- /* The configuration file */
- case 'f':
- conf = optarg;
- break;
-
- /* Write out a pid file */
- case 'p':
- pidfile = optarg;
- break;
-
- /* Process console input instead */
+ case 'd':
+ {
+ char* t;
+ daemonize = 0;
+ g_debuglevel = strtol(optarg, &t, 10);
+ if(*t || g_debuglevel > 4)
+ errx(1, "invalid debug log level");
+ g_debuglevel += LOG_ERR;
+ }
+ break;
+
+ /* The configuration file */
+ case 'f':
+ conf = optarg;
+ break;
+
+ /* Write out a pid file */
+ case 'p':
+ pidfile = optarg;
+ break;
+
+ /* Process console input instead */
case 'X':
- g_console = 1;
- daemonize = 0;
- break;
+ g_console = 1;
+ daemonize = 0;
+ break;
- /* Usage information */
- case '?':
- default:
- return usage();
- break;
- }
- }
+ /* Usage information */
+ case '?':
+ default:
+ return usage();
+ break;
+ }
+ }
- argc -= optind;
- argv += optind;
+ argc -= optind;
+ argv += optind;
- if(argc != 0)
- return usage();
+ if(argc != 0)
+ return usage();
- ha_messagex(LOG_DEBUG, "starting up...");
+ ha_messagex(NULL, LOG_DEBUG, "starting up...");
- /* From here on out we need to quit in an orderly fashion */
+ /* From here on out we need to quit in an orderly fashion */
- /* Run global initialization on all handlers */
- for(i = 0; i < countof(g_handlerlist); i++)
- {
- if(g_handlerlist[i]->f_init)
+ /* Run global initialization on all handlers */
+ for(i = 0; i < countof(g_handlerlist); i++)
{
- if((r = (g_handlerlist[i]->f_init)(NULL)) == -1)
- goto finally;
+ if(g_handlerlist[i]->f_init)
+ {
+ if((r = (g_handlerlist[i]->f_init)(NULL)) == -1)
+ goto finally;
+ }
}
- }
- /* Initialize our configuration buffer */
- ha_bufinit(&cbuf);
+ /* Initialize our configuration buffer */
+ ha_bufinit(&cbuf);
- /* Parse the configuration */
- config_parse(conf, &cbuf);
+ /* Parse the configuration */
+ config_parse(conf, &cbuf);
- if(!g_console)
- {
- /* Create the thread buffers */
- threads = (httpauth_thread_t*)calloc(g_maxthreads, sizeof(httpauth_thread_t));
- if(!threads)
- errx(1, "out of memory");
+ if(!g_console)
+ {
+ /* Create the thread buffers */
+ threads = (httpauth_thread_t*)calloc(g_maxthreads, sizeof(httpauth_thread_t));
+ if(!threads)
+ errx(1, "out of memory");
- /* Get the socket type */
- if(sock_any_pton(g_socket, &sany, DEFAULT_PORT) == -1)
- errx(1, "invalid socket name or ip: %s", g_socket);
+ /* TODO: Import the new sock_any from clamsmtp */
+ /* Get the socket type */
+ if(sock_any_pton(g_socket, &sany, DEFAULT_PORT) == -1)
+ errx(1, "invalid socket name or ip: %s", g_socket);
- /* Create the socket */
- sock = socket(SANY_TYPE(sany), SOCK_STREAM, 0);
- if(sock < 0)
- err(1, "couldn't open socket");
+ /* Create the socket */
+ sock = socket(SANY_TYPE(sany), SOCK_STREAM, 0);
+ if(sock < 0)
+ err(1, "couldn't open socket");
- /* Unlink the socket file if it exists */
- /* TODO: Is this safe? */
- unlink(g_socket);
+ /* Unlink the socket file if it exists */
+ /* TODO: Is this safe? */
+ unlink(g_socket);
- if(bind(sock, &SANY_ADDR(sany), SANY_LEN(sany)) != 0)
- err(1, "couldn't bind to address: %s", g_socket);
+ if(bind(sock, &SANY_ADDR(sany), SANY_LEN(sany)) != 0)
+ err(1, "couldn't bind to address: %s", g_socket);
- /* Let 5 connections queue up */
- if(listen(sock, 5) != 0)
- err(1, "couldn't listen on socket");
+ /* Let 5 connections queue up */
+ if(listen(sock, 5) != 0)
+ err(1, "couldn't listen on socket");
- ha_messagex(LOG_DEBUG, "created socket: %s", g_socket);
- }
+ ha_messagex(NULL, LOG_DEBUG, "created socket: %s", g_socket);
+ }
- /* Initialize all the handlers */
- for(h = g_handlers; h; h = h->next)
- {
- if(h->ctx.handler->f_init)
+ /* Initialize all the handlers */
+ for(h = g_handlers; h; h = h->next)
{
- if((r = (h->ctx.handler->f_init)(&(h->ctx))) == -1)
- goto finally;
+ if(h->ctx.handler->f_init)
+ {
+ if((r = (h->ctx.handler->f_init)(&(h->ctx))) == -1)
+ goto finally;
+ }
}
- }
-
-
- /* This is for debugging the internal processes */
- if(g_console)
- {
- ha_messagex(LOG_DEBUG, "processing from console");
- r = httpauth_processor(0, 1);
- goto finally;
- }
- /* This is the daemon section of the code */
- else
- {
- if(daemonize)
+ /* This is for debugging the internal processes */
+ if(g_console)
{
- /* Fork a daemon nicely here */
- if(daemon(0, 0) == -1)
- {
- ha_message(LOG_ERR, "couldn't run httpauth as daemon");
- exit(1);
- }
-
- ha_messagex(LOG_DEBUG, "running as a daemon");
- g_daemonized = 1;
+ ha_messagex(NULL, LOG_DEBUG, "processing from console");
+ r = httpauth_processor(0, 1);
+ goto finally;
}
- writepid(pidfile);
- /* Handle some signals */
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, on_quit);
- signal(SIGTERM, on_quit);
+ /* This is the daemon section of the code */
+ else
+ {
+ if(daemonize)
+ {
+ /* Fork a daemon nicely here */
+ if(daemon(0, 0) == -1)
+ {
+ ha_message(NULL, LOG_ERR, "couldn't run httpauth as daemon");
+ exit(1);
+ }
- siginterrupt(SIGINT, 1);
- siginterrupt(SIGTERM, 1);
+ ha_messagex(NULL, LOG_DEBUG, "running as a daemon");
+ g_daemonized = 1;
+ }
- /* Open the system log */
- openlog("httpauthd", 0, LOG_AUTHPRIV);
+ writepid(pidfile);
- ha_messagex(LOG_DEBUG, "accepting connections");
+ /* Handle some signals */
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, on_quit);
+ signal(SIGTERM, on_quit);
- /* Now loop and accept the connections */
- while(!g_quit)
- {
- int fd;
+ siginterrupt(SIGINT, 1);
+ siginterrupt(SIGTERM, 1);
- fd = accept(sock, NULL, NULL);
- if(fd == -1)
- {
- switch(errno)
- {
- case EINTR:
- case EAGAIN:
- break;
+ /* Open the system log */
+ openlog("httpauthd", 0, LOG_AUTHPRIV);
- case ECONNABORTED:
- ha_message(LOG_ERR, "couldn't accept a connection");
- break;
+ ha_messagex(NULL, LOG_DEBUG, "accepting connections");
- default:
- ha_message(LOG_ERR, "couldn't accept a connection");
- g_quit = 1;
- break;
- };
+ /* Now loop and accept the connections */
+ while(!g_quit)
+ {
+ int fd;
- if(g_quit)
- break;
+ fd = accept(sock, NULL, NULL);
+ if(fd == -1)
+ {
+ switch(errno)
+ {
+ case EINTR:
+ case EAGAIN:
+ break;
+
+ case ECONNABORTED:
+ ha_message(NULL, LOG_ERR, "couldn't accept a connection");
+ break;
+
+ default:
+ ha_message(NULL, LOG_ERR, "couldn't accept a connection");
+ g_quit = 1;
+ break;
+ };
+
+ if(g_quit)
+ break;
+
+ continue;
+ }
- continue;
- }
+ memset(&sany, 0, sizeof(sany));
+ SANY_LEN(sany) = sizeof(sany);
- memset(&sany, 0, sizeof(sany));
- SANY_LEN(sany) = sizeof(sany);
+ /* TODO: Move this code into the thread */
+ /* Get the peer name */
+ if(getpeername(fd, &SANY_ADDR(sany), &SANY_LEN(sany)) == -1 ||
+ sock_any_ntop(&sany, peername, MAXPATHLEN, SANY_OPT_NOPORT) == -1)
+ ha_messagex(NULL, LOG_WARNING, "%d: couldn't get peer address", fd);
+ else
+ ha_messagex(NULL, LOG_INFO, "%d: accepted connection from: %s", fd, peername);
- /* Get the peer name */
- if(getpeername(fd, &SANY_ADDR(sany), &SANY_LEN(sany)) == -1 ||
- sock_any_ntop(&sany, peername, MAXPATHLEN, SANY_OPT_NOPORT) == -1)
- ha_messagex(LOG_WARNING, "%d: couldn't get peer address", fd);
- else
- ha_messagex(LOG_INFO, "%d: accepted connection from: %s", fd, peername);
+ /* Look for thread and also clean up others */
+ for(i = 0; i < g_maxthreads; i++)
+ {
+ /* Clean up quit threads */
+ if(threads[i].tid != 0)
+ {
+ if(threads[i].fd == -1)
+ {
+ ha_messagex(NULL, LOG_DEBUG, "cleaning up completed thread");
+ pthread_join(threads[i].tid, NULL);
+ threads[i].tid = 0;
+ }
+ }
+
+ /* Start a new thread if neccessary */
+ if(fd != -1 && threads[i].tid == 0)
+ {
+ threads[i].fd = fd;
+ r = pthread_create(&(threads[i].tid), NULL, httpauth_thread,
+ (void*)(threads + i));
+ if(r != 0)
+ {
+ errno = r;
+ ha_message(NULL, LOG_ERR, "couldn't create thread");
+ g_quit = 1;
+ break;
+ }
+
+ ha_messagex(NULL, LOG_DEBUG, "%d: created thread for connection", fd);
+ fd = -1;
+ break;
+ }
+ }
- /* Look for thread and also clean up others */
- for(i = 0; i < g_maxthreads; i++)
- {
- /* Clean up quit threads */
- if(threads[i].tid != 0)
- {
- if(threads[i].fd == -1)
- {
- ha_messagex(LOG_DEBUG, "cleaning up completed thread");
- pthread_join(threads[i].tid, NULL);
- threads[i].tid = 0;
- }
+ /* Check to make sure we have a thread */
+ if(fd != -1)
+ {
+ ha_messagex(NULL, LOG_ERR, "too many connections open (max %d)", g_maxthreads);
+ httpauth_respond(NULL, fd, HA_SERVER_ERROR, 0, "too many connections");
+ shutdown(fd, SHUT_RDWR);
+ }
}
- /* Start a new thread if neccessary */
- if(fd != -1 && threads[i].tid == 0)
+ ha_messagex(NULL, LOG_INFO, "waiting for threads to quit");
+
+ /* Quit all threads here */
+ for(i = 0; i < g_maxthreads; i++)
{
- threads[i].fd = fd;
- r = pthread_create(&(threads[i].tid), NULL, httpauth_thread,
- (void*)(threads + i));
- if(r != 0)
- {
- errno = r;
- ha_message(LOG_ERR, "couldn't create thread");
- g_quit = 1;
- break;
- }
+ /* Clean up quit threads */
+ if(threads[i].tid != 0)
+ {
+ if(threads[i].fd != -1)
+ shutdown(threads[i].fd, SHUT_RDWR);
- ha_messagex(LOG_DEBUG, "%d: created thread for connection", fd);
- fd = -1;
- break;
+ pthread_join(threads[i].tid, NULL);
+ }
}
- }
-
- /* Check to make sure we have a thread */
- if(fd != -1)
- {
- ha_messagex(LOG_ERR, "too many connections open (max %d)", g_maxthreads);
- httpauth_respond(fd, HA_SERVER_ERROR, 0, "too many connections");
- shutdown(fd, SHUT_RDWR);
- }
- }
-
- ha_messagex(LOG_INFO, "waiting for threads to quit");
- /* Quit all threads here */
- for(i = 0; i < g_maxthreads; i++)
- {
- /* Clean up quit threads */
- if(threads[i].tid != 0)
- {
- if(threads[i].fd != -1)
- shutdown(threads[i].fd, SHUT_RDWR);
-
- pthread_join(threads[i].tid, NULL);
- }
+ r = 0;
}
- r = 0;
- }
-
finally:
- ha_messagex(LOG_DEBUG, "performing cleanup...");
+ ha_messagex(NULL, LOG_DEBUG, "performing cleanup...");
- /* Uninitialize all the handlers */
- for(h = g_handlers; h; h = h->next)
- {
- if(h->ctx.handler->f_destroy)
- (h->ctx.handler->f_destroy)(&(h->ctx));
- }
-
- /* Run global destroy for all handlers */
- for(i = 0; i < countof(g_handlerlist); i++)
- {
- if(g_handlerlist[i]->f_destroy)
- (g_handlerlist[i]->f_destroy)(NULL);
- }
+ /* Uninitialize all the handlers */
+ for(h = g_handlers; h; h = h->next)
+ {
+ if(h->ctx.handler->f_destroy)
+ (h->ctx.handler->f_destroy)(&(h->ctx));
+ }
- /* Clean up memory and stuff */
- ha_buffree(&cbuf);
+ /* Run global destroy for all handlers */
+ for(i = 0; i < countof(g_handlerlist); i++)
+ {
+ if(g_handlerlist[i]->f_destroy)
+ (g_handlerlist[i]->f_destroy)(NULL);
+ }
- /* Close the mutex */
- pthread_mutex_destroy(&g_mutex);
- pthread_mutexattr_destroy(&g_mutexattr);
+ /* Clean up memory and stuff */
+ ha_buffree(&cbuf);
- ha_messagex(LOG_DEBUG, "stopped");
+ /* Close the mutex */
+ pthread_mutex_destroy(&g_mutex);
+ pthread_mutexattr_destroy(&g_mutexattr);
- return r == -1 ? 1 : 0;
+ ha_messagex(NULL, LOG_DEBUG, "stopped");
+ return r == -1 ? 1 : 0;
}
static void on_quit(int signal)
{
- g_quit = 1;
- fprintf(stderr, "httpauthd: got signal to quit\n");
+ g_quit = 1;
+ fprintf(stderr, "httpauthd: got signal to quit\n");
}
static int usage()
{
- fprintf(stderr, "usage: httpauthd [-d level] [-X] [-p pidfile] [-f conffile]\n");
- return 2;
+ fprintf(stderr, "usage: httpauthd [-d level] [-X] [-p pidfile] [-f conffile]\n");
+ return 2;
}
static void writepid(const char* pidfile)
{
- FILE* f = fopen(pidfile, "w");
- if(f == NULL)
- {
- warnx("couldn't open pid file: %s", pidfile);
- }
- else
- {
- fprintf(f, "%d\n", (int)getpid());
-
- if(ferror(f))
- warnx("couldn't write to pid file: %s", pidfile);
-
- fclose(f);
- }
+ FILE* f = fopen(pidfile, "w");
+ if(f == NULL)
+ {
+ warnx("couldn't open pid file: %s", pidfile);
+ }
+ else
+ {
+ fprintf(f, "%d\n", (int)getpid());
+
+ if(ferror(f))
+ warnx("couldn't write to pid file: %s", pidfile);
+
+ fclose(f);
+ }
}
static void* httpauth_thread(void* arg)
{
- httpauth_thread_t* thread = (httpauth_thread_t*)arg;
- int r;
+ httpauth_thread_t* thread = (httpauth_thread_t*)arg;
+ int r;
- siginterrupt(SIGINT, 1);
- siginterrupt(SIGTERM, 1);
-
- ASSERT(thread);
- ASSERT(thread->fd != -1);
+ siginterrupt(SIGINT, 1);
+ siginterrupt(SIGTERM, 1);
- /* call the processor */
- r = httpauth_processor(thread->fd, thread->fd);
+ ASSERT(thread);
+ ASSERT(thread->fd != -1);
- ha_messagex(LOG_INFO, "%d: closed connection", thread->fd);
+ /* call the processor */
+ r = httpauth_processor(thread->fd, thread->fd);
- /* mark this as done */
- thread->fd = -1;
+ /* TODO: Move this to more appropriate place (where we have a req) */
+ ha_messagex(NULL, LOG_INFO, "%d: closed connection", thread->fd);
- return (void*)r;
+ /* mark this as done */
+ thread->fd = -1;
+ return (void*)r;
}
/* -----------------------------------------------------------------------
* Logging
*/
-void log_request(ha_request_t* req, ha_buffer_t* buf, int fd)
+void log_request(ha_request_t* rq)
{
- const httpauth_command_t* cmd;
- const char* t;
- const char* t2;
- int i;
+ const httpauth_command_t* cmd;
+ const char* t;
+ const char* t2;
+ int i;
- if(g_debuglevel < LOG_DEBUG)
- return;
+ if(g_debuglevel < LOG_DEBUG)
+ return;
- if(req->type == REQTYPE_IGNORE || req->type == -1)
- return;
+ if(rq->req_type == REQTYPE_IGNORE || rq->req_type == -1)
+ return;
- ha_bufcpy(buf, "");
+ ha_bufcpy(rq->buf, "");
- for(i = 0; i < HA_MAX_ARGS; i++)
- {
- if(req->args[i])
+ for(i = 0; i < HA_MAX_ARGS; i++)
{
- ha_bufjoin(buf);
- ha_bufmcat(buf, ha_buflen(buf) > 0 ? ", " : "", req->args[i], NULL);
+ if(rq->req_args[i])
+ {
+ ha_bufjoin(rq->buf);
+ ha_bufmcat(rq->buf, ha_buflen(rq->buf) > 0 ? ", " : "", rq->req_args[i], NULL);
+ }
}
- }
- t = ha_bufdata(buf);
+ t = ha_bufdata(rq->buf);
+ t2 = NULL;
- t2 = NULL;
-
- /* Figure out which command it is */
- for(cmd = kCommands; cmd->name; cmd++)
- {
- if(cmd->code == req->type)
+ /* Figure out which command it is */
+ for(cmd = kCommands; cmd->name; cmd++)
{
- t2 = cmd->name;
- break;
+ if(cmd->code == rq->req_type)
+ {
+ t2 = cmd->name;
+ break;
+ }
}
- }
- ASSERT(t2);
+ ASSERT(t2);
- ha_messagex(LOG_DEBUG, "%d: received request: "
- "[ type: %s / args: %s ]", fd, t2, t);
+ ha_messagex(rq, LOG_DEBUG, "received request: [ type: %s / args: %s ]", t2, t);
- for(i = 0; i < HA_MAX_HEADERS; i++)
- {
- if(req->headers[i].name)
+ for(i = 0; i < HA_MAX_HEADERS; i++)
{
- ASSERT(req->headers[i].data);
- ha_messagex(LOG_DEBUG, "%d: received header: [ %s: %s ]", fd,
- req->headers[i].name, req->headers[i].data);
+ if(rq->req_headers[i].name)
+ {
+ ASSERT(rq->req_headers[i].data);
+ ha_messagex(rq, LOG_DEBUG, "received header: [ %s: %s ]",
+ rq->req_headers[i].name, rq->req_headers[i].data);
+ }
}
- }
}
-void log_response(ha_response_t* resp, int fd)
+void log_response(ha_request_t* rq)
{
- int i;
+ int i;
- if(g_debuglevel < LOG_DEBUG)
- return;
+ if(g_debuglevel < LOG_DEBUG)
+ return;
- ha_messagex(LOG_DEBUG, "%d: sending response: "
- "[ code: 200 / ccode: %d / detail: %s ]", fd,
- resp->code, resp->detail ? resp->detail : "");
+ ha_messagex(rq, LOG_DEBUG, "sending response: [ code: 200 / ccode: %d / detail: %s ]",
+ rq->resp_code, rq->resp_detail ? rq->resp_detail : "");
- for(i = 0; i < HA_MAX_HEADERS; i++)
- {
- if(resp->headers[i].name)
+ for(i = 0; i < HA_MAX_HEADERS; i++)
{
- ASSERT(resp->headers[i].data);
- ha_messagex(LOG_DEBUG, "%d: sending header: [ %s: %s ]", fd,
- resp->headers[i].name, resp->headers[i].data);
+ if(rq->resp_headers[i].name)
+ {
+ ASSERT(rq->resp_headers[i].data);
+ ha_messagex(rq, LOG_DEBUG, "sending header: [ %s: %s ]",
+ rq->resp_headers[i].name, rq->resp_headers[i].data);
+ }
}
- }
}
-void log_respcode(int code, const char* msg, int fd)
+void log_respcode(ha_request_t* rq, int code, const char* msg)
{
- if(g_debuglevel < LOG_DEBUG)
- return;
+ if(g_debuglevel < LOG_DEBUG)
+ return;
- ha_messagex(LOG_DEBUG, "%d: sending response: "
- "[ code: %d / detail: %s ]", fd, code, msg ? msg : "");
+ ha_messagex(rq, LOG_DEBUG, "sending response: [ code: %d / detail: %s ]",
+ code, msg ? msg : "");
}
/* -----------------------------------------------------------------------
* Command Parsing and Handling
*/
-static int httpauth_read(int ifd, ha_request_t* req,
- ha_buffer_t* buf)
+static int httpauth_read(ha_request_t* rq, int ifd)
{
- const httpauth_command_t* cmd;
- char* t;
- int i, r;
- int more = 1;
+ const httpauth_command_t* cmd;
+ char* t;
+ int i, r;
+ int more = 1;
- ASSERT(req && buf);
- ASSERT(ifd != -1);
+ ASSERT(r);
+ ASSERT(ifd != -1);
- /* Clean up the request header */
- req->type = -1;
- memset(req->args, 0, sizeof(req->args));
- memset(req->headers, 0, sizeof(req->headers));
+ /* Clean up the request header */
+ rq->req_type = -1;
+ memset(rq->req_args, 0, sizeof(rq->req_args));
+ memset(rq->req_headers, 0, sizeof(rq->req_headers));
- /* This guarantees a bit of memory allocated, and resets buffer */
- ha_bufreset(buf);
+ /* This guarantees a bit of memory allocated, and resets buffer */
+ ha_bufreset(rq->buf);
- r = ha_bufreadline(ifd, buf);
- if(r == -1)
- return -1;
+ r = ha_bufreadline(ifd, rq->buf);
+ if(r == -1)
+ return -1;
- /* Check if this is the last line */
- if(r == 0)
- more = 0;
+ /* Check if this is the last line */
+ if(r == 0)
+ more = 0;
- /* Check to see if we got anything */
- if(ha_buflen(buf) == 0)
- {
- req->type = REQTYPE_IGNORE;
- return more;
- }
+ /* Check to see if we got anything */
+ if(ha_buflen(rq->buf) == 0)
+ {
+ rq->req_type = REQTYPE_IGNORE;
+ return more;
+ }
- /* Find the first space in the line */
- t = ha_bufparseword(buf, " \t");
+ /* Find the first space in the line */
+ t = ha_bufparseword(rq->buf, " \t");
- if(t)
- {
- /* Figure out which command it is */
- for(cmd = kCommands; cmd->name; cmd++)
+ if(t)
{
- if(strcasecmp(t, cmd->name) == 0)
- {
- req->type = cmd->code;
- break;
- }
+ /* Figure out which command it is */
+ for(cmd = kCommands; cmd->name; cmd++)
+ {
+ if(strcasecmp(t, cmd->name) == 0)
+ {
+ rq->req_type = cmd->code;
+ break;
+ }
+ }
}
- }
-
- else
- {
- req->type = REQTYPE_IGNORE;
- return more;
- }
- /* Check for invalid command */
- if(req->type == -1)
- return more;
+ else
+ {
+ rq->req_type = REQTYPE_IGNORE;
+ return more;
+ }
- /* Now parse the arguments if any */
- for(i = 0; i < cmd->word_args; i++)
- req->args[i] = ha_bufparseword(buf, " \t");
+ /* Check for invalid command */
+ if(rq->req_type == -1)
+ return more;
- /* Does it want the rest as one argument? */
- if(cmd->rest_arg)
- req->args[i] = ha_bufparseline(buf, 1);
+ /* Now parse the arguments if any */
+ for(i = 0; i < cmd->word_args; i++)
+ rq->req_args[i] = ha_bufparseword(rq->buf, " \t");
+ /* Does it want the rest as one argument? */
+ if(cmd->rest_arg)
+ rq->req_args[i] = ha_bufparseline(rq->buf, 1);
- /* Now skip anything else we have in the buffer */
- ha_bufskip(buf);
+ /* Now skip anything else we have in the buffer */
+ ha_bufskip(rq->buf);
- /* If we need headers, then read them now */
- if(cmd->headers)
- {
- const char** head; /* For iterating through valid headers */
- int valid = 0; /* The last header was valid */
- i = 0; /* The header we're working with */
- for(;;)
+ /* If we need headers, then read them now */
+ if(cmd->headers)
{
- /* Make sure we have more data */
- if(!more)
- break;
-
- r = ha_bufreadline(ifd, buf);
- if(r == -1)
- return -1;
-
- /* Check if this is the last line */
- if(r == 0)
- more = 0;
-
- /* An empty line is the end of the headers */
- if(ha_buflen(buf) == 0)
- break;
+ const char** head; /* For iterating through valid headers */
+ int valid = 0; /* The last header was valid */
+ i = 0; /* The header we're working with */
- /* Check if the header starts with a space */
- if(isspace(ha_bufchar(buf)))
- {
- /* Skip all the spaces */
- while(ha_buflen(buf) > 0 && isspace(ha_bufchar(buf)))
- ha_bufeat(buf);
+ for(;;)
+ {
+ /* Make sure we have more data */
+ if(!more)
+ break;
- /* An empty line is the end of the headers
- even if that line has spaces on it */
- if(ha_buflen(buf) == 0)
- break;
+ r = ha_bufreadline(ifd, rq->buf);
+ if(r == -1)
+ return -1;
- /* A header that has data on it but started
- with a space continues the previous header */
- if(valid && i > 0)
- {
- t = ha_bufparseline(buf, 0);
- if(t)
- {
- char* t2 = (char*)req->headers[i - 1].data + strlen(req->headers[i - 1].data);
-
- /* Fill the area between the end of the last
- valid header and this with spaces */
- memset(t2, ' ', t - t2);
- }
- }
- }
- else
- {
- if(i < HA_MAX_HEADERS)
- {
- t = ha_bufparseword(buf, ":");
+ /* Check if this is the last line */
+ if(r == 0)
+ more = 0;
- if(t)
- {
- for(head = cmd->headers; ; head++)
- {
- if(!(*head))
- {
- t = NULL;
+ /* An empty line is the end of the headers */
+ if(ha_buflen(rq->buf) == 0)
break;
- }
- if(strcasecmp(t, *head) == 0)
- break;
+ /* Check if the header starts with a space */
+ if(isspace(ha_bufchar(rq->buf)))
+ {
+ /* Skip all the spaces */
+ while(ha_buflen(rq->buf) > 0 && isspace(ha_bufchar(rq->buf)))
+ ha_bufeat(rq->buf);
+
+ /* An empty line is the end of the headers
+ even if that line has spaces on it */
+ if(ha_buflen(rq->buf) == 0)
+ break;
+
+ /* A header that has data on it but started
+ with a space continues the previous header */
+ if(valid && i > 0)
+ {
+ t = ha_bufparseline(rq->buf, 0);
+ if(t)
+ {
+ char* t2 = (char*)rq->req_headers[i - 1].data + strlen(rq->req_headers[i - 1].data);
+
+ /* Fill the area between the end of the last
+ valid header and this with spaces */
+ memset(t2, ' ', t - t2);
+ }
+ }
+ }
+ else
+ {
+ if(i < HA_MAX_HEADERS)
+ {
+ t = ha_bufparseword(rq->buf, ":");
+
+ if(t)
+ {
+ for(head = cmd->headers; ; head++)
+ {
+ if(!(*head))
+ {
+ t = NULL;
+ break;
+ }
+
+ if(strcasecmp(t, *head) == 0)
+ break;
+ }
+ }
+
+ if(t)
+ {
+ rq->req_headers[i].name = t;
+ rq->req_headers[i].data = ha_bufparseline(rq->buf, 1);
+ i++;
+ }
+
+ valid = (t != NULL) ? 1 : 0;
+ }
}
- }
-
- if(t)
- {
- req->headers[i].name = t;
- req->headers[i].data = ha_bufparseline(buf, 1);
- i++;
- }
- valid = (t != NULL) ? 1 : 0;
+ ha_bufskip(rq->buf);
}
- }
-
- ha_bufskip(buf);
}
- }
- return more;
+ return more;
}
-static int write_data(int ofd, const char* data)
+static int write_data(ha_request_t* rq, int ofd, const char* data)
{
- int r;
+ int r;
- ASSERT(data);
- ASSERT(ofd != -1);
+ ASSERT(data);
+ ASSERT(ofd != -1);
- while(*data != 0)
- {
- r = write(ofd, data, strlen(data));
+ while(*data != 0)
+ {
+ r = write(ofd, data, strlen(data));
- if(r > 0)
- data += r;
+ if(r > 0)
+ data += r;
- else if(r == -1)
- {
- if(errno == EAGAIN)
- continue;
+ else if(r == -1)
+ {
+ if(errno == EAGAIN)
+ continue;
- /* The other end closed. no message */
- if(errno != EPIPE)
- ha_message(LOG_ERR, "couldn't write data");
+ /* The other end closed. no message */
+ if(errno != EPIPE)
+ ha_message(rq, LOG_ERR, "couldn't write data");
- return HA_CRITERROR;
+ return HA_CRITERROR;
+ }
}
- }
- return 0;
+ return 0;
}
-static int httpauth_respond(int ofd, int scode, int ccode, const char* msg)
+static int httpauth_respond(ha_request_t* rq, int ofd, int scode, int ccode, const char* msg)
{
- char num[16];
+ char num[16];
- ASSERT(ofd != -1);
- ASSERT(scode > 99 && scode < 1000);
- ASSERT(ccode == 0 || (ccode > 99 && ccode < 1000));
+ ASSERT(ofd != -1);
+ ASSERT(scode > 99 && scode < 1000);
+ ASSERT(ccode == 0 || (ccode > 99 && ccode < 1000));
- /* Can only have a client code when server code is 200 */
- ASSERT(ccode == 0 || scode == HA_SERVER_OK);
+ /* Can only have a client code when server code is 200 */
+ ASSERT(ccode == 0 || scode == HA_SERVER_OK);
- sprintf(num, "%d ", scode);
+ sprintf(num, "%d ", scode);
- if(write_data(ofd, num) < 0)
- return HA_CRITERROR;
+ if(write_data(rq, ofd, num) < 0)
+ return HA_CRITERROR;
- if(ccode != 0)
- {
- sprintf(num, "%d ", ccode);
+ if(ccode != 0)
+ {
+ sprintf(num, "%d ", ccode);
- if(write_data(ofd, num) < 0)
- return HA_CRITERROR;
- }
+ if(write_data(rq, ofd, num) < 0)
+ return HA_CRITERROR;
+ }
- if(!msg)
- {
- switch(scode)
+ if(!msg)
{
- case HA_SERVER_ACCEPTED:
- msg = "Accepted";
- break;
- case HA_SERVER_ERROR:
- msg = "Internal Error ";
- break;
- case HA_SERVER_BADREQ:
- msg = "Bad Request ";
- break;
- case HA_SERVER_DECLINE:
- msg = "Unauthorized ";
- break;
- default:
- msg = NULL;
- break;
- };
- }
+ switch(scode)
+ {
+ case HA_SERVER_ACCEPTED:
+ msg = "Accepted";
+ break;
+ case HA_SERVER_ERROR:
+ msg = "Internal Error ";
+ break;
+ case HA_SERVER_BADREQ:
+ msg = "Bad Request ";
+ break;
+ case HA_SERVER_DECLINE:
+ msg = "Unauthorized ";
+ break;
+ default:
+ msg = NULL;
+ break;
+ };
+ }
- if(msg && write_data(ofd, msg) < 0)
- return HA_CRITERROR;
+ if(msg && write_data(rq, ofd, msg) < 0)
+ return HA_CRITERROR;
- /* When the client code is 0, then caller should log */
- if(ccode == 0)
- log_respcode(scode, msg, ofd);
+ /* When the client code is 0, then caller should log */
+ if(ccode == 0)
+ log_respcode(rq, scode, msg);
- return write_data(ofd, "\n");
+ return write_data(rq, ofd, "\n");
}
const char kHeaderDelimiter[] = ": ";
-static int httpauth_write(int ofd, ha_response_t* resp)
+static int httpauth_write(ha_request_t* rq, int ofd)
{
- int i;
- int wrote = 0;
+ int i;
+ int wrote = 0;
- ASSERT(ofd != -1);
- ASSERT(resp);
+ ASSERT(ofd != -1);
+ ASSERT(rq);
- if(httpauth_respond(ofd, HA_SERVER_OK, resp->code, resp->detail) < 0)
- return HA_CRITERROR;
+ if(httpauth_respond(rq, ofd, HA_SERVER_OK, rq->resp_code, rq->resp_detail) < 0)
+ return HA_CRITERROR;
- for(i = 0; i < HA_MAX_HEADERS; i++)
- {
- if(resp->headers[i].name)
+ for(i = 0; i < HA_MAX_HEADERS; i++)
{
- if(write_data(ofd, resp->headers[i].name) == -1 ||
- write_data(ofd, kHeaderDelimiter) == -1 ||
- write_data(ofd, resp->headers[i].data) == -1 ||
- write_data(ofd, "\n") == -1)
- return -1;
+ if(rq->resp_headers[i].name)
+ {
+ if(write_data(rq, ofd, rq->resp_headers[i].name) == -1 ||
+ write_data(rq, ofd, kHeaderDelimiter) == -1 ||
+ write_data(rq, ofd, rq->resp_headers[i].data) == -1 ||
+ write_data(rq, ofd, "\n") == -1)
+ return -1;
- wrote = 1;
+ wrote = 1;
+ }
}
- }
- if(write_data(ofd, "\n") == -1)
- return -1;
+ if(write_data(rq, ofd, "\n") == -1)
+ return -1;
- log_response(resp, ofd);
+ log_response(rq);
- return 0;
+ return 0;
}
-static int httpauth_error(int ofd, int r)
+static int httpauth_error(ha_request_t* rq, int ofd, int r)
{
- int scode = 0;
- const char* msg = NULL;
+ int scode = 0;
+ const char* msg = NULL;
- ASSERT(r < 0);
+ ASSERT(r < 0);
- switch(r)
- {
- case HA_BADREQ:
- scode = HA_SERVER_BADREQ;
- break;
+ switch(r)
+ {
+ case HA_BADREQ:
+ scode = HA_SERVER_BADREQ;
+ break;
- case HA_CRITERROR:
- msg = "Critical Error";
- /* fall through */
+ case HA_CRITERROR:
+ msg = "Critical Error";
+ /* fall through */
- case HA_FAILED:
- scode = HA_SERVER_ERROR;
- break;
+ case HA_FAILED:
+ scode = HA_SERVER_ERROR;
+ break;
- default:
- ASSERT(0 && "invalid error code");
- break;
- }
+ default:
+ ASSERT(0 && "invalid error code");
+ break;
+ };
- return httpauth_respond(ofd, scode, 0, msg);
+ return httpauth_respond(rq, ofd, scode, 0, msg);
}
-static int httpauth_ready(int ofd, ha_buffer_t* buf)
+static int httpauth_ready(ha_request_t* rq, int ofd)
{
- const char* t;
- httpauth_loaded_t* h;
+ const char* t;
+ httpauth_loaded_t* h;
- ASSERT(ofd != -1);
- ASSERT(buf);
+ ASSERT(ofd != -1);
+ ASSERT(rq);
- /* We send a ready banner to our client */
+ /* We send a ready banner to our client */
- if(ha_buferr(buf))
- return httpauth_error(ofd, HA_CRITERROR);
-
- else
- return httpauth_respond(ofd, HA_SERVER_READY, 0, "HTTPAUTH/1.0");
+ if(ha_buferr(rq->buf))
+ return httpauth_error(rq, ofd, HA_CRITERROR);
+ else
+ return httpauth_respond(rq, ofd, HA_SERVER_READY, 0, "HTTPAUTH/1.0");
}
-static int httpauth_auth(int ofd, ha_request_t* req, ha_response_t* resp)
+static int httpauth_auth(ha_request_t* rq, int ofd)
{
- int r;
-
- ASSERT(req && resp);
-
- if(!req->context)
- {
- ha_messagex(LOG_ERR, "no auth handler set");
- return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "No Auth Handler Set");
- }
-
- /* Clear out our response */
- resp->code = -1;
- resp->detail = NULL;
- memset(resp->headers, 0, sizeof(resp->headers));
- ASSERT(resp->buf != NULL);
-
- /* Check our connection argument */
- if(!req->args[AUTH_ARG_CONN] || !(req->args[AUTH_ARG_CONN][0]))
- {
- ha_messagex(LOG_ERR, "missing connection ID in request");
- return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing Connection ID");
- }
-
- /* Check our uri argument */
- if(!req->args[AUTH_ARG_URI] || !(req->args[AUTH_ARG_URI][0]))
- {
- ha_messagex(LOG_ERR, "missing URI in request");
- return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing URI");
- }
-
- /* Check our connection arguments */
- if(!req->args[AUTH_ARG_METHOD] || !(req->args[AUTH_ARG_METHOD][0]))
- {
- ha_messagex(LOG_ERR, "missing HTTP method in request");
- return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing HTTP Method");
- }
-
- ASSERT(req->context->handler && req->context->handler->f_process);
- r = (req->context->handler->f_process)(req, resp);
- if(r < 0)
- return r;
-
- if(httpauth_write(ofd, resp) < 0)
- return HA_CRITERROR;
-
- return HA_OK;
+ int r;
+
+ ASSERT(rq);
+
+ if(!rq->context)
+ {
+ ha_messagex(rq, LOG_ERR, "no auth handler set");
+ return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "No Auth Handler Set");
+ }
+
+ /* Clear out our response */
+ rq->resp_code = -1;
+ rq->resp_detail = NULL;
+ memset(rq->resp_headers, 0, sizeof(rq->resp_headers));
+
+ /* Check our connection argument */
+ if(!rq->req_args[AUTH_ARG_CONN] || !(rq->req_args[AUTH_ARG_CONN][0]))
+ {
+ ha_messagex(rq, LOG_ERR, "missing connection ID in request");
+ return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Missing Connection ID");
+ }
+
+ /* Check our uri argument */
+ if(!rq->req_args[AUTH_ARG_URI] || !(rq->req_args[AUTH_ARG_URI][0]))
+ {
+ ha_messagex(rq, LOG_ERR, "missing URI in request");
+ return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Missing URI");
+ }
+
+ /* Check our connection arguments */
+ if(!rq->req_args[AUTH_ARG_METHOD] || !(rq->req_args[AUTH_ARG_METHOD][0]))
+ {
+ ha_messagex(rq, LOG_ERR, "missing HTTP method in request");
+ return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Missing HTTP Method");
+ }
+
+ ASSERT(rq->context->handler && rq->context->handler->f_process);
+ r = (rq->context->handler->f_process)(rq);
+ if(r < 0)
+ return r;
+
+ if(httpauth_write(rq, ofd) < 0)
+ return HA_CRITERROR;
+
+ return HA_OK;
}
-static int httpauth_set(int ofd, ha_request_t* req)
+static int httpauth_set(ha_request_t* rq, int ofd)
{
- httpauth_loaded_t* h;
- const char* name = req->args[0];
- const char* value = req->args[1];
-
- ASSERT(req);
-
- /* Check our name argument */
- if(!name || !*name)
- {
- ha_messagex(LOG_ERR, "missing name in SET request");
- return HA_BADREQ;
- }
-
- if(strcasecmp(name, "Domain") == 0)
- {
- req->digest_domain = value ? value : "";
- }
-
- else if(strcasecmp(name, "Handler") == 0)
- {
- if(!value || !*value)
+ httpauth_loaded_t* h;
+ const char* name = rq->req_args[0];
+ const char* value = rq->req_args[1];
+
+ /* Check our name argument */
+ if(!name || !*name)
{
- ha_messagex(LOG_ERR, "no auth handler specified in SET request.");
- return HA_BADREQ;
+ ha_messagex(rq, LOG_ERR, "missing name in SET request");
+ return HA_BADREQ;
}
- /* Find a handler for this type */
- for(h = g_handlers; h; h = h->next)
+ if(strcasecmp(name, "Domain") == 0)
{
- if(strcasecmp(h->ctx.name, value) == 0)
- {
- req->context = &(h->ctx);
- value = NULL;
- break;
- }
+ rq->digest_domain = value ? value : "";
}
- if(value != NULL)
+ else if(strcasecmp(name, "Handler") == 0)
{
- ha_messagex(LOG_ERR, "unknown authentication type: %s", req->args[0]);
- return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Unknown Auth Handler");
+ if(!value || !*value)
+ {
+ ha_messagex(rq, LOG_ERR, "no auth handler specified in SET request.");
+ return HA_BADREQ;
+ }
+
+ /* Find a handler for this type */
+ for(h = g_handlers; h; h = h->next)
+ {
+ if(strcasecmp(h->ctx.name, value) == 0)
+ {
+ rq->context = &(h->ctx);
+ value = NULL;
+ break;
+ }
+ }
+
+ if(value != NULL)
+ {
+ ha_messagex(rq, LOG_ERR, "unknown authentication type: %s", rq->req_args[0]);
+ return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Unknown Auth Handler");
+ }
}
- }
- else
- {
- ha_messagex(LOG_ERR, "bad option in SET request");
- return HA_BADREQ;
- }
+ else
+ {
+ ha_messagex(rq, LOG_ERR, "bad option in SET request");
+ return HA_BADREQ;
+ }
- return httpauth_respond(ofd, HA_SERVER_ACCEPTED, 0, NULL);
+ return httpauth_respond(rq, ofd, HA_SERVER_ACCEPTED, 0, NULL);
}
static int httpauth_processor(int ifd, int ofd)
{
- ha_buffer_t buf;
- ha_request_t req;
- ha_response_t resp;
- int result = -1;
- int r;
+ ha_buffer_t buf;
+ ha_request_t rq;
+ int result = -1;
+ int r;
- ASSERT(ifd != -1);
- ASSERT(ofd != -1);
+ ASSERT(ifd != -1);
+ ASSERT(ofd != -1);
- /* Initialize the memory buffers */
- ha_bufinit(&buf);
+ /* Initialize the memory buffers */
+ ha_bufinit(&buf);
- memset(&req, 0, sizeof(req));
- memset(&resp, 0, sizeof(resp));
+ memset(&rq, 0, sizeof(rq));
- /* Set up some context stuff */
- req.digest_domain = "";
- req.buf = &buf;
- resp.buf = &buf;
+ /* Set up some context stuff */
+ rq.digest_domain = "";
+ rq.buf = &buf;
- if(httpauth_ready(ofd, &buf) == -1)
- {
- result = 1;
- goto finally;
- }
+ if(httpauth_ready(&rq, ofd) == -1)
+ {
+ result = 1;
+ goto finally;
+ }
- /* Now loop and handle the commands */
- while(result == -1)
- {
- ha_bufreset(&buf);
+ /* Now loop and handle the commands */
+ while(result == -1)
+ {
+ ha_bufreset(&buf);
- r = httpauth_read(ifd, &req, &buf);
+ r = httpauth_read(&rq, ifd);
- if(ha_buferr(&buf))
- r = HA_CRITERROR;
+ if(ha_buferr(&buf))
+ r = HA_CRITERROR;
- if(r < 0)
- {
- httpauth_error(ofd, r);
- result = 1;
- break;
- }
+ if(r < 0)
+ {
+ httpauth_error(&rq, ofd, r);
+ result = 1;
+ break;
+ }
- log_request(&req, &buf, ifd);
+ log_request(&rq);
- if(r == 0)
- result = 0;
+ if(r == 0)
+ result = 0;
- switch(req.type)
- {
- case REQTYPE_AUTH:
- r = httpauth_auth(ofd, &req, &resp);
- break;
+ switch(rq.req_type)
+ {
+ case REQTYPE_AUTH:
+ r = httpauth_auth(&rq, ofd);
+ break;
- case REQTYPE_SET:
- r = httpauth_set(ofd, &req);
- break;
+ case REQTYPE_SET:
+ r = httpauth_set(&rq, ofd);
+ break;
- case REQTYPE_QUIT:
- r = HA_OK;
- result = 0;
- break;
+ case REQTYPE_QUIT:
+ r = HA_OK;
+ result = 0;
+ break;
- case REQTYPE_IGNORE:
- r = HA_FALSE;
- break;
+ case REQTYPE_IGNORE:
+ r = HA_FALSE;
+ break;
- default:
- ha_messagex(LOG_WARNING, "%d: received unknown command from client", ifd);
- r = httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Unknown command");
- break;
- };
+ default:
+ ha_messagex(&rq, LOG_WARNING, "received unknown command from client");
+ r = httpauth_respond(&rq, ofd, HA_SERVER_BADREQ, 0, "Unknown command");
+ break;
+ };
- if(ha_buferr(&buf))
- r = HA_CRITERROR;
+ if(ha_buferr(&buf))
+ r = HA_CRITERROR;
- if(r < 0)
- {
- httpauth_error(ofd, r);
+ if(r < 0)
+ {
+ httpauth_error(&rq, ofd, r);
- if(r == HA_CRITERROR)
- result = 1;
+ if(r == HA_CRITERROR)
+ result = 1;
+ }
}
- }
- if(ifd == ofd)
- shutdown(ofd, SHUT_RDWR);
- else
- close(ofd);
+ if(ifd == ofd)
+ {
+ shutdown(ofd, SHUT_RDWR);
+ close(ofd);
+ }
+ else
+ {
+ close(ifd);
+ close(ofd);
+ }
finally:
- ha_buffree(&buf);
-
- return result;
+ ha_buffree(&buf);
+ return result;
}
/* -----------------------------------------------------------------------
@@ -1129,335 +1122,335 @@ finally:
*/
static ha_context_t* config_addhandler(ha_buffer_t* buf, const char* alias,
- ha_handler_t* handler, const ha_context_t* defaults)
+ ha_handler_t* handler, const ha_context_t* defaults)
{
- httpauth_loaded_t* loaded;
- int len;
+ httpauth_loaded_t* loaded;
+ int len;
- ASSERT(buf && alias && handler && defaults);
+ ASSERT(buf && alias && handler && defaults);
- len = sizeof(httpauth_loaded_t) + handler->context_size;
+ len = sizeof(httpauth_loaded_t) + handler->context_size;
- loaded = (httpauth_loaded_t*)ha_bufmalloc(buf, len);
- if(!loaded)
- errx(1, "out of memory");
+ loaded = (httpauth_loaded_t*)ha_bufmalloc(buf, len);
+ if(!loaded)
+ errx(1, "out of memory");
- memset(loaded, 0, len);
+ memset(loaded, 0, len);
- /* Setup the options from the defaults */
- memcpy(&(loaded->ctx), defaults, sizeof(ha_context_t));
+ /* Setup the options from the defaults */
+ memcpy(&(loaded->ctx), defaults, sizeof(ha_context_t));
- if(handler->context_size)
- {
- void* mem = ((unsigned char*)(loaded)) + sizeof(httpauth_loaded_t);
-
- /* Initialize the defaults properly */
- if(handler->context_default)
- memcpy(mem, handler->context_default, handler->context_size);
+ if(handler->context_size)
+ {
+ void* mem = ((unsigned char*)(loaded)) + sizeof(httpauth_loaded_t);
- loaded->ctx.ctx_data = mem;
- }
+ /* Initialize the defaults properly */
+ if(handler->context_default)
+ memcpy(mem, handler->context_default, handler->context_size);
- else
- {
- loaded->ctx.ctx_data = NULL;
- }
+ loaded->ctx.ctx_data = mem;
+ }
- loaded->ctx.name = (char*)alias;
- loaded->ctx.handler = handler;
+ else
+ {
+ loaded->ctx.ctx_data = NULL;
+ }
- if(!g_handlers)
- {
- g_handlers = loaded;
- }
- else
- {
- httpauth_loaded_t* l = g_handlers;
+ loaded->ctx.name = (char*)alias;
+ loaded->ctx.handler = handler;
- for(;;)
+ if(!g_handlers)
+ {
+ g_handlers = loaded;
+ }
+ else
{
- if(strcasecmp(alias, l->ctx.name) == 0)
- errx(1, "duplicate handler section for '%s'", alias);
+ httpauth_loaded_t* l = g_handlers;
- if(!(l->next))
- break;
+ for(;;)
+ {
+ if(strcasecmp(alias, l->ctx.name) == 0)
+ errx(1, "duplicate handler section for '%s'", alias);
- l = l->next;
- }
+ if(!(l->next))
+ break;
- l->next = loaded;
- }
+ l = l->next;
+ }
- ha_messagex(LOG_DEBUG, "configuration: handler: %s (%s)", alias, handler->type);
- return &(loaded->ctx);
+ l->next = loaded;
+ }
+
+ ha_messagex(NULL, LOG_DEBUG, "configuration: handler: %s (%s)", alias, handler->type);
+ return &(loaded->ctx);
}
#define VALID_ALIAS_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_-."
static int config_parse(const char* file, ha_buffer_t* buf)
{
- ha_context_t defaults;
- ha_context_t* ctx = NULL;
- int line = 0;
- int fd;
- char* t;
- char* name;
- char* value;
- int more = 1;
- int recog;
- int r, i;
-
- ASSERT(file && buf);
-
- /* Open the configuration file */
- fd = open(file, O_RDONLY);
- if(fd == -1)
- err(1, "couldn't open configuration file: %s", file);
-
- /* These are the default options for the contexts */
- memset(&defaults, 0, sizeof(defaults));
- defaults.allowed_types = 0xFFFFFFFF; /* All types by default */
- defaults.cache_timeout = DEFAULT_TIMEOUT; /* Timeout for cache */
- defaults.cache_max = DEFAULT_CACHEMAX;
- defaults.realm = "";
-
- /* Read each line and process */
- while(more)
- {
- ha_bufskip(buf);
-
- if((more = ha_bufreadline(fd, buf)) == -1)
- return -1;
-
- line++;
-
- /* Eat all white space at beginning of line */
- while(ha_buflen(buf) && isspace(ha_bufchar(buf)))
- ha_bufeat(buf);
-
- /* Skip blank lines */
- if(ha_buflen(buf) == 0)
- continue;
-
- /* Skip comment lines */
- if(ha_bufchar(buf) == '#')
- continue;
-
- /* Check for a handler */
- if(ha_bufchar(buf) == '[')
+ ha_context_t defaults;
+ ha_context_t* ctx = NULL;
+ int line = 0;
+ int fd;
+ char* t;
+ char* name;
+ char* value;
+ int more = 1;
+ int recog;
+ int r, i;
+
+ ASSERT(file && buf);
+
+ /* Open the configuration file */
+ fd = open(file, O_RDONLY);
+ if(fd == -1)
+ err(1, "couldn't open configuration file: %s", file);
+
+ /* These are the default options for the contexts */
+ memset(&defaults, 0, sizeof(defaults));
+ defaults.allowed_types = 0xFFFFFFFF; /* All types by default */
+ defaults.cache_timeout = DEFAULT_TIMEOUT; /* Timeout for cache */
+ defaults.cache_max = DEFAULT_CACHEMAX;
+ defaults.realm = "";
+
+ /* Read each line and process */
+ while(more)
{
- ha_handler_t* handler = NULL;
- const char* x;
+ ha_bufskip(buf);
- ha_bufeat(buf);
- name = ha_bufparseline(buf, 1);
+ if((more = ha_bufreadline(fd, buf)) == -1)
+ return -1;
- if(!name || name[strlen(name) - 1] != ']')
- errx(1, "handler section invalid (line %d)", line);
+ line++;
+ /* Eat all white space at beginning of line */
+ while(ha_buflen(buf) && isspace(ha_bufchar(buf)))
+ ha_bufeat(buf);
- /* remove the bracket */
- name[strlen(name) - 1] = 0;
+ /* Skip blank lines */
+ if(ha_buflen(buf) == 0)
+ continue;
- /*
- * Take out any colon found, past which would
- * be an aliased name
- */
- t = strchr(name, ':');
- if(t != NULL)
- {
- *t = 0;
- t++;
+ /* Skip comment lines */
+ if(ha_bufchar(buf) == '#')
+ continue;
- /* Rid of whitespace on ends */
- t = trim_space(t);
+ /* Check for a handler */
+ if(ha_bufchar(buf) == '[')
+ {
+ ha_handler_t* handler = NULL;
+ const char* x;
- /* Validate the alias name */
- if(!*t || strspn(t, VALID_ALIAS_CHARS) != strlen(t))
- errx(1, "invalid name for handler: %s", t);
- }
+ ha_bufeat(buf);
+ name = ha_bufparseline(buf, 1);
- /* Rid of whitespace */
- name = trim_space(name);
+ if(!name || name[strlen(name) - 1] != ']')
+ errx(1, "handler section invalid (line %d)", line);
- /* Look for a handler with this type */
- for(i = 0; i < countof(g_handlerlist); i++)
- {
- if(g_handlerlist[i] && g_handlerlist[i]->type &&
- strcasecmp(name, g_handlerlist[i]->type) == 0)
- {
- handler = g_handlerlist[i];
- break;
- }
- }
- if(handler == NULL)
- errx(1, "unknown handler type '%s' (line %d)", name, line);
+ /* remove the bracket */
+ name[strlen(name) - 1] = 0;
- /* If we had a last handler then add it to handlers */
- ctx = config_addhandler(buf, t ? t : name, handler, &defaults);
+ /*
+ * Take out any colon found, past which would
+ * be an aliased name
+ */
+ t = strchr(name, ':');
+ if(t != NULL)
+ {
+ *t = 0;
+ t++;
- /* Rest doesn't apply to handler headers */
- continue;
- }
+ /* Rid of whitespace on ends */
+ t = trim_space(t);
+ /* Validate the alias name */
+ if(!*t || strspn(t, VALID_ALIAS_CHARS) != strlen(t))
+ errx(1, "invalid name for handler: %s", t);
+ }
- /* Parse out the name */
- name = ha_bufparseword(buf, ":");
- if(!name || !name[0])
- errx(1, "configuration file invalid (line %d)", line);
+ /* Rid of whitespace */
+ name = trim_space(name);
- strlwr(name);
+ /* Look for a handler with this type */
+ for(i = 0; i < countof(g_handlerlist); i++)
+ {
+ if(g_handlerlist[i] && g_handlerlist[i]->type &&
+ strcasecmp(name, g_handlerlist[i]->type) == 0)
+ {
+ handler = g_handlerlist[i];
+ break;
+ }
+ }
- /* And get the rest of the line */
- value = ha_bufparseline(buf, 1);
- if(value == NULL)
- errx(1, "configuration missing value at (line %d)", line);
+ if(handler == NULL)
+ errx(1, "unknown handler type '%s' (line %d)", name, line);
+ /* If we had a last handler then add it to handlers */
+ ctx = config_addhandler(buf, t ? t : name, handler, &defaults);
- recog = 0;
+ /* Rest doesn't apply to handler headers */
+ continue;
+ }
- /* Is this the global section? */
- if(!ctx)
- {
- /* Look and see if that's a name we want */
- if(strcmp("socket", name) == 0)
- {
- g_socket = value;
- recog = 1;
- }
-
- else if(strcmp("maxthreads", name) == 0)
- {
- if(ha_confint(name, value, 1, 256, &g_maxthreads) == -1)
- exit(1);
- recog = 1;
- }
- }
- /* Otherwise we're in a handler */
- else
- {
- if(ctx->handler->f_config)
- {
- r = (ctx->handler->f_config)(ctx, name, value);
- if(r < 0)
- return r;
+ /* Parse out the name */
+ name = ha_bufparseword(buf, ":");
+ if(!name || !name[0])
+ errx(1, "configuration file invalid (line %d)", line);
- if(!recog && r == HA_OK)
- recog = 1;
- }
- }
+ strlwr(name);
- /* Options that are legal in both global and internal sections */
- if(!recog)
- {
- ha_context_t* opts = ctx ? ctx : &defaults;
- ASSERT(opts);
-
- if(strcmp(name, "cachetimeout") == 0)
- {
- int v;
- if(ha_confint(name, value, 0, 86400, &v) < 0)
- exit(1); /* Message already printed */
-
- opts->cache_timeout = v;
- recog = 1;
- }
-
- else if(strcmp(name, "cachemax") == 0)
- {
- int v;
- if(ha_confint(name, value, 0, 0x7FFFFFFF, &v) < 0)
- exit(1); /* Message already printed */
-
- opts->cache_max = v;
- recog = 1;
- }
-
- else if(strcmp(name, "authtypes") == 0)
- {
- int types = 0;
- char* t;
-
- strlwr(value);
-
- /* Split the line into tokens at the spaces */
- while(*value)
- {
- value = trim_space(value);
- t = value;
+ /* And get the rest of the line */
+ value = ha_bufparseline(buf, 1);
+ if(value == NULL)
+ errx(1, "configuration missing value at (line %d)", line);
- while(*t && !isspace(*t))
- t++;
- if(strncmp(value, "basic", 5) == 0)
- types |= HA_TYPE_BASIC;
+ recog = 0;
- else if(strncmp(value, "digest", 6) == 0)
- types |= HA_TYPE_DIGEST;
+ /* Is this the global section? */
+ if(!ctx)
+ {
+ /* Look and see if that's a name we want */
+ if(strcmp("socket", name) == 0)
+ {
+ g_socket = value;
+ recog = 1;
+ }
- else if(strncmp(value, "ntlm", 4) == 0)
- types |= HA_TYPE_NTLM;
+ else if(strcmp("maxthreads", name) == 0)
+ {
+ if(ha_confint(name, value, 1, 256, &g_maxthreads) == -1)
+ exit(1);
+ recog = 1;
+ }
+ }
- else
- errx(1, "invalid type for '%s': %s (line %d)", name, value, line);
+ /* Otherwise we're in a handler */
+ else
+ {
+ if(ctx->handler->f_config)
+ {
+ r = (ctx->handler->f_config)(ctx, name, value);
+ if(r < 0)
+ return r;
- value = t;
+ if(!recog && r == HA_OK)
+ recog = 1;
+ }
}
- if(types == 0)
- errx(1, "no authentication types for '%s' (line %d)", name, line);
+ /* Options that are legal in both global and internal sections */
+ if(!recog)
+ {
+ ha_context_t* opts = ctx ? ctx : &defaults;
+ ASSERT(opts);
- opts->allowed_types = types;
- recog = 1;
- }
+ if(strcmp(name, "cachetimeout") == 0)
+ {
+ int v;
+ if(ha_confint(name, value, 0, 86400, &v) < 0)
+ exit(1); /* Message already printed */
- else if(strcmp(name, "realm") == 0)
- {
- opts->realm = value;
- recog = 1;
- }
+ opts->cache_timeout = v;
+ recog = 1;
+ }
- else if(strcmp(name, "digestignoreuri") == 0)
- {
- int v;
- if(ha_confbool(name, value, &v) < 0)
- exit(1); /* Message already printed */
+ else if(strcmp(name, "cachemax") == 0)
+ {
+ int v;
+ if(ha_confint(name, value, 0, 0x7FFFFFFF, &v) < 0)
+ exit(1); /* Message already printed */
- opts->digest_ignoreuri = v;
- recog = 1;
- }
+ opts->cache_max = v;
+ recog = 1;
+ }
- else if(strcmp(name, "digestignorenc") == 0)
- {
- int v;
- if(ha_confbool(name, value, &v) < 0)
- exit(1); /* Message already printed */
+ else if(strcmp(name, "authtypes") == 0)
+ {
+ int types = 0;
+ char* t;
- opts->digest_ignorenc = v;
- recog = 1;
- }
+ strlwr(value);
+
+ /* Split the line into tokens at the spaces */
+ while(*value)
+ {
+ value = trim_space(value);
+ t = value;
+
+ while(*t && !isspace(*t))
+ t++;
+
+ if(strncmp(value, "basic", 5) == 0)
+ types |= HA_TYPE_BASIC;
+
+ else if(strncmp(value, "digest", 6) == 0)
+ types |= HA_TYPE_DIGEST;
+
+ else if(strncmp(value, "ntlm", 4) == 0)
+ types |= HA_TYPE_NTLM;
+
+ else
+ errx(1, "invalid type for '%s': %s (line %d)", name, value, line);
+
+ value = t;
+ }
+
+ if(types == 0)
+ errx(1, "no authentication types for '%s' (line %d)", name, line);
+
+ opts->allowed_types = types;
+ recog = 1;
+ }
+
+ else if(strcmp(name, "realm") == 0)
+ {
+ opts->realm = value;
+ recog = 1;
+ }
+
+ else if(strcmp(name, "digestignoreuri") == 0)
+ {
+ int v;
+ if(ha_confbool(name, value, &v) < 0)
+ exit(1); /* Message already printed */
+
+ opts->digest_ignoreuri = v;
+ recog = 1;
+ }
+
+ else if(strcmp(name, "digestignorenc") == 0)
+ {
+ int v;
+ if(ha_confbool(name, value, &v) < 0)
+ exit(1); /* Message already printed */
+
+ opts->digest_ignorenc = v;
+ recog = 1;
+ }
#ifdef _DEBUG
- else if(strcmp(name, "digestdebugnonce") == 0)
- {
- opts->digest_debugnonce = value;
- recog = 1;
- }
+ else if(strcmp(name, "digestdebugnonce") == 0)
+ {
+ opts->digest_debugnonce = value;
+ recog = 1;
+ }
#endif
- }
+ }
- if(!recog)
- errx(1, "unrecognized configuration setting '%s' (line %d)", name, line);
- else
- ha_messagex(LOG_DEBUG, "configuration: setting: [ %s: %s ]", name, value);
- }
+ if(!recog)
+ errx(1, "unrecognized configuration setting '%s' (line %d)", name, line);
+ else
+ ha_messagex(NULL, LOG_DEBUG, "configuration: setting: [ %s: %s ]", name, value);
+ }
- if(!g_handlers)
- ha_messagex(LOG_WARNING, "configuration: no handlers found in configuration file");
+ if(!g_handlers)
+ ha_messagex(NULL, LOG_WARNING, "configuration: no handlers found in configuration file");
- return 0;
+ return 0;
}
diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h
index 84a30cd..39bf94e 100644
--- a/daemon/httpauthd.h
+++ b/daemon/httpauthd.h
@@ -2,6 +2,8 @@
#ifndef __HTTPAUTHD_H__
#define __HTTPAUTHD_H__
+#include <syslog.h>
+
/* -----------------------------------------------------------------------
* Memory Buffers
*/
@@ -11,10 +13,10 @@ struct ha_buffer_internal;
/* A buffer which owns memory */
typedef struct ha_buffer
{
- struct ha_buffer_internal* _ft;
- struct ha_buffer_internal* _dt;
- char* _pp;
- char* _rp;
+ struct ha_buffer_internal* _ft;
+ struct ha_buffer_internal* _dt;
+ char* _pp;
+ char* _rp;
}
ha_buffer_t;
@@ -28,16 +30,16 @@ void ha_buffree(ha_buffer_t* buf);
void ha_bufreset(ha_buffer_t* buf);
#define ha_buflen(buf) \
- ((buf)->_rp - (buf)->_pp)
+ ((buf)->_rp - (buf)->_pp)
#define ha_bufchar(buf) \
- ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? *((buf)->_pp) : '\0' )
+ ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? *((buf)->_pp) : '\0' )
#define ha_bufdata(buf) \
- ((buf)->_pp)
+ ((buf)->_pp)
#define ha_buferr(buf) \
- ((buf)->_dt == NULL)
+ ((buf)->_dt == NULL)
/* Buffer input functions ------------------------------------------------ */
@@ -51,10 +53,10 @@ char* ha_bufparseline(ha_buffer_t* buf, int trim);
char* ha_bufparseword(ha_buffer_t* buf, const char* delims);
#define ha_bufskip(buf) \
- ((buf)->_pp = (buf)->_rp)
+ ((buf)->_pp = (buf)->_rp)
#define ha_bufeat(buf) \
- ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? ++((buf)->_pp) : (buf)->_pp)
+ ((!ha_buferr(buf) && ha_buflen(buf) > 0) ? ++((buf)->_pp) : (buf)->_pp)
/* Buffer output functions ----------------------------------------------- */
@@ -69,7 +71,7 @@ char* ha_bufncpy(ha_buffer_t* buf, const char* src, size_t len);
/* Opens up the end of the current block so it can be joined by more data */
#define ha_bufjoin(buf) \
- ((buf)->_rp && ((buf)->_rp != (buf)->_pp) ? (buf)->_rp-- : (buf)->_rp)
+ ((buf)->_rp && ((buf)->_rp != (buf)->_pp) ? (buf)->_rp-- : (buf)->_rp)
#define ha_bufcat ha_bufcpy
@@ -102,7 +104,6 @@ void* ha_bufdechex(ha_buffer_t* buf, const char* src, size_t* bytes);
struct ha_context;
struct ha_request;
-struct ha_response;
/*
* This function initializes the handler. It gets called
@@ -131,18 +132,18 @@ typedef int (*auth_config_t)(struct ha_context* ctx, const char* name, const cha
* for this handler. Note that all data access in this
* function must be thread-safe.
*/
-typedef int (*auth_process_t)(const struct ha_request* req, struct ha_response* resp);
+typedef int (*auth_process_t)(struct ha_request* rq);
/* An authentication handler */
typedef struct ha_handler
{
- const char* type;
- auth_init_t f_init; /* #1 Called to initialize handler */
- auth_destroy_t f_destroy; /* #3 Called when exiting */
- auth_config_t f_config; /* #0 Called for each config param */
- auth_process_t f_process; /* #2 Called for each auth request */
- const void* context_default; /* The default context */
- const size_t context_size; /* Bytes of extra context needed */
+ const char* type;
+ auth_init_t f_init; /* #1 Called to initialize handler */
+ auth_destroy_t f_destroy; /* #3 Called when exiting */
+ auth_config_t f_config; /* #0 Called for each config param */
+ auth_process_t f_process; /* #2 Called for each auth request */
+ const void* context_default; /* The default context */
+ const size_t context_size; /* Bytes of extra context needed */
}
ha_handler_t;
@@ -177,22 +178,22 @@ ha_handler_t;
/* Context passed to the handler functions above */
typedef struct ha_context
{
- const char* name; /* A name assigned by the configuration file */
- const ha_handler_t* handler; /* The original handler structure */
- void* ctx_data; /* Handler specific data */
-
- /* Context specific options */
- unsigned int allowed_types;
- int cache_timeout;
- int cache_max;
-
- /* For basic and digest auth: */
- const char* realm;
-
- /* For digest auth: */
- unsigned int digest_ignoreuri : 1;
- unsigned int digest_ignorenc : 1;
- const char* digest_debugnonce;
+ const char* name; /* A name assigned by the configuration file */
+ const ha_handler_t* handler; /* The original handler structure */
+ void* ctx_data; /* Handler specific data */
+
+ /* Context specific options */
+ unsigned int allowed_types;
+ int cache_timeout;
+ int cache_max;
+
+ /* For basic and digest auth: */
+ const char* realm;
+
+ /* For digest auth: */
+ unsigned int digest_ignoreuri : 1;
+ unsigned int digest_ignorenc : 1;
+ const char* digest_debugnonce;
}
ha_context_t;
@@ -228,8 +229,8 @@ ha_context_t;
/* A single header in memory */
typedef struct ha_header
{
- const char* name;
- const char* data;
+ const char* name;
+ const char* data;
}
ha_header_t;
@@ -243,19 +244,25 @@ ha_header_t;
#define AUTH_ARG_METHOD 1
#define AUTH_ARG_URI 2
-/* A single request from client */
+/* A single request from client along with response */
typedef struct ha_request
{
- int type;
- const char* args[HA_MAX_ARGS];
- ha_header_t headers[HA_MAX_HEADERS];
+ unsigned int id; /* Unique connection identifier */
+
+ int req_type; /* The command type */
+ const char* req_args[HA_MAX_ARGS]; /* Arguments for the command */
+ ha_header_t req_headers[HA_MAX_HEADERS]; /* Headers for command */
+
+ /* Additional request info */
+ ha_context_t* context;
+ const char* digest_domain;
- /* Additional request info */
- ha_context_t* context;
- const char* digest_domain;
+ /* The buffer in use */
+ ha_buffer_t* buf;
- /* The buffer in use */
- ha_buffer_t* buf;
+ int resp_code; /* The response code */
+ const char* resp_detail; /* The details for response */
+ ha_header_t resp_headers[HA_MAX_HEADERS]; /* Headers for the response */
}
ha_request_t;
@@ -267,22 +274,12 @@ ha_request_t;
#define HA_SERVER_BADREQ 400
#define HA_SERVER_BUSY 500
-/* A response to the client */
-typedef struct ha_response
-{
- int code;
- const char* detail;
- ha_header_t headers[HA_MAX_HEADERS];
- ha_buffer_t* buf;
-}
-ha_response_t;
-
/* Request functions */
-const ha_header_t* ha_findheader(const ha_request_t* req, const char* name);
-const char* ha_getheader(const ha_request_t* req, const char* name, const char* prefix);
+const ha_header_t* ha_findheader(const ha_request_t* rq, const char* name);
+const char* ha_getheader(const ha_request_t* rq, const char* name, const char* prefix);
/* Response functions */
-void ha_addheader(ha_response_t* resp, const char* name, const char* data);
+void ha_addheader(ha_request_t* rq, const char* name, const char* data);
/* Configuration functions */
int ha_confbool(const char* name, const char* conf, int* value);
@@ -292,8 +289,8 @@ int ha_confint(const char* name, const char* conf, int min, int max, int* value)
* Error Handling
*/
-void ha_message(int level, const char* msg, ...);
-void ha_messagex(int level, const char* msg, ...);
+void ha_message(const ha_request_t* rq, int level, const char* msg, ...);
+void ha_messagex(const ha_request_t* rq, int level, const char* msg, ...);
/* -----------------------------------------------------------------------
@@ -318,14 +315,14 @@ void ha_messagex(int level, const char* msg, ...);
typedef struct ha_uri
{
- const char* scheme;
- const char* user;
- const char* pw;
- const char* host;
- unsigned short port;
- const char* path;
- const char* query;
- const char* fragment;
+ const char* scheme;
+ const char* user;
+ const char* pw;
+ const char* host;
+ unsigned short port;
+ const char* path;
+ const char* query;
+ const char* fragment;
}
ha_uri_t;
diff --git a/daemon/ldap.c b/daemon/ldap.c
index e0349fb..719ac0d 100644
--- a/daemon/ldap.c
+++ b/daemon/ldap.c
@@ -72,8 +72,8 @@ typedef struct ldap_context
ldap_context_t;
/* Forward declarations for callbacks */
-static int complete_digest(const ha_request_t* req, const char* user, unsigned char* ha1);
-static int validate_basic(const ha_request_t* req, const char* user, const char* password);
+static int complete_digest(ha_request_t* rq, const char* user, unsigned char* ha1);
+static int validate_basic(ha_request_t* rq, const char* user, const char* password);
/* The defaults for the context */
static const ldap_context_t ldap_defaults =
@@ -101,20 +101,20 @@ static const ldap_context_t ldap_defaults =
* Internal Functions
*/
-static int report_ldap(const char* msg, int code)
+static int report_ldap(const ha_request_t* rq, const char* msg, int code)
{
ASSERT(code != LDAP_SUCCESS);
switch(code)
{
case LDAP_NO_MEMORY:
- ha_messagex(LOG_CRIT, "out of memory");
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
return HA_CRITERROR;
default:
if(!msg)
msg = "error";
- ha_messagex(LOG_ERR, "ldap: %s: %s", msg, ldap_err2string(code));
+ ha_messagex(rq, LOG_ERR, "%s: %s", msg, ldap_err2string(code));
return HA_FAILED;
};
}
@@ -159,49 +159,49 @@ static const char* escape_ldap(ha_buffer_t* buf, const char* str)
return ha_bufdata(buf);
}
-static const char* substitute_params(ldap_context_t* ctx, const ha_request_t* req,
+static const char* substitute_params(const ha_request_t* rq, ldap_context_t* ctx,
const char* user, const char* str)
{
const char* t;
- ASSERT(ctx && req && user && str);
+ ASSERT(ctx && rq && user && str);
/* TODO: We need to be escaping the user and realm properly */
/* This starts a new block to join */
- ha_bufcpy(req->buf, "");
+ ha_bufcpy(rq->buf, "");
while(str[0])
{
t = strchr(str, '%');
if(!t)
{
- ha_bufjoin(req->buf);
- ha_bufcpy(req->buf, str);
+ ha_bufjoin(rq->buf);
+ ha_bufcpy(rq->buf, str);
break;
}
- ha_bufjoin(req->buf);
- ha_bufncpy(req->buf, str, t - str);
+ ha_bufjoin(rq->buf);
+ ha_bufncpy(rq->buf, str, t - str);
t++;
switch(t[0])
{
case 'u':
- ha_bufjoin(req->buf);
- escape_ldap(req->buf, user);
+ ha_bufjoin(rq->buf);
+ escape_ldap(rq->buf, user);
t++;
break;
case 'r':
- ha_bufjoin(req->buf);
- escape_ldap(req->buf, req->context->realm);
+ ha_bufjoin(rq->buf);
+ escape_ldap(rq->buf, rq->context->realm);
t++;
break;
case '%':
- ha_bufjoin(req->buf);
- ha_bufcpy(req->buf, "%");
+ ha_bufjoin(rq->buf);
+ ha_bufcpy(rq->buf, "%");
t++;
break;
};
@@ -209,7 +209,7 @@ static const char* substitute_params(ldap_context_t* ctx, const ha_request_t* re
str = t;
}
- return ha_bufdata(req->buf);
+ return ha_bufdata(rq->buf);
}
static const char* make_password_md5(ha_buffer_t* buf, const char* clearpw)
@@ -295,17 +295,17 @@ static const char* find_cleartext_password(ha_buffer_t* buf, const char** pws)
return NULL;
}
-static int parse_ldap_ha1(ha_buffer_t* buf, struct berval* bv, unsigned char* ha1)
+static int parse_ldap_ha1(const ha_request_t* rq, struct berval* bv, unsigned char* ha1)
{
size_t len;
void* d;
- ASSERT(buf && bv && ha1);
+ ASSERT(rq && bv && ha1);
/* Raw binary */
if(bv->bv_len == MD5_LEN)
{
- ha_messagex(LOG_DEBUG, "ldap: found ha1 in raw binary format");
+ ha_messagex(rq, LOG_DEBUG, "found ha1 in raw binary format");
memcpy(ha1, bv->bv_val, MD5_LEN);
return HA_OK;
}
@@ -314,11 +314,11 @@ static int parse_ldap_ha1(ha_buffer_t* buf, struct berval* bv, unsigned char* ha
else if(bv->bv_len == (MD5_LEN * 2))
{
len = MD5_LEN;
- d = ha_bufdechex(buf, bv->bv_val, &len);
+ d = ha_bufdechex(rq->buf, bv->bv_val, &len);
if(d && len == MD5_LEN)
{
- ha_messagex(LOG_DEBUG, "ldap: found ha1 in hex encoded format");
+ ha_messagex(rq, LOG_DEBUG, "found ha1 in hex encoded format");
memcpy(ha1, d, MD5_LEN);
return HA_OK;
}
@@ -328,21 +328,21 @@ static int parse_ldap_ha1(ha_buffer_t* buf, struct berval* bv, unsigned char* ha
else
{
len = MD5_LEN;
- d = ha_bufdec64(buf, bv->bv_val, &len);
+ d = ha_bufdec64(rq->buf, bv->bv_val, &len);
if(d && len == MD5_LEN)
{
- ha_messagex(LOG_DEBUG, "ldap: found ha1 in b64 encoded format");
- memcpy(ha1, ha_bufdata(buf), MD5_LEN);
+ ha_messagex(rq, LOG_DEBUG, "found ha1 in b64 encoded format");
+ memcpy(ha1, ha_bufdata(rq->buf), MD5_LEN);
return HA_OK;
}
}
- return ha_buferr(buf) ? HA_CRITERROR : HA_FALSE;
+ return ha_buferr(rq->buf) ? HA_CRITERROR : HA_FALSE;
}
-static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
- ha_buffer_t* buf, const char* user, const char* clearpw)
+static int validate_ldap_password(const ha_request_t* rq, ldap_context_t* ctx, LDAP* ld,
+ LDAPMessage* entry, const char* user, const char* clearpw)
{
char** pws;
char** t;
@@ -352,7 +352,7 @@ static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* en
int res = HA_FALSE;
int unknown = 0;
- ASSERT(entry && ld && ctx && clearpw);
+ ASSERT(entry && ld && ctx && clearpw && rq);
ASSERT(ctx->pw_attr);
pws = ldap_get_values(ld, entry, ctx->pw_attr);
@@ -371,7 +371,7 @@ static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* en
break;
case LDAP_PW_MD5:
- p = make_password_md5(buf, clearpw);
+ p = make_password_md5(rq->buf, clearpw);
break;
case LDAP_PW_CRYPT:
@@ -382,7 +382,7 @@ static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* en
break;
case LDAP_PW_SHA:
- p = make_password_sha(buf, clearpw);
+ p = make_password_sha(rq->buf, clearpw);
break;
case LDAP_PW_UNKNOWN:
@@ -402,7 +402,7 @@ static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* en
if(strcmp(pw, p) == 0)
{
- ha_messagex(LOG_DEBUG, "ldap: successful validate against password");
+ ha_messagex(rq, LOG_DEBUG, "successful validate against password");
res = HA_OK;
break;
}
@@ -412,13 +412,13 @@ static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* en
}
if(res == HA_FALSE && unknown)
- ha_messagex(LOG_ERR, "ldap: server does not contain any compatible passwords for user: %s", user);
+ ha_messagex(rq, LOG_ERR, "server does not contain any compatible passwords for user: %s", user);
return res;
}
-static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
- ha_buffer_t* buf, const char* user, const char* realm,
+static int validate_ldap_ha1(const ha_request_t* rq, ldap_context_t* ctx, LDAP* ld,
+ LDAPMessage* entry, const char* user, const char* realm,
const char* clearpw)
{
struct berval** ha1s;
@@ -428,7 +428,7 @@ static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
int r, first = 1;
int res = HA_FALSE;
- ASSERT(ctx && ld && entry && buf && user && clearpw);
+ ASSERT(ctx && ld && entry && rq && user && clearpw);
if(!ctx->ha1_attr)
return HA_FALSE;
@@ -441,7 +441,7 @@ static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
for(b = ha1s ; *b; b++)
{
- r = parse_ldap_ha1(buf, *b, k);
+ r = parse_ldap_ha1(rq, *b, k);
if(r < 0)
{
res = r;
@@ -451,7 +451,7 @@ static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
if(r == HA_FALSE)
{
if(first)
- ha_messagex(LOG_ERR, "ldap: server contains invalid HA1 digest hash for user: %s", user);
+ ha_messagex(rq, LOG_ERR, "server contains invalid HA1 digest hash for user: %s", user);
first = 0;
continue;
@@ -459,7 +459,7 @@ static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
if(memcmp(key, k, MD5_LEN) == 0)
{
- ha_messagex(LOG_DEBUG, "ldap: successful validate against ha1");
+ ha_messagex(rq, LOG_DEBUG, "successful validate against ha1");
res = HA_OK;
break;
}
@@ -471,7 +471,7 @@ static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
return res;
}
-static LDAP* get_ldap_connection(ldap_context_t* ctx)
+static LDAP* get_ldap_connection(const ha_request_t* rq, ldap_context_t* ctx)
{
LDAP* ld;
int i, r;
@@ -483,7 +483,7 @@ static LDAP* get_ldap_connection(ldap_context_t* ctx)
/* An open connection in the pool */
if(ctx->pool[i])
{
- ha_messagex(LOG_DEBUG, "ldap: using cached connection");
+ ha_messagex(rq, LOG_DEBUG, "using cached connection");
ld = ctx->pool[i];
ctx->pool[i] = NULL;
return ld;
@@ -492,14 +492,14 @@ static LDAP* get_ldap_connection(ldap_context_t* ctx)
if(ctx->pool_mark >= ctx->ldap_max)
{
- ha_messagex(LOG_ERR, "ldap: too many open connections");
+ ha_messagex(rq, LOG_ERR, "too many open connections");
return NULL;
}
ld = ldap_init(ctx->servers, ctx->port);
if(!ld)
{
- ha_message(LOG_ERR, "ldap: couldn't initialize connection");
+ ha_message(rq, LOG_ERR, "couldn't initialize connection");
return NULL;
}
@@ -509,25 +509,25 @@ static LDAP* get_ldap_connection(ldap_context_t* ctx)
ctx->password ? ctx->password : "");
if(r != LDAP_SUCCESS)
{
- report_ldap("ldap: couldn't bind to LDAP server", r);
+ report_ldap(rq, "couldn't bind to LDAP server", r);
ldap_unbind_s(ld);
return NULL;
}
}
ctx->pool_mark++;
- ha_messagex(LOG_DEBUG, "ldap: opened new connection (total %d)", ctx->pool_mark);
+ ha_messagex(rq, LOG_DEBUG, "opened new connection (total %d)", ctx->pool_mark);
return ld;
}
-static void discard_ldap_connection(ldap_context_t* ctx, LDAP* ld)
+static void discard_ldap_connection(const ha_request_t* rq, ldap_context_t* ctx, LDAP* ld)
{
ldap_unbind_s(ld);
ctx->pool_mark--;
- ha_messagex(LOG_DEBUG, "ldap: discarding connection (total %d)", ctx->pool_mark);
+ ha_messagex(rq, LOG_DEBUG, "discarding connection (total %d)", ctx->pool_mark);
}
-static void save_ldap_connection(ldap_context_t* ctx, LDAP* ld)
+static void save_ldap_connection(const ha_request_t* rq, ldap_context_t* ctx, LDAP* ld)
{
int i, e;
@@ -544,7 +544,7 @@ static void save_ldap_connection(ldap_context_t* ctx, LDAP* ld)
case LDAP_SERVER_DOWN:
case LDAP_LOCAL_ERROR:
case LDAP_NO_MEMORY:
- discard_ldap_connection(ctx, ld);
+ discard_ldap_connection(rq, ctx, ld);
break;
default:
@@ -553,7 +553,7 @@ static void save_ldap_connection(ldap_context_t* ctx, LDAP* ld)
/* An open connection in the pool */
if(!ctx->pool[i])
{
- ha_messagex(LOG_DEBUG, "ldap: caching connection for later use");
+ ha_messagex(rq, LOG_DEBUG, "caching connection for later use");
ctx->pool[i] = ld;
ld = NULL;
break;
@@ -563,7 +563,7 @@ static void save_ldap_connection(ldap_context_t* ctx, LDAP* ld)
};
}
-static int retrieve_user_entry(ldap_context_t* ctx, const ha_request_t* req, LDAP* ld,
+static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP* ld,
const char* user, const char** dn,
LDAPMessage** entry, LDAPMessage** result)
{
@@ -574,12 +574,12 @@ static int retrieve_user_entry(ldap_context_t* ctx, const ha_request_t* req, LDA
int scope;
int r;
- ASSERT(ctx && req && ld && user && dn && entry && result);
+ ASSERT(ctx && rq && ld && user && dn && entry && result);
if(ctx->filter)
{
/* Filters can also have %u and %r */
- filter = substitute_params(ctx, req, user, ctx->filter);
+ filter = substitute_params(rq, ctx, user, ctx->filter);
if(!filter)
return HA_CRITERROR;
}
@@ -598,7 +598,7 @@ static int retrieve_user_entry(ldap_context_t* ctx, const ha_request_t* req, LDA
base = *dn ? *dn : ctx->base;
scope = *dn ? LDAP_SCOPE_BASE : ctx->scope;
- ha_messagex(LOG_DEBUG, "ldap: performing search: [ base: %s / scope: %d / filter: %s ]",
+ ha_messagex(rq, LOG_DEBUG, "performing search: [ base: %s / scope: %d / filter: %s ]",
base, scope, filter);
r = ldap_search_st(ld, base, scope, filter, (char**)attrs, 0, &tv, result);
@@ -607,11 +607,11 @@ static int retrieve_user_entry(ldap_context_t* ctx, const ha_request_t* req, LDA
{
if(r == LDAP_NO_SUCH_OBJECT)
{
- ha_messagex(LOG_WARNING, "ldap: user not found in LDAP: %s", user);
+ ha_messagex(rq, LOG_WARNING, "user not found in %s", user);
return HA_FALSE;
}
- return report_ldap("couldn't search LDAP server", r);
+ return report_ldap(rq, "couldn't search LDAP server", r);
}
@@ -623,25 +623,25 @@ static int retrieve_user_entry(ldap_context_t* ctx, const ha_request_t* req, LDA
if(!(*dn))
{
*dn = ldap_get_dn(ld, *entry);
- ha_messagex(LOG_DEBUG, "ldap: found entry for user: %s", *dn);
+ ha_messagex(rq, LOG_DEBUG, "found entry for user: %s", *dn);
}
return HA_OK;
case 0:
- ha_messagex(LOG_WARNING, "ldap: user not found in LDAP: %s", user);
+ ha_messagex(rq, LOG_WARNING, "user not found in %s", user);
break;
default:
- ha_messagex(LOG_WARNING, "ldap: more than one user found for filter: %s", filter);
+ ha_messagex(rq, LOG_WARNING, "more than one user found for filter: %s", filter);
break;
};
return HA_FALSE;
}
-static int complete_digest(const ha_request_t* req, const char* user, unsigned char* ha1)
+static int complete_digest(ha_request_t* rq, const char* user, unsigned char* ha1)
{
- ldap_context_t* ctx = (ldap_context_t*)req->context->ctx_data;
+ ldap_context_t* ctx = (ldap_context_t*)rq->context->ctx_data;
LDAP* ld = NULL; /* freed in finally */
LDAPMessage* results = NULL; /* freed in finally */
LDAPMessage* entry = NULL; /* no need to free */
@@ -651,9 +651,9 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
const char* dn = NULL;
int r;
- ASSERT(req && ha1 && user);
+ ASSERT(rq && ha1 && user);
- ld = get_ldap_connection(ctx);
+ ld = get_ldap_connection(rq, ctx);
if(!ld)
{
ret = HA_FAILED;
@@ -668,18 +668,18 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
if(ctx->dnmap)
{
/* The map can have %u and %r to denote user and realm */
- dn = substitute_params(ctx, req, user, ctx->dnmap);
+ dn = substitute_params(rq, ctx, user, ctx->dnmap);
if(!dn)
{
ret = HA_FAILED;
goto finally;
}
- ha_messagex(LOG_INFO, "ldap: mapped %s to %s", user, dn);
+ ha_messagex(rq, LOG_INFO, "mapped %s to %s", user, dn);
}
/* Okay now we contact the LDAP server. */
- r = retrieve_user_entry(ctx, req, ld, user, &dn, &entry, &results);
+ r = retrieve_user_entry(rq, ctx, ld, user, &dn, &entry, &results);
if(r != HA_OK)
{
ret = r;
@@ -694,15 +694,15 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
{
if(*ha1s)
{
- ret = parse_ldap_ha1(req->buf, *ha1s, ha1);
+ ret = parse_ldap_ha1(rq, *ha1s, ha1);
if(ret != HA_OK)
{
if(ret == HA_FALSE)
- ha_messagex(LOG_ERR, "ldap: server contains invalid HA1 for user: %s", user);
+ ha_messagex(rq, LOG_ERR, "server contains invalid HA1 for user: %s", user);
}
}
- ha_messagex(LOG_DEBUG, "ldap: using HA1 from ldap");
+ ha_messagex(rq, LOG_DEBUG, "using HA1 from ldap");
ldap_value_free_len(ha1s);
goto finally;
}
@@ -713,11 +713,11 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
if(pws)
{
/* Find a cleartext password */
- const char* t = find_cleartext_password(req->buf, (const char**)pws);
+ const char* t = find_cleartext_password(rq->buf, (const char**)pws);
if(t)
{
- digest_makeha1(ha1, user, req->context->realm, t);
+ digest_makeha1(ha1, user, rq->context->realm, t);
ret = HA_OK;
}
@@ -725,17 +725,17 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
if(ret == HA_OK)
{
- ha_messagex(LOG_DEBUG, "ldap: using clear password from ldap");
+ ha_messagex(rq, LOG_DEBUG, "using clear password from ldap");
goto finally;
}
}
- ha_messagex(LOG_ERR, "ldap: server contains no clear password or HA1 for user: %s", user);
+ ha_messagex(rq, LOG_ERR, "server contains no clear password or HA1 for user: %s", user);
finally:
if(ld)
- save_ldap_connection(ctx, ld);
+ save_ldap_connection(rq, ctx, ld);
if(results)
ldap_msgfree(results);
@@ -743,9 +743,9 @@ finally:
return ret;
}
-static int validate_basic(const ha_request_t* req, const char* user, const char* password)
+static int validate_basic(ha_request_t* rq, const char* user, const char* password)
{
- ldap_context_t* ctx = (ldap_context_t*)req->context->ctx_data;
+ ldap_context_t* ctx = (ldap_context_t*)rq->context->ctx_data;
LDAP* ld = NULL;
LDAPMessage* entry = NULL;
LDAPMessage* results = NULL;
@@ -754,9 +754,9 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
int found = 0;
int r;
- ASSERT(req && user && password);
+ ASSERT(rq && user && password);
- ld = get_ldap_connection(ctx);
+ ld = get_ldap_connection(rq, ctx);
if(!ld)
{
ret = HA_FAILED;
@@ -772,14 +772,14 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
if(ctx->dnmap)
{
/* The map can have %u and %r to denote user and realm */
- dn = substitute_params(ctx, req, user, ctx->dnmap);
+ dn = substitute_params(rq, ctx, user, ctx->dnmap);
if(!dn)
{
ret = HA_CRITERROR;
goto finally;
}
- ha_messagex(LOG_INFO, "ldap: mapped %s to %s", user, dn);
+ ha_messagex(rq, LOG_INFO, "mapped %s to %s", user, dn);
}
@@ -800,7 +800,7 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
if(!ctx->dobind || !dn || ctx->filter)
{
- r = retrieve_user_entry(ctx, req, ld, user, &dn, &entry, &results);
+ r = retrieve_user_entry(rq, ctx, ld, user, &dn, &entry, &results);
if(r != HA_OK)
{
ret = r;
@@ -818,17 +818,17 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
if(r != LDAP_SUCCESS)
{
if(r == LDAP_INVALID_CREDENTIALS)
- ha_messagex(LOG_WARNING, "ldap: basic authentication (via bind) failed for user: %s",
+ ha_messagex(rq, LOG_WARNING, "basic authentication (via bind) failed for user: %s",
user);
else
- report_ldap("couldn't bind to LDAP server", r);
+ report_ldap(rq, "couldn't bind to LDAP server", r);
goto finally;
}
/* It worked! */
- ha_messagex(LOG_NOTICE, "ldap: validated basic user using bind: %s", user);
+ ha_messagex(rq, LOG_NOTICE, "validated basic user using bind: %s", user);
found = 1;
/* Now we have to rebind the connection back to the main user */
@@ -836,10 +836,10 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
ctx->password ? ctx->password : "");
if(r != LDAP_SUCCESS)
{
- report_ldap("ldap: couldn't rebind LDAP connection back to auth credentials", r);
+ report_ldap(rq, "couldn't rebind LDAP connection back to auth credentials", r);
/* Discard the connection since it's useless to us */
- discard_ldap_connection(ctx, ld);
+ discard_ldap_connection(rq, ctx, ld);
ld = NULL;
}
}
@@ -848,27 +848,27 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
/* Otherwise we compare the password attribute */
else
{
- ret = validate_ldap_password(ctx, ld, entry, req->buf, user, password);
+ ret = validate_ldap_password(rq, ctx, ld, entry, user, password);
if(ret == HA_FALSE)
- ret = validate_ldap_ha1(ctx, ld, entry, req->buf, user,
- req->context->realm, password);
+ ret = validate_ldap_ha1(rq, ctx, ld, entry, user,
+ rq->context->realm, password);
if(ret == HA_OK)
{
- ha_messagex(LOG_NOTICE, "ldap: validated basic user password/ha1: %s", user);
+ ha_messagex(rq, LOG_NOTICE, "validated basic user password/ha1: %s", user);
found = 1;
}
else
{
- ha_messagex(LOG_WARNING, "ldap: invalid, unreadable or unrecognized password for user: %s", user);
+ ha_messagex(rq, LOG_WARNING, "invalid, unreadable or unrecognized password for user: %s", user);
}
}
finally:
if(ld)
- save_ldap_connection(ctx, ld);
+ save_ldap_connection(rq, ctx, ld);
if(results)
ldap_msgfree(results);
@@ -946,7 +946,7 @@ int ldap_config(ha_context_t* context, const char* name, const char* value)
ctx->scope = LDAP_SCOPE_ONELEVEL;
else
{
- ha_messagex(LOG_ERR, "invalid value for '%s' (must be 'sub', 'base' or 'one')", name);
+ ha_messagex(NULL, LOG_ERR, "invalid value for '%s' (must be 'sub', 'base' or 'one')", name);
return HA_FAILED;
}
@@ -987,14 +987,14 @@ int ldap_inithand(ha_context_t* context)
/* Check for mandatory configuration */
if(!ctx->servers)
{
- ha_messagex(LOG_ERR, "ldap: configuration incomplete. "
+ ha_messagex(NULL, LOG_ERR, "configuration incomplete. "
"Must have LDAPServers.");
return HA_FAILED;
}
if(!ctx->dnmap && (!ctx->filter || !ctx->base))
{
- ha_messagex(LOG_ERR, "ldap: configuration incomplete. "
+ ha_messagex(NULL, LOG_ERR, "configuration incomplete. "
"When not using LDAPDNMap must specify LDAPBase and LDAPFilter.");
return HA_FAILED;
}
@@ -1010,12 +1010,12 @@ int ldap_inithand(ha_context_t* context)
ctx->pool = (LDAP**)malloc(sizeof(LDAP*) * ctx->ldap_max);
if(!ctx->pool)
{
- ha_messagex(LOG_CRIT, "out of memory");
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
return HA_CRITERROR;
}
memset(ctx->pool, 0, sizeof(LDAP*) * ctx->ldap_max);
- ha_messagex(LOG_INFO, "ldap: initialized handler");
+ ha_messagex(NULL, LOG_INFO, "initialized handler");
}
return HA_OK;
@@ -1046,7 +1046,7 @@ void ldap_destroy(ha_context_t* context)
}
bd_destroy(context);
- ha_messagex(LOG_INFO, "ldap: uninitialized handler");
+ ha_messagex(NULL, LOG_INFO, "uninitialized ldap handler");
}
diff --git a/daemon/misc.c b/daemon/misc.c
index 8e361be..f48d801 100644
--- a/daemon/misc.c
+++ b/daemon/misc.c
@@ -20,60 +20,71 @@ extern pthread_mutex_t g_mutex;
const char kMsgDelimiter[] = ": ";
#define MAX_MSGLEN 128
-void ha_messagex(int level, const char* msg, ...)
+static void vmessage(const ha_request_t* rq, int level, int err,
+ const char* msg, va_list ap)
{
- va_list ap;
- va_start(ap, msg);
+ size_t len;
+ char* m;
+ int e = errno;
+ int x;
- ASSERT(msg);
+ if(g_daemonized)
+ {
+ if(level >= LOG_DEBUG)
+ return;
+ }
+ else
+ {
+ if(g_debuglevel < level)
+ return;
+ }
+
+ ASSERT(msg);
- /* Either to syslog or stderr */
- if(g_daemonized)
- {
- if(level < LOG_DEBUG)
- vsyslog(level, msg, ap);
- }
+ len = strlen(msg) + 20 + MAX_MSGLEN;
+ m = (char*)alloca(len);
- else
- {
- if(g_debuglevel >= level)
- vwarnx(msg, ap);
- }
+ if(m)
+ {
+ if(rq)
+ snprintf(m, len, "%06X: %s%s", rq->id, msg, err ? ": " : "");
+ else
+ snprintf(m, len, "%s%s", msg, err ? ": " : "");
- va_end(ap);
+ if(err)
+ {
+ /* TODO: strerror_r doesn't want to work for us
+ strerror_r(e, m + strlen(m), MAX_MSGLEN); */
+ strncat(m, strerror(e), len);
+ }
+
+ m[len - 1] = 0;
+ msg = m;
+ }
+
+ /* Either to syslog or stderr */
+ if(g_daemonized)
+ vsyslog(level, msg, ap);
+ else
+ vwarnx(msg, ap);
}
-void ha_message(int level, const char* msg, ...)
+void ha_messagex(const ha_request_t* rq, int level, const char* msg, ...)
{
- va_list ap;
- va_start(ap, msg);
-
- ASSERT(msg);
+ va_list ap;
- /* Either to syslog or stderr */
- if(g_daemonized)
- {
- if(level < LOG_DEBUG)
- {
- char* m = (char*)alloca(strlen(msg) + MAX_MSGLEN + sizeof(kMsgDelimiter));
+ va_start(ap, msg);
+ vmessage(rq, level, 0, msg, ap);
+ va_end(ap);
+}
- if(m)
- {
- strcpy(m, msg);
- strcat(m, kMsgDelimiter);
- strerror_r(errno, m + strlen(m), MAX_MSGLEN);
- }
+void ha_message(const ha_request_t* rq, int level, const char* msg, ...)
+{
+ va_list ap;
- vsyslog(LOG_ERR, m ? m : msg, ap);
- }
- }
- else
- {
- if(g_debuglevel >= level)
- vwarn(msg, ap);
- }
-
- va_end(ap);
+ va_start(ap, msg);
+ vmessage(rq, level, 1, msg, ap);
+ va_end(ap);
}
@@ -81,67 +92,67 @@ void ha_message(int level, const char* msg, ...)
* Header Functionality
*/
-const ha_header_t* ha_findheader(const ha_request_t* req, const char* name)
+const ha_header_t* ha_findheader(const ha_request_t* rq, const char* name)
{
- int i;
+ int i;
- ASSERT(req && name);
+ ASSERT(rq && name);
- for(i = 0; i < HA_MAX_HEADERS; i++)
- {
- if(req->headers[i].name)
+ for(i = 0; i < HA_MAX_HEADERS; i++)
{
- if(strcasecmp(req->headers[i].name, name) == 0)
- return &(req->headers[i]);
+ if(rq->req_headers[i].name)
+ {
+ if(strcasecmp(rq->req_headers[i].name, name) == 0)
+ return &(rq->req_headers[i]);
+ }
}
- }
- return NULL;
+ return NULL;
}
-const char* ha_getheader(const ha_request_t* req, const char* name, const char* prefix)
+const char* ha_getheader(const ha_request_t* rq, const char* name, const char* prefix)
{
- int i, l;
+ int i, l;
- ASSERT(req && name);
+ ASSERT(rq && name);
- for(i = 0; i < HA_MAX_HEADERS; i++)
- {
- if(req->headers[i].name)
+ for(i = 0; i < HA_MAX_HEADERS; i++)
{
- if(strcasecmp(req->headers[i].name, name) == 0)
- {
- if(!prefix)
- return req->headers[i].data;
+ if(rq->req_headers[i].name)
+ {
+ if(strcasecmp(rq->req_headers[i].name, name) == 0)
+ {
+ if(!prefix)
+ return rq->req_headers[i].data;
- l = strlen(prefix);
+ l = strlen(prefix);
- if(strncasecmp(prefix, req->headers[i].data, l) == 0)
- return req->headers[i].data + l;
- }
+ if(strncasecmp(prefix, rq->req_headers[i].data, l) == 0)
+ return rq->req_headers[i].data + l;
+ }
+ }
}
- }
- return NULL;
+ return NULL;
}
-void ha_addheader(ha_response_t* resp, const char* name, const char* data)
+void ha_addheader(ha_request_t* rq, const char* name, const char* data)
{
- int i = 0;
+ int i = 0;
- ASSERT(resp && name && data);
+ ASSERT(rq && name && data);
- for(i = 0; i < HA_MAX_HEADERS; i++)
- {
- if(!(resp->headers[i].name))
+ for(i = 0; i < HA_MAX_HEADERS; i++)
{
- resp->headers[i].name = name;
- resp->headers[i].data = data;
- return;
+ if(!(rq->resp_headers[i].name))
+ {
+ rq->resp_headers[i].name = name;
+ rq->resp_headers[i].data = data;
+ return;
+ }
}
- }
- ha_messagex(LOG_WARNING, "too many headers in response. discarding '%s'", name);
+ ha_messagex(rq, LOG_WARNING, "too many headers in response. discarding '%s'", name);
}
@@ -151,51 +162,51 @@ void ha_addheader(ha_response_t* resp, const char* name, const char* data)
void ha_lock(pthread_mutex_t* mtx)
{
- int r;
+ int r;
#ifdef _DEBUG
- int wait = 0;
+ int wait = 0;
#endif
- if(!mtx)
- mtx = &g_mutex;
+ if(!mtx)
+ mtx = &g_mutex;
#ifdef _DEBUG
- r = pthread_mutex_trylock(mtx);
- if(r == EBUSY)
- {
- wait = 1;
- ha_message(LOG_DEBUG, "thread will block: %d", pthread_self());
- r = pthread_mutex_lock(mtx);
- }
+ r = pthread_mutex_trylock(mtx);
+ if(r == EBUSY)
+ {
+ wait = 1;
+ ha_message(NULL, LOG_DEBUG, "thread will block: %d", pthread_self());
+ r = pthread_mutex_lock(mtx);
+ }
#else
- r = pthread_mutex_lock(mtx);
+ r = pthread_mutex_lock(mtx);
#endif
- if(r != 0)
- {
- errno = r;
- ha_message(LOG_CRIT, "threading problem. couldn't lock mutex");
- }
+ if(r != 0)
+ {
+ errno = r;
+ ha_message(NULL, LOG_CRIT, "threading problem. couldn't lock mutex");
+ }
#ifdef _DEBUG
- else if(wait)
- {
- ha_message(LOG_DEBUG, "thread unblocked: %d", pthread_self());
- }
+ else if(wait)
+ {
+ ha_message(NULL, LOG_DEBUG, "thread unblocked: %d", pthread_self());
+ }
#endif
}
void ha_unlock(pthread_mutex_t* mtx)
{
- int r = pthread_mutex_unlock(mtx ? mtx : &g_mutex);
- if(r != 0)
- {
- errno = r;
- ha_message(LOG_CRIT, "threading problem. couldn't unlock mutex");
- }
+ int r = pthread_mutex_unlock(mtx ? mtx : &g_mutex);
+ if(r != 0)
+ {
+ errno = r;
+ ha_message(NULL, LOG_CRIT, "threading problem. couldn't unlock mutex");
+ }
}
@@ -205,51 +216,51 @@ void ha_unlock(pthread_mutex_t* mtx)
int ha_confbool(const char* name, const char* conf, int* value)
{
- ASSERT(name && value);
-
- if(conf == NULL ||
- conf[0] == 0 ||
- strcasecmp(conf, "0") == 0 ||
- strcasecmp(conf, "no") == 0 ||
- strcasecmp(conf, "false") == 0 ||
- strcasecmp(conf, "f") == 0 ||
- strcasecmp(conf, "off") == 0)
- {
- *value = 0;
- return HA_OK;
- }
-
- if(strcasecmp(conf, "1") == 0 ||
- strcasecmp(conf, "yes") == 0 ||
- strcasecmp(conf, "true") == 0 ||
- strcasecmp(conf, "t") == 0 ||
- strcasecmp(conf, "on") == 0)
- {
- *value = 1;
- return HA_OK;
- }
+ ASSERT(name && value);
+
+ if(conf == NULL ||
+ conf[0] == 0 ||
+ strcasecmp(conf, "0") == 0 ||
+ strcasecmp(conf, "no") == 0 ||
+ strcasecmp(conf, "false") == 0 ||
+ strcasecmp(conf, "f") == 0 ||
+ strcasecmp(conf, "off") == 0)
+ {
+ *value = 0;
+ return HA_OK;
+ }
- ha_messagex(LOG_ERR, "invalid configuration value '%s': must be 'on' or 'off'.", name);
- return HA_FAILED;
+ if(strcasecmp(conf, "1") == 0 ||
+ strcasecmp(conf, "yes") == 0 ||
+ strcasecmp(conf, "true") == 0 ||
+ strcasecmp(conf, "t") == 0 ||
+ strcasecmp(conf, "on") == 0)
+ {
+ *value = 1;
+ return HA_OK;
+ }
+
+ ha_messagex(NULL, LOG_ERR, "invalid configuration value '%s': must be 'on' or 'off'.", name);
+ return HA_FAILED;
}
int ha_confint(const char* name, const char* conf, int min, int max, int* value)
{
- char* p;
+ char* p;
- ASSERT(name && conf && value);
- ASSERT(min <= max);
+ ASSERT(name && conf && value);
+ ASSERT(min <= max);
- errno = 0;
- *value = strtol(conf, &p, 10);
+ errno = 0;
+ *value = strtol(conf, &p, 10);
- if(*p || errno == ERANGE || (*value < min) || (*value > max))
- {
- ha_messagex(LOG_ERR, "invalid configuration value '%s': must be a number between %d and %d", name, min, max);
- return HA_FAILED;
- }
+ if(*p || errno == ERANGE || (*value < min) || (*value > max))
+ {
+ ha_messagex(NULL, LOG_ERR, "invalid configuration value '%s': must be a number between %d and %d", name, min, max);
+ return HA_FAILED;
+ }
- return HA_OK;
+ return HA_OK;
}
@@ -259,366 +270,366 @@ int ha_confint(const char* name, const char* conf, int min, int max, int* value)
char* ha_uriformat(ha_buffer_t* buf, const ha_uri_t* uri)
{
- ASSERT(buf && uri);
+ ASSERT(buf && uri);
- /* This creates a new block */
- ha_bufcpy(buf, "");
+ /* This creates a new block */
+ ha_bufcpy(buf, "");
+
+ if(uri->host)
+ {
+ const char* l = "";
+ const char* r = "";
- if(uri->host)
- {
- const char* l = "";
- const char* r = "";
+ ha_bufmcat(buf, uri->scheme ? uri->scheme : "http",
+ "://", NULL);
- ha_bufmcat(buf, uri->scheme ? uri->scheme : "http",
- "://", NULL);
+ if(uri->user)
+ {
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, uri->user,
+ uri->pw ? ":" : "",
+ uri->pw ? uri->pw : "",
+ "@", NULL);
+ }
- if(uri->user)
+ if(strchr(uri->host, ':')) /* v6 ip */
+ {
+ l = "[";
+ r = "]";
+ }
+
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, l, uri->host, r, NULL);
+ }
+
+ if(uri->path)
{
- ha_bufjoin(buf);
- ha_bufmcat(buf, uri->user,
- uri->pw ? ":" : "",
- uri->pw ? uri->pw : "",
- "@", NULL);
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, "/", uri->path);
}
- if(strchr(uri->host, ':')) /* v6 ip */
+ if(uri->query)
{
- l = "[";
- r = "]";
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, "?", uri->query);
}
- ha_bufjoin(buf);
- ha_bufmcat(buf, l, uri->host, r, NULL);
- }
-
- if(uri->path)
- {
- ha_bufjoin(buf);
- ha_bufmcat(buf, "/", uri->path);
- }
-
- if(uri->query)
- {
- ha_bufjoin(buf);
- ha_bufmcat(buf, "?", uri->query);
- }
-
- if(uri->fragment)
- {
- ha_bufjoin(buf);
- ha_bufmcat(buf, "#", uri->fragment);
- }
-
- return ha_bufdata(buf);
+ if(uri->fragment)
+ {
+ ha_bufjoin(buf);
+ ha_bufmcat(buf, "#", uri->fragment);
+ }
+
+ return ha_bufdata(buf);
}
int ha_uriparse(ha_buffer_t* buf, const char* suri, ha_uri_t* uri)
{
- char* s;
- char* s1;
- char* hostinfo;
- char* endstr;
- char* str;
- int port;
- int v6_offset1 = 0;
-
- ASSERT(buf && suri && uri);
+ char* s;
+ char* s1;
+ char* hostinfo;
+ char* endstr;
+ char* str;
+ int port;
+ int v6_offset1 = 0;
- /* TODO: We need to http decode the uri */
+ ASSERT(buf && suri && uri);
- /* Copy the memory */
- str = ha_bufcpy(buf, suri);
+ /* TODO: We need to http decode the uri */
- if(!str)
- return HA_CRITERROR;
+ /* Copy the memory */
+ str = ha_bufcpy(buf, suri);
- /* Initialize the structure */
- memset(uri, 0, sizeof(*uri));
+ if(!str)
+ return HA_CRITERROR;
- /*
- * We assume the processor has a branch predictor like most --
- * it assumes forward branches are untaken and backwards are taken. That's
- * the reason for the gotos. -djg
- */
-
- if(str[0] == '/')
- {
-deal_with_path:
- *str == 0;
- ++str;
+ /* Initialize the structure */
+ memset(uri, 0, sizeof(*uri));
/*
- * we expect uri to point to first character of path ... remember
- * that the path could be empty -- http://foobar?query for example
+ * We assume the processor has a branch predictor like most --
+ * it assumes forward branches are untaken and backwards are taken. That's
+ * the reason for the gotos. -djg
*/
- s = str;
- while(*s && *s != '?' && *s != '#')
- ++s;
-
- if(s != str)
- uri->path = str;
- if(*s == 0)
- return HA_OK;
-
- if(*s == '?')
+ if(str[0] == '/')
{
- *s = 0;
- ++s;
- uri->query = s;
+deal_with_path:
+ *str == 0;
+ ++str;
- s1 = strchr(s, '#');
- if(s1)
- {
- *s1 = 0;
- ++s1;
- uri->fragment = s1;
- }
+ /*
+ * we expect uri to point to first character of path ... remember
+ * that the path could be empty -- http://foobar?query for example
+ */
+ s = str;
+ while(*s && *s != '?' && *s != '#')
+ ++s;
- return HA_OK;
- }
+ if(s != str)
+ uri->path = str;
- *s = 0;
- ++s;
+ if(*s == 0)
+ return HA_OK;
- /* otherwise it's a fragment */
- uri->fragment = s;
- return HA_OK;
- }
+ if(*s == '?')
+ {
+ *s = 0;
+ ++s;
+ uri->query = s;
+
+ s1 = strchr(s, '#');
+ if(s1)
+ {
+ *s1 = 0;
+ ++s1;
+ uri->fragment = s1;
+ }
+
+ return HA_OK;
+ }
+
+ *s = 0;
+ ++s;
- /* find the scheme: */
- s = str;
+ /* otherwise it's a fragment */
+ uri->fragment = s;
+ return HA_OK;
+ }
- while(*s && *s != ':' && *s != '/' && *s != '?' && *s != '#')
- s++;
+ /* find the scheme: */
+ s = str;
- /* scheme must be non-empty and followed by :// */
- if(s == str || s[0] != ':' || s[1] != '/' || s[2] != '/')
- goto deal_with_path; /* backwards predicted taken! */
+ while(*s && *s != ':' && *s != '/' && *s != '?' && *s != '#')
+ s++;
- uri->scheme = str;
- *s = 0;
- s += 3;
+ /* scheme must be non-empty and followed by :// */
+ if(s == str || s[0] != ':' || s[1] != '/' || s[2] != '/')
+ goto deal_with_path; /* backwards predicted taken! */
- hostinfo = s;
+ uri->scheme = str;
+ *s = 0;
+ s += 3;
- while(*s && *s != '/' && *s != '?' && *s != '#')
- ++s;
+ hostinfo = s;
- str = s; /* whatever follows hostinfo is start of uri */
+ while(*s && *s != '/' && *s != '?' && *s != '#')
+ ++s;
- /*
- * If there's a username:password@host:port, the @ we want is the last @...
- * too bad there's no memrchr()... For the C purists, note that hostinfo
- * is definately not the first character of the original uri so therefore
- * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
- */
- do
- {
- --s;
- }
- while(s >= hostinfo && *s != '@');
+ str = s; /* whatever follows hostinfo is start of uri */
- if(s < hostinfo)
- {
- /* again we want the common case to be fall through */
-deal_with_host:
/*
- * We expect hostinfo to point to the first character of
- * the hostname. If there's a port it is the first colon,
- * except with IPv6.
+ * If there's a username:password@host:port, the @ we want is the last @...
+ * too bad there's no memrchr()... For the C purists, note that hostinfo
+ * is definately not the first character of the original uri so therefore
+ * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
*/
- if(*hostinfo == '[')
+ do
{
- v6_offset1 = 1;
-
- s = str;
- for(;;)
- {
--s;
+ }
+ while(s >= hostinfo && *s != '@');
- if(s < hostinfo)
+ if(s < hostinfo)
+ {
+ /* again we want the common case to be fall through */
+deal_with_host:
+ /*
+ * We expect hostinfo to point to the first character of
+ * the hostname. If there's a port it is the first colon,
+ * except with IPv6.
+ */
+ if(*hostinfo == '[')
{
- s = NULL; /* no port */
- break;
+ v6_offset1 = 1;
+
+ s = str;
+ for(;;)
+ {
+ --s;
+
+ if(s < hostinfo)
+ {
+ s = NULL; /* no port */
+ break;
+ }
+
+ else if(*s == ']')
+ {
+ *s = 0;
+ s = NULL; /* no port */;
+ break;
+ }
+
+ else if(*s == ':')
+ {
+ *s = 0;
+ ++s; /* found a port */
+ break;
+ }
+ }
}
- else if(*s == ']')
+ else
{
- *s = 0;
- s = NULL; /* no port */;
- break;
+ s = memchr(hostinfo, ':', str - hostinfo);
+ if(s)
+ {
+ *s = 0;
+ ++s;
+ }
}
- else if(*s == ':')
+ uri->host = hostinfo + v6_offset1;
+
+ if(s == NULL)
{
- *s = 0;
- ++s; /* found a port */
- break;
+ /* we expect the common case to have no port */
+ goto deal_with_path;
}
- }
- }
- else
- {
- s = memchr(hostinfo, ':', str - hostinfo);
- if(s)
- {
- *s = 0;
- ++s;
- }
+ if(str != s)
+ {
+ port = strtol(s, &endstr, 10);
+ uri->port = port;
+ if(*endstr != '\0')
+ return HA_FAILED;
+ }
+
+ goto deal_with_path;
}
- uri->host = hostinfo + v6_offset1;
+ /* Remove the @ symbol */
+ *s = 0;
- if(s == NULL)
+ /* first colon delimits username:password */
+ s1 = memchr(hostinfo, ':', s - hostinfo);
+ if(s1)
{
- /* we expect the common case to have no port */
- goto deal_with_path;
- }
+ *s1 = 0;
+ ++s1;
- if(str != s)
+ uri->user = hostinfo;
+ uri->pw = s1;
+ }
+ else
{
- port = strtol(s, &endstr, 10);
- uri->port = port;
- if(*endstr != '\0')
- return HA_FAILED;
+ str = hostinfo;
}
- goto deal_with_path;
- }
-
- /* Remove the @ symbol */
- *s = 0;
-
- /* first colon delimits username:password */
- s1 = memchr(hostinfo, ':', s - hostinfo);
- if(s1)
- {
- *s1 = 0;
- ++s1;
-
- uri->user = hostinfo;
- uri->pw = s1;
- }
- else
- {
- str = hostinfo;
- }
-
- hostinfo = s + 1;
- goto deal_with_host;
+ hostinfo = s + 1;
+ goto deal_with_host;
}
-int uri_cmp_part_s(const char* s1, const char* s2, const char* def, int cs)
+static int uri_cmp_part_s(const char* s1, const char* s2, const char* def, int cs)
{
- if(def)
- {
- if(s1 && strcmp(def, s1) == 0)
- s1 = NULL;
- if(s2 && strcmp(def, s2) == 0)
- s2 = NULL;
- }
-
- if(!s1 && !s2)
- return 0;
+ if(def)
+ {
+ if(s1 && strcmp(def, s1) == 0)
+ s1 = NULL;
+ if(s2 && strcmp(def, s2) == 0)
+ s2 = NULL;
+ }
+
+ if(!s1 && !s2)
+ return 0;
- if(!s1)
- return -1;
+ if(!s1)
+ return -1;
- if(!s2)
- return 1;
+ if(!s2)
+ return 1;
- return cs ? strcasecmp(s1, s2) : strcmp(s1, s2);
+ return cs ? strcasecmp(s1, s2) : strcmp(s1, s2);
}
-int uri_cmp_part_n(int n1, int n2, int def)
+static int uri_cmp_part_n(int n1, int n2, int def)
{
- if(def)
- {
- if(n1 == def)
- n1 = 0;
- if(n2 == def)
- n2 = 0;
- }
-
- if(n1 == n2)
- return 0;
+ if(def)
+ {
+ if(n1 == def)
+ n1 = 0;
+ if(n2 == def)
+ n2 = 0;
+ }
+
+ if(n1 == n2)
+ return 0;
- else if(n1 < n2)
- return -1;
+ else if(n1 < n2)
+ return -1;
- else if(n2 > n1)
- return 1;
+ else if(n2 > n1)
+ return 1;
- /* Not reached */
- ASSERT(0);
+ /* Not reached */
+ ASSERT(0);
}
int ha_uricmp(ha_uri_t* one, ha_uri_t* two)
{
- int r;
+ int r;
- ASSERT(one && two);
+ ASSERT(one && two);
- /* We don't compare user or password */
+ /* We don't compare user or password */
- /* The scheme */
- if((r = uri_cmp_part_s(one->scheme, two->scheme, "http", 0)) != 0 ||
- (r = uri_cmp_part_s(one->host, two->host, NULL, 1)) != 0 != 0 ||
- (r = uri_cmp_part_n(one->port, two->port, 80)) != 0 ||
- (r = uri_cmp_part_s(one->path, two->path, NULL, 0)) != 0 ||
- (r = uri_cmp_part_s(one->query, two->query, NULL, 0)) != 0 ||
- (r = uri_cmp_part_s(one->fragment, two->fragment, NULL, 0)))
- return r;
+ /* The scheme */
+ if((r = uri_cmp_part_s(one->scheme, two->scheme, "http", 0)) != 0 ||
+ (r = uri_cmp_part_s(one->host, two->host, NULL, 1)) != 0 != 0 ||
+ (r = uri_cmp_part_n(one->port, two->port, 80)) != 0 ||
+ (r = uri_cmp_part_s(one->path, two->path, NULL, 0)) != 0 ||
+ (r = uri_cmp_part_s(one->query, two->query, NULL, 0)) != 0 ||
+ (r = uri_cmp_part_s(one->fragment, two->fragment, NULL, 0)))
+ return r;
- return 0;
+ return 0;
}
int ha_genrandom(unsigned char* data, size_t len)
{
- int r, dd;
-
- ASSERT(data && len > 0);
-
- dd = open("/dev/urandom", O_RDONLY);
- if(dd == -1)
- {
- ha_message(LOG_ERR, "couldn't open /dev/urandom");
- return HA_FAILED;
- }
+ int r, dd;
- for(;;)
- {
- r = read(dd, data, len);
+ ASSERT(data && len > 0);
- if(r == -1)
+ dd = open("/dev/urandom", O_RDONLY);
+ if(dd == -1)
{
- switch(errno)
- {
- case EINTR:
- case EAGAIN:
- continue;
-
- default:
- ha_message(LOG_ERR, "couldn't read random bytes from /dev/urandom");
- break;
- }
-
- break;
+ ha_message(NULL, LOG_ERR, "couldn't open /dev/urandom");
+ return HA_FAILED;
}
- else if(r >= 0)
+ for(;;)
{
- if(r >= len)
- break;
+ r = read(dd, data, len);
+
+ if(r == -1)
+ {
+ switch(errno)
+ {
+ case EINTR:
+ case EAGAIN:
+ continue;
+
+ default:
+ ha_message(NULL, LOG_ERR, "couldn't read random bytes from /dev/urandom");
+ break;
+ };
+
+ break;
+ }
- len -= r;
- data += r;
+ else if(r >= 0)
+ {
+ if(r >= len)
+ break;
+
+ len -= r;
+ data += r;
+ }
}
- }
- close(dd);
- return r == -1 ? HA_FAILED : HA_OK;
+ close(dd);
+ return r == -1 ? HA_FAILED : HA_OK;
}
diff --git a/daemon/ntlm.c b/daemon/ntlm.c
index 031e19d..63d4580 100644
--- a/daemon/ntlm.c
+++ b/daemon/ntlm.c
@@ -19,7 +19,7 @@
*/
#define NTLM_HASH_KEY_LEN MD5_LEN
-#define NTLM_ESTABLISHED (void*)1
+#define NTLM_ESTABLISHED (void*)1
/* -------------------------------------------------------------------------------
@@ -29,9 +29,9 @@
/* A pending connection */
typedef struct ntlm_connection
{
- void* handle;
- char nonce[NONCE_LEN];
- unsigned int flags;
+ void* handle;
+ char nonce[NONCE_LEN];
+ unsigned int flags;
}
ntlm_connection_t;
@@ -39,16 +39,16 @@ ntlm_connection_t;
/* The main context */
typedef struct ntlm_context
{
- /* Settings ---------------------------------------------------------- */
- const char* server; /* Server to authenticate against */
- const char* domain; /* NTLM domain to authenticate against */
- const char* backup; /* Backup server if primary is down */
- int pending_max; /* Maximum number of connections at once */
- int pending_timeout; /* Timeout for authentication (in seconds) */
-
- /* Context ----------------------------------------------------------- */
- hsh_t* pending; /* Pending connections */
- hsh_t* established; /* Established connections */
+ /* Settings ---------------------------------------------------------- */
+ const char* server; /* Server to authenticate against */
+ const char* domain; /* NTLM domain to authenticate against */
+ const char* backup; /* Backup server if primary is down */
+ int pending_max; /* Maximum number of connections at once */
+ int pending_timeout; /* Timeout for authentication (in seconds) */
+
+ /* Context ----------------------------------------------------------- */
+ hsh_t* pending; /* Pending connections */
+ hsh_t* established; /* Established connections */
}
ntlm_context_t;
@@ -56,8 +56,8 @@ ntlm_context_t;
/* The default context settings */
static const ntlm_context_t ntlm_defaults =
{
- NULL, NULL, NULL, DEFAULT_PENDING_MAX, DEFAULT_PENDING_TIMEOUT,
- NULL, NULL
+ NULL, NULL, NULL, DEFAULT_PENDING_MAX, DEFAULT_PENDING_TIMEOUT,
+ NULL, NULL
};
@@ -70,467 +70,467 @@ static pthread_mutexattr_t g_smblib_mutexattr;
* Internal Functions
*/
-static ntlm_connection_t* makeconnection(ntlm_context_t* ctx)
+static ntlm_connection_t* makeconnection(ha_request_t* rq, ntlm_context_t* ctx)
{
- ntlm_connection_t* conn;
-
- ASSERT(ctx);
-
- conn = (ntlm_connection_t*)malloc(sizeof(ntlm_connection_t));
- if(!conn)
- {
- ha_messagex(LOG_CRIT, "out of memory");
- return NULL;
- }
-
- memset(conn, 0, sizeof(*conn));
-
- /*
- * Open a connection to to the domain controller. I don't think
- * we can cache these connections or use them again as opening
- * a connection here results in an nonce being generated.
- */
- conn->handle = ntlmssp_connect(ctx->server, ctx->backup,
- ctx->domain, conn->nonce);
- if(!conn->handle)
- {
- ha_messagex(LOG_ERR, "ntlm: couldn't connect to the domain server %s (backup: %s)",
- ctx->server, ctx->backup ? ctx->backup : "none");
- free(conn);
- return NULL;
- }
+ ntlm_connection_t* conn;
+
+ ASSERT(ctx);
+
+ conn = (ntlm_connection_t*)malloc(sizeof(ntlm_connection_t));
+ if(!conn)
+ {
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
+ return NULL;
+ }
+
+ memset(conn, 0, sizeof(*conn));
+
+ /*
+ * Open a connection to to the domain controller. I don't think
+ * we can cache these connections or use them again as opening
+ * a connection here results in an nonce being generated.
+ */
+ conn->handle = ntlmssp_connect(ctx->server, ctx->backup,
+ ctx->domain, conn->nonce);
+ if(!conn->handle)
+ {
+ ha_messagex(rq, LOG_ERR, "couldn't connect to the domain server %s (backup: %s)",
+ ctx->server, ctx->backup ? ctx->backup : "none");
+ free(conn);
+ return NULL;
+ }
- ha_messagex(LOG_INFO, "ntlm: established connection to server");
- return conn;
+ ha_messagex(rq, LOG_INFO, "established connection to server");
+ return conn;
}
-static void freeconnection(ntlm_connection_t* conn)
+static void freeconnection(ha_request_t* rq, ntlm_connection_t* conn)
{
- ASSERT(conn);
+ ASSERT(conn);
- if(conn->handle)
- {
- ha_messagex(LOG_DEBUG, "ntlm: disconnected from server");
- ntlmssp_disconnect(conn->handle);
- conn->handle = NULL;
- }
+ if(conn->handle)
+ {
+ ha_messagex(rq, LOG_DEBUG, "disconnected from server");
+ ntlmssp_disconnect(conn->handle);
+ conn->handle = NULL;
+ }
- free(conn);
+ free(conn);
}
static void free_hash_object(void* arg, void* val)
{
- if(val)
- {
- ASSERT(val != NTLM_ESTABLISHED);
- freeconnection((ntlm_connection_t*)val);
- }
+ if(val)
+ {
+ ASSERT(val != NTLM_ESTABLISHED);
+ freeconnection(NULL, (ntlm_connection_t*)val);
+ }
}
static ntlm_connection_t* getpending(ntlm_context_t* ctx, const void* key)
{
- ntlm_connection_t* ret;
+ ntlm_connection_t* ret;
- ASSERT(ctx && key);
+ ASSERT(ctx && key);
- ha_lock(NULL);
+ ha_lock(NULL);
- ret = (ntlm_connection_t*)hsh_rem(ctx->pending, key);
+ ret = (ntlm_connection_t*)hsh_rem(ctx->pending, key);
- ha_unlock(NULL);
+ ha_unlock(NULL);
- return ret;
+ return ret;
}
static int putpending(ntlm_context_t* ctx, const void* key, ntlm_connection_t* conn)
{
- int r = 0;
+ int r = 0;
- ASSERT(ctx && key && conn);
- ASSERT(conn->handle);
+ ASSERT(ctx && key && conn);
+ ASSERT(conn->handle);
- if(!hsh_get(ctx->pending, key))
- {
- ha_lock(NULL);
+ if(!hsh_get(ctx->pending, key))
+ {
+ ha_lock(NULL);
- if(!hsh_set(ctx->pending, key, (void*)conn))
- {
- free_hash_object(NULL, conn);
- ha_messagex(LOG_ERR, "out of memory");
- r = -1;
- }
+ if(!hsh_set(ctx->pending, key, (void*)conn))
+ {
+ free_hash_object(NULL, conn);
+ ha_messagex(NULL, LOG_ERR, "out of memory");
+ r = -1;
+ }
- ha_unlock(NULL);
- }
+ ha_unlock(NULL);
+ }
- return r;
+ return r;
}
-int ntlm_auth_basic(ntlm_context_t* ctx, char* key, const char* header,
- ha_response_t* resp, ha_buffer_t* buf)
+int ntlm_auth_basic(ha_request_t* rq, ntlm_context_t* ctx, char* key,
+ const char* header)
{
- ntlm_connection_t* conn;
- char* t;
- basic_header_t basic;
- const char* domain = NULL;
- int found = 0;
- int r;
-
- ASSERT(ctx && key && header && resp && buf);
-
- /*
- * We're doing basic authentication on the connection
- * which invalidates any NTLM authentication we've started
- * or done on this connection.
- */
- conn = getpending(ctx, key);
- if(conn)
- {
- ha_messagex(LOG_WARNING, "ntlm: basic auth killed a pending ntlm auth in progress");
- freeconnection(conn);
- }
-
- if((r = basic_parse(header, buf, &basic)) < 0)
- return r;
-
- /* Check and see if this connection is in the cache */
- ha_lock(NULL);
-
- if(hsh_get(ctx->established, basic.key) == NTLM_ESTABLISHED)
- found = 1;
-
- ha_unlock(NULL);
-
- if(found)
- ha_messagex(LOG_NOTICE, "ntlm: validated basic user against cache: %s", basic.user);
+ ntlm_connection_t* conn;
+ char* t;
+ basic_header_t basic;
+ const char* domain = NULL;
+ int found = 0;
+ int r;
- else
- {
- /* Try to find a domain in the user */
- if((t = strchr(basic.user, '\\')) != NULL ||
- (t = strchr(basic.user, '/')) != NULL)
- {
- /* Break at the domain */
- domain = basic.user;
- basic.user = t + 1;
- *t = 0;
-
- /* Make sure this is our domain */
- if(strcasecmp(domain, ctx->domain) != 0)
- domain = NULL;
- }
+ ASSERT(ctx && key && header && rq);
- if(!domain)
+ /*
+ * We're doing basic authentication on the connection
+ * which invalidates any NTLM authentication we've started
+ * or done on this connection.
+ */
+ conn = getpending(ctx, key);
+ if(conn)
{
- /* Use the default domain if none specified */
- domain = ctx->domain;
+ ha_messagex(rq, LOG_WARNING, "basic auth killed a pending ntlm auth in progress");
+ freeconnection(rq, conn);
}
- /* Make sure above did not fail */
- if(basic.user && basic.user[0] && basic.password &&
- domain && domain[0])
- {
- ha_messagex(LOG_DEBUG, "ntlm: checking user against server: %s", basic.user);
-
- /* We need to lock to go into smblib */
- ha_lock(&g_smblib_mutex);
-
- /* Found in smbval/valid.h */
- if(ntlmssp_validuser(basic.user, basic.password, ctx->server,
- ctx->backup, domain) == NTV_NO_ERROR)
- {
- /* If valid then we return */
- found = 1;
- }
-
- ha_unlock(&g_smblib_mutex);
- }
-
- if(found)
- ha_messagex(LOG_NOTICE, "ntlm: validated basic user against server: %s", basic.user);
- }
-
- if(found)
- {
- int r;
- resp->code = HA_SERVER_OK;
- resp->detail = basic.user;
+ if((r = basic_parse(header, rq->buf, &basic)) < 0)
+ return r;
+ /* Check and see if this connection is in the cache */
ha_lock(NULL);
- /* We put this connection into the successful connections */
- r = hsh_set(ctx->established, basic.key, NTLM_ESTABLISHED);
+ if(hsh_get(ctx->established, basic.key) == NTLM_ESTABLISHED)
+ found = 1;
ha_unlock(NULL);
- if(!r)
- {
- ha_messagex(LOG_CRIT, "out of memory");
- return HA_CRITERROR;
- }
-
- return HA_OK;
- }
-
- return HA_FALSE;
-}
+ if(found)
+ ha_messagex(rq, LOG_NOTICE, "validated basic user against cache: %s", basic.user);
-int ntlm_auth_ntlm(ntlm_context_t* ctx, void* key, const char* header,
- ha_response_t* resp, ha_buffer_t* buf)
-{
- ntlmssp_info_rec ntlmssp;
- ntlm_connection_t* conn = NULL;
- unsigned int flags = 0;
- int ret = HA_FALSE;
- size_t len = 0;
- void* d;
- int r;
-
- ASSERT(ctx && key && header && resp && buf);
-
- /*
- * Retrieve and remove the connection from the pending bag.
- * We add it back again below if that's necessary.
- */
- conn = getpending(ctx, key);
-
- /*
- * We use the flags from an already established connection
- * if we've been pending and stuff
- */
-
- if(conn && conn->flags)
- flags = conn->flags;
-
- /*
- * First we figure out what kind of message the client
- * is sending us.
- */
-
- d = ha_bufdec64(buf, header, &len);
-
- if(!d || len == 0)
- goto finally;
-
- r = ntlmssp_decode_msg(&ntlmssp, d, len, &flags);
- if(r != 0)
- {
- ha_messagex(LOG_WARNING, "ntlm: decoding NTLMSSP message failed (error %d)", r);
- resp->code = HA_SERVER_BADREQ;
- goto finally;
- }
-
-
- switch(ntlmssp.msg_type)
- {
-
- /* An initial NTLM request? */
- case 1:
+ else
{
- /* Win9x doesn't seem to send a domain or host */
- int win9x = !ntlmssp.host[0] && !ntlmssp.domain[0];
-
- /*
- * If we already have a connection to the domain controller
- * then we're in trouble. Basically this is the second
- * type 1 message we've received over this connection.
- *
- * TODO: Eventually what we want to do here is wait for the
- * other authentication request to complete, or something
- * like that.
- */
- if(conn)
- {
- /*
- * In this case we also add the connection back into the
- * pending stack so that the correct request will complete
- * properly when it comes through.
- */
- r = putpending(ctx, key, conn);
- conn = NULL;
-
- if(r < 0)
+ /* Try to find a domain in the user */
+ if((t = strchr(basic.user, '\\')) != NULL ||
+ (t = strchr(basic.user, '/')) != NULL)
{
- ret = HA_CRITERROR;
+ /* Break at the domain */
+ domain = basic.user;
+ basic.user = t + 1;
+ *t = 0;
+
+ /* Make sure this is our domain */
+ if(strcasecmp(domain, ctx->domain) != 0)
+ domain = NULL;
}
- else
+
+ if(!domain)
{
- ha_messagex(LOG_ERR, "ntlm: received out of order NTLM request from client");
- resp->code = HA_SERVER_BADREQ;
+ /* Use the default domain if none specified */
+ domain = ctx->domain;
}
- goto finally;
- }
-
+ /* Make sure above did not fail */
+ if(basic.user && basic.user[0] && basic.password &&
+ domain && domain[0])
+ {
+ ha_messagex(rq, LOG_DEBUG, "checking user against server: %s", basic.user);
- /*
- * Check how many connections we have to the domain controller
- * and if too many then cut off here.
- */
- if(ctx->pending_max != -1)
- {
- ha_lock(NULL);
+ /* We need to lock to go into smblib */
+ ha_lock(&g_smblib_mutex);
- if(hsh_count(ctx->pending) >= ctx->pending_max)
- hsh_bump(ctx->pending);
+ /* Found in smbval/valid.h */
+ if(ntlmssp_validuser(basic.user, basic.password, ctx->server,
+ ctx->backup, domain) == NTV_NO_ERROR)
+ {
+ /* If valid then we return */
+ found = 1;
+ }
- ha_unlock(NULL);
- }
+ ha_unlock(&g_smblib_mutex);
+ }
+ if(found)
+ ha_messagex(rq, LOG_NOTICE, "validated basic user against server: %s", basic.user);
+ }
- /*
- * Open a connection to to the domain controller. I don't think
- * we can cache these connections or use them again as opening
- * a connection here results in an nonce being generated.
- */
- conn = makeconnection(ctx);
+ if(found)
+ {
+ int r;
+ rq->resp_code = HA_SERVER_OK;
+ rq->resp_detail = basic.user;
- if(!conn)
- {
- ret = HA_FAILED;
- goto finally;
- }
-
- /* Save away any flags given us by ntlm_decode_msg */
- conn->flags = flags;
-
- /* Start building the header */
- ha_bufcpy(buf, HA_PREFIX_NTLM);
-
- if(win9x)
- {
- struct ntlm_msg2_win9x msg_win9x;
- ntlmssp_encode_msg2_win9x(conn->nonce, &msg_win9x, (char*)ctx->domain, flags);
- ha_bufjoin(buf);
- ha_bufenc64(buf, (unsigned char*)&msg_win9x, sizeof(msg_win9x));
- }
- else
- {
- struct ntlm_msg2 msg;
- ntlmssp_encode_msg2(conn->nonce, &msg);
- ha_bufjoin(buf);
- ha_bufenc64(buf, (unsigned char*)&msg, sizeof(msg));
- }
-
- if(ha_buferr(buf))
- goto finally;
+ ha_lock(NULL);
- /*
- * TODO: Our callers need to be able to keep alive
- * connections that have authentication going on.
- */
+ /* We put this connection into the successful connections */
+ r = hsh_set(ctx->established, basic.key, NTLM_ESTABLISHED);
- /* Cache this connection in our pending set ... */
- r = putpending(ctx, key, conn);
+ ha_unlock(NULL);
- /*
- * By marking this as null, the cleanup code
- * won't free the connection since it's been
- * cached above.
- */
- conn = NULL;
+ if(!r)
+ {
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
+ return HA_CRITERROR;
+ }
- if(r < 0)
- {
- ret = HA_CRITERROR;
- }
- else
- {
- ha_messagex(LOG_DEBUG, "ntlm: sending ntlm challenge");
- ha_addheader(resp, "WWW-Authenticate", ha_bufdata(buf));
- resp->code = HA_SERVER_DECLINE;
- }
- goto finally;
+ return HA_OK;
}
- /* A response to a challenge */
- case 3:
- {
- /*
- * We need to have a connection at this point or this whole thing
- * has come in in the wrong order. Actually it's a client error
- * for stuff to come in wrong. But since some web servers also
- * kill keep-alives and stuff, we forgive and just ask the client
- * for the authentication info again.
- */
- if(!conn || !conn->handle)
- {
- ha_messagex(LOG_WARNING, "ntlm: received out of order NTLM response from client");
- resp->code = HA_SERVER_BADREQ;
- goto finally;
- }
+ return HA_FALSE;
+}
- if(!ntlmssp.user)
- {
- ha_messagex(LOG_WARNING, "ntlm: received NTLM response without user name");
- resp->code = HA_SERVER_BADREQ;
- goto finally;
- }
+int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
+ const char* header)
+{
+ ntlmssp_info_rec ntlmssp;
+ ntlm_connection_t* conn = NULL;
+ unsigned int flags = 0;
+ int ret = HA_FALSE;
+ size_t len = 0;
+ void* d;
+ int r;
- /* We have to lock while going into smblib */
- ha_lock(&g_smblib_mutex);
+ ASSERT(ctx && key && header && rq);
- /* Now authenticate them against the DC */
- r = ntlmssp_auth(conn->handle, ntlmssp.user, ntlmssp.nt, 1,
- ntlmssp.domain[0] ? (char*)ntlmssp.domain : (char*)ctx->domain);
+ /*
+ * Retrieve and remove the connection from the pending bag.
+ * We add it back again below if that's necessary.
+ */
+ conn = getpending(ctx, key);
- ha_unlock(&g_smblib_mutex);
+ /*
+ * We use the flags from an already established connection
+ * if we've been pending and stuff
+ */
- /* The connection gets disconnected below */
+ if(conn && conn->flags)
+ flags = conn->flags;
- if(r == NTV_LOGON_ERROR)
- {
- /*
- * Note that we don't set a code here. This causes our
- * caller to put in all the proper headers for us.
- */
- ha_messagex(LOG_WARNING, "ntlm: failed NTLM logon for user '%s'", ntlmssp.user);
- ret = HA_FALSE;
- }
+ /*
+ * First we figure out what kind of message the client
+ * is sending us.
+ */
- /* A successful login ends here */
- else
- {
- int r;
- resp->detail = ntlmssp.user;
- ha_messagex(LOG_NOTICE, "ntlm: validated ntlm user against server", ntlmssp.user);
+ d = ha_bufdec64(rq->buf, header, &len);
- ha_lock(NULL);
+ if(!d || len == 0)
+ goto finally;
- /* We put this connection into the successful connections */
- r = hsh_set(ctx->established, key, NTLM_ESTABLISHED);
+ r = ntlmssp_decode_msg(&ntlmssp, d, len, &flags);
+ if(r != 0)
+ {
+ ha_messagex(rq, LOG_WARNING, "decoding NTLMSSP message failed (error %d)", r);
+ rq->resp_code = HA_SERVER_BADREQ;
+ goto finally;
+ }
- ha_unlock(NULL);
- if(!r)
+ switch(ntlmssp.msg_type)
+ {
+
+ /* An initial NTLM request? */
+ case 1:
{
- ha_messagex(LOG_CRIT, "out of memory");
- ret = HA_CRITERROR;
+ /* Win9x doesn't seem to send a domain or host */
+ int win9x = !ntlmssp.host[0] && !ntlmssp.domain[0];
+
+ /*
+ * If we already have a connection to the domain controller
+ * then we're in trouble. Basically this is the second
+ * type 1 message we've received over this connection.
+ *
+ * TODO: Eventually what we want to do here is wait for the
+ * other authentication request to complete, or something
+ * like that.
+ */
+ if(conn)
+ {
+ /*
+ * In this case we also add the connection back into the
+ * pending stack so that the correct request will complete
+ * properly when it comes through.
+ */
+ r = putpending(ctx, key, conn);
+ conn = NULL;
+
+ if(r < 0)
+ {
+ ret = HA_CRITERROR;
+ }
+ else
+ {
+ ha_messagex(rq, LOG_ERR, "received out of order NTLM request from client");
+ rq->resp_code = HA_SERVER_BADREQ;
+ }
+
+ goto finally;
+ }
+
+
+ /*
+ * Check how many connections we have to the domain controller
+ * and if too many then cut off here.
+ */
+ if(ctx->pending_max != -1)
+ {
+ ha_lock(NULL);
+
+ if(hsh_count(ctx->pending) >= ctx->pending_max)
+ hsh_bump(ctx->pending);
+
+ ha_unlock(NULL);
+ }
+
+
+ /*
+ * Open a connection to to the domain controller. I don't think
+ * we can cache these connections or use them again as opening
+ * a connection here results in an nonce being generated.
+ */
+ conn = makeconnection(rq, ctx);
+
+ if(!conn)
+ {
+ ret = HA_FAILED;
+ goto finally;
+ }
+
+ /* Save away any flags given us by ntlm_decode_msg */
+ conn->flags = flags;
+
+ /* Start building the header */
+ ha_bufcpy(rq->buf, HA_PREFIX_NTLM);
+
+ if(win9x)
+ {
+ struct ntlm_msg2_win9x msg_win9x;
+ ntlmssp_encode_msg2_win9x(conn->nonce, &msg_win9x, (char*)ctx->domain, flags);
+ ha_bufjoin(rq->buf);
+ ha_bufenc64(rq->buf, (unsigned char*)&msg_win9x, sizeof(msg_win9x));
+ }
+ else
+ {
+ struct ntlm_msg2 msg;
+ ntlmssp_encode_msg2(conn->nonce, &msg);
+ ha_bufjoin(rq->buf);
+ ha_bufenc64(rq->buf, (unsigned char*)&msg, sizeof(msg));
+ }
+
+ if(ha_buferr(rq->buf))
+ goto finally;
+
+ /*
+ * TODO: Our callers need to be able to keep alive
+ * connections that have authentication going on.
+ */
+
+ /* Cache this connection in our pending set ... */
+ r = putpending(ctx, key, conn);
+
+ /*
+ * By marking this as null, the cleanup code
+ * won't free the connection since it's been
+ * cached above.
+ */
+ conn = NULL;
+
+ if(r < 0)
+ {
+ ret = HA_CRITERROR;
+ }
+ else
+ {
+ ha_messagex(rq, LOG_DEBUG, "sending ntlm challenge");
+ ha_addheader(rq, "WWW-Authenticate", ha_bufdata(rq->buf));
+ rq->resp_code = HA_SERVER_DECLINE;
+ }
+ goto finally;
}
- else
+
+ /* A response to a challenge */
+ case 3:
{
- ret = HA_OK;
+ /*
+ * We need to have a connection at this point or this whole thing
+ * has come in in the wrong order. Actually it's a client error
+ * for stuff to come in wrong. But since some web servers also
+ * kill keep-alives and stuff, we forgive and just ask the client
+ * for the authentication info again.
+ */
+ if(!conn || !conn->handle)
+ {
+ ha_messagex(rq, LOG_WARNING, "received out of order NTLM response from client");
+ rq->resp_code = HA_SERVER_BADREQ;
+ goto finally;
+ }
+
+ if(!ntlmssp.user)
+ {
+ ha_messagex(rq, LOG_WARNING, "received NTLM response without user name");
+ rq->resp_code = HA_SERVER_BADREQ;
+ goto finally;
+ }
+
+ /* We have to lock while going into smblib */
+ ha_lock(&g_smblib_mutex);
+
+ /* Now authenticate them against the DC */
+ r = ntlmssp_auth(conn->handle, ntlmssp.user, ntlmssp.nt, 1,
+ ntlmssp.domain[0] ? (char*)ntlmssp.domain : (char*)ctx->domain);
+
+ ha_unlock(&g_smblib_mutex);
+
+ /* The connection gets disconnected below */
+
+ if(r == NTV_LOGON_ERROR)
+ {
+ /*
+ * Note that we don't set a code here. This causes our
+ * caller to put in all the proper headers for us.
+ */
+ ha_messagex(rq, LOG_WARNING, "failed NTLM logon for user '%s'", ntlmssp.user);
+ ret = HA_FALSE;
+ }
+
+ /* A successful login ends here */
+ else
+ {
+ int r;
+ rq->resp_detail = ntlmssp.user;
+ ha_messagex(rq, LOG_NOTICE, "validated ntlm user against server", ntlmssp.user);
+
+ ha_lock(NULL);
+
+ /* We put this connection into the successful connections */
+ r = hsh_set(ctx->established, key, NTLM_ESTABLISHED);
+
+ ha_unlock(NULL);
+
+ if(!r)
+ {
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
+ ret = HA_CRITERROR;
+ }
+ else
+ {
+ ret = HA_OK;
+ }
+ }
+
+ goto finally;
}
- }
-
- goto finally;
- }
- default:
- ha_messagex(LOG_WARNING, "ntlm: received invalid NTLM message (type %d)", ntlmssp.msg_type);
- resp->code = HA_SERVER_BADREQ;
- goto finally;
- };
+ default:
+ ha_messagex(rq, LOG_WARNING, "received invalid NTLM message (type %d)", ntlmssp.msg_type);
+ rq->resp_code = HA_SERVER_BADREQ;
+ goto finally;
+ };
finally:
- if(ha_buferr(buf))
- ret = HA_CRITERROR;
+ if(ha_buferr(rq->buf))
+ ret = HA_CRITERROR;
- if(conn)
- freeconnection(conn);
+ if(conn)
+ freeconnection(rq, conn);
- return ret;
+ return ret;
}
@@ -540,245 +540,245 @@ finally:
int ntlm_config(ha_context_t* context, const char* name, const char* value)
{
- ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data);
+ ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data);
- ASSERT(name && value && value[0]);
+ ASSERT(name && value && value[0]);
- if(strcmp(name, "ntlmserver") == 0)
- {
- ctx->server = value;
- return HA_OK;
- }
+ if(strcmp(name, "ntlmserver") == 0)
+ {
+ ctx->server = value;
+ return HA_OK;
+ }
- else if(strcmp(name, "ntlmbackup") == 0)
- {
- ctx->backup = value;
- return HA_OK;
- }
+ else if(strcmp(name, "ntlmbackup") == 0)
+ {
+ ctx->backup = value;
+ return HA_OK;
+ }
- else if(strcmp(name, "ntlmdomain") == 0)
- {
- ctx->domain = value;
- return HA_OK;
- }
+ else if(strcmp(name, "ntlmdomain") == 0)
+ {
+ ctx->domain = value;
+ return HA_OK;
+ }
- else if(strcmp(name, "pendingmax") == 0)
- {
- return ha_confint(name, value, 1, 256, &(ctx->pending_max));
- }
+ else if(strcmp(name, "pendingmax") == 0)
+ {
+ return ha_confint(name, value, 1, 256, &(ctx->pending_max));
+ }
- else if(strcmp(name, "pendingtimeout") == 0)
- {
- return ha_confint(name, value, 1, 86400, &(ctx->pending_timeout));
- }
+ else if(strcmp(name, "pendingtimeout") == 0)
+ {
+ return ha_confint(name, value, 1, 86400, &(ctx->pending_timeout));
+ }
- return HA_FALSE;
+ return HA_FALSE;
}
int ntlm_init(ha_context_t* context)
{
- /* Per context initialization */
- if(context)
- {
- ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data);
- hsh_table_calls_t htc;
+ /* Per context initialization */
+ if(context)
+ {
+ ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data);
+ hsh_table_calls_t htc;
- ASSERT(ctx);
+ ASSERT(ctx);
- /* Make sure there are some types of authentication we can do */
- if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_NTLM)))
- {
- ha_messagex(LOG_ERR, "NTLM module configured, but does not implement any "
- "configured authentication type.");
- return HA_FAILED;
- }
+ /* Make sure there are some types of authentication we can do */
+ if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_NTLM)))
+ {
+ ha_messagex(NULL, LOG_ERR, "NTLM module configured, but does not implement any "
+ "configured authentication type.");
+ return HA_FAILED;
+ }
- /* Check for mandatory configuration */
- if(!(ctx->server) || !(ctx->domain))
- {
- ha_messagex(LOG_ERR, "NTLM configuration incomplete. "
- "Must have NTLMServer and NTLMDomain configured.");
- return HA_FAILED;
- }
+ /* Check for mandatory configuration */
+ if(!(ctx->server) || !(ctx->domain))
+ {
+ ha_messagex(NULL, LOG_ERR, "NTLM configuration incomplete. "
+ "Must have NTLMServer and NTLMDomain configured.");
+ return HA_FAILED;
+ }
- ASSERT(!ctx->pending);
- ASSERT(!ctx->established);
+ ASSERT(!ctx->pending);
+ ASSERT(!ctx->established);
- /* Initialize our tables */
- if(!(ctx->pending = hsh_create(NTLM_HASH_KEY_LEN)) ||
- !(ctx->established = hsh_create(NTLM_HASH_KEY_LEN)))
- {
- ha_messagex(LOG_CRIT, "out of memory");
- return HA_CRITERROR;
- }
+ /* Initialize our tables */
+ if(!(ctx->pending = hsh_create(NTLM_HASH_KEY_LEN)) ||
+ !(ctx->established = hsh_create(NTLM_HASH_KEY_LEN)))
+ {
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
+ return HA_CRITERROR;
+ }
- htc.f_freeval = free_hash_object;
- htc.arg = NULL;
- hsh_set_table_calls(ctx->pending, &htc);
+ htc.f_freeval = free_hash_object;
+ htc.arg = NULL;
+ hsh_set_table_calls(ctx->pending, &htc);
- ha_messagex(LOG_INFO, "ntlm: initialized handler");
- }
+ ha_messagex(NULL, LOG_INFO, "initialized ntlm handler");
+ }
- /* Global Initialization */
- else
- {
- /* Create the smblib mutex */
- if(pthread_mutexattr_init(&g_smblib_mutexattr) != 0 ||
- pthread_mutexattr_settype(&g_smblib_mutexattr, HA_MUTEX_TYPE) ||
- pthread_mutex_init(&g_smblib_mutex, &g_smblib_mutexattr) != 0)
+ /* Global Initialization */
+ else
{
- ha_messagex(LOG_CRIT, "threading problem. can't create mutex");
- return HA_CRITERROR;
+ /* Create the smblib mutex */
+ if(pthread_mutexattr_init(&g_smblib_mutexattr) != 0 ||
+ pthread_mutexattr_settype(&g_smblib_mutexattr, HA_MUTEX_TYPE) ||
+ pthread_mutex_init(&g_smblib_mutex, &g_smblib_mutexattr) != 0)
+ {
+ ha_messagex(NULL, LOG_CRIT, "threading problem. can't create mutex");
+ return HA_CRITERROR;
+ }
}
- }
- return HA_OK;
+ return HA_OK;
}
void ntlm_destroy(ha_context_t* context)
{
- /* Per context destroy */
- if(context)
- {
- /* Note: We don't need to be thread safe here anymore */
- ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data);
+ /* Per context destroy */
+ if(context)
+ {
+ /* Note: We don't need to be thread safe here anymore */
+ ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data);
- if(ctx->pending)
- hsh_free(ctx->pending);
+ if(ctx->pending)
+ hsh_free(ctx->pending);
- if(ctx->established)
- hsh_free(ctx->established);
+ if(ctx->established)
+ hsh_free(ctx->established);
- ha_messagex(LOG_INFO, "ntlm: uninitialized handler");
- }
+ ha_messagex(NULL, LOG_INFO, "uninitialized handler");
+ }
- /* Global Destroy */
- else
- {
- /* Close the mutex */
- pthread_mutex_destroy(&g_smblib_mutex);
- pthread_mutexattr_destroy(&g_smblib_mutexattr);
- }
+ /* Global Destroy */
+ else
+ {
+ /* Close the mutex */
+ pthread_mutex_destroy(&g_smblib_mutex);
+ pthread_mutexattr_destroy(&g_smblib_mutexattr);
+ }
}
-int ntlm_process(const ha_request_t* req, ha_response_t* resp)
+int ntlm_process(ha_request_t* rq)
{
- ntlm_context_t* ctx = (ntlm_context_t*)(req->context->ctx_data);
- void* ntlm_connection_t = NULL;
- unsigned char key[NTLM_HASH_KEY_LEN];
- const char* header = NULL;
- time_t t = time(NULL);
- int ret, r;
+ ntlm_context_t* ctx = (ntlm_context_t*)(rq->context->ctx_data);
+ void* ntlm_connection_t = NULL;
+ unsigned char key[NTLM_HASH_KEY_LEN];
+ const char* header = NULL;
+ time_t t = time(NULL);
+ int ret, r;
- ASSERT(req && resp);
- ASSERT(req->args[AUTH_ARG_CONN]);
+ ASSERT(rq);
+ ASSERT(rq->req_args[AUTH_ARG_CONN]);
- resp->code = -1;
+ rq->resp_code = -1;
- /* Hash the unique key */
- md5_string(key, req->args[AUTH_ARG_CONN]);
+ /* Hash the unique key */
+ md5_string(key, rq->req_args[AUTH_ARG_CONN]);
- ha_lock(NULL);
+ ha_lock(NULL);
- /*
- * Purge out stale connection stuff. This includes
- * authenticated connections which have expired as
- * well as half open connections which expire.
- */
- r = hsh_purge(ctx->pending, t - ctx->pending_timeout);
- r += hsh_purge(ctx->established, t - req->context->cache_timeout);
+ /*
+ * Purge out stale connection stuff. This includes
+ * authenticated connections which have expired as
+ * well as half open connections which expire.
+ */
+ r = hsh_purge(ctx->pending, t - ctx->pending_timeout);
+ r += hsh_purge(ctx->established, t - rq->context->cache_timeout);
- ha_unlock(NULL);
+ ha_unlock(NULL);
- if(r > 0)
- ha_messagex(LOG_DEBUG, "ntlm: purged info from cache: %d", r);
+ if(r > 0)
+ ha_messagex(rq, LOG_DEBUG, "purged info from cache: %d", r);
- /* Look for a NTLM header */
- if(req->context->allowed_types & HA_TYPE_NTLM)
- {
- header = ha_getheader(req, "Authorization", HA_PREFIX_NTLM);
- if(header)
+ /* Look for a NTLM header */
+ if(rq->context->allowed_types & HA_TYPE_NTLM)
{
- /* Trim off for decoding */
- header = trim_start(header);
+ header = ha_getheader(rq, "Authorization", HA_PREFIX_NTLM);
+ if(header)
+ {
+ /* Trim off for decoding */
+ header = trim_start(header);
- ha_messagex(LOG_DEBUG, "ntlm: processing ntlm auth header");
- ret = ntlm_auth_ntlm(ctx, key, header, resp, req->buf);
- if(ret < 0)
- return ret;
+ ha_messagex(rq, LOG_DEBUG, "processing ntlm auth header");
+ ret = ntlm_auth_ntlm(rq, ctx, key, header);
+ if(ret < 0)
+ return ret;
+ }
}
- }
-
- /* If basic is enabled, and no NTLM */
- if(!header && req->context->allowed_types & HA_TYPE_BASIC)
- {
- /* Look for a Basic header */
- header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC);
- if(header)
+
+ /* If basic is enabled, and no NTLM */
+ if(!header && rq->context->allowed_types & HA_TYPE_BASIC)
{
- /* Trim off for decoding */
- header = trim_start(header);
+ /* Look for a Basic header */
+ header = ha_getheader(rq, "Authorization", HA_PREFIX_BASIC);
+ if(header)
+ {
+ /* Trim off for decoding */
+ header = trim_start(header);
- ha_messagex(LOG_DEBUG, "ntlm: processing basic auth header");
- ret = ntlm_auth_basic(ctx, key, header, resp, req->buf);
- if(ret < 0)
- return ret;
+ ha_messagex(rq, LOG_DEBUG, "processing basic auth header");
+ ret = ntlm_auth_basic(rq, ctx, key, header);
+ if(ret < 0)
+ return ret;
+ }
}
- }
- /* The authorization header was not found */
- else
- {
- ha_lock(NULL);
-
- /*
- * NTLM trusts a connection after it's been authenticated
- * so just pass success for those. Note that we do this
- * in the absence of a authorization header so that we
- * allow connections to be re-authenticated.
- */
+ /* The authorization header was not found */
+ else
+ {
+ ha_lock(NULL);
- if(hsh_get(ctx->established, key) == NTLM_ESTABLISHED)
- {
- hsh_touch(ctx->established, key);
- resp->code = HA_SERVER_OK;
- }
+ /*
+ * NTLM trusts a connection after it's been authenticated
+ * so just pass success for those. Note that we do this
+ * in the absence of a authorization header so that we
+ * allow connections to be re-authenticated.
+ */
- ha_unlock(NULL);
+ if(hsh_get(ctx->established, key) == NTLM_ESTABLISHED)
+ {
+ hsh_touch(ctx->established, key);
+ rq->resp_code = HA_SERVER_OK;
+ }
- if(resp->code == HA_SERVER_OK)
- ha_messagex(LOG_NOTICE, "ntlm: validated user against connection cache");
+ ha_unlock(NULL);
- /* TODO: We need to be able to retrieve the user here somehow */
- }
+ if(rq->resp_code == HA_SERVER_OK)
+ ha_messagex(rq, LOG_NOTICE, "validated user against connection cache");
+ /* TODO: We need to be able to retrieve the user here somehow */
+ }
- /* If nobody's set any other response then... */
- if(resp->code != -1)
- {
- /* If authentication failed tell the browser about it */
- resp->code = HA_SERVER_DECLINE;
- if(req->context->allowed_types & HA_TYPE_NTLM)
+ /* If nobody's set any other response then... */
+ if(rq->resp_code != -1)
{
- ha_addheader(resp, "WWW-Authenticate", HA_PREFIX_NTLM);
- ha_messagex(LOG_DEBUG, "ntlm: sent ntlm auth request");
- }
+ /* If authentication failed tell the browser about it */
+ rq->resp_code = HA_SERVER_DECLINE;
- if(req->context->allowed_types & HA_TYPE_BASIC)
- {
- ha_bufmcat(req->buf, HA_PREFIX_BASIC, "realm=\"", req->context->realm, "\"", NULL);
+ if(rq->context->allowed_types & HA_TYPE_NTLM)
+ {
+ ha_addheader(rq, "WWW-Authenticate", HA_PREFIX_NTLM);
+ ha_messagex(rq, LOG_DEBUG, "sent ntlm auth request");
+ }
- if(ha_buferr(req->buf))
- return HA_CRITERROR;
+ if(rq->context->allowed_types & HA_TYPE_BASIC)
+ {
+ ha_bufmcat(rq->buf, HA_PREFIX_BASIC, "realm=\"", rq->context->realm, "\"", NULL);
- ha_addheader(resp, "WWW-Authenticate", ha_bufdata(req->buf));
- ha_messagex(LOG_DEBUG, "ntlm: sent basic auth request");
+ if(ha_buferr(rq->buf))
+ return HA_CRITERROR;
+
+ ha_addheader(rq, "WWW-Authenticate", ha_bufdata(rq->buf));
+ ha_messagex(rq, LOG_DEBUG, "sent basic auth request");
+ }
}
- }
- return ret;
+ return ret;
}
@@ -789,12 +789,12 @@ int ntlm_process(const ha_request_t* req, ha_response_t* resp)
ha_handler_t ntlm_handler =
{
- "NTLM", /* The type */
- ntlm_init, /* Initialization function */
- ntlm_destroy, /* Uninitialization routine */
- ntlm_config, /* Config routine */
- ntlm_process, /* Processing routine */
- &ntlm_defaults, /* Default settings */
- sizeof(ntlm_context_t)
+ "NTLM", /* The type */
+ ntlm_init, /* Initialization function */
+ ntlm_destroy, /* Uninitialization routine */
+ ntlm_config, /* Config routine */
+ ntlm_process, /* Processing routine */
+ &ntlm_defaults, /* Default settings */
+ sizeof(ntlm_context_t)
};
diff --git a/daemon/simple.c b/daemon/simple.c
index d570a25..bda60c3 100644
--- a/daemon/simple.c
+++ b/daemon/simple.c
@@ -20,17 +20,17 @@
typedef struct simple_context
{
- /* Base Handler ------------------------------------------------------ */
- bd_context_t bd;
+ /* Base Handler ------------------------------------------------------ */
+ bd_context_t bd;
- /* Settings ---------------------------------------------------------- */
- const char* filename; /* The file name with the user names */
+ /* Settings ---------------------------------------------------------- */
+ const char* filename; /* The file name with the user names */
}
simple_context_t;
/* Forward declarations for callbacks */
-static int complete_digest(const ha_request_t* req, const char* user, unsigned char* ha1);
-static int validate_basic(const ha_request_t* req, const char* user, const char* password);
+static int complete_digest(ha_request_t* rq, const char* user, unsigned char* ha1);
+static int validate_basic(ha_request_t* rq, const char* user, const char* password);
/* The defaults for the context */
static const simple_context_t simple_defaults =
@@ -43,9 +43,9 @@ static const simple_context_t simple_defaults =
* Internal Functions
*/
-static int complete_digest(const ha_request_t* req, const char* user, unsigned char* ha1)
+static int complete_digest(ha_request_t* rq, const char* user, unsigned char* ha1)
{
- simple_context_t* ctx = (simple_context_t*)req->context->ctx_data;
+ simple_context_t* ctx = (simple_context_t*)rq->context->ctx_data;
FILE* f;
char* t;
char* t2;
@@ -53,13 +53,13 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
char line[SIMPLE_MAXLINE];
int ret = HA_FALSE;
- ASSERT(ctx && req && user && user[0]);
- ha_messagex(LOG_DEBUG, "searching password file for user's ha1: %s", user);
+ ASSERT(ctx && rq && user && user[0]);
+ ha_messagex(rq, LOG_DEBUG, "searching password file for user's ha1: %s", user);
f = fopen(ctx->filename, "r");
if(!f)
{
- ha_message(LOG_ERR, "simple: can't open file for basic auth: %s", ctx->filename);
+ ha_message(rq, LOG_ERR, "can't open file for basic auth: %s", ctx->filename);
return HA_FAILED;
}
@@ -75,7 +75,7 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
if(ferror(f))
{
- ha_message(LOG_ERR, "simple: error reading basic password file");
+ ha_message(rq, LOG_ERR, "error reading basic password file");
ret = HA_FAILED;
break;
}
@@ -98,15 +98,15 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
t2++;
/* Check the realm */
- if(strcmp(t, req->context->realm) == 0)
+ if(strcmp(t, rq->context->realm) == 0)
{
len = MD5_LEN;
/* Now try and decode the ha1 */
- t = ha_bufdechex(req->buf, t2, &len);
+ t = ha_bufdechex(rq->buf, t2, &len);
if(t && len == MD5_LEN)
{
- ha_messagex(LOG_DEBUG, "simple: found ha1 for user: %s", user);
+ ha_messagex(rq, LOG_DEBUG, "found ha1 for user: %s", user);
memcpy(ha1, t, MD5_LEN);
ret = HA_OK;
break;
@@ -115,22 +115,22 @@ static int complete_digest(const ha_request_t* req, const char* user, unsigned c
}
if(!t2 || ret != HA_OK)
- ha_messagex(LOG_WARNING, "simple: user '%s' found in file, but password not in digest format", user);
+ ha_messagex(rq, LOG_WARNING, "user '%s' found in file, but password not in digest format", user);
}
}
}
fclose(f);
- if(ha_buferr(req->buf))
+ if(ha_buferr(rq->buf))
return HA_CRITERROR;
return ret;
}
-static int validate_basic(const ha_request_t* req, const char* user, const char* password)
+static int validate_basic(ha_request_t* rq, const char* user, const char* password)
{
- simple_context_t* ctx = (simple_context_t*)req->context->ctx_data;
+ simple_context_t* ctx = (simple_context_t*)rq->context->ctx_data;
FILE* f;
char line[SIMPLE_MAXLINE];
unsigned char ha1[MD5_LEN];
@@ -139,18 +139,18 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
size_t len;
int ret = HA_FALSE;
- ASSERT(ctx && req);
+ ASSERT(ctx && rq);
ASSERT(user && user[0] && password);
- ha_messagex(LOG_DEBUG, "simple: validating user against password file: %s", user);
+ ha_messagex(rq, LOG_DEBUG, "validating user against password file: %s", user);
f = fopen(ctx->filename, "r");
if(!f)
{
- ha_message(LOG_ERR, "simple: can't open file for basic auth: %s", ctx->filename);
+ ha_message(rq, LOG_ERR, "can't open file for basic auth: %s", ctx->filename);
return HA_FAILED;
}
- digest_makeha1(ha1, user, req->context->realm, password);
+ digest_makeha1(ha1, user, rq->context->realm, password);
/*
* Note: There should be no returns or jumps between
@@ -164,7 +164,7 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
if(ferror(f))
{
- ha_message(LOG_ERR, "simple: error reading basic password file");
+ ha_message(rq, LOG_ERR, "error reading basic password file");
ret = HA_FAILED;
break;
}
@@ -192,7 +192,7 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
if(strcmp(t2, t) == 0)
{
- ha_messagex(LOG_DEBUG, "simple: found valid crypt password for user: %s", user);
+ ha_messagex(rq, LOG_DEBUG, "found valid crypt password for user: %s", user);
ret = HA_OK;
break;
}
@@ -205,22 +205,22 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
t2++;
/* Check the realm */
- if(strcmp(t, req->context->realm) == 0)
+ if(strcmp(t, rq->context->realm) == 0)
{
len = MD5_LEN;
/* Now try antd decode the ha1 */
- t = ha_bufdechex(req->buf, t2, &len);
+ t = ha_bufdechex(rq->buf, t2, &len);
if(t && len == MD5_LEN && memcmp(ha1, t, MD5_LEN) == 0)
{
- ha_messagex(LOG_DEBUG, "simple: found valid ha1 for user: %s", user);
+ ha_messagex(rq, LOG_DEBUG, "found valid ha1 for user: %s", user);
ret = HA_OK;
break;
}
}
}
- if(ha_buferr(req->buf))
+ if(ha_buferr(rq->buf))
break;
}
}
@@ -228,7 +228,7 @@ static int validate_basic(const ha_request_t* req, const char* user, const char*
fclose(f);
- if(ha_buferr(req->buf))
+ if(ha_buferr(rq->buf))
return HA_CRITERROR;
return ret;
@@ -270,21 +270,21 @@ int simple_init(ha_context_t* context)
/* Check to make sure the file exists */
if(!ctx->filename)
{
- ha_messagex(LOG_ERR, "simple: configuration incomplete. "
- "Must have a PasswordFile configured.");
+ ha_messagex(NULL, LOG_ERR, "configuration incomplete. "
+ "Must have a PasswordFile configured.");
return HA_FAILED;
}
fd = open(ctx->filename, O_RDONLY);
if(fd == -1)
{
- ha_message(LOG_ERR, "simple: can't open file for authentication: %s", ctx->filename);
+ ha_message(NULL, LOG_ERR, "can't open file for authentication: %s", ctx->filename);
return HA_FAILED;
}
close(fd);
- ha_messagex(LOG_INFO, "simple: initialized handler");
+ ha_messagex(NULL, LOG_INFO, "initialized simple handler");
}
return HA_OK;
@@ -297,12 +297,12 @@ int simple_init(ha_context_t* context)
ha_handler_t simple_handler =
{
- "SIMPLE", /* The type */
- simple_init, /* Initialization function */
- bd_destroy, /* Uninitialization routine */
- simple_config, /* Config routine */
- bd_process, /* Processing routine */
- NULL, /* A default context */
- sizeof(simple_context_t) /* Size of the context */
+ "SIMPLE", /* The type */
+ simple_init, /* Initialization function */
+ bd_destroy, /* Uninitialization routine */
+ simple_config, /* Config routine */
+ bd_process, /* Processing routine */
+ NULL, /* A default context */
+ sizeof(simple_context_t) /* Size of the context */
};
diff --git a/daemon/usuals.h b/daemon/usuals.h
index e14ecf5..97d355b 100644
--- a/daemon/usuals.h
+++ b/daemon/usuals.h
@@ -29,10 +29,10 @@
#define countof(x) (sizeof(x) / sizeof(x[0]))
#ifdef _DEBUG
- #include "assert.h"
- #define ASSERT assert
+ #include "assert.h"
+ #define ASSERT assert
#else
- #define ASSERT
+ #define ASSERT
#endif
#endif /* __USUALS_H__ */