diff options
Diffstat (limited to 'daemon/ldap.c')
-rw-r--r-- | daemon/ldap.c | 179 |
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; } |