From 570c17aa3bb6a39030ebefc5618f0c3fa8cf0089 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Sun, 25 Apr 2004 05:50:07 +0000 Subject: Debugging of simple authentication handler --- daemon/simple.c | 188 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 125 insertions(+), 63 deletions(-) (limited to 'daemon/simple.c') diff --git a/daemon/simple.c b/daemon/simple.c index d51e9d9..e33e833 100644 --- a/daemon/simple.c +++ b/daemon/simple.c @@ -33,20 +33,13 @@ typedef struct simple_context /* Context ----------------------------------------------------------- */ hash_t* cache; /* Some cached records or basic */ + +#ifdef _DEBUG + const char* debug_nonce; +#endif } simple_context_t; -/* The defaults for the context */ -static const simple_context_t simple_defaults = -{ - NULL, /* filename */ - NULL, /* realm */ - NULL, /* domains */ - 0, /* cache_max */ - 0, /* cache_timeout */ - NULL /* cache */ -}; - /* ------------------------------------------------------------------------------- * Internal Functions @@ -156,6 +149,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, FILE* f; int found = 0; char* t; + char* t2; char line[SIMPLE_MAXLINE]; ASSERT(ctx && rec && buf && user && user[0] && code); @@ -195,33 +189,39 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, /* Check the user */ if(strcmp(line, user) == 0) { - /* Now decode the rest of the line and see if it matches up */ - t = ha_bufdechex(buf, t, MD5_LEN); - - if(t != NULL) + /* Otherwise it might be a digest type ha1. */ + t2 = strchr(t, ':'); + if(t2) { - memcpy(rec->ha1, t, MD5_LEN); - found = 1; - break; + *t2 = 0; + t2++; + + /* Check the realm */ + if(strcmp(t, ctx->realm) == 0) + { + /* Now try antd decode the ha1 */ + t = ha_bufdechex(buf, t2, MD5_LEN); + if(t != NULL) + { + memcpy(rec->ha1, t, MD5_LEN); + found = 1; + break; + } + } } - else - { - if(ha_buferr(buf)) - break; - + if(!t2 || !found) ha_messagex(LOG_WARNING, "user '%s' found in file, but password not in digest format", user); - } } } - - fclose(f); } + fclose(f); + if(ha_buferr(buf)) return HA_ERROR; - return found ? HA_FALSE : HA_OK; + return found ? HA_OK : HA_FALSE; } static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, @@ -264,6 +264,14 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, break; } + /* Take white space off end of line */ + t = line + strlen(line); + while(t != line && isspace(*(t - 1))) + { + *(t - 1) = 0; + t--; + } + t = strchr(line, ':'); if(t) { @@ -274,40 +282,48 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, /* Check the user */ if(strcmp(line, user) == 0) { - /* We can validate against an ha1, so check if it decodes as one */ - t2 = ha_bufdechex(buf, t, MD5_LEN); + /* Not sure if crypt is thread safe so we lock */ + ha_lock(NULL); - if(t2 && memcmp(ha1, t2, MD5_LEN) == 0) + /* Check the password */ + t2 = crypt(clearpw, t); + + ha_unlock(NULL); + + if(strcmp(crypt(clearpw, t), t) == 0) { - memcpy(ha1, t2, MD5_LEN); found = 1; break; } - /* Otherwise we try a nice crypt style password */ - else + /* Otherwise it might be a digest type ha1. */ + t2 = strchr(t, ':'); + if(t2) { - /* Not sure if crypt is thread safe so we lock */ - ha_lock(); - - /* Check the password */ - if(strcmp(crypt(clearpw, t), t) == 0) + *t2 = 0; + t2++; + + /* Check the realm */ + if(strcmp(t, ctx->realm) == 0) + { + /* Now try antd decode the ha1 */ + t = ha_bufdechex(buf, t2, MD5_LEN); + if(t && memcmp(ha1, t, MD5_LEN) == 0) + { found = 1; - - ha_unlock(); - - if(found) - break; + break; + } + } } if(ha_buferr(buf)) break; } } - - fclose(f); } + fclose(f); + if(ha_buferr(buf)) return HA_ERROR; @@ -347,8 +363,9 @@ static int simple_basic_response(simple_context_t* ctx, const char* header, finally: - if(resp->code == HA_SERVER_ACCEPT) + if(ret = HA_OK) { + resp->code = HA_SERVER_ACCEPT; resp->detail = basic.user; /* We put this connection into the successful connections */ @@ -361,16 +378,33 @@ finally: static int simple_digest_challenge(simple_context_t* ctx, ha_response_t* resp, ha_buffer_t* buf, int stale) { - unsigned char nonce[DIGEST_NONCE_LEN]; + const char* nonce_str; const char* header; ASSERT(ctx && resp && buf); /* Generate an nonce */ - digest_makenonce(nonce, g_simple_secret, NULL); + +#ifdef _DEBUG + if(ctx->debug_nonce) + { + nonce_str = ctx->debug_nonce; + ha_messagex(LOG_WARNING, "using debug nonce. security non-existant."); + } + else +#endif + { + unsigned char nonce[DIGEST_NONCE_LEN]; + digest_makenonce(nonce, g_simple_secret, NULL); + + nonce_str = ha_bufenchex(buf, nonce, DIGEST_NONCE_LEN); + if(!nonce_str) + return HA_ERROR; + } + /* Now generate a message to send */ - header = digest_challenge(buf, nonce, ctx->realm, ctx->domains, stale); + header = digest_challenge(buf, nonce_str, ctx->realm, ctx->domains, stale); if(!header) return HA_ERROR; @@ -403,14 +437,34 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, if(digest_parse(header, buf, &dg, nonce) == HA_ERROR) return HA_ERROR; - r = digest_checknonce(nonce, g_simple_secret, &expiry); - if(r != HA_OK) +#ifdef _DEBUG + if(ctx->debug_nonce) { - if(r == HA_FALSE) + if(dg.nonce && strcmp(dg.nonce, ctx->debug_nonce) != 0) + { + ret = HA_FALSE; ha_messagex(LOG_WARNING, "digest response contains invalid nonce"); + goto finally; + } - ret = r; - goto finally; + /* Do a rough hash into the real nonce, for use as a key */ + md5_string(nonce, ctx->debug_nonce); + + /* Debug nonce's never expire */ + expiry = time(NULL); + } + else +#endif + { + r = digest_checknonce(nonce, g_simple_secret, &expiry); + if(r != HA_OK) + { + if(r == HA_FALSE) + ha_messagex(LOG_WARNING, "digest response contains invalid nonce"); + + ret = r; + goto finally; + } } rec = get_cached_digest(ctx, nonce); @@ -520,6 +574,14 @@ int simple_config(ha_context_t* context, const char* name, const char* value) return HA_OK; } +#ifdef _DEBUG + else if(strcmp(name, "digestdebugnonce") == 0) + { + ctx->debug_nonce = value; + return HA_OK; + } +#endif + return HA_FALSE; } @@ -600,7 +662,7 @@ int simple_process(ha_context_t* context, ha_request_t* req, ha_response_t* resp, ha_buffer_t* buf) { simple_context_t* ctx = (simple_context_t*)(context->data); - const char* header; + const char* header = NULL; int ret = HA_FALSE; int found = 0; basic_header_t basic; @@ -652,13 +714,6 @@ int simple_process(ha_context_t* context, ha_request_t* req, { resp->code = HA_SERVER_DECLINE; - if(context->types & HA_TYPE_DIGEST) - { - ret = simple_digest_challenge(ctx, resp, buf, 0); - if(ret == HA_ERROR) - return ret; - } - if(context->types & HA_TYPE_BASIC) { ha_bufmcat(buf, "BASIC realm=\"", ctx->realm , "\"", NULL); @@ -668,6 +723,13 @@ int simple_process(ha_context_t* context, ha_request_t* req, ha_addheader(resp, "WWW-Authenticate", ha_bufdata(buf)); } + + if(context->types & HA_TYPE_DIGEST) + { + ret = simple_digest_challenge(ctx, resp, buf, 0); + if(ret == HA_ERROR) + return ret; + } } return ret; @@ -685,7 +747,7 @@ ha_handler_t simple_handler = simple_destroy, /* Uninitialization routine */ simple_config, /* Config routine */ simple_process, /* Processing routine */ - &simple_defaults, /* A default context */ + NULL, /* A default context */ sizeof(simple_context_t) /* Size of the context */ }; -- cgit v1.2.3