summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/bd.c679
-rw-r--r--daemon/bd.h9
-rw-r--r--daemon/digest.c45
-rw-r--r--daemon/digest.h10
-rwxr-xr-xdaemon/dummy.c8
-rw-r--r--daemon/httpauthd.c22
-rw-r--r--daemon/httpauthd.h7
-rw-r--r--daemon/ldap.c98
-rw-r--r--daemon/misc.c6
-rw-r--r--daemon/mysql.c42
-rw-r--r--daemon/ntlmssp.c2
-rw-r--r--daemon/pgsql.c26
-rw-r--r--daemon/simple.c14
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;