diff options
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/bd.c | 679 | ||||
-rw-r--r-- | daemon/bd.h | 9 | ||||
-rw-r--r-- | daemon/digest.c | 45 | ||||
-rw-r--r-- | daemon/digest.h | 10 | ||||
-rwxr-xr-x | daemon/dummy.c | 8 | ||||
-rw-r--r-- | daemon/httpauthd.c | 22 | ||||
-rw-r--r-- | daemon/httpauthd.h | 7 | ||||
-rw-r--r-- | daemon/ldap.c | 98 | ||||
-rw-r--r-- | daemon/misc.c | 6 | ||||
-rw-r--r-- | daemon/mysql.c | 42 | ||||
-rw-r--r-- | daemon/ntlmssp.c | 2 | ||||
-rw-r--r-- | daemon/pgsql.c | 26 | ||||
-rw-r--r-- | daemon/simple.c | 14 |
13 files changed, 579 insertions, 389 deletions
diff --git a/daemon/bd.c b/daemon/bd.c index e11a56b..eb0bec0 100644 --- a/daemon/bd.c +++ b/daemon/bd.c @@ -29,6 +29,7 @@ #include "basic.h" #include "md5.h" #include "bd.h" +#include "stringx.h" static unsigned char g_digest_secret[DIGEST_SECRET_LEN]; @@ -38,193 +39,277 @@ static unsigned char g_digest_secret[DIGEST_SECRET_LEN]; * Defaults and Constants */ -#define BASIC_ESTABLISHED (void*)1 +enum { + RECORD_TYPE_BASIC, + RECORD_TYPE_DIGEST +}; /* Kept by the us 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; -} -digest_record_t; +typedef struct bd_record { + int type; + + /* Used for Digest */ + unsigned char nonce[DIGEST_NONCE_LEN]; + unsigned char userhash[MD5_LEN]; + unsigned char ha1[MD5_LEN]; + unsigned int nc; + + /* Used for both */ + char **groups; +} bd_record_t; /* ------------------------------------------------------------------------------- * Internal Functions */ -static void free_hash_object(void* arg, void* val) +static void +free_hash_object (void *arg, void *val) { - if(val && val != BASIC_ESTABLISHED) - free(val); + bd_record_t *rec = val; + if (!rec) + return; + str_array_free (rec->groups); + free (rec); } -static digest_record_t* get_cached_digest(bd_context_t* ctx, ha_context_t* c, - unsigned char* nonce) +static int +have_cached_basic (bd_context_t* ctx, unsigned char* key) { - digest_record_t* rec; + bd_record_t *rec; - ASSERT(ctx && c && nonce); + ASSERT (ctx && key); - if(c->cache_max == 0) - return NULL; + ha_lock(NULL); - ha_lock(NULL); - - rec = (digest_record_t*)hsh_get(ctx->cache, nonce); + rec = (bd_record_t*)hsh_get (ctx->cache, key); + if (rec && rec->type != RECORD_TYPE_BASIC) + rec = NULL; + else + hsh_touch (ctx->cache, key); - /* Just in case it's a basic :) */ - if(rec && rec != BASIC_ESTABLISHED) - hsh_rem(ctx->cache, nonce); - - ha_unlock(NULL); + ha_unlock(NULL); - ASSERT(!rec || memcmp(nonce, rec->nonce, DIGEST_NONCE_LEN) == 0); - return rec; + return rec != NULL; } -static int have_cached_basic(bd_context_t* ctx, unsigned char* key) +static int +add_cached_basic (bd_context_t *ctx, unsigned char *key, char **groups) { - int ret = 0; + bd_record_t *rec; + int r; - ASSERT(ctx && key); + ASSERT (ctx && key); - ha_lock(NULL); + rec = (bd_record_t*)malloc (sizeof (*rec)); + if (!rec) { + str_array_free (groups); + ha_memerr (NULL); + return HA_CRITERROR; + } - ret = (hsh_get(ctx->cache, key) == BASIC_ESTABLISHED); + memset (rec, 0, sizeof (*rec)); + rec->type = RECORD_TYPE_BASIC; + rec->groups = groups; - ha_unlock(NULL); + ha_lock (NULL); - return ret; -} + while (hsh_count (ctx->cache) >= ctx->cache_max) + hsh_bump (ctx->cache); -static int save_cached_digest(bd_context_t* ctx, ha_context_t* c, - digest_record_t* rec) -{ - int r; + r = hsh_set (ctx->cache, key, rec); - ASSERT(ctx && rec); + ha_unlock (NULL); - if(c->cache_max == 0) - { - free_hash_object(NULL, rec); - return HA_FALSE; - } + if (!r) { + free_hash_object (NULL, rec); + ha_memerr (NULL); + return HA_CRITERROR; + } - ha_lock(NULL); + return HA_OK; +} - while(hsh_count(ctx->cache) >= c->cache_max) - hsh_bump(ctx->cache); +static int +prepare_digest_from_cached (bd_context_t *ctx, digest_context_t *dg, + ha_request_t *rq, unsigned char *nonce) +{ + bd_record_t *rec; + int ret; + + ASSERT (dg && rq && nonce); + + ha_lock (NULL); + + rec = (bd_record_t*)hsh_get (ctx->cache, nonce); + if (rec && rec->type == RECORD_TYPE_DIGEST) { + ASSERT (memcmp (nonce, rec->nonce, DIGEST_NONCE_LEN) == 0); + memcpy (dg->server_userhash, rec->userhash, sizeof (dg->server_userhash)); + memcpy (dg->server_ha1, rec->ha1, sizeof (dg->server_ha1)); + dg->server_nc = ++(rec->nc); + hsh_touch (ctx->cache, nonce); + ret = HA_OK; + } else { + memset (dg->server_userhash, 0, sizeof (dg->server_userhash)); + memset (dg->server_ha1, 0, sizeof (dg->server_ha1)); + dg->server_nc = 1; + ret = HA_FALSE; + } + + ha_unlock (NULL); + + dg->server_uri = rq->req_args[AUTH_ARG_URI]; + dg->server_method = rq->req_args[AUTH_ARG_METHOD]; + + return ret; +} - r = hsh_set(ctx->cache, rec->nonce, rec); +static int +add_digest_rec (bd_context_t *ctx, unsigned char *nonce, + const char *user, digest_context_t *dg, char **groups) +{ + bd_record_t* rec = (bd_record_t*)malloc (sizeof (*rec)); + int r; - ha_unlock(NULL); + ASSERT (nonce && user); - if(!r) - { + if(!rec) { + str_array_free (groups); ha_memerr(NULL); - return HA_CRITERROR; - } + return HA_CRITERROR; + } - return HA_OK; -} + memset (rec, 0, sizeof (*rec)); + rec->type = RECORD_TYPE_DIGEST; + memcpy (rec->nonce, nonce, DIGEST_NONCE_LEN); + memcpy (rec->ha1, dg->server_ha1, MD5_LEN); -static int add_cached_basic(bd_context_t* ctx, ha_context_t* c, - unsigned char* key) -{ - int r; + /* We take ownership of groups */ + rec->groups = groups; + rec->nc = dg->server_nc; - ASSERT(ctx && c && key); + md5_string (rec->userhash, user); - if(c->cache_max == 0) - return HA_FALSE; + ha_lock (NULL); - ha_lock(NULL); + while (hsh_count (ctx->cache) >= ctx->cache_max) + hsh_bump (ctx->cache); - while(hsh_count(ctx->cache) >= c->cache_max) - hsh_bump(ctx->cache); + r = hsh_set (ctx->cache, nonce, rec); - r = hsh_set(ctx->cache, key, BASIC_ESTABLISHED); + ha_unlock (NULL); - ha_unlock(NULL); - - if(!r) - { - ha_memerr(NULL); - return HA_CRITERROR; - } + if (!r) { + free_hash_object (NULL, rec); + ha_memerr (NULL); + return HA_CRITERROR; + } - return HA_OK; + return HA_OK; } -digest_record_t* make_digest_rec(unsigned char* nonce, const char* user) +static int +include_group_headers (bd_context_t *ctx, ha_request_t *rq, unsigned char *key) { - digest_record_t* rec = (digest_record_t*)malloc(sizeof(*rec)); - - ASSERT(nonce && user); - - if(!rec) - { - ha_memerr(NULL); - return NULL; - } - - memset(rec, 0, sizeof(*rec)); - memcpy(rec->nonce, nonce, DIGEST_NONCE_LEN); - - md5_string(rec->userhash, user); - return rec; + bd_record_t *rec; + int have, all = 0; + char *header; + char **ug; + char **rg; + + if (!rq->requested_groups || !rq->requested_groups[0]) + return HA_OK; + + ha_lock (NULL); + + /* This starts a new block to join */ + ha_bufcpy (rq->buf, ""); + + rec = hsh_get (ctx->cache, key); + if (rec) { + for (ug = rec->groups; ug && *ug; ++ug) { + have = all; + for (rg = rq->requested_groups; rg && *rg && !have; ++rg) { + if (strcasecmp (*rg, "*") == 0) { + have = all = 1; + break; + } else if (strcasecmp (*rg, *ug) == 0) { + have = 1; + break; + } + } + + if (have) { + ha_bufjoin (rq->buf); + ha_bufcpy (rq->buf, "\""); + ha_bufjoin (rq->buf); + digest_escape (rq->buf, *ug); + ha_bufjoin (rq->buf); + ha_bufcpy (rq->buf, "\" "); + } + } + } + + ha_unlock (NULL); + + header = ha_bufdata (rq->buf); + if (!header) + return HA_CRITERROR; + + ha_addheader (rq, "X-HttpAuth-Groups", header); + return HA_OK; } -static int do_basic_response(ha_request_t* rq, bd_context_t* ctx, const char* header) +static int +do_basic_response (ha_request_t* rq, bd_context_t* ctx, const char* header) { - basic_header_t basic; - int ret = HA_FALSE; + basic_header_t basic; + char **groups = NULL; + int ret = HA_FALSE; - ASSERT(header && rq); + ASSERT (header && rq); - if((ret = basic_parse(header, rq->buf, &basic)) < 0) - return ret; + if ((ret = basic_parse (header, rq->buf, &basic)) < 0) + return ret; - /* Past this point we don't return directly */ + /* Past this point we don't return directly */ - /* Check and see if this connection is in the cache */ - if(have_cached_basic(ctx, basic.key)) - { - ha_messagex(rq, LOG_NOTICE, "validated basic user against cache: %s", - basic.user); - RETURN(HA_OK); - } + /* Check and see if this connection is in the cache */ + if (have_cached_basic (ctx, basic.key)) { + ha_messagex (rq, LOG_NOTICE, "validated basic user against cache: %s", + basic.user); + RETURN (HA_OK); + } - /* If we have a user name and password */ - if(!basic.user || !basic.user[0] || - !basic.password || !basic.password[0]) - { - ha_messagex(rq, LOG_NOTICE, "no valid basic auth info"); - RETURN(HA_FALSE); - } + /* If we have a user name and password */ + if(!basic.user || !basic.user[0] || + !basic.password || !basic.password[0]) { + ha_messagex(rq, LOG_NOTICE, "no valid basic auth info"); + RETURN(HA_FALSE); + } - ASSERT(ctx->f_validate_basic); - ret = ctx->f_validate_basic(rq, basic.user, basic.password); + ASSERT (ctx->f_validate_basic); + ret = ctx->f_validate_basic (rq, basic.user, basic.password, &groups); -finally: + /* + * We put this connection into the successful connections. + * This takes ownership of groups. + */ + if (ret == HA_OK) + ret = add_cached_basic (ctx, basic.key, groups); - if(ret == HA_OK) - { - rq->resp_code = HA_SERVER_OK; - rq->resp_detail = basic.user; +finally: - /* We put this connection into the successful connections */ - ret = add_cached_basic(ctx, rq->context, basic.key); - } + if (ret == HA_OK) { + rq->resp_code = HA_SERVER_OK; + rq->resp_detail = basic.user; + include_group_headers (ctx, rq, basic.key); + } - return ret; + return ret; } 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; @@ -264,208 +349,172 @@ static int do_digest_challenge(ha_request_t* rq, bd_context_t* ctx, int stale) static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* header) { - unsigned char nonce[DIGEST_NONCE_LEN]; - digest_context_t dg; - digest_record_t* rec = NULL; - const char* t; - time_t expiry; - int ret = HA_FALSE; - int stale = 0; - int r; + unsigned char nonce[DIGEST_NONCE_LEN]; + digest_context_t dg; + const char *t; + char **groups = NULL; + time_t expiry; + int ret = HA_FALSE; + int stale = 0; + int r, cached; - ASSERT(ctx && header && rq); + ASSERT (ctx && header && rq); - /* We use this below to send a default response */ - rq->resp_code = -1; + /* We use this below to send a default response */ + rq->resp_code = -1; - if((r = digest_parse(header, rq->buf, &(dg.client))) < 0) - return r; + if ((r = digest_parse (header, rq->buf, &(dg.client))) < 0) + return r; - if(!dg.client.username) - { - ha_messagex(rq, LOG_WARNING, "digest response contains no user name"); - RETURN(HA_FALSE); - } + if (!dg.client.username) { + ha_messagex(rq, LOG_WARNING, "digest response contains no user name"); + RETURN(HA_FALSE); + } #ifdef _DEBUG - if(rq->context->digest_debugnonce) - { - if(dg.client.nonce && strcmp(dg.client.nonce, rq->context->digest_debugnonce) != 0) - { - ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce"); - RETURN(HA_FALSE); - } - - /* Do a rough hash into the real nonce, for use as a key */ - md5_string(nonce, rq->context->digest_debugnonce); - - /* Debug nonce's never expire */ - expiry = time(NULL); - } - else + if (rq->context->digest_debugnonce) { + if (dg.client.nonce && strcmp (dg.client.nonce, rq->context->digest_debugnonce) != 0) { + ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce"); + RETURN(HA_FALSE); + } + + /* Do a rough hash into the real nonce, for use as a key */ + md5_string (nonce, rq->context->digest_debugnonce); + + /* Debug nonce's never expire */ + expiry = time (NULL); + } else #endif - { - /* Parse out the nonce from that header */ - memset(nonce, 0, DIGEST_NONCE_LEN); - - if(dg.client.nonce) - { - size_t len = DIGEST_NONCE_LEN; - void* d = ha_bufdechex(rq->buf, dg.client.nonce, &len); - - if(d && len == DIGEST_NONCE_LEN) - memcpy(nonce, d, DIGEST_NONCE_LEN); - } - - r = digest_checknonce(nonce, g_digest_secret, &expiry); - if(r != HA_OK) - { - if(r == HA_FALSE) - ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce"); - - RETURN(r); - } - - /* Check to see if we're stale */ - if((expiry + rq->context->cache_timeout) <= time(NULL)) - { - ha_messagex(rq, LOG_INFO, "nonce expired, sending stale challenge: %s", - dg.client.username); - - stale = 1; - RETURN(HA_FALSE); - } - } - - /* See if we have this one from before. */ - rec = get_cached_digest(ctx, rq->context, nonce); - - /* - * Fill in the required fields. - */ - dg.server_nc = rec ? ++(rec->nc) : 0; /* Note bumping up nc */ - dg.server_uri = rq->req_args[AUTH_ARG_URI]; - dg.server_method = rq->req_args[AUTH_ARG_METHOD]; - - /* Check the majority of the fields */ - ret = digest_pre_check(&dg, rq->context, rq->buf); - - if(ret != HA_OK) - { - if(ret == HA_BADREQ) - { - ret = HA_FALSE; - rq->resp_code = HA_SERVER_BADREQ; - } - - RETURN(ret); - } - - /* - * If this is the first instance then we pass off to our derived - * handler for validation and completion of the ha1. This completes - * the authentication, and leaves us the ha1 caching. - */ - if(!rec) - { - ha_messagex(rq, LOG_INFO, "no record in cache, creating one: %s", dg.client.username); - - /* - * If we're valid but don't have a record in the - * cache then complete the record properly. - */ - - rec = make_digest_rec(nonce, dg.client.username); - if(!rec) - RETURN(HA_CRITERROR); - - - ASSERT(ctx->f_validate_digest); - r = ctx->f_validate_digest(rq, dg.client.username, &dg); - if(r != HA_OK) - RETURN(r); - - /* Save away pertinent information when successful*/ - memcpy(rec->ha1, dg.ha1, MD5_LEN); - } - - /* We had a record so ... */ - else - { - /* Bump up the ncount */ - rec->nc++; - - /* Check the user name */ - if(md5_strcmp(rec->userhash, dg.client.username) != 0) - { - ha_messagex(NULL, LOG_ERR, "digest response contains invalid username"); - RETURN(HA_FALSE); - } - - /* And do the validation ourselves */ - memcpy(dg.ha1, rec->ha1, MD5_LEN); - - ret = digest_complete_check(&dg, rq->context, rq->buf); - - if(ret != HA_OK) - { - if(ret == HA_BADREQ) - { - ret = HA_FALSE; - rq->resp_code = HA_SERVER_BADREQ; - } - - if(ret == HA_FALSE) - ha_messagex(NULL, LOG_WARNING, "digest re-authentication failed for user: %s", - dg.client.username); - - RETURN(ret); - } - } - - - rq->resp_code = HA_SERVER_OK; - rq->resp_detail = dg.client.username; - - /* Figure out if we need a new nonce */ - if((expiry + (rq->context->cache_timeout - - (rq->context->cache_timeout / 8))) < time(NULL)) - { - ha_messagex(rq, LOG_INFO, "nonce almost expired, creating new one: %s", - dg.client.username); - - digest_makenonce(nonce, g_digest_secret, NULL); - stale = 1; - } - - t = digest_respond(&dg, rq->buf, stale ? nonce : NULL); - if(!t) - RETURN(HA_CRITERROR); - - if(t[0]) - ha_addheader(rq, "Authentication-Info", t); - - ha_messagex(rq, LOG_NOTICE, "validated digest user: %s", dg.client.username); - - /* Put the connection into the cache */ - if((ret = save_cached_digest(ctx, rq->context, rec)) == HA_OK) - rec = NULL; + { + /* Parse out the nonce from that header */ + memset (nonce, 0, DIGEST_NONCE_LEN); + + if (dg.client.nonce) { + size_t len = DIGEST_NONCE_LEN; + void* d = ha_bufdechex (rq->buf, dg.client.nonce, &len); + + if (d && len == DIGEST_NONCE_LEN) + memcpy (nonce, d, DIGEST_NONCE_LEN); + } + + r = digest_checknonce (nonce, g_digest_secret, &expiry); + if (r != HA_OK) { + if (r == HA_FALSE) + ha_messagex (rq, LOG_WARNING, "digest response contains invalid nonce"); + stale = 1; + RETURN (r); + } + + /* Check to see if we're stale */ + if ((expiry + rq->context->cache_timeout) <= time (NULL)) { + ha_messagex(rq, LOG_INFO, "nonce expired, sending stale challenge: %s", + dg.client.username); + + stale = 1; + RETURN (HA_FALSE); + } + } + + /* + * Fill in all the required fields from any cached response, + * and check the user name if cached. Otherwise initializes + * to default values. + */ + cached = (prepare_digest_from_cached (ctx, &dg, rq, nonce) == HA_OK); + + /* Check the majority of the fields */ + ret = digest_pre_check (&dg, rq->context, rq->buf); + if (ret != HA_OK) { + if (ret == HA_BADREQ) { + ret = HA_FALSE; + rq->resp_code = HA_SERVER_BADREQ; + } + + RETURN (ret); + } + + /* + * If this is the first instance then we pass off to our derived + * handler for validation and completion of the ha1. This completes + * the authentication, and leaves us the ha1 caching. + */ + if (!cached) { + ha_messagex (rq, LOG_INFO, "no record in cache, creating one: %s", + dg.client.username); + + /* + * If we're valid but don't have a record in the + * cache then complete the record properly. + */ + + ASSERT (ctx->f_validate_digest); + r = ctx->f_validate_digest (rq, dg.client.username, &dg, &groups); + if (r != HA_OK) + RETURN (r); + + /* Add the digest record to the cache */ + r = add_digest_rec (ctx, nonce, dg.client.username, &dg, groups); + if (r != HA_OK) + RETURN (r); + + /* We had a record so ... */ + } else { + + /* Check the user name */ + if (md5_strcmp (dg.server_userhash, dg.client.username) != 0) { + ha_messagex(NULL, LOG_ERR, "digest response contains invalid username"); + RETURN(HA_FALSE); + } + + /* And do the validation ourselves */ + ret = digest_complete_check (&dg, rq->context, rq->buf); + + if (ret != HA_OK) { + if (ret == HA_BADREQ) { + ret = HA_FALSE; + rq->resp_code = HA_SERVER_BADREQ; + } + + if (ret == HA_FALSE) + ha_messagex (NULL, LOG_WARNING, "digest re-authentication failed for user: %s", + dg.client.username); + + RETURN (ret); + } + } + + rq->resp_code = HA_SERVER_OK; + rq->resp_detail = dg.client.username; + include_group_headers (ctx, rq, nonce); + + /* Figure out if we need a new nonce */ + if ((expiry + (rq->context->cache_timeout - + (rq->context->cache_timeout / 8))) < time (NULL)) { + ha_messagex (rq, LOG_INFO, "nonce almost expired, creating new one: %s", + dg.client.username); + + digest_makenonce (nonce, g_digest_secret, NULL); + stale = 1; + } + + t = digest_respond (&dg, rq->buf, stale ? nonce : NULL); + if (!t) + RETURN (HA_CRITERROR); + + if (t[0]) + ha_addheader(rq, "Authentication-Info", t); + + ha_messagex(rq, LOG_NOTICE, "validated digest user: %s", dg.client.username); finally: - /* If the record wasn't stored away then free it */ - if(rec) - free(rec); - - /* If nobody above responded then challenge the client again */ - if(ret == HA_FALSE && rq->resp_code == -1) - return do_digest_challenge(rq, ctx, stale); + /* If nobody above responded then challenge the client again */ + if (ret == HA_FALSE && rq->resp_code == -1) + return do_digest_challenge (rq, ctx, stale); - return ret; + return ret; } - - const char* bd_substitute(const ha_request_t* rq, const char* user, const char* str) { bd_context_t* ctx = (bd_context_t*)rq->context->ctx_data; @@ -559,6 +608,7 @@ int bd_init(ha_context_t* context) htc.f_freeval = free_hash_object; htc.arg = NULL; hsh_set_table_calls(ctx->cache, &htc); + ctx->cache_max = context->cache_max; } return HA_OK; @@ -567,7 +617,6 @@ int bd_init(ha_context_t* context) void bd_destroy(ha_context_t* context) { bd_context_t* ctx; - int i; if(!context) return; diff --git a/daemon/bd.h b/daemon/bd.h index a42af68..1697cfb 100644 --- a/daemon/bd.h +++ b/daemon/bd.h @@ -39,8 +39,8 @@ * HA_OK: completed successfully * HA_FAILED: error retrieving hash (should have logged error) */ -typedef int (*bd_validate_digest)(ha_request_t* rq, - const char* user, digest_context_t* dg); +typedef int (*bd_validate_digest)(ha_request_t* rq, const char* user, + digest_context_t* dg, char ***groups); /* * A callback for validating a given user's password. @@ -50,8 +50,8 @@ typedef int (*bd_validate_digest)(ha_request_t* rq, * HA_FALSE: invalid password * HA_FAILED: error validating (should have logged error) */ -typedef int (*bd_validate_basic)(ha_request_t* rq, - const char* user, const char* password); +typedef int (*bd_validate_basic) (ha_request_t *rq, const char *user, + const char *password, char ***groups); /* * Escapes a value for sending to 'server' @@ -71,6 +71,7 @@ typedef struct bd_context /* Require locking --------------------------------------*/ hsh_t* cache; /* Some cached records or basic */ + unsigned int cache_max; /* Maximum number of records in cache */ } bd_context_t; diff --git a/daemon/digest.c b/daemon/digest.c index ecde6b7..21cb453 100644 --- a/daemon/digest.c +++ b/daemon/digest.c @@ -27,6 +27,7 @@ #include "digest.h" #include "stringx.h" +#include <ctype.h> #include <syslog.h> /* A globally unique counter used to guarantee uniqueness of nonces */ @@ -333,8 +334,9 @@ int digest_pre_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t if(*e || nc != dg->server_nc) { - ha_messagex(NULL, LOG_WARNING, "digest response has wrong nc value. " - "possible replay attack: %s", dg->client.nc); + ha_messagex(NULL, LOG_WARNING, "digest response has wrong nc value: %s " + "possible replay attack, should be: %d", + dg->client.nc, dg->server_nc); return HA_FALSE; } } @@ -415,7 +417,7 @@ static int internal_check(digest_context_t* dg, const char* http_method, ha_buff */ /* Encode ha1 */ - t = ha_bufenchex(buf, dg->ha1, MD5_LEN); + t = ha_bufenchex(buf, dg->server_ha1, MD5_LEN); if(t == NULL) return HA_CRITERROR; @@ -541,7 +543,7 @@ const char* digest_respond(digest_context_t* dg, ha_buffer_t* buf, /* Otherwise we do the whole song and dance */ /* Encode ha1 */ - t = ha_bufenchex(buf, dg->ha1, MD5_LEN); + t = ha_bufenchex(buf, dg->server_ha1, MD5_LEN); if(t == NULL) return NULL; @@ -614,3 +616,38 @@ void digest_makeha1(unsigned char* digest, const char* user, md5_update(&md5, password, strlen(password)); md5_final(digest, &md5); } + +#define MUST_ESCAPE "\"\' \t\n\r\v\\" + +void +digest_escape (ha_buffer_t *buf, const char *orig) +{ + const char* t; + size_t pos; + + assert (orig); + assert (buf); + + ha_bufcpy(buf, ""); + + t = orig; + while (*t) { + pos = strcspn (t, MUST_ESCAPE); + + if(pos > 0) { + ha_bufjoin (buf); + ha_bufncpy (buf, t, pos); + t += pos; + } + + while (*t && !strchr (MUST_ESCAPE, *t)) { + char esc[3]; + esc[0] = '\\'; + esc[1] = *t; + esc[2] = '\0'; + ha_bufjoin (buf); + ha_bufcpy (buf, esc); + t++; + } + } +} diff --git a/daemon/digest.h b/daemon/digest.h index af8a1d7..7a0f59c 100644 --- a/daemon/digest.h +++ b/daemon/digest.h @@ -22,8 +22,11 @@ #ifndef __DIGEST_H__ #define __DIGEST_H__ +#include "httpauthd.h" #include "md5.h" +#include <sys/time.h> + #define DIGEST_NONCE_LEN sizeof(time_t) + sizeof(unsigned int) + MD5_LEN #define DIGEST_SECRET_LEN 16 @@ -53,7 +56,8 @@ typedef struct digest_context const char* server_uri; const char* server_method; - unsigned char ha1[MD5_LEN]; + unsigned char server_userhash[MD5_LEN]; + unsigned char server_ha1[MD5_LEN]; } digest_context_t; @@ -78,4 +82,8 @@ int digest_complete_check(digest_context_t* dg, const ha_context_t* opts, ha_buf /* This assumes a digest_context that's been checked and validated successfully */ const char* digest_respond(digest_context_t* dg, ha_buffer_t* buf, unsigned char* next); +void digest_makenonce(unsigned char* nonce, unsigned char* secret, unsigned char* old); +int digest_checknonce(unsigned char* nonce, unsigned char* secret, time_t* tm); +void digest_escape (ha_buffer_t *buf, const char *orig); + #endif /* __DIGEST_H__ */ diff --git a/daemon/dummy.c b/daemon/dummy.c index ca83e54..245d32a 100755 --- a/daemon/dummy.c +++ b/daemon/dummy.c @@ -33,8 +33,8 @@ */ /* Forward declarations for callbacks */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg); -static int validate_basic(ha_request_t* rq, const char* user, const char* password); +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups); +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups); /* The defaults for the context */ static const bd_context_t dummy_defaults = BD_CALLBACKS(validate_digest, validate_basic, NULL); @@ -43,12 +43,12 @@ static const bd_context_t dummy_defaults = BD_CALLBACKS(validate_digest, validat * Internal Functions */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg) +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups) { return HA_OK; } -static int validate_basic(ha_request_t* rq, const char* user, const char* password) +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups) { return HA_OK; } diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c index 1161517..09fb1d7 100644 --- a/daemon/httpauthd.c +++ b/daemon/httpauthd.c @@ -31,6 +31,7 @@ #include <pthread.h> #include <fcntl.h> #include <err.h> +#include <ctype.h> #include <signal.h> #include "usuals.h" @@ -85,6 +86,8 @@ httpauth_loaded_t; /* The list of handlers in use */ httpauth_loaded_t* g_handlers = NULL; +extern int pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind); + /* ----------------------------------------------------------------------- * Structures and Constants */ @@ -162,7 +165,6 @@ static void writepid(const char* pid); static void* httpauth_thread(void* arg); static int httpauth_processor(int ifd, int ofd); 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); @@ -176,7 +178,6 @@ int main(int argc, char* argv[]) 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; @@ -944,9 +945,6 @@ static int httpauth_error(ha_request_t* rq, int ofd, int r) static int httpauth_ready(ha_request_t* rq, int ofd) { - const char* t; - httpauth_loaded_t* h; - ASSERT(ofd != -1); ASSERT(rq); @@ -1027,6 +1025,14 @@ static int httpauth_set(ha_request_t* rq, ha_buffer_t* cbuf, int ofd) rq->digest_domain = ha_bufcpy(rq->conn_buf, value ? value : ""); } + else if (strcasecmp (name, "Groups") == 0) { + + /* we need to copy this string so it doesn't get destroyed on next req */ + if (rq->requested_groups) + str_array_free (rq->requested_groups); + rq->requested_groups = str_array_parse_quoted (value ? value : ""); + } + else if(strcasecmp(name, "Handler") == 0) { if(!value || !*value) @@ -1048,7 +1054,7 @@ static int httpauth_set(ha_request_t* rq, ha_buffer_t* cbuf, int ofd) if(value != NULL) { - ha_messagex(rq, LOG_ERR, "unknown authentication handler: %s", rq->req_args[0]); + ha_messagex(rq, LOG_ERR, "unknown authentication handler: %s", value); return httpauth_respond(rq, ofd, HA_SERVER_BADREQ, 0, "Unknown Auth Handler"); } } @@ -1107,6 +1113,7 @@ static int httpauth_processor(int ifd, int ofd) /* Set up some context stuff */ rq.digest_domain = ""; + rq.requested_groups = NULL; rq.buf = &buf; rq.conn_buf = &cbuf; @@ -1188,6 +1195,8 @@ finally: close(ofd); } + if (rq.requested_groups) + str_array_free (rq.requested_groups); ha_messagex(&rq, LOG_INFO, "closed connection"); ha_buffree(&cbuf); @@ -1320,7 +1329,6 @@ static int config_parse(const char* file, ha_buffer_t* buf) if(ha_bufchar(buf) == '[') { ha_handler_t* handler = NULL; - const char* x; ha_bufeat(buf); name = ha_bufparseline(buf, 1); diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h index 1540138..e533dde 100644 --- a/daemon/httpauthd.h +++ b/daemon/httpauthd.h @@ -138,13 +138,13 @@ ha_context_t; #define HA_MAX_ARGS 4 /* - * The maximum number of pertinent headers to read - * from the client. If you need to add valid headers + * The maximum number of pertinent headers to read/send + * from/to the client. If you need to add valid headers * make sure to update this number *and* the list * of valid headers in httpauthd.c */ -#define HA_MAX_HEADERS 2 +#define HA_MAX_HEADERS 8 /* * The maximum number of handlers. If you add @@ -183,6 +183,7 @@ typedef struct ha_request /* Additional request info */ ha_context_t* context; const char* digest_domain; + char** requested_groups; /* The buffer in use for the request */ ha_buffer_t* buf; diff --git a/daemon/ldap.c b/daemon/ldap.c index a1aa1a1..f4324be 100644 --- a/daemon/ldap.c +++ b/daemon/ldap.c @@ -24,10 +24,16 @@ #include "md5.h" #include "sha1.h" #include "bd.h" +#include "stringx.h" #include <sys/time.h> +#include <ctype.h> + +#define __USE_XOPEN +#include <unistd.h> /* LDAP library */ +#define LDAP_DEPRECATED 1 #include <ldap.h> /* ------------------------------------------------------------------------------- @@ -73,6 +79,7 @@ typedef struct ldap_context const char* base; /* Base for the filter */ const char* pw_attr; /* The clear password attribute */ const char* ha1_attr; /* Password for an encrypted Digest H(A1) */ + const char* group_attr; /* The group attribute */ const char* user; /* User to bind as */ const char* password; /* Password to bind with */ const char* dnmap; /* For mapping users to dns */ @@ -90,8 +97,8 @@ typedef struct ldap_context ldap_context_t; /* Forward declarations for callbacks */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg); -static int validate_basic(ha_request_t* rq, const char* user, const char* password); +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups); +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups); static void escape_ldap(const ha_request_t* rq, ha_buffer_t* buf, const char* value); /* The defaults for the context */ @@ -104,6 +111,7 @@ static const ldap_context_t ldap_defaults = NULL, /* base */ "userPassword", /* pw_attr */ NULL, /* ha1_attr */ + NULL, /* group_attr */ NULL, /* user */ NULL, /* password */ NULL, /* dnmap */ @@ -563,10 +571,10 @@ static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP { struct timeval tv; const char* filter; - const char* attrs[3]; + const char* attrs[4]; const char* base; int scope; - int r; + int r, i; ASSERT(ctx && rq && ld && user && dn && entry && result); @@ -582,9 +590,14 @@ static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP filter = "(objectClass=*)"; } - attrs[0] = ctx->dobind ? NULL : ctx->pw_attr; - attrs[1] = ctx->dobind ? NULL : ctx->ha1_attr; - attrs[2] = NULL; + i = 0; + if (ctx->group_attr) + attrs[i++] = ctx->group_attr; + if (ctx->dobind && ctx->pw_attr) + attrs[i++] = ctx->pw_attr; + if (ctx->dobind && ctx->ha1_attr) + attrs[i++] = ctx->ha1_attr; + attrs[i] = NULL; tv.tv_sec = ctx->ldap_timeout; tv.tv_usec = 0; @@ -633,7 +646,43 @@ static int retrieve_user_entry(const ha_request_t* rq, ldap_context_t* ctx, LDAP return HA_FALSE; } -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg) +static int +get_user_groups (ldap_context_t *ctx, LDAP *ld, LDAPMessage *entry, char*** result) +{ + struct berval **vals, **v; + char **groups = NULL; + int ret = HA_OK; + + if (!ctx->group_attr) { + *result = NULL; + return HA_OK; + } + + groups = str_array_create (NULL); + vals = ldap_get_values_len (ld, entry, ctx->group_attr); + for (v = vals; v && *v; ++v) { + if ((*v)->bv_len) { + groups = str_array_appendn (groups, (*v)->bv_val, (*v)->bv_len); + if (!groups) { + ha_memerr (NULL); + ret = HA_CRITERROR; + break; + } + } + } + + if (vals) + ldap_value_free_len (vals); + if (ret != HA_OK) + str_array_free (groups); + else + *result = groups; + return ret; +} + +static int +validate_digest (ha_request_t *rq, const char *user, + digest_context_t *dg, char ***groups) { ldap_context_t* ctx = (ldap_context_t*)rq->context->ctx_data; LDAP* ld = NULL; /* freed in finally */ @@ -684,7 +733,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* for(h = ha1s; *h; ++h) { - r = parse_ldap_ha1(rq, *h, dg->ha1); + r = parse_ldap_ha1(rq, *h, dg->server_ha1); if(r == HA_FALSE) { @@ -722,7 +771,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* { foundany = 1; - digest_makeha1(dg->ha1, user, rq->context->realm, password); + digest_makeha1(dg->server_ha1, user, rq->context->realm, password); /* Run the actual check */ ret = digest_complete_check(dg, rq->context, rq->buf); @@ -739,6 +788,13 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* finally: + /* Fill in the user's groups */ + if (ret == HA_OK) { + r = get_user_groups (ctx, ld, entry, groups); + if (r < 0) + ret = r; + } + if(ha1s) ldap_value_free_len(ha1s); @@ -754,7 +810,9 @@ finally: return ret; } -static int validate_basic(ha_request_t* rq, const char* user, const char* password) +static int +validate_basic (ha_request_t *rq, const char *user, + const char *password, char ***groups) { ldap_context_t* ctx = (ldap_context_t*)rq->context->ctx_data; LDAP* ld = NULL; @@ -845,7 +903,11 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo /* Discard the connection since it's useless to us */ discard_ldap_connection(rq, ctx, ld); ld = NULL; - } + ret = HA_FALSE; + + } else { + ret = HA_OK; + } } @@ -870,6 +932,12 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo } finally: + /* Fill in the user's groups */ + if (ret == HA_OK) { + r = get_user_groups (ctx, ld, entry, groups); + if (r < 0) + ret = r; + } if(results) ldap_msgfree(results); @@ -909,6 +977,12 @@ int ldap_config(ha_context_t* context, const char* name, const char* value) return HA_OK; } + else if(strcmp(name, "ldapgroupattr") == 0) + { + ctx->group_attr = value; + return HA_OK; + } + else if(strcmp(name, "ldappwattr") == 0) { ctx->pw_attr = value; diff --git a/daemon/misc.c b/daemon/misc.c index ca14ee3..49c585e 100644 --- a/daemon/misc.c +++ b/daemon/misc.c @@ -27,6 +27,7 @@ #include <err.h> #include <stdio.h> #include <fcntl.h> +#include <unistd.h> extern int g_debuglevel; extern int g_daemonized; @@ -53,7 +54,6 @@ static void vmessage(const ha_request_t* rq, int level, int err, size_t len; char* m; int e = errno; - int x; if(g_daemonized) { @@ -390,7 +390,7 @@ int ha_uriparse(ha_buffer_t* buf, const char* suri, ha_uri_t* uri) if(str[0] == '/') { deal_with_path: - *str == 0; + *str = 0; ++str; /* @@ -611,7 +611,7 @@ int ha_uricmp(ha_uri_t* one, ha_uri_t* two) /* 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_s(one->host, two->host, NULL, 1)) != 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 || diff --git a/daemon/mysql.c b/daemon/mysql.c index e926bb2..69a28ff 100644 --- a/daemon/mysql.c +++ b/daemon/mysql.c @@ -27,6 +27,9 @@ #include <sys/time.h> +#define __USE_XOPEN +#include <unistd.h> + /* Mysql library */ #include <mysql.h> #include <errmsg.h> @@ -48,14 +51,14 @@ typedef struct mysql_context /* Readonly Settings ------------------------------------------------- */ const char* host; /* The connection host or path */ - unsigned int port; /* The connection port */ + int port; /* The connection port */ const char* user; /* The pgsql user name */ const char* password; /* The pgsql password */ const char* database; /* The database name */ - const char* query; /* The query */ - const char* pw_column; /* The database query to retrieve a password */ + const char* user_query; /* The database query to get the user info */ + const char* pw_column; /* The database column with a password */ int pw_type; /* The type of password encoded in database */ - const char* ha1_column; /* The database query to retrieve a ha1 */ + const char* ha1_column; /* The database column with a ha1 */ int mysql_max; /* Number of open connections allowed */ int mysql_timeout; /* Maximum amount of time to dedicate to a query */ @@ -68,8 +71,8 @@ typedef struct mysql_context mysql_context_t; /* Forward declarations for callbacks */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg); -static int validate_basic(ha_request_t* rq, const char* user, const char* password); +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups); +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups); static void escape_mysql(const ha_request_t* rq, ha_buffer_t* buf, const char* value); /* The defaults for the context */ @@ -82,7 +85,7 @@ static const mysql_context_t mysql_defaults = NULL, /* user */ NULL, /* password */ NULL, /* database */ - NULL, /* query */ + NULL, /* user_query */ NULL, /* pw_attr */ DB_PW_CLEAR, /* pw_type */ NULL, /* ha1_attr */ @@ -97,7 +100,7 @@ static const mysql_context_t mysql_defaults = static pthread_mutex_t g_mysql_mutex; static pthread_mutexattr_t g_mysql_mutexattr; - +extern int pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind); /* ------------------------------------------------------------------------------- * Internal Functions @@ -164,7 +167,6 @@ static int validate_ha1(ha_request_t* rq, mysql_context_t* ctx, const char* user { unsigned char dbha1[MD5_LEN]; unsigned char ha1[MD5_LEN]; - const char* p; int r = dec_mysql_binary(rq, dbpw, dbha1, MD5_LEN); @@ -344,7 +346,7 @@ static void discard_mysql_connection(const ha_request_t* rq, mysql_context_t* ct static void save_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx, MYSQL* my) { - int i, e; + int i; ASSERT(ctx); @@ -424,10 +426,10 @@ static int retrieve_user_rows(ha_request_t* rq, mysql_context_t* ctx, if(!my) RETURN(HA_FAILED); - ASSERT(ctx->query); + ASSERT(ctx->user_query); /* The map can have %u and %r to denote user and realm */ - query = bd_substitute(rq, user, ctx->query); + query = bd_substitute(rq, user, ctx->user_query); if(!query) RETURN(HA_CRITERROR); @@ -472,7 +474,7 @@ finally: return ret; } -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg) +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups) { mysql_context_t* ctx = (mysql_context_t*)rq->context->ctx_data; MYSQL_RES* res = NULL; @@ -480,7 +482,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* int ret = HA_FALSE; int pw_column = -1; int ha1_column = -1; - int r, i, foundany = 0; + int foundany = 0; const char* v; ASSERT(rq && user && dg); @@ -511,7 +513,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* { foundany = 1; - digest_makeha1(dg->ha1, user, rq->context->realm, v); + digest_makeha1(dg->server_ha1, user, rq->context->realm, v); ha_messagex(rq, LOG_DEBUG, "testing clear text password for digest auth"); /* Run the actual check */ @@ -527,7 +529,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* v = *(row + ha1_column); if(v != NULL) { - ret = dec_mysql_binary(rq, v, dg->ha1, MD5_LEN); + ret = dec_mysql_binary(rq, v, dg->server_ha1, MD5_LEN); if(ret < 0) RETURN(ret) else if(ret == HA_FALSE) @@ -554,7 +556,7 @@ finally: return ret; } -static int validate_basic(ha_request_t* rq, const char* user, const char* password) +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups) { mysql_context_t* ctx = (mysql_context_t*)rq->context->ctx_data; MYSQL_RES* res = NULL; @@ -562,7 +564,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo int ret = HA_FALSE; int pw_column = -1; int ha1_column = -1; - int i, foundany = 0; + int foundany = 0; const char* v; ASSERT(rq && user && password); @@ -665,7 +667,7 @@ int mysql_config(ha_context_t* context, const char* name, const char* value) if(strcmp(name, "dbquery") == 0) { - ctx->query = value; + ctx->user_query = value; return HA_OK; } @@ -727,7 +729,7 @@ int mysql_initialize(ha_context_t* context) ASSERT(ctx); /* Check for mandatory configuration */ - if(!ctx->database || !ctx->query) + if(!ctx->database || !ctx->user_query) { ha_messagex(NULL, LOG_ERR, "mysql configuration incomplete. " "Must have DBDatabase and DBQuery."); diff --git a/daemon/ntlmssp.c b/daemon/ntlmssp.c index ca8c5a8..1b51264 100644 --- a/daemon/ntlmssp.c +++ b/daemon/ntlmssp.c @@ -239,7 +239,7 @@ ntlm_msg3_getusername(unsigned char *raw_msg, unsigned msglen, return 16; else { /* Win9x client leave username in uppercase...fix it: */ - while (*username!=(unsigned char)NULL) { + while (*username!=(unsigned char)0) { c=tolower((int)*username); *username=(unsigned char)c; username++; diff --git a/daemon/pgsql.c b/daemon/pgsql.c index 0306cbf..f19624a 100644 --- a/daemon/pgsql.c +++ b/daemon/pgsql.c @@ -25,10 +25,17 @@ #include "sha1.h" #include "bd.h" +#define __USE_XOPEN +#include <unistd.h> + #include <sys/time.h> /* Postgresql library */ +#ifdef HAVE_LIBPQ_FE_H #include <libpq-fe.h> +#else +#include <postgresql/libpq-fe.h> +#endif /* ------------------------------------------------------------------------------- * Structures @@ -66,8 +73,8 @@ typedef struct pgsql_context pgsql_context_t; /* Forward declarations for callbacks */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg); -static int validate_basic(ha_request_t* rq, const char* user, const char* password); +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups); +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups); static void escape_pgsql(const ha_request_t* rq, ha_buffer_t* buf, const char* value); /* The defaults for the context */ @@ -136,7 +143,7 @@ static int dec_pgsql_binary(const ha_request_t* rq, const char* enc, } /* Raw binary postgres encoded */ - d = PQunescapeBytea(enc, &enclen); + d = PQunescapeBytea((const unsigned char*)enc, &enclen); if(d != NULL) { if(enclen == len) @@ -170,7 +177,6 @@ static int validate_ha1(ha_request_t* rq, pgsql_context_t* ctx, const char* user { unsigned char dbha1[MD5_LEN]; unsigned char ha1[MD5_LEN]; - const char* p; int r = dec_pgsql_binary(rq, dbpw, dbha1, MD5_LEN); @@ -383,7 +389,7 @@ static void discard_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ct static void save_pgsql_connection(const ha_request_t* rq, pgsql_context_t* ctx, PGconn* pg) { - int i, e; + int i; ASSERT(ctx); @@ -518,14 +524,14 @@ finally: return ret; } -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg) +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups) { pgsql_context_t* ctx = (pgsql_context_t*)rq->context->ctx_data; PGresult* res = NULL; int ret = HA_FALSE; int pw_column = -1; int ha1_column = -1; - int r, i, foundany = 0; + int i, foundany = 0; ASSERT(rq && user && dg); @@ -554,7 +560,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* { foundany = 1; - digest_makeha1(dg->ha1, user, rq->context->realm, PQgetvalue(res, i, pw_column)); + digest_makeha1(dg->server_ha1, user, rq->context->realm, PQgetvalue(res, i, pw_column)); ha_messagex(rq, LOG_DEBUG, "testing clear text password for digest auth"); /* Run the actual check */ @@ -569,7 +575,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* { if(!PQgetisnull(res, i, ha1_column)) { - ret = dec_pgsql_binary(rq, PQgetvalue(res, i, ha1_column), dg->ha1, MD5_LEN); + ret = dec_pgsql_binary(rq, PQgetvalue(res, i, ha1_column), dg->server_ha1, MD5_LEN); if(ret < 0) RETURN(ret) else if(ret == HA_FALSE) @@ -596,7 +602,7 @@ finally: return ret; } -static int validate_basic(ha_request_t* rq, const char* user, const char* password) +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups) { pgsql_context_t* ctx = (pgsql_context_t*)rq->context->ctx_data; PGresult* res = NULL; diff --git a/daemon/simple.c b/daemon/simple.c index 1c37c23..1e3cc64 100644 --- a/daemon/simple.c +++ b/daemon/simple.c @@ -28,9 +28,11 @@ #include "hash.h" #include "bd.h" #include "md5.h" +#include "stringx.h" #include <stdio.h> #include <fcntl.h> +#include <unistd.h> #define SIMPLE_MAXLINE 256 @@ -49,8 +51,8 @@ typedef struct simple_context simple_context_t; /* Forward declarations for callbacks */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg); -static int validate_basic(ha_request_t* rq, const char* user, const char* password); +static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg, char ***groups); +static int validate_basic(ha_request_t* rq, const char* user, const char* password, char ***groups); /* The defaults for the context */ static const simple_context_t simple_defaults = @@ -63,7 +65,8 @@ static const simple_context_t simple_defaults = * Internal Functions */ -static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg) +static int validate_digest(ha_request_t* rq, const char* user, + digest_context_t* dg, char ***groups) { simple_context_t* ctx = (simple_context_t*)rq->context->ctx_data; FILE* f; @@ -142,7 +145,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* } ha_messagex(rq, LOG_DEBUG, "found ha1 for user: %s", user); - memcpy(dg->ha1, t, MD5_LEN); + memcpy(dg->server_ha1, t, MD5_LEN); foundgood = 1; /* Try to do the validation */ @@ -168,7 +171,8 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* return ret; } -static int validate_basic(ha_request_t* rq, const char* user, const char* password) +static int validate_basic(ha_request_t* rq, const char* user, + const char* password, char ***groups) { simple_context_t* ctx = (simple_context_t*)rq->context->ctx_data; FILE* f; |