summaryrefslogtreecommitdiff
path: root/daemon/ldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/ldap.c')
-rw-r--r--daemon/ldap.c179
1 files changed, 89 insertions, 90 deletions
diff --git a/daemon/ldap.c b/daemon/ldap.c
index 9fd513f..a996305 100644
--- a/daemon/ldap.c
+++ b/daemon/ldap.c
@@ -73,8 +73,6 @@ typedef struct ldap_context
int ldap_max; /* Number of open connections allowed */
int ldap_timeout; /* Maximum amount of time to dedicate to an ldap query */
- const ha_context_opts_t* opts; /* Options from httpauthd.c */
-
/* Context ----------------------------------------------------------- */
hash_t* cache; /* Some cached records or basic */
@@ -135,13 +133,14 @@ static int report_ldap(const char* msg, int code)
};
}
-static digest_record_t* get_cached_digest(ldap_context_t* ctx, unsigned char* nonce)
+static digest_record_t* get_cached_digest(ldap_context_t* ctx, ha_context_t* c,
+ unsigned char* nonce)
{
digest_record_t* rec;
- ASSERT(ctx && nonce);
+ ASSERT(ctx && c && nonce);
- if(ctx->opts->cache_max == 0)
+ if(c->cache_max == 0)
return NULL;
ha_lock(NULL);
@@ -173,13 +172,14 @@ static int have_cached_basic(ldap_context_t* ctx, unsigned char* key)
return ret;
}
-static int save_cached_digest(ldap_context_t* ctx, digest_record_t* rec)
+static int save_cached_digest(ldap_context_t* ctx, ha_context_t* c,
+ digest_record_t* rec)
{
int r;
ASSERT(ctx && rec);
- if(ctx->opts->cache_max == 0)
+ if(c->cache_max == 0)
{
free_hash_object(NULL, rec);
return HA_FALSE;
@@ -187,7 +187,7 @@ static int save_cached_digest(ldap_context_t* ctx, digest_record_t* rec)
ha_lock(NULL);
- while(hash_count(ctx->cache) >= ctx->opts->cache_max)
+ while(hash_count(ctx->cache) >= c->cache_max)
hash_bump(ctx->cache);
r = hash_set(ctx->cache, rec->nonce, rec);
@@ -203,18 +203,19 @@ static int save_cached_digest(ldap_context_t* ctx, digest_record_t* rec)
return HA_OK;
}
-static int add_cached_basic(ldap_context_t* ctx, unsigned char* key)
+static int add_cached_basic(ldap_context_t* ctx, ha_context_t* c,
+ unsigned char* key)
{
int r;
- ASSERT(ctx && key);
+ ASSERT(ctx && c && key);
- if(ctx->opts->cache_max == 0)
+ if(c->cache_max == 0)
return HA_FALSE;
ha_lock(NULL);
- while(hash_count(ctx->cache) >= ctx->opts->cache_max)
+ while(hash_count(ctx->cache) >= c->cache_max)
hash_bump(ctx->cache);
r = hash_set(ctx->cache, key, BASIC_ESTABLISHED);
@@ -270,49 +271,49 @@ static const char* escape_ldap(ha_buffer_t* buf, const char* str)
return ha_bufdata(buf);
}
-static const char* substitute_params(ldap_context_t* ctx, ha_buffer_t* buf,
+static const char* substitute_params(ldap_context_t* ctx, const ha_request_t* req,
const char* user, const char* str)
{
const char* t;
- ASSERT(ctx && buf && user && str);
+ ASSERT(ctx && req && user && str);
/* TODO: We need to be escaping the user and realm properly */
/* This starts a new block to join */
- ha_bufcpy(buf, "");
+ ha_bufcpy(req->buf, "");
while(str[0])
{
t = strchr(str, '%');
if(!t)
{
- ha_bufjoin(buf);
- ha_bufcpy(buf, str);
+ ha_bufjoin(req->buf);
+ ha_bufcpy(req->buf, str);
break;
}
- ha_bufjoin(buf);
- ha_bufncpy(buf, str, t - str);
+ ha_bufjoin(req->buf);
+ ha_bufncpy(req->buf, str, t - str);
t++;
switch(t[0])
{
case 'u':
- ha_bufjoin(buf);
- escape_ldap(buf, user);
+ ha_bufjoin(req->buf);
+ escape_ldap(req->buf, user);
t++;
break;
case 'r':
- ha_bufjoin(buf);
- escape_ldap(buf, ctx->opts->realm);
+ ha_bufjoin(req->buf);
+ escape_ldap(req->buf, req->context->realm);
t++;
break;
case '%':
- ha_bufjoin(buf);
- ha_bufcpy(buf, "%");
+ ha_bufjoin(req->buf);
+ ha_bufcpy(req->buf, "%");
t++;
break;
};
@@ -320,7 +321,7 @@ static const char* substitute_params(ldap_context_t* ctx, ha_buffer_t* buf,
str = t;
}
- return ha_bufdata(buf);
+ return ha_bufdata(req->buf);
}
static const char* make_password_md5(ha_buffer_t* buf, const char* clearpw)
@@ -530,7 +531,8 @@ static int validate_ldap_password(ldap_context_t* ctx, LDAP* ld, LDAPMessage* en
}
static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
- ha_buffer_t* buf, const char* user, const char* clearpw)
+ ha_buffer_t* buf, const char* user, const char* realm,
+ const char* clearpw)
{
struct berval** ha1s;
struct berval** b;
@@ -548,7 +550,7 @@ static int validate_ldap_ha1(ldap_context_t* ctx, LDAP* ld, LDAPMessage* entry,
if(ha1s)
{
- digest_makeha1(key, user, ctx->opts->realm, clearpw);
+ digest_makeha1(key, user, realm, clearpw);
for(b = ha1s ; *b; b++)
{
@@ -674,7 +676,7 @@ static void save_ldap_connection(ldap_context_t* ctx, LDAP* ld)
}
}
-static int retrieve_user_entry(ldap_context_t* ctx, ha_buffer_t* buf, LDAP* ld,
+static int retrieve_user_entry(ldap_context_t* ctx, const ha_request_t* req, LDAP* ld,
const char* user, const char** dn,
LDAPMessage** entry, LDAPMessage** result)
{
@@ -685,12 +687,12 @@ static int retrieve_user_entry(ldap_context_t* ctx, ha_buffer_t* buf, LDAP* ld,
int scope;
int r;
- ASSERT(ctx && buf && ld && user && dn && entry && result);
+ ASSERT(ctx && req && ld && user && dn && entry && result);
if(ctx->filter)
{
/* Filters can also have %u and %r */
- filter = substitute_params(ctx, buf, user, ctx->filter);
+ filter = substitute_params(ctx, req, user, ctx->filter);
if(!filter)
return HA_CRITERROR;
}
@@ -751,7 +753,7 @@ static int retrieve_user_entry(ldap_context_t* ctx, ha_buffer_t* buf, LDAP* ld,
}
static int complete_digest_ha1(ldap_context_t* ctx, digest_record_t* rec,
- ha_buffer_t* buf, const char* user)
+ const ha_request_t* req, const char* user)
{
LDAP* ld = NULL; /* freed in finally */
LDAPMessage* results = NULL; /* freed in finally */
@@ -762,7 +764,7 @@ static int complete_digest_ha1(ldap_context_t* ctx, digest_record_t* rec,
const char* dn = NULL;
int r;
- ASSERT(ctx && rec && buf && user);
+ ASSERT(ctx && req && rec && user);
ld = get_ldap_connection(ctx);
if(!ld)
@@ -779,7 +781,7 @@ static int complete_digest_ha1(ldap_context_t* ctx, digest_record_t* rec,
if(ctx->dnmap)
{
/* The map can have %u and %r to denote user and realm */
- dn = substitute_params(ctx, buf, user, ctx->dnmap);
+ dn = substitute_params(ctx, req, user, ctx->dnmap);
if(!dn)
{
ret = HA_CRITERROR;
@@ -790,7 +792,7 @@ static int complete_digest_ha1(ldap_context_t* ctx, digest_record_t* rec,
}
/* Okay now we contact the LDAP server. */
- r = retrieve_user_entry(ctx, buf, ld, user, &dn, &entry, &results);
+ r = retrieve_user_entry(ctx, req, ld, user, &dn, &entry, &results);
if(r != HA_OK)
{
ret = r;
@@ -805,7 +807,7 @@ static int complete_digest_ha1(ldap_context_t* ctx, digest_record_t* rec,
{
if(*ha1s)
{
- ret = parse_ldap_ha1(buf, *ha1s, rec->ha1);
+ ret = parse_ldap_ha1(req->buf, *ha1s, rec->ha1);
if(ret != HA_OK)
{
if(ret == HA_FALSE)
@@ -824,11 +826,11 @@ static int complete_digest_ha1(ldap_context_t* ctx, digest_record_t* rec,
if(pws)
{
/* Find a cleartext password */
- const char* t = find_cleartext_password(buf, (const char**)pws);
+ const char* t = find_cleartext_password(req->buf, (const char**)pws);
if(t)
{
- digest_makeha1(rec->ha1, user, ctx->opts->realm, t);
+ digest_makeha1(rec->ha1, user, req->context->realm, t);
ret = HA_OK;
}
@@ -855,7 +857,7 @@ finally:
}
static int basic_ldap_response(ldap_context_t* ctx, const char* header,
- ha_response_t* resp, ha_buffer_t* buf)
+ const ha_request_t* req, ha_response_t* resp)
{
basic_header_t basic;
LDAP* ld = NULL;
@@ -866,9 +868,9 @@ static int basic_ldap_response(ldap_context_t* ctx, const char* header,
int found = 0;
int r;
- ASSERT(buf && header && resp && buf);
+ ASSERT(header && resp && req);
- if((r = basic_parse(header, buf, &basic)) < 0)
+ if((r = basic_parse(header, req->buf, &basic)) < 0)
return r;
/* Past this point we don't return directly */
@@ -908,7 +910,7 @@ static int basic_ldap_response(ldap_context_t* ctx, const char* header,
if(ctx->dnmap)
{
/* The map can have %u and %r to denote user and realm */
- dn = substitute_params(ctx, buf, basic.user, ctx->dnmap);
+ dn = substitute_params(ctx, req, basic.user, ctx->dnmap);
if(!dn)
{
ret = HA_CRITERROR;
@@ -936,7 +938,7 @@ static int basic_ldap_response(ldap_context_t* ctx, const char* header,
if(!ctx->dobind || !dn || ctx->filter)
{
- r = retrieve_user_entry(ctx, buf, ld, basic.user, &dn, &entry, &results);
+ r = retrieve_user_entry(ctx, req, ld, basic.user, &dn, &entry, &results);
if(r != HA_OK)
{
ret = r;
@@ -972,9 +974,10 @@ static int basic_ldap_response(ldap_context_t* ctx, const char* header,
/* Otherwise we compare the password attribute */
else
{
- ret = validate_ldap_password(ctx, ld, entry, buf, basic.user, basic.password);
+ ret = validate_ldap_password(ctx, ld, entry, req->buf, basic.user, basic.password);
if(ret == HA_FALSE)
- ret = validate_ldap_ha1(ctx, ld, entry, buf, basic.user, basic.password);
+ ret = validate_ldap_ha1(ctx, ld, entry, req->buf, basic.user,
+ req->context->realm, basic.password);
if(ret == HA_OK)
{
@@ -1003,25 +1006,25 @@ finally:
resp->detail = basic.user;
/* We put this connection into the successful connections */
- ret = add_cached_basic(ctx, basic.key);
+ ret = add_cached_basic(ctx, req->context, basic.key);
}
return ret;
}
static int digest_ldap_challenge(ldap_context_t* ctx, const ha_request_t* req,
- ha_response_t* resp, ha_buffer_t* buf, int stale)
+ ha_response_t* resp, int stale)
{
unsigned char nonce[DIGEST_NONCE_LEN];
const char* nonce_str;
const char* header;
- ASSERT(ctx && resp && buf);
+ ASSERT(ctx && resp && req);
#ifdef _DEBUG
- if(ctx->opts->digest_debugnonce)
+ if(req->context->digest_debugnonce)
{
- nonce_str = ctx->opts->digest_debugnonce;
+ nonce_str = req->context->digest_debugnonce;
ha_messagex(LOG_WARNING, "ldap: using debug nonce. security non-existant.");
}
else
@@ -1030,14 +1033,14 @@ static int digest_ldap_challenge(ldap_context_t* ctx, const ha_request_t* req,
unsigned char nonce[DIGEST_NONCE_LEN];
digest_makenonce(nonce, g_ldap_secret, NULL);
- nonce_str = ha_bufenchex(buf, nonce, DIGEST_NONCE_LEN);
+ nonce_str = ha_bufenchex(req->buf, nonce, DIGEST_NONCE_LEN);
if(!nonce_str)
return HA_CRITERROR;
}
/* Now generate a message to send */
- header = digest_challenge(buf, nonce_str, ctx->opts->realm,
- req->opts->digest_domains, stale);
+ header = digest_challenge(req->buf, nonce_str, req->context->realm,
+ req->digest_domain, stale);
if(!header)
return HA_CRITERROR;
@@ -1051,7 +1054,7 @@ static int digest_ldap_challenge(ldap_context_t* ctx, const ha_request_t* req,
}
static int digest_ldap_response(ldap_context_t* ctx, const char* header,
- const ha_request_t* req, ha_response_t* resp, ha_buffer_t* buf)
+ const ha_request_t* req, ha_response_t* resp)
{
unsigned char nonce[DIGEST_NONCE_LEN];
digest_header_t dg;
@@ -1062,18 +1065,18 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
int stale = 0;
int r;
- ASSERT(ctx && header && req && resp && buf);
+ ASSERT(ctx && header && req && resp);
/* We use this below to send a default response */
resp->code = -1;
- if((r = digest_parse(header, buf, &dg, nonce)) < 0)
+ if((r = digest_parse(header, req->buf, &dg, nonce)) < 0)
return r;
#ifdef _DEBUG
- if(ctx->opts->digest_debugnonce)
+ if(req->context->digest_debugnonce)
{
- if(dg.nonce && strcmp(dg.nonce, ctx->opts->digest_debugnonce) != 0)
+ if(dg.nonce && strcmp(dg.nonce, req->context->digest_debugnonce) != 0)
{
ret = HA_FALSE;
ha_messagex(LOG_WARNING, "ldap: digest response contains invalid nonce");
@@ -1081,7 +1084,7 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
}
/* Do a rough hash into the real nonce, for use as a key */
- md5_string(nonce, ctx->opts->digest_debugnonce);
+ md5_string(nonce, req->context->digest_debugnonce);
/* Debug nonce's never expire */
expiry = time(NULL);
@@ -1099,10 +1102,10 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
}
}
- rec = get_cached_digest(ctx, nonce);
+ rec = get_cached_digest(ctx, req->context, nonce);
/* Check to see if we're stale */
- if((expiry + ctx->opts->cache_timeout) <= time(NULL))
+ if((expiry + req->context->cache_timeout) <= time(NULL))
{
ha_messagex(LOG_INFO, "ldap: nonce expired, sending stale challenge: %s",
dg.username);
@@ -1127,7 +1130,7 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
goto finally;
}
- r = complete_digest_ha1(ctx, rec, buf, dg.username);
+ r = complete_digest_ha1(ctx, rec, req, dg.username);
if(r != HA_OK)
{
ret = r;
@@ -1141,7 +1144,7 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
rec->nc++;
}
- ret = digest_check(&dg, rec, ctx->opts, buf,
+ ret = digest_check(&dg, rec, req->context, req->buf,
req->args[AUTH_ARG_METHOD], req->args[AUTH_ARG_URI]);
if(ret == HA_BADREQ)
@@ -1156,8 +1159,8 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
resp->detail = dg.username;
/* Figure out if we need a new nonce */
- if((expiry + (ctx->opts->cache_timeout -
- (ctx->opts->cache_timeout / 8))) < time(NULL))
+ if((expiry + (req->context->cache_timeout -
+ (req->context->cache_timeout / 8))) < time(NULL))
{
ha_messagex(LOG_INFO, "ldap: nonce almost expired, creating new one: %s",
dg.username);
@@ -1166,7 +1169,7 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
stale = 1;
}
- t = digest_respond(buf, &dg, rec, stale ? nonce : NULL);
+ t = digest_respond(req->buf, &dg, rec, stale ? nonce : NULL);
if(!t)
{
ret = HA_CRITERROR;
@@ -1179,7 +1182,7 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
ha_messagex(LOG_NOTICE, "ldap: validated digest user: %s", dg.username);
/* Put the connection into the cache */
- if((r = save_cached_digest(ctx, rec)) < 0)
+ if((r = save_cached_digest(ctx, req->context, rec)) < 0)
ret = r;
rec = NULL;
@@ -1193,7 +1196,7 @@ finally:
/* If nobody above responded then challenge the client again */
if(resp->code == -1)
- return digest_ldap_challenge(ctx, req, resp, buf, stale);
+ return digest_ldap_challenge(ctx, req, resp, stale);
return ret;
}
@@ -1205,7 +1208,7 @@ finally:
int ldap_config(ha_context_t* context, const char* name, const char* value)
{
- ldap_context_t* ctx = (ldap_context_t*)(context->data);
+ ldap_context_t* ctx = (ldap_context_t*)(context->ctx_data);
ASSERT(name && value && value[0]);
@@ -1306,12 +1309,12 @@ int ldap_inithand(ha_context_t* context)
/* Context specific initialization */
else
{
- ldap_context_t* ctx = (ldap_context_t*)(context->data);
+ ldap_context_t* ctx = (ldap_context_t*)(context->ctx_data);
ASSERT(ctx);
/* Make sure there are some types of authentication we can do */
- if(!(context->opts->types & (HA_TYPE_BASIC | HA_TYPE_DIGEST)))
+ if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_DIGEST)))
{
ha_messagex(LOG_ERR, "ldap: module configured, but does not implement any "
"configured authentication type.");
@@ -1357,9 +1360,6 @@ int ldap_inithand(ha_context_t* context)
memset(ctx->pool, 0, sizeof(LDAP*) * ctx->ldap_max);
- /* Copy some settings over for easy access */
- ctx->opts = context->opts;
-
ha_messagex(LOG_INFO, "ldap: initialized handler");
}
@@ -1375,7 +1375,7 @@ void ldap_destroy(ha_context_t* context)
return;
/* Note: We don't need to be thread safe here anymore */
- ctx = (ldap_context_t*)(context->data);
+ ctx = (ldap_context_t*)(context->ctx_data);
ASSERT(ctx);
@@ -1398,22 +1398,21 @@ void ldap_destroy(ha_context_t* context)
ha_messagex(LOG_INFO, "ldap: uninitialized handler");
}
-int ldap_process(ha_context_t* context, const ha_request_t* req,
- ha_response_t* resp, ha_buffer_t* buf)
+int ldap_process(const ha_request_t* req, ha_response_t* resp)
{
- ldap_context_t* ctx = (ldap_context_t*)context->data;
+ ldap_context_t* ctx = (ldap_context_t*)req->context->ctx_data;
time_t t = time(NULL);
const char* header = NULL;
int ret, r;
- ASSERT(req && resp && buf);
+ ASSERT(req && resp);
ASSERT(req->args[AUTH_ARG_METHOD]);
ASSERT(req->args[AUTH_ARG_URI]);
ha_lock(NULL);
/* Purge out stale connection stuff. */
- r = hash_purge(ctx->cache, t - ctx->opts->cache_timeout);
+ r = hash_purge(ctx->cache, t - req->context->cache_timeout);
ha_unlock(NULL);
@@ -1425,26 +1424,26 @@ int ldap_process(ha_context_t* context, const ha_request_t* req,
/* Check the headers and see if we got a response thingy */
- if(context->opts->types & HA_TYPE_DIGEST)
+ if(req->context->allowed_types & HA_TYPE_DIGEST)
{
header = ha_getheader(req, "Authorization", HA_PREFIX_DIGEST);
if(header)
{
ha_messagex(LOG_DEBUG, "ldap: processing digest auth header");
- ret = digest_ldap_response(ctx, header, req, resp, buf);
+ ret = digest_ldap_response(ctx, header, req, resp);
if(ret < 0)
return ret;
}
}
/* Or a basic authentication */
- if(!header && context->opts->types & HA_TYPE_BASIC)
+ if(!header && req->context->allowed_types & HA_TYPE_BASIC)
{
header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC);
if(header)
{
ha_messagex(LOG_DEBUG, "ldap: processing basic auth header");
- ret = basic_ldap_response(ctx, header, resp, buf);
+ ret = basic_ldap_response(ctx, header, req, resp);
if(ret < 0)
return ret;
}
@@ -1456,20 +1455,20 @@ int ldap_process(ha_context_t* context, const ha_request_t* req,
{
resp->code = HA_SERVER_DECLINE;
- if(context->opts->types & HA_TYPE_BASIC)
+ if(req->context->allowed_types & HA_TYPE_BASIC)
{
- ha_bufmcat(buf, "BASIC realm=\"", ctx->opts->realm , "\"", NULL);
+ ha_bufmcat(req->buf, "BASIC realm=\"", req->context->realm , "\"", NULL);
- if(ha_buferr(buf))
+ if(ha_buferr(req->buf))
return HA_CRITERROR;
- ha_addheader(resp, "WWW-Authenticate", ha_bufdata(buf));
+ ha_addheader(resp, "WWW-Authenticate", ha_bufdata(req->buf));
ha_messagex(LOG_DEBUG, "ldap: sent basic auth request");
}
- if(context->opts->types & HA_TYPE_DIGEST)
+ if(req->context->allowed_types & HA_TYPE_DIGEST)
{
- ret = digest_ldap_challenge(ctx, req, resp, buf, 0);
+ ret = digest_ldap_challenge(ctx, req, resp, 0);
if(ret < 0)
return ret;
}