summaryrefslogtreecommitdiff
path: root/daemon/simple.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/simple.c')
-rw-r--r--daemon/simple.c143
1 files changed, 76 insertions, 67 deletions
diff --git a/daemon/simple.c b/daemon/simple.c
index 4c7fb28..5b4eb60 100644
--- a/daemon/simple.c
+++ b/daemon/simple.c
@@ -25,18 +25,12 @@ unsigned char g_simple_secret[DIGEST_SECRET_LEN];
typedef struct simple_context
{
+ /* Settings ----------------------------------------------------------- */
const char* filename; /* The file name with the user names */
- const char* realm; /* The realm for basic authentication */
- const char* domains; /* Domains for which digest auth is valid */
- int cache_max; /* Maximum number of connections at once */
- int cache_timeout;
+ ha_options_t* opts; /* Options from httpauthd.c */
/* Context ----------------------------------------------------------- */
hash_t* cache; /* Some cached records or basic */
-
-#ifdef _DEBUG
- const char* debug_nonce;
-#endif
}
simple_context_t;
@@ -57,7 +51,7 @@ static digest_record_t* get_cached_digest(simple_context_t* ctx, unsigned char*
ASSERT(ctx && nonce);
- if(ctx->cache_max == 0)
+ if(ctx->opts->cache_max == 0)
return NULL;
ha_lock(NULL);
@@ -95,7 +89,7 @@ static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec)
ASSERT(ctx && rec);
- if(ctx->cache_max == 0)
+ if(ctx->opts->cache_max == 0)
{
free_hash_object(NULL, rec);
return HA_FALSE;
@@ -103,7 +97,7 @@ static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec)
ha_lock(NULL);
- while(hash_count(ctx->cache) >= ctx->cache_max)
+ while(hash_count(ctx->cache) >= ctx->opts->cache_max)
hash_bump(ctx->cache);
r = hash_set(ctx->cache, rec->nonce, rec);
@@ -126,12 +120,12 @@ static int add_cached_basic(simple_context_t* ctx, unsigned char* key)
ASSERT(ctx && key);
- if(ctx->cache_max == 0)
+ if(ctx->opts->cache_max == 0)
return HA_FALSE;
ha_lock(NULL);
- while(hash_count(ctx->cache) >= ctx->cache_max)
+ while(hash_count(ctx->cache) >= ctx->opts->cache_max)
hash_bump(ctx->cache);
r = hash_set(ctx->cache, key, BASIC_ESTABLISHED);
@@ -158,11 +152,12 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec,
int ret = HA_FALSE;
ASSERT(ctx && rec && buf && user && user[0]);
+ ha_messagex(LOG_DEBUG, "searching password file for user's ha1: %s", user);
f = fopen(ctx->filename, "r");
if(!f)
{
- ha_message(LOG_ERR, "can't open file for basic auth: %s", ctx->filename);
+ ha_message(LOG_ERR, "simple: can't open file for basic auth: %s", ctx->filename);
return HA_FAILED;
}
@@ -178,7 +173,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec,
if(ferror(f))
{
- ha_message(LOG_ERR, "error reading basic password file");
+ ha_message(LOG_ERR, "simple: error reading basic password file");
ret = HA_FAILED;
break;
}
@@ -201,7 +196,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec,
t2++;
/* Check the realm */
- if(strcmp(t, ctx->realm) == 0)
+ if(strcmp(t, ctx->opts->realm) == 0)
{
len = MD5_LEN;
@@ -209,6 +204,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec,
t = ha_bufdechex(buf, t2, &len);
if(t && len == MD5_LEN)
{
+ ha_messagex(LOG_DEBUG, "simple: found ha1 for user: %s", user);
memcpy(rec->ha1, t, MD5_LEN);
ret = HA_OK;
break;
@@ -217,7 +213,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec,
}
if(!t2 || ret != HA_OK)
- ha_messagex(LOG_WARNING, "user '%s' found in file, but password not in digest format", user);
+ ha_messagex(LOG_WARNING, "simple: user '%s' found in file, but password not in digest format", user);
}
}
}
@@ -243,15 +239,16 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf,
ASSERT(ctx && buf);
ASSERT(user && user[0] && clearpw);
+ ha_messagex(LOG_DEBUG, "simple: validating user against password file: %s", user);
f = fopen(ctx->filename, "r");
if(!f)
{
- ha_message(LOG_ERR, "can't open file for basic auth: %s", ctx->filename);
+ ha_message(LOG_ERR, "simple: can't open file for basic auth: %s", ctx->filename);
return HA_FAILED;
}
- digest_makeha1(ha1, user, ctx->realm, clearpw);
+ digest_makeha1(ha1, user, ctx->opts->realm, clearpw);
/*
* Note: There should be no returns or jumps between
@@ -265,7 +262,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf,
if(ferror(f))
{
- ha_message(LOG_ERR, "error reading basic password file");
+ ha_message(LOG_ERR, "simple: error reading basic password file");
ret = HA_FAILED;
break;
}
@@ -298,6 +295,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf,
if(strcmp(crypt(clearpw, t), t) == 0)
{
+ ha_messagex(LOG_DEBUG, "simple: found valid crypt password for user: %s", user);
ret = HA_OK;
break;
}
@@ -310,7 +308,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf,
t2++;
/* Check the realm */
- if(strcmp(t, ctx->realm) == 0)
+ if(strcmp(t, ctx->opts->realm) == 0)
{
len = MD5_LEN;
@@ -318,6 +316,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf,
t = ha_bufdechex(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);
ret = HA_OK;
break;
}
@@ -356,6 +355,7 @@ static int simple_basic_response(simple_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, "simple: validated basic user against cache: %s", basic.user);
found = 1;
ret = HA_OK;
goto finally;
@@ -369,9 +369,15 @@ static int simple_basic_response(simple_context_t* ctx, const char* header,
ret = validate_user_password(ctx, buf, basic.user, basic.password);
+ if(ret == HA_OK)
+ ha_messagex(LOG_NOTICE, "simple: validated basic user against file: %s", basic.user);
+
+ else
+ ha_messagex(LOG_WARNING, "simple: basic authentication failed for user: %s", basic.user);
+
finally:
- if(ret = HA_OK)
+ if(ret == HA_OK)
{
resp->code = HA_SERVER_ACCEPT;
resp->detail = basic.user;
@@ -384,7 +390,7 @@ finally:
}
static int simple_digest_challenge(simple_context_t* ctx, ha_response_t* resp,
- ha_buffer_t* buf, int stale)
+ ha_buffer_t* buf, int stale)
{
const char* nonce_str;
const char* header;
@@ -394,10 +400,10 @@ static int simple_digest_challenge(simple_context_t* ctx, ha_response_t* resp,
/* Generate an nonce */
#ifdef _DEBUG
- if(ctx->debug_nonce)
+ if(ctx->opts->digest_debugnonce)
{
- nonce_str = ctx->debug_nonce;
- ha_messagex(LOG_WARNING, "using debug nonce. security non-existant.");
+ nonce_str = ctx->opts->digest_debugnonce;
+ ha_messagex(LOG_WARNING, "simple: using debug nonce. security non-existant.");
}
else
#endif
@@ -412,7 +418,8 @@ static int simple_digest_challenge(simple_context_t* ctx, ha_response_t* resp,
/* Now generate a message to send */
- header = digest_challenge(buf, nonce_str, ctx->realm, ctx->domains, stale);
+ header = digest_challenge(buf, nonce_str, ctx->opts->realm,
+ ctx->opts->digest_domains, stale);
if(!header)
return HA_CRITERROR;
@@ -421,6 +428,7 @@ static int simple_digest_challenge(simple_context_t* ctx, ha_response_t* resp,
resp->code = HA_SERVER_DECLINE;
ha_addheader(resp, "WWW-Authenticate", header);
+ ha_messagex(LOG_DEBUG, "simple: created digest challenge with nonce: %s", nonce_str);
return HA_OK;
}
@@ -446,18 +454,18 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
return r;
#ifdef _DEBUG
- if(ctx->debug_nonce)
+ if(ctx->opts->digest_debugnonce)
{
- if(dg.nonce && strcmp(dg.nonce, ctx->debug_nonce) != 0)
+ if(dg.nonce && strcmp(dg.nonce, ctx->opts->digest_debugnonce) != 0)
{
resp->code = HA_SERVER_BADREQ;
ret = HA_FALSE;
- ha_messagex(LOG_WARNING, "digest response contains invalid nonce");
+ ha_messagex(LOG_WARNING, "simple: digest response contains invalid nonce");
goto finally;
}
/* Do a rough hash into the real nonce, for use as a key */
- md5_string(nonce, ctx->debug_nonce);
+ md5_string(nonce, ctx->opts->digest_debugnonce);
/* Debug nonce's never expire */
expiry = time(NULL);
@@ -471,7 +479,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
if(r == HA_FALSE)
{
resp->code = HA_SERVER_BADREQ;
- ha_messagex(LOG_WARNING, "digest response contains invalid nonce");
+ ha_messagex(LOG_WARNING, "simple: digest response contains invalid nonce");
}
ret = r;
@@ -482,14 +490,19 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
rec = get_cached_digest(ctx, nonce);
/* Check to see if we're stale */
- if((expiry + ctx->cache_timeout) <= time(NULL))
+ if((expiry + ctx->opts->cache_timeout) <= time(NULL))
{
+ ha_messagex(LOG_INFO, "simple: nonce expired, sending stale challenge: %s",
+ dg.username);
+
stale = 1;
goto finally;
}
if(!rec)
{
+ ha_messagex(LOG_INFO, "simple: no record in cache, creating one: %s", dg.username);
+
/*
* If we're valid but don't have a record in the
* cache then complete the record properly.
@@ -513,7 +526,8 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
/* Increment our nonce count */
rec->nc++;
- ret = digest_check(ctx->realm, method, uri, buf, &dg, rec);
+ ret = digest_check(ctx->opts->realm, method,
+ ctx->opts->digest_ignoreuri ? NULL : uri, buf, &dg, rec);
if(ret == HA_BADREQ)
{
@@ -527,8 +541,12 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
resp->detail = dg.username;
/* Figure out if we need a new nonce */
- if((expiry + (ctx->cache_timeout - (ctx->cache_timeout / 8))) < time(NULL))
+ if((expiry + (ctx->opts->cache_timeout -
+ (ctx->opts->cache_timeout / 8))) < time(NULL))
{
+ ha_messagex(LOG_INFO, "simple: nonce almost expired, creating new one: %s",
+ dg.username);
+
digest_makenonce(nonce, g_simple_secret, NULL);
stale = 1;
}
@@ -543,6 +561,8 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
if(t[0])
ha_addheader(resp, "Authentication-Info", t);
+ ha_messagex(LOG_NOTICE, "simple: validated digest user: %s", dg.username);
+
/* Put the connection into the cache */
if((r = save_cached_digest(ctx, rec)) < 0)
ret = r;
@@ -580,26 +600,6 @@ int simple_config(ha_context_t* context, const char* name, const char* value)
return HA_OK;
}
- else if(strcmp(name, "realm") == 0)
- {
- ctx->realm = value;
- return HA_OK;
- }
-
- else if(strcmp(name, "digestdomains") == 0)
- {
- ctx->domains = value;
- return HA_OK;
- }
-
-#ifdef _DEBUG
- else if(strcmp(name, "digestdebugnonce") == 0)
- {
- ctx->debug_nonce = value;
- return HA_OK;
- }
-#endif
-
return HA_FALSE;
}
@@ -608,6 +608,7 @@ int simple_init(ha_context_t* context)
/* Global initialization */
if(!context)
{
+ ha_messagex(LOG_DEBUG, "simple: generating secret");
return ha_genrandom(g_simple_secret, DIGEST_SECRET_LEN);
}
@@ -620,9 +621,9 @@ int simple_init(ha_context_t* context)
ASSERT(ctx);
/* Make sure there are some types of authentication we can do */
- if(!(context->types & (HA_TYPE_BASIC | HA_TYPE_DIGEST)))
+ if(!(context->opts.types & (HA_TYPE_BASIC | HA_TYPE_DIGEST)))
{
- ha_messagex(LOG_ERR, "Simple module configured, but does not implement any "
+ ha_messagex(LOG_ERR, "simple: module configured, but does not implement any "
"configured authentication type.");
return HA_FAILED;
}
@@ -631,7 +632,7 @@ int simple_init(ha_context_t* context)
/* Check to make sure the file exists */
if(!ctx->filename)
{
- ha_messagex(LOG_ERR, "Basic configuration incomplete. "
+ ha_messagex(LOG_ERR, "simple: configuration incomplete. "
"Must have a PasswordFile configured.");
return HA_FAILED;
}
@@ -639,7 +640,7 @@ int simple_init(ha_context_t* context)
fd = open(ctx->filename, O_RDONLY);
if(fd == -1)
{
- ha_message(LOG_ERR, "can't open file for simple authentication: %s", ctx->filename);
+ ha_message(LOG_ERR, "simple: can't open file for authentication: %s", ctx->filename);
return HA_FAILED;
}
@@ -655,9 +656,9 @@ int simple_init(ha_context_t* context)
}
/* Copy some settings over for easy access */
- ctx->cache_max = context->cache_max;
- ctx->cache_timeout = context->cache_timeout;
+ ctx->opts = &(context->opts);
+ ha_messagex(LOG_INFO, "simple: initialized handler");
}
return HA_OK;
@@ -673,6 +674,8 @@ void simple_destroy(ha_context_t* context)
if(ctx->cache)
hash_free(ctx->cache);
+
+ ha_messagex(LOG_INFO, "simple: uninitialized handler");
}
}
@@ -684,6 +687,7 @@ int simple_process(ha_context_t* context, ha_request_t* req,
int ret = HA_FALSE;
int found = 0;
basic_header_t basic;
+ int r;
ASSERT(context && req && resp && buf);
ASSERT(req->args[AUTH_ARG_METHOD]);
@@ -692,21 +696,24 @@ int simple_process(ha_context_t* context, ha_request_t* req,
ha_lock(NULL);
/* Purge the cache */
- hash_purge(ctx->cache, time(NULL) - ctx->cache_timeout);
+ r = hash_purge(ctx->cache, time(NULL) - ctx->opts->cache_timeout);
ha_unlock(NULL);
+ if(r > 0)
+ ha_messagex(LOG_DEBUG, "simple: purged cache records: %d", r);
/* We use this below to detect whether to send a default response */
resp->code = -1;
/* Check the headers and see if we got a response thingy */
- if(context->types & HA_TYPE_DIGEST)
+ if(context->opts.types & HA_TYPE_DIGEST)
{
header = ha_getheader(req, "Authorization", HA_PREFIX_DIGEST);
if(header)
{
+ ha_messagex(LOG_DEBUG, "simple: processing digest auth header");
ret = simple_digest_response(ctx, header, req->args[AUTH_ARG_METHOD],
req->args[AUTH_ARG_URI], resp, buf);
if(ret < 0)
@@ -715,8 +722,9 @@ int simple_process(ha_context_t* context, ha_request_t* req,
}
/* Or a basic authentication */
- if(!header && context->types & HA_TYPE_BASIC)
+ if(!header && context->opts.types & HA_TYPE_BASIC)
{
+ ha_messagex(LOG_DEBUG, "simple: processing basic auth header");
header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC);
if(header)
{
@@ -732,17 +740,18 @@ int simple_process(ha_context_t* context, ha_request_t* req,
{
resp->code = HA_SERVER_DECLINE;
- if(context->types & HA_TYPE_BASIC)
+ if(context->opts.types & HA_TYPE_BASIC)
{
- ha_bufmcat(buf, "BASIC realm=\"", ctx->realm , "\"", NULL);
+ ha_bufmcat(buf, "BASIC realm=\"", ctx->opts->realm , "\"", NULL);
if(ha_buferr(buf))
return HA_CRITERROR;
ha_addheader(resp, "WWW-Authenticate", ha_bufdata(buf));
+ ha_messagex(LOG_DEBUG, "simple: sent basic auth request");
}
- if(context->types & HA_TYPE_DIGEST)
+ if(context->opts.types & HA_TYPE_DIGEST)
{
ret = simple_digest_challenge(ctx, resp, buf, 0);
if(ret < 0)