From 80b0e2c0fdad108454ae87130496f595f0b81b81 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 7 May 2004 22:02:29 +0000 Subject: - Reworked the internal API - Added common functions for trimming - Debugging - Reworked the module to the new protocol --- daemon/simple.c | 151 +++++++++++++++++++++++++++----------------------------- 1 file changed, 72 insertions(+), 79 deletions(-) (limited to 'daemon/simple.c') diff --git a/daemon/simple.c b/daemon/simple.c index 7165c9c..8059051 100644 --- a/daemon/simple.c +++ b/daemon/simple.c @@ -27,7 +27,6 @@ typedef struct simple_context { /* Settings ----------------------------------------------------------- */ const char* filename; /* The file name with the user names */ - const ha_context_opts_t* opts; /* Options from httpauthd.c */ /* Context ----------------------------------------------------------- */ hash_t* cache; /* Some cached records or basic */ @@ -45,13 +44,14 @@ static void free_hash_object(void* arg, void* val) free(val); } -static digest_record_t* get_cached_digest(simple_context_t* ctx, unsigned char* nonce) +static digest_record_t* get_cached_digest(simple_context_t* ctx, ha_context_t* c, + unsigned char* nonce) { digest_record_t* rec; - ASSERT(ctx && nonce); + ASSERT(ctx && c && nonce); - if(ctx->opts->cache_max == 0) + if(c->cache_max == 0) return NULL; ha_lock(NULL); @@ -83,13 +83,14 @@ static int have_cached_basic(simple_context_t* ctx, unsigned char* key) return ret; } -static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec) +static int save_cached_digest(simple_context_t* ctx, ha_context_t* c, + digest_record_t* rec) { int r; - ASSERT(ctx && rec); + ASSERT(ctx && c && rec); - if(ctx->opts->cache_max == 0) + if(c->cache_max == 0) { free_hash_object(NULL, rec); return HA_FALSE; @@ -97,7 +98,7 @@ static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec) ha_lock(NULL); - while(hash_count(ctx->cache) >= ctx->opts->cache_max) + while(hash_count(ctx->cache) >= c->cache_max) hash_bump(ctx->cache); r = hash_set(ctx->cache, rec->nonce, rec); @@ -114,18 +115,19 @@ static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec) return HA_OK; } -static int add_cached_basic(simple_context_t* ctx, unsigned char* key) +static int add_cached_basic(simple_context_t* ctx, ha_context_t* c, + unsigned char* key) { int r; - ASSERT(ctx && key); + ASSERT(ctx && c && key); - if(ctx->opts->cache_max == 0) + if(c->cache_max == 0) return HA_FALSE; ha_lock(NULL); - while(hash_count(ctx->cache) >= ctx->opts->cache_max) + while(hash_count(ctx->cache) >= c->cache_max) hash_bump(ctx->cache); r = hash_set(ctx->cache, key, BASIC_ESTABLISHED); @@ -142,7 +144,7 @@ static int add_cached_basic(simple_context_t* ctx, unsigned char* key) } static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, - ha_buffer_t* buf, const char* user) + const ha_request_t* req, const char* user) { FILE* f; char* t; @@ -151,7 +153,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, char line[SIMPLE_MAXLINE]; int ret = HA_FALSE; - ASSERT(ctx && rec && buf && user && user[0]); + ASSERT(ctx && rec && req && user && user[0]); ha_messagex(LOG_DEBUG, "searching password file for user's ha1: %s", user); f = fopen(ctx->filename, "r"); @@ -196,12 +198,12 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, t2++; /* Check the realm */ - if(strcmp(t, ctx->opts->realm) == 0) + if(strcmp(t, req->context->realm) == 0) { len = MD5_LEN; /* Now try antd decode the ha1 */ - t = ha_bufdechex(buf, t2, &len); + t = ha_bufdechex(req->buf, t2, &len); if(t && len == MD5_LEN) { ha_messagex(LOG_DEBUG, "simple: found ha1 for user: %s", user); @@ -220,13 +222,13 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, fclose(f); - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) return HA_CRITERROR; return ret; } -static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, +static int validate_user_password(simple_context_t* ctx, const ha_request_t* req, const char* user, const char* clearpw) { FILE* f; @@ -237,7 +239,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, size_t len; int ret = HA_FALSE; - ASSERT(ctx && buf); + ASSERT(ctx && req); ASSERT(user && user[0] && clearpw); ha_messagex(LOG_DEBUG, "simple: validating user against password file: %s", user); @@ -248,7 +250,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, return HA_FAILED; } - digest_makeha1(ha1, user, ctx->opts->realm, clearpw); + digest_makeha1(ha1, user, req->context->realm, clearpw); /* * Note: There should be no returns or jumps between @@ -268,12 +270,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, } /* Take white space off end of line */ - t = line + strlen(line); - while(t != line && isspace(*(t - 1))) - { - *(t - 1) = 0; - t--; - } + trim_end(line); t = strchr(line, ':'); if(t) @@ -308,12 +305,12 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, t2++; /* Check the realm */ - if(strcmp(t, ctx->opts->realm) == 0) + if(strcmp(t, req->context->realm) == 0) { len = MD5_LEN; /* Now try antd decode the ha1 */ - t = ha_bufdechex(buf, t2, &len); + t = ha_bufdechex(req->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); @@ -323,7 +320,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, } } - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) break; } } @@ -331,23 +328,23 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, fclose(f); - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) return HA_CRITERROR; return ret; } static int simple_basic_response(simple_context_t* ctx, const char* header, - ha_response_t* resp, ha_buffer_t* buf) + const ha_request_t* req, ha_response_t* resp) { basic_header_t basic; int ret = HA_FALSE; int found = 0; int r; - ASSERT(buf && header && resp && buf); + ASSERT(header && req && resp); - if((r = basic_parse(header, buf, &basic)) < 0) + if((r = basic_parse(header, req->buf, &basic)) < 0) return r; /* Past this point we don't return directly */ @@ -367,7 +364,7 @@ static int simple_basic_response(simple_context_t* ctx, const char* header, goto finally; - ret = validate_user_password(ctx, buf, basic.user, basic.password); + ret = validate_user_password(ctx, req, basic.user, basic.password); if(ret == HA_OK) ha_messagex(LOG_NOTICE, "simple: validated basic user against file: %s", basic.user); @@ -383,26 +380,26 @@ finally: resp->detail = basic.user; /* We put this connection into the successful connections */ - ret = add_cached_basic(ctx, basic.key); + ret = add_cached_basic(ctx, req->context, basic.key); } return ret; } static int simple_digest_challenge(simple_context_t* ctx, const ha_request_t* req, - ha_response_t* resp, ha_buffer_t* buf, int stale) + ha_response_t* resp, int stale) { const char* nonce_str; const char* header; - ASSERT(ctx && resp && buf); + ASSERT(ctx && req && resp); /* Generate an nonce */ #ifdef _DEBUG - if(ctx->opts->digest_debugnonce) + if(req->context->digest_debugnonce) { - nonce_str = ctx->opts->digest_debugnonce; + nonce_str = req->context->digest_debugnonce; ha_messagex(LOG_WARNING, "simple: using debug nonce. security non-existant."); } else @@ -411,15 +408,15 @@ static int simple_digest_challenge(simple_context_t* ctx, const ha_request_t* re unsigned char nonce[DIGEST_NONCE_LEN]; digest_makenonce(nonce, g_simple_secret, NULL); - nonce_str = ha_bufenchex(buf, nonce, DIGEST_NONCE_LEN); + nonce_str = ha_bufenchex(req->buf, nonce, DIGEST_NONCE_LEN); if(!nonce_str) return HA_CRITERROR; } /* Now generate a message to send */ - header = digest_challenge(buf, nonce_str, ctx->opts->realm, - req->opts->digest_domains, stale); + header = digest_challenge(req->buf, nonce_str, req->context->realm, + req->digest_domain, stale); if(!header) return HA_CRITERROR; @@ -433,7 +430,7 @@ static int simple_digest_challenge(simple_context_t* ctx, const ha_request_t* re } static int simple_digest_response(simple_context_t* ctx, const char* header, - const ha_request_t* req, ha_response_t* resp, ha_buffer_t* buf) + const ha_request_t* req, ha_response_t* resp) { unsigned char nonce[DIGEST_NONCE_LEN]; digest_header_t dg; @@ -444,18 +441,18 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, int stale = 0; int r; - ASSERT(ctx && header && req && resp && buf); + ASSERT(ctx && header && req && resp); /* We use this below to send a default response */ resp->code = -1; - if((r = digest_parse(header, buf, &dg, nonce)) < 0) + if((r = digest_parse(header, req->buf, &dg, nonce)) < 0) return r; #ifdef _DEBUG - if(ctx->opts->digest_debugnonce) + if(req->context->digest_debugnonce) { - if(dg.nonce && strcmp(dg.nonce, ctx->opts->digest_debugnonce) != 0) + if(dg.nonce && strcmp(dg.nonce, req->context->digest_debugnonce) != 0) { ret = HA_FALSE; ha_messagex(LOG_WARNING, "simple: digest response contains invalid nonce"); @@ -463,7 +460,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, } /* Do a rough hash into the real nonce, for use as a key */ - md5_string(nonce, ctx->opts->digest_debugnonce); + md5_string(nonce, req->context->digest_debugnonce); /* Debug nonce's never expire */ expiry = time(NULL); @@ -482,10 +479,10 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, } } - rec = get_cached_digest(ctx, nonce); + rec = get_cached_digest(ctx, req->context, nonce); /* Check to see if we're stale */ - if((expiry + ctx->opts->cache_timeout) <= time(NULL)) + if((expiry + req->context->cache_timeout) <= time(NULL)) { ha_messagex(LOG_INFO, "simple: nonce expired, sending stale challenge: %s", dg.username); @@ -510,7 +507,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, goto finally; } - r = complete_digest_ha1(ctx, rec, buf, dg.username); + r = complete_digest_ha1(ctx, rec, req, dg.username); if(r != HA_OK) { ret = r; @@ -524,7 +521,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, rec->nc++; } - ret = digest_check(&dg, rec, ctx->opts, buf, + ret = digest_check(&dg, rec, req->context, req->buf, req->args[AUTH_ARG_METHOD], req->args[AUTH_ARG_URI]); if(ret == HA_BADREQ) @@ -539,8 +536,8 @@ 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->opts->cache_timeout - - (ctx->opts->cache_timeout / 8))) < time(NULL)) + if((expiry + (req->context->cache_timeout - + (req->context->cache_timeout / 8))) < time(NULL)) { ha_messagex(LOG_INFO, "simple: nonce almost expired, creating new one: %s", dg.username); @@ -549,7 +546,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, stale = 1; } - t = digest_respond(buf, &dg, rec, stale ? nonce : NULL); + t = digest_respond(req->buf, &dg, rec, stale ? nonce : NULL); if(!t) { ret = HA_CRITERROR; @@ -562,7 +559,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, 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) + if((r = save_cached_digest(ctx, req->context, rec)) < 0) ret = r; rec = NULL; @@ -576,7 +573,7 @@ finally: /* If nobody above responded then challenge the client again */ if(resp->code == -1) - return simple_digest_challenge(ctx, req, resp, buf, stale); + return simple_digest_challenge(ctx, req, resp, stale); return ret; } @@ -588,7 +585,7 @@ finally: int simple_config(ha_context_t* context, const char* name, const char* value) { - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(context->ctx_data); ASSERT(name && name[0] && value && value[0]); @@ -613,13 +610,13 @@ int simple_init(ha_context_t* context) /* Context specific initialization */ else { - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(context->ctx_data); int fd; ASSERT(ctx); /* Make sure there are some types of authentication we can do */ - if(!(context->opts->types & (HA_TYPE_BASIC | HA_TYPE_DIGEST))) + if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_DIGEST))) { ha_messagex(LOG_ERR, "simple: module configured, but does not implement any " "configured authentication type."); @@ -653,9 +650,6 @@ int simple_init(ha_context_t* context) return HA_CRITERROR; } - /* Copy some settings over for easy access */ - ctx->opts = context->opts; - ha_messagex(LOG_INFO, "simple: initialized handler"); } @@ -668,7 +662,7 @@ void simple_destroy(ha_context_t* context) if(context) { /* Note: We don't need to be thread safe here anymore */ - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(context->ctx_data); if(ctx->cache) hash_free(ctx->cache); @@ -677,24 +671,23 @@ void simple_destroy(ha_context_t* context) } } -int simple_process(ha_context_t* context, const ha_request_t* req, - ha_response_t* resp, ha_buffer_t* buf) +int simple_process(const ha_request_t* req, ha_response_t* resp) { - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(req->context->ctx_data); const char* header = NULL; int ret = HA_FALSE; int found = 0; basic_header_t basic; int r; - ASSERT(context && req && resp && buf); + ASSERT(req && resp); ASSERT(req->args[AUTH_ARG_METHOD]); ASSERT(req->args[AUTH_ARG_URI]); ha_lock(NULL); /* Purge the cache */ - r = hash_purge(ctx->cache, time(NULL) - ctx->opts->cache_timeout); + r = hash_purge(ctx->cache, time(NULL) - req->context->cache_timeout); ha_unlock(NULL); @@ -706,26 +699,26 @@ int simple_process(ha_context_t* context, const ha_request_t* req, /* Check the headers and see if we got a response thingy */ - if(context->opts->types & HA_TYPE_DIGEST) + if(req->context->allowed_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, resp, buf); + ret = simple_digest_response(ctx, header, req, resp); if(ret < 0) return ret; } } /* Or a basic authentication */ - if(!header && context->opts->types & HA_TYPE_BASIC) + if(!header && req->context->allowed_types & HA_TYPE_BASIC) { ha_messagex(LOG_DEBUG, "simple: processing basic auth header"); header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC); if(header) { - ret = simple_basic_response(ctx, header, resp, buf); + ret = simple_basic_response(ctx, header, req, resp); if(ret < 0) return ret; } @@ -737,20 +730,20 @@ int simple_process(ha_context_t* context, const ha_request_t* req, { resp->code = HA_SERVER_DECLINE; - if(context->opts->types & HA_TYPE_BASIC) + if(req->context->allowed_types & HA_TYPE_BASIC) { - ha_bufmcat(buf, "BASIC realm=\"", ctx->opts->realm , "\"", NULL); + ha_bufmcat(req->buf, "BASIC realm=\"", req->context->realm , "\"", NULL); - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) return HA_CRITERROR; - ha_addheader(resp, "WWW-Authenticate", ha_bufdata(buf)); + ha_addheader(resp, "WWW-Authenticate", ha_bufdata(req->buf)); ha_messagex(LOG_DEBUG, "simple: sent basic auth request"); } - if(context->opts->types & HA_TYPE_DIGEST) + if(req->context->allowed_types & HA_TYPE_DIGEST) { - ret = simple_digest_challenge(ctx, req, resp, buf, 0); + ret = simple_digest_challenge(ctx, req, resp, 0); if(ret < 0) return ret; } -- cgit v1.2.3