From 80b0e2c0fdad108454ae87130496f595f0b81b81 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 7 May 2004 22:02:29 +0000 Subject: - Reworked the internal API - Added common functions for trimming - Debugging - Reworked the module to the new protocol --- apache1x/mod_httpauth.c | 215 +++++++++++++++++++++++----------------------- common/buffer.c | 6 +- common/stringx.c | 29 +++++++ common/stringx.h | 9 ++ configure.in | 4 +- daemon/Makefile.am | 2 +- daemon/basic.c | 7 +- daemon/digest.c | 23 ++--- daemon/digest.h | 2 +- daemon/httpauthd.c | 221 +++++++++++++++++++++++++++--------------------- daemon/httpauthd.h | 48 +++++------ daemon/ldap.c | 179 +++++++++++++++++++-------------------- daemon/ntlm.c | 42 +++++---- daemon/simple.c | 151 ++++++++++++++++----------------- sample/httpauthd.conf | 6 +- 15 files changed, 496 insertions(+), 448 deletions(-) create mode 100644 common/stringx.c create mode 100644 common/stringx.h diff --git a/apache1x/mod_httpauth.c b/apache1x/mod_httpauth.c index fae668e..39cdd8d 100644 --- a/apache1x/mod_httpauth.c +++ b/apache1x/mod_httpauth.c @@ -8,6 +8,7 @@ #include #include "sock_any.h" +#include "stringx.h" #define DEFAULT_PORT 8020 @@ -17,9 +18,9 @@ typedef struct httpauth_context { const char* socketname; int socket; - const char* method; int types; - char* authtypes; + const char* method; + const char* domain; pool* child_pool; } httpauth_context_t; @@ -68,7 +69,7 @@ static const char* set_socket(cmd_parms* cmd, void* config, const char* val) static const char* set_method(cmd_parms* cmd, void* config, const char* val) { httpauth_context_t* conf = (httpauth_context_t*)config; - conf->method = ap_pstrdup(cmd->pool, val); + conf->method = val; return NULL; } @@ -96,6 +97,13 @@ static const char* set_types(cmd_parms* cmd, void* config, const char* val) return NULL; } +static const char* set_domain(cmd_parms* cmd, void* config, const char* val) +{ + httpauth_context_t* conf = (httpauth_context_t*)config; + conf->domain = trim_space(ap_pstrdup(cmd->pool, val)); + return NULL; +} + static const command_rec httpauth_cmds[] = { { "HttpAuthSocket", set_socket, NULL, OR_AUTHCFG, TAKE1, @@ -104,6 +112,8 @@ static const command_rec httpauth_cmds[] = "The method that httpauthd should use to authenticate" }, { "HttpAuthTypes", set_types, NULL, OR_AUTHCFG, ITERATE, "The types of authentiction allowed (Basic, Digest, NTLM ...)" }, + { "HttpAuthDigestDomain", set_domain, NULL, OR_AUTHCFG, RAW_ARGS, + "The domain for which digest authentication is relevant" }, { NULL, NULL, NULL, 0, 0, NULL } }; @@ -111,32 +121,6 @@ static const command_rec httpauth_cmds[] = * Socket handling code */ -const char* trim_start(const char* data) -{ - while(*data && ap_isspace(*data)) - ++data; - return data; -} - -char* trim_end(char* data) -{ - char* t = data + strlen(data); - - while(t > data && ap_isspace(*(t - 1))) - { - t--; - *t = 0; - } - - return data; -} - -char* trim_space(char* data) -{ - data = (char*)trim_start(data); - return trim_end(data); -} - void read_junk(httpauth_context_t* ctx, request_rec* r) { char buf[16]; @@ -280,6 +264,13 @@ int read_response(httpauth_context_t* ctx, request_rec* r, if(code) *code = c; + if(c >= 400) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "httpauth: received error from httpauthd: %d %s", c, line); + return -1; + } + /* Get the second response code if we're a 200 */ if(c == 200) { @@ -296,7 +287,9 @@ int read_response(httpauth_context_t* ctx, request_rec* r, *ccode = c; } - *details = trim_space(line); + if(details) + *details = trim_space(line); + return 0; } @@ -416,6 +409,46 @@ void disconnect_socket(httpauth_context_t* ctx, server_rec* s) } } +int write_data(httpauth_context_t* ctx, server_rec* s, const char* data) +{ + int r; + + if(ctx->socket == -1) + { + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "httpauth: Socket to httpauthd daemon closed. Can't write data."); + return -1; + } + + while(*data != 0) + { + r = write(ctx->socket, data, strlen(data)); + + if(r > 0) + data += r; + + else if(r == -1) + { + if(errno == EAGAIN) + continue; + + /* The other end closed. no message */ + if(errno == EPIPE) + disconnect_socket(ctx, s); + + else + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "httpauth: Couldn't write data to daemon"); + + errno = 0; + return -1; + } + } + + errno = 0; + return 0; +} + int connect_socket(httpauth_context_t* ctx, request_rec* r) { struct sockaddr_any sany; @@ -468,97 +501,76 @@ int connect_httpauth(httpauth_context_t* ctx, request_rec* r) if(read_response(ctx, r, &code, NULL, &details) == -1) goto finally; - if(code >= 400) + if(code != 100) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "httpauth: received error from httpauthd: %d", code); + "httpauth: protocol error (Expected 100, got %d)", code); goto finally; } - if(code != 100) + /* Check theversion number */ + details = trim_space(details); + + if(strcmp(details, "HTTPAUTH/1.0") != 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "httpauth: protocol error (Expected 100, got %d)", code); + "httpauth: Daemon speaking incompatible protocol version: %s", details); goto finally; } - /* - * Not pretty code :) In order to keep from parsing up - * the whole available types string that we get from the - * client, and keeping an array etc... we just make sure - * that the auth type requested is in the string, and - * it's on word boundaries. - */ - - t = ap_strcasestr(details, ctx->method); - if(t) + /* Send our method */ + if(ctx->method) { - /* Make sure we're at a parse mark */ - if(t == details || ap_isspace(*(t - 1))) - { - /* Make sure end is at a parse mark */ - t += strlen(ctx->method); - if(!*t || ap_isspace(*t)) - { - ap_log_rerror(APLOG_MARK, APLOG_INFO, r, - "httpauth: connected to daemon (methods: %s)", details); + t = ap_pstrcat(r->pool, "SET Method ", ctx->method, "\n", NULL); - /* We're cool! */ - ret = 0; - goto finally; - } - } - } + if(write_data(ctx, r->server, t) == -1) + goto finally; - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "httpauth: The configured method '%s' is not provided by httpauthd: %s", - ctx->method, details); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r, + "httpauth: sent method to daemon: %s", t); -finally: - if(ret == -1) - disconnect_socket(ctx, r->server); + if(read_response(ctx, r, &code, NULL, NULL) == -1) + goto finally; - return ret; -} - -int write_data(httpauth_context_t* ctx, server_rec* s, const char* data) -{ - int r; - - if(ctx->socket == -1) - { - ap_log_error(APLOG_MARK, APLOG_ERR, s, - "httpauth: Socket to httpauthd daemon closed. Can't write data."); - return -1; + if(code != 202) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "httpauth: protocol error (Expected 202, got %d)", code); + goto finally; + } } - while(*data != 0) + /* Send any setup info we have */ + if(ctx->domain) { - r = write(ctx->socket, data, strlen(data)); - - if(r > 0) - data += r; + t = ap_pstrcat(r->pool, "SET Domain ", ctx->domain, "\n", NULL); - else if(r == -1) - { - if(errno == EAGAIN) - continue; + if(write_data(ctx, r->server, t) == -1) + goto finally; - /* The other end closed. no message */ - if(errno == EPIPE) - disconnect_socket(ctx, s); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, r, + "httpauth: sent domains to daemon: %s", t); - else - ap_log_error(APLOG_MARK, APLOG_ERR, s, - "httpauth: Couldn't write data to daemon"); + if(read_response(ctx, r, &code, NULL, NULL) == -1) + goto finally; - errno = 0; - return -1; + if(code != 202) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "httpauth: protocol error (Expected 202, got %d)", code); + goto finally; } } - errno = 0; - return 0; + /* We're cool! */ + ret = 0; + ap_log_rerror(APLOG_MARK, APLOG_INFO, r, "httpauth: connected to daemon"); + +finally: + if(ret == -1) + disconnect_socket(ctx, r->server); + + return ret; } int write_request(httpauth_context_t* ctx, request_rec* r) @@ -574,7 +586,7 @@ int write_request(httpauth_context_t* ctx, request_rec* r) */ /* Send the request header to httpauthd */ - t = ap_pstrcat(r->pool, "AUTH ", ctx->method, " XXX ", r->method, + t = ap_pstrcat(r->pool, "AUTH XXX ", r->method, " ", r->unparsed_uri, "\n", NULL); if(write_data(ctx, r->server, t) == -1) @@ -679,14 +691,6 @@ static int httpauth_authenticate(request_rec* r) if(read_response(ctx, r, &code, &ccode, &details) == -1) return SERVER_ERROR; - if(code >= 400 && code < 600) - { - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, - "httpauth: received server error from httpauthd: %d%s%s%s", - code, details ? " (" : "", details ? details : "", details ? ")" : ""); - return SERVER_ERROR; - } - if(code != 200) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, @@ -756,3 +760,4 @@ module MODULE_VAR_EXPORT httpauth_module = * so we include this here */ #include "../common/sock_any.c" +#include "../common/stringx.c" diff --git a/common/buffer.c b/common/buffer.c index 72f0b6c..5a77922 100644 --- a/common/buffer.c +++ b/common/buffer.c @@ -1,6 +1,7 @@ #include "usuals.h" #include "httpauthd.h" +#include "stringx.h" #include @@ -316,10 +317,7 @@ char* ha_bufparseline(ha_buffer_t* buf, int trim) buf->_pp = t + 1; if(trim) - { - while(t > line && isspace(*(--t))) - *t = 0; - } + line = trim_space(line); /* We don't return empty strings */ if(line[0] == 0) diff --git a/common/stringx.c b/common/stringx.c new file mode 100644 index 0000000..159a7f4 --- /dev/null +++ b/common/stringx.c @@ -0,0 +1,29 @@ + +#include +#include "stringx.h" + +const char* trim_start(const char* data) +{ + while(*data && isspace(*data)) + ++data; + return data; +} + +char* trim_end(char* data) +{ + char* t = data + strlen(data); + + while(t > data && isspace(*(t - 1))) + { + t--; + *t = 0; + } + + return data; +} + +char* trim_space(char* data) +{ + data = (char*)trim_start(data); + return trim_end(data); +} diff --git a/common/stringx.h b/common/stringx.h new file mode 100644 index 0000000..4776170 --- /dev/null +++ b/common/stringx.h @@ -0,0 +1,9 @@ + +#ifndef __STRINGX_H__ +#define __STRINGX_H__ + +const char* trim_start(const char* data); +char* trim_end(char* data); +char* trim_space(char* data); + +#endif /* __STRINGX_H__ */ diff --git a/configure.in b/configure.in index 9937e2f..5ba49a1 100644 --- a/configure.in +++ b/configure.in @@ -36,8 +36,8 @@ dnl Nate Nielsen dnl dnl Process this file with autoconf to produce a configure script. -AC_INIT(httpauth, 0.1, nielsen@memberwebs.com) -AM_INIT_AUTOMAKE(httpauth, 0.1) +AC_INIT(httpauth, 0.2, nielsen@memberwebs.com) +AM_INIT_AUTOMAKE(httpauth, 0.2) LDFLAGS="$LDFLAGS -L/usr/local/lib" CFLAGS="$CFLAGS -I/usr/local/include -g -O0" diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 9e8292a..5ad8665 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -4,7 +4,7 @@ sbin_PROGRAMS = httpauthd httpauthd_SOURCES = httpauthd.c httpauthd.h usuals.h compat.h compat.c \ buffer.c misc.c basic.h basic.c ntlm.c hash.c hash.h ntlmssp.h ntlmssp.c \ md5.c md5.h sha1.c sha1.h digest.h digest.c ldap.c defaults.h simple.c \ - ../common/sock_any.c ../common/sock_any.h \ + ../common/sock_any.c ../common/sock_any.h ../common/stringx.c\ \ smblib/smblib.c smblib/smblib-util.c smblib/file.c smblib/smb-errors.c \ smblib/exper.c smblib/smblib-api.c smblib/smblib.h smblib/std-defines.h \ diff --git a/daemon/basic.c b/daemon/basic.c index 1d476ca..fc0a096 100644 --- a/daemon/basic.c +++ b/daemon/basic.c @@ -2,6 +2,7 @@ #include "usuals.h" #include "httpauthd.h" #include "basic.h" +#include "stringx.h" int basic_parse(const char* header, ha_buffer_t* buf, basic_header_t* rec) { @@ -10,15 +11,13 @@ int basic_parse(const char* header, ha_buffer_t* buf, basic_header_t* rec) memset(rec, 0, sizeof(*rec)); - /* Trim the white space */ - while(*header && isspace(*header)) - header++; - /* * Authorization header is in this format: * * "Basic " B64(user ":" password) */ + + header = trim_start(header); header = (const char*)ha_bufdec64(buf, header, NULL); if(!header) diff --git a/daemon/digest.c b/daemon/digest.c index 95f62f0..405a661 100644 --- a/daemon/digest.c +++ b/daemon/digest.c @@ -3,6 +3,7 @@ #include "md5.h" #include "httpauthd.h" #include "digest.h" +#include "stringx.h" #include @@ -145,10 +146,7 @@ int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec, while(header[0]) { /* find key */ - - while(header[0] && isspace(header[0])) - header++; - + header = (char*)trim_start(header); key = header; while(header[0] && header[0] != '=' && header[0] != ',' && @@ -165,9 +163,7 @@ int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec, if(isspace(header[0])) { - while(header[0] && isspace(header[0])) - header++; - + header = (char*)trim_start(header); next = header[0]; } @@ -175,8 +171,7 @@ int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec, if(next == '=') { - while(header[0] && isspace(header[0])) - header++; + header = (char*)trim_start(header); if(header[0] == '\"') /* quoted string */ { @@ -252,7 +247,7 @@ int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec, return HA_OK; } -int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_opts_t* opts, +int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_t* ctx, ha_buffer_t* buf, const char* method, const char* uri) { unsigned char hash[MD5_LEN]; @@ -260,7 +255,7 @@ int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_opt const char* digest; const char* t; - ASSERT(opts && method && buf && dg && rec); + ASSERT(ctx && method && buf && dg && rec); /* TODO: Many of these should somehow communicate BAD REQ back to the client */ @@ -291,7 +286,7 @@ int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_opt return HA_BADREQ; } - if(strcmp(dg->realm, opts->realm) != 0) + if(strcmp(dg->realm, ctx->realm) != 0) { ha_messagex(LOG_ERR, "digest response contains invalid realm: %s", dg->realm); return HA_FALSE; @@ -318,7 +313,7 @@ int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_opt return HA_BADREQ; } - if(!opts->digest_ignorenc) + if(!ctx->digest_ignorenc) { /* The nonce count */ if(!dg->nc || !dg->nc[0]) @@ -368,7 +363,7 @@ int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_opt return HA_BADREQ; } - if(!opts->digest_ignoreuri && strcmp(dg->uri, uri) != 0) + if(!ctx->digest_ignoreuri && strcmp(dg->uri, uri) != 0) { ha_uri_t d_uri; ha_uri_t s_uri; diff --git a/daemon/digest.h b/daemon/digest.h index de5dae3..8b3ecdf 100644 --- a/daemon/digest.h +++ b/daemon/digest.h @@ -42,7 +42,7 @@ int ha_digestparse(char* header, ha_buffer_t* buf, digest_header_t* rec, int ha_digestnonce(time_t* tm, unsigned char* nonce); -int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_opts_t* opts, +int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_t* opts, ha_buffer_t* buf, const char* method, const char* uri); const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg, diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c index 1092e94..00cb261 100644 --- a/daemon/httpauthd.c +++ b/daemon/httpauthd.c @@ -16,6 +16,7 @@ #include "httpauthd.h" #include "defaults.h" #include "sock_any.h" +#include "stringx.h" /* * This shouldn't be used by handlers, @@ -58,8 +59,9 @@ typedef struct httpauth_command { const char* name; int code; - int args; - const char** headers; + int word_args; /* Arguments to be parsed as words */ + int rest_arg; /* Parse remainder as one arg? */ + const char** headers; /* Headers needed/allowed */ } httpauth_command_t; @@ -73,10 +75,10 @@ const char* kAuthHeaders[] = /* The command definitions */ const httpauth_command_t kCommands[] = { - { "auth", REQTYPE_AUTH, 4, kAuthHeaders }, - { "set", REQTYPE_SET, 2, 0 }, - { "quit", REQTYPE_QUIT, 0, 0 }, - { NULL, -1, -1 } + { "auth", REQTYPE_AUTH, 3, 0, kAuthHeaders }, + { "set", REQTYPE_SET, 1, 1, NULL }, + { "quit", REQTYPE_QUIT, 0, 0, NULL }, + { NULL, -1, 0, 0, NULL } }; typedef struct httpauth_thread @@ -537,8 +539,10 @@ static int httpauth_read(int ifd, ha_request_t* req, ASSERT(ifd != -1); /* Clean up the request header */ - memset(req, 0, sizeof(*req)); req->type = -1; + memset(req->args, 0, sizeof(req->args)); + memset(req->headers, 0, sizeof(req->headers)); + /* This guarantees a bit of memory allocated, and resets buffer */ ha_bufreset(buf); @@ -585,9 +589,13 @@ static int httpauth_read(int ifd, ha_request_t* req, return more; /* Now parse the arguments if any */ - for(i = 0; i < cmd->args; i++) + for(i = 0; i < cmd->word_args; i++) req->args[i] = ha_bufparseword(buf, " \t"); + /* Does it want the rest as one argument? */ + if(cmd->rest_arg) + req->args[i] = ha_bufparseline(buf, 1); + /* Now skip anything else we have in the buffer */ ha_bufskip(buf); @@ -742,6 +750,9 @@ static int httpauth_respond(int ofd, int scode, int ccode, const char* msg) { switch(scode) { + case HA_SERVER_ACCEPTED: + msg = "Accepted"; + break; case HA_SERVER_ERROR: msg = "Internal Error "; break; @@ -849,62 +860,49 @@ static int httpauth_ready(int ofd, ha_buffer_t* buf) } -static int httpauth_auth(int ofd, ha_request_t* req, - ha_response_t* resp, ha_buffer_t* outb) +static int httpauth_auth(int ofd, ha_request_t* req, ha_response_t* resp) { - httpauth_loaded_t* h; - int processed = 0; int r; - ASSERT(req && resp && outb); + ASSERT(req && resp); + + if(!req->context) + { + ha_messagex(LOG_ERR, "no auth method set"); + return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "No Auth Method Set"); + } /* Clear out our response */ - memset(resp, 0, sizeof(*resp)); + resp->code = -1; + resp->detail = NULL; + memset(resp->headers, 0, sizeof(resp->headers)); + ASSERT(resp->buf != NULL); /* Check our connection argument */ if(!req->args[AUTH_ARG_CONN] || !(req->args[AUTH_ARG_CONN][0])) { ha_messagex(LOG_ERR, "missing connection ID in request"); - return HA_BADREQ; + return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing Connection ID"); } /* Check our uri argument */ if(!req->args[AUTH_ARG_URI] || !(req->args[AUTH_ARG_URI][0])) { ha_messagex(LOG_ERR, "missing URI in request"); - return HA_BADREQ; + return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing URI"); } /* Check our connection arguments */ if(!req->args[AUTH_ARG_METHOD] || !(req->args[AUTH_ARG_METHOD][0])) { - ha_messagex(LOG_ERR, "missing method in request"); - return HA_BADREQ; - } - - /* Find a handler for this type */ - for(h = g_handlers; h; h = h->next) - { - if(strcasecmp(h->ctx.name, req->args[0]) == 0) - { - ha_messagex(LOG_INFO, "processing request with method: %s (%s)", - h->ctx.name, h->ctx.handler->type); - - /* Now let the handler handle it */ - ASSERT(h->ctx.handler->f_process); - - processed = 1; - r = (h->ctx.handler->f_process)(&(h->ctx), req, resp, outb); - if(r < 0) - return r; - } + ha_messagex(LOG_ERR, "missing HTTP method in request"); + return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Missing HTTP Method"); } - if(!processed) - { - ha_messagex(LOG_ERR, "unknown authentication type: %s", req->args[0]); - return HA_BADREQ; - } + ASSERT(req->context->handler && req->context->handler->f_process); + r = (req->context->handler->f_process)(req, resp); + if(r < 0) + return r; if(httpauth_write(ofd, resp) < 0) return HA_CRITERROR; @@ -912,12 +910,14 @@ static int httpauth_auth(int ofd, ha_request_t* req, return HA_OK; } -static int httpauth_set(int ofd, ha_request_t* req, ha_request_opts_t* opts, - ha_buffer_t* outb) +static int httpauth_set(int ofd, ha_request_t* req) { + httpauth_loaded_t* h; const char* name = req->args[0]; const char* value = req->args[1]; + ASSERT(req); + /* Check our name argument */ if(!name || !*name) { @@ -927,7 +927,33 @@ static int httpauth_set(int ofd, ha_request_t* req, ha_request_opts_t* opts, if(strcasecmp(name, "Domain") == 0) { - opts->digest_domains = value ? value : ""; + req->digest_domain = value ? value : ""; + } + + else if(strcasecmp(name, "Method") == 0) + { + if(!value || !*value) + { + ha_messagex(LOG_ERR, "no auth method specified in SET request."); + return HA_BADREQ; + } + + /* Find a handler for this type */ + for(h = g_handlers; h; h = h->next) + { + if(strcasecmp(h->ctx.name, value) == 0) + { + req->context = &(h->ctx); + value = NULL; + break; + } + } + + if(value != NULL) + { + ha_messagex(LOG_ERR, "unknown authentication type: %s", req->args[0]); + return httpauth_respond(ofd, HA_SERVER_BADREQ, 0, "Unknown Auth Method"); + } } else @@ -942,11 +968,9 @@ static int httpauth_set(int ofd, ha_request_t* req, ha_request_opts_t* opts, static int httpauth_processor(int ifd, int ofd) { - ha_buffer_t inb; - ha_buffer_t outb; + ha_buffer_t buf; ha_request_t req; ha_response_t resp; - ha_request_opts_t opts; int result = -1; int r; @@ -954,14 +978,18 @@ static int httpauth_processor(int ifd, int ofd) ASSERT(ofd != -1); /* Initialize the memory buffers */ - ha_bufinit(&inb); - ha_bufinit(&outb); + ha_bufinit(&buf); + + memset(&req, 0, sizeof(req)); + memset(&resp, 0, sizeof(resp)); + + /* Set up some context stuff */ + req.digest_domain = ""; + req.buf = &buf; + resp.buf = &buf; - /* Initialize default options */ - memset(&opts, 0, sizeof(opts)); - opts.digest_domains = ""; - if(httpauth_ready(ofd, &outb) == -1) + if(httpauth_ready(ofd, &buf) == -1) { result = 1; goto finally; @@ -970,15 +998,14 @@ static int httpauth_processor(int ifd, int ofd) /* Now loop and handle the commands */ while(result == -1 && !g_quit) { - ha_bufreset(&outb); - ha_bufreset(&inb); + ha_bufreset(&buf); - r = httpauth_read(ifd, &req, &inb); + r = httpauth_read(ifd, &req, &buf); if(g_quit) continue; - if(ha_buferr(&inb)) + if(ha_buferr(&buf)) r = HA_CRITERROR; if(r < 0) @@ -988,21 +1015,19 @@ static int httpauth_processor(int ifd, int ofd) break; } - log_request(&req, &inb, ifd); + log_request(&req, &buf, ifd); if(r == 0) result = 0; - req.opts = &opts; - switch(req.type) { case REQTYPE_AUTH: - r = httpauth_auth(ofd, &req, &resp, &outb); + r = httpauth_auth(ofd, &req, &resp); break; case REQTYPE_SET: - r = httpauth_set(ofd, &req, &opts, &outb); + r = httpauth_set(ofd, &req); break; case REQTYPE_QUIT: @@ -1023,7 +1048,7 @@ static int httpauth_processor(int ifd, int ofd) if(g_quit) continue; - if(ha_buferr(&outb)) + if(ha_buferr(&buf)) r = HA_CRITERROR; if(r < 0) @@ -1041,8 +1066,7 @@ static int httpauth_processor(int ifd, int ofd) close(ofd); finally: - ha_buffree(&outb); - ha_buffree(&inb); + ha_buffree(&buf); return result; } @@ -1052,44 +1076,40 @@ finally: */ static ha_context_t* config_addhandler(ha_buffer_t* buf, const char* alias, - ha_handler_t* handler, const ha_context_opts_t* defaults) + ha_handler_t* handler, const ha_context_t* defaults) { httpauth_loaded_t* loaded; - ha_context_opts_t* opts; int len; ASSERT(buf && alias && handler && defaults); - len = sizeof(httpauth_loaded_t) + sizeof(ha_context_opts_t) + - handler->context_size; + len = sizeof(httpauth_loaded_t) + handler->context_size; loaded = (httpauth_loaded_t*)ha_bufmalloc(buf, len); if(!loaded) errx(1, "out of memory"); + memset(loaded, 0, len); - /* Setup the options */ - opts = (ha_context_opts_t*)(((unsigned char*)loaded) + - sizeof(httpauth_loaded_t)); + /* Setup the options from the defaults */ + memcpy(&(loaded->ctx), defaults, sizeof(ha_context_t)); - memcpy(opts, defaults, sizeof(ha_context_opts_t)); - loaded->ctx.opts = opts; if(handler->context_size) { - void* mem = ((unsigned char*)(opts)) + sizeof(ha_context_opts_t); + void* mem = ((unsigned char*)(loaded)) + sizeof(httpauth_loaded_t); /* Initialize the defaults properly */ if(handler->context_default) memcpy(mem, handler->context_default, handler->context_size); - loaded->ctx.data = mem; + loaded->ctx.ctx_data = mem; } else { - loaded->ctx.data = NULL; + loaded->ctx.ctx_data = NULL; } loaded->ctx.name = (char*)alias; @@ -1121,13 +1141,15 @@ static ha_context_t* config_addhandler(ha_buffer_t* buf, const char* alias, return &(loaded->ctx); } +#define VALID_ALIAS_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_-." + static int config_parse(const char* file, ha_buffer_t* buf) { - ha_context_opts_t defaults; + ha_context_t defaults; ha_context_t* ctx = NULL; int line = 0; int fd; - const char** t; + char* t; char* name; char* value; int more = 1; @@ -1143,14 +1165,11 @@ static int config_parse(const char* file, ha_buffer_t* buf) /* These are the default options for the contexts */ memset(&defaults, 0, sizeof(defaults)); - defaults.types = 0xFFFFFFFF; /* All types by default */ + defaults.allowed_types = 0xFFFFFFFF; /* All types by default */ defaults.cache_timeout = DEFAULT_TIMEOUT; /* Timeout for cache */ defaults.cache_max = DEFAULT_CACHEMAX; defaults.realm = ""; - - ha_bufreset(buf); - /* Read each line and process */ while(more) { @@ -1189,6 +1208,26 @@ static int config_parse(const char* file, ha_buffer_t* buf) /* remove the bracket */ name[strlen(name) - 1] = 0; + /* + * Take out any colon found, past which would + * be an aliased name + */ + t = strchr(name, ':'); + if(t != NULL) + { + *t = 0; + t++; + + /* Rid of whitespace on ends */ + t = trim_space(t); + + /* Validate the alias name */ + if(!*t || strspn(t, VALID_ALIAS_CHARS) != strlen(t)) + errx(1, "invalid name for method: %s", t); + } + + /* Rid of whitespace */ + name = trim_space(name); /* Look for a handler with this type */ for(i = 0; i < countof(g_handlerlist); i++) @@ -1205,7 +1244,7 @@ static int config_parse(const char* file, ha_buffer_t* buf) errx(1, "unknown method type '%s' (line %d)", name, line); /* If we had a last handler then add it to handlers */ - ctx = config_addhandler(buf, name, handler, &defaults); + ctx = config_addhandler(buf, t ? t : name, handler, &defaults); /* Rest doesn't apply to handler headers */ continue; @@ -1248,12 +1287,6 @@ static int config_parse(const char* file, ha_buffer_t* buf) /* Otherwise we're in a handler */ else { - if(strcmp("alias", name) == 0) - { - ctx->name = value; - recog = 1; - } - if(ctx->handler->f_config) { r = (ctx->handler->f_config)(ctx, name, value); @@ -1268,7 +1301,7 @@ static int config_parse(const char* file, ha_buffer_t* buf) /* Options that are legal in both global and internal sections */ if(!recog) { - ha_context_opts_t* opts = ctx ? (ha_context_opts_t*)(ctx->opts) : &defaults; + ha_context_t* opts = ctx ? ctx : &defaults; ASSERT(opts); if(strcmp(name, "cachetimeout") == 0) @@ -1301,9 +1334,7 @@ static int config_parse(const char* file, ha_buffer_t* buf) /* Split the line into tokens at the spaces */ while(*value) { - while(*value && isspace(*value)) - value++; - + value = trim_space(value); t = value; while(*t && !isspace(*t)) @@ -1327,7 +1358,7 @@ static int config_parse(const char* file, ha_buffer_t* buf) if(types == 0) errx(1, "no authentication types for '%s' (line %d)", name, line); - opts->types = types; + opts->allowed_types = types; recog = 1; } diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h index ce5b21b..84a30cd 100644 --- a/daemon/httpauthd.h +++ b/daemon/httpauthd.h @@ -131,8 +131,7 @@ typedef int (*auth_config_t)(struct ha_context* ctx, const char* name, const cha * for this handler. Note that all data access in this * function must be thread-safe. */ -typedef int (*auth_process_t)(struct ha_context* ctx, const struct ha_request* req, - struct ha_response* resp, ha_buffer_t* mem); +typedef int (*auth_process_t)(const struct ha_request* req, struct ha_response* resp); /* An authentication handler */ typedef struct ha_handler @@ -175,12 +174,15 @@ ha_handler_t; #define HA_BADREQ -3 - -/* Standard options for the current context */ -typedef struct ha_context_opts +/* Context passed to the handler functions above */ +typedef struct ha_context { - /* Basic options */ - unsigned int types; + const char* name; /* A name assigned by the configuration file */ + const ha_handler_t* handler; /* The original handler structure */ + void* ctx_data; /* Handler specific data */ + + /* Context specific options */ + unsigned int allowed_types; int cache_timeout; int cache_max; @@ -192,16 +194,6 @@ typedef struct ha_context_opts unsigned int digest_ignorenc : 1; const char* digest_debugnonce; } -ha_context_opts_t; - -/* Context passed to the handler functions above */ -typedef struct ha_context -{ - const char* name; /* A name assigned by the configuration file */ - const ha_handler_t* handler; /* The original handler structure */ - const ha_context_opts_t* opts; /* The options */ - void* data; /* Handler specific data */ -} ha_context_t; @@ -247,16 +239,9 @@ ha_header_t; #define REQTYPE_AUTH 2 #define REQTYPE_SET 3 -#define AUTH_ARG_CONN 1 -#define AUTH_ARG_METHOD 2 -#define AUTH_ARG_URI 3 - -/* Options for the current request */ -typedef struct ha_request_opts -{ - const char* digest_domains; -} -ha_request_opts_t; +#define AUTH_ARG_CONN 0 +#define AUTH_ARG_METHOD 1 +#define AUTH_ARG_URI 2 /* A single request from client */ typedef struct ha_request @@ -264,7 +249,13 @@ typedef struct ha_request int type; const char* args[HA_MAX_ARGS]; ha_header_t headers[HA_MAX_HEADERS]; - const ha_request_opts_t* opts; + + /* Additional request info */ + ha_context_t* context; + const char* digest_domain; + + /* The buffer in use */ + ha_buffer_t* buf; } ha_request_t; @@ -282,6 +273,7 @@ typedef struct ha_response int code; const char* detail; ha_header_t headers[HA_MAX_HEADERS]; + ha_buffer_t* buf; } ha_response_t; 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; } diff --git a/daemon/ntlm.c b/daemon/ntlm.c index a46eecc..85bee1d 100644 --- a/daemon/ntlm.c +++ b/daemon/ntlm.c @@ -7,6 +7,7 @@ #include "defaults.h" #include "md5.h" #include "basic.h" +#include "stringx.h" #include @@ -539,7 +540,7 @@ finally: int ntlm_config(ha_context_t* context, const char* name, const char* value) { - ntlm_context_t* ctx = (ntlm_context_t*)(context->data); + ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); ASSERT(name && value && value[0]); @@ -579,12 +580,12 @@ int ntlm_init(ha_context_t* context) /* Per context initialization */ if(context) { - ntlm_context_t* ctx = (ntlm_context_t*)(context->data); + ntlm_context_t* ctx = (ntlm_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_NTLM))) + if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_NTLM))) { ha_messagex(LOG_ERR, "NTLM module configured, but does not implement any " "configured authentication type."); @@ -635,7 +636,7 @@ void ntlm_destroy(ha_context_t* context) if(context) { /* Note: We don't need to be thread safe here anymore */ - ntlm_context_t* ctx = (ntlm_context_t*)(context->data); + ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); if(ctx->pending) hash_free(ctx->pending); @@ -655,17 +656,16 @@ void ntlm_destroy(ha_context_t* context) } } -int ntlm_process(ha_context_t* context, const ha_request_t* req, - ha_response_t* resp, ha_buffer_t* buf) +int ntlm_process(const ha_request_t* req, ha_response_t* resp) { - ntlm_context_t* ctx = (ntlm_context_t*)(context->data); + ntlm_context_t* ctx = (ntlm_context_t*)(req->context->ctx_data); void* ntlm_connection_t = NULL; unsigned char key[NTLM_HASH_KEY_LEN]; const char* header = NULL; time_t t = time(NULL); int ret, r; - ASSERT(context && req && resp && buf); + ASSERT(req && resp); ASSERT(req->args[AUTH_ARG_CONN]); resp->code = -1; @@ -682,7 +682,7 @@ int ntlm_process(ha_context_t* context, const ha_request_t* req, * well as half open connections which expire. */ r = hash_purge(ctx->pending, t - ctx->pending_timeout); - r += hash_purge(ctx->established, t - context->opts->cache_timeout); + r += hash_purge(ctx->established, t - req->context->cache_timeout); ha_unlock(NULL); @@ -690,35 +690,33 @@ int ntlm_process(ha_context_t* context, const ha_request_t* req, ha_messagex(LOG_DEBUG, "ntlm: purged info from cache: %d", r); /* Look for a NTLM header */ - if(context->opts->types & HA_TYPE_NTLM) + if(req->context->allowed_types & HA_TYPE_NTLM) { header = ha_getheader(req, "Authorization", HA_PREFIX_NTLM); if(header) { /* Trim off for decoding */ - while(*header && isspace(*header)) - header++; + header = trim_start(header); ha_messagex(LOG_DEBUG, "ntlm: processing ntlm auth header"); - ret = ntlm_auth_ntlm(ctx, key, header, resp, buf); + ret = ntlm_auth_ntlm(ctx, key, header, resp, req->buf); if(ret < 0) return ret; } } /* If basic is enabled, and no NTLM */ - if(!header && context->opts->types & HA_TYPE_BASIC) + if(!header && req->context->allowed_types & HA_TYPE_BASIC) { /* Look for a Basic header */ header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC); if(header) { /* Trim off for decoding */ - while(*header && isspace(*header)) - header++; + header = trim_start(header); ha_messagex(LOG_DEBUG, "ntlm: processing basic auth header"); - ret = ntlm_auth_basic(ctx, key, header, resp, buf); + ret = ntlm_auth_basic(ctx, key, header, resp, req->buf); if(ret < 0) return ret; } @@ -757,20 +755,20 @@ int ntlm_process(ha_context_t* context, const ha_request_t* req, /* If authentication failed tell the browser about it */ resp->code = HA_SERVER_DECLINE; - if(context->opts->types & HA_TYPE_NTLM) + if(req->context->allowed_types & HA_TYPE_NTLM) { ha_addheader(resp, "WWW-Authenticate", HA_PREFIX_NTLM); ha_messagex(LOG_DEBUG, "ntlm: sent ntlm auth request"); } - if(context->opts->types & HA_TYPE_BASIC) + if(req->context->allowed_types & HA_TYPE_BASIC) { - ha_bufmcat(buf, HA_PREFIX_BASIC, "realm=\"", context->opts->realm, "\"", NULL); + ha_bufmcat(req->buf, HA_PREFIX_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, "ntlm: sent basic auth request"); } } diff --git a/daemon/simple.c b/daemon/simple.c index 7165c9c..8059051 100644 --- a/daemon/simple.c +++ b/daemon/simple.c @@ -27,7 +27,6 @@ typedef struct simple_context { /* Settings ----------------------------------------------------------- */ const char* filename; /* The file name with the user names */ - const ha_context_opts_t* opts; /* Options from httpauthd.c */ /* Context ----------------------------------------------------------- */ hash_t* cache; /* Some cached records or basic */ @@ -45,13 +44,14 @@ static void free_hash_object(void* arg, void* val) free(val); } -static digest_record_t* get_cached_digest(simple_context_t* ctx, unsigned char* nonce) +static digest_record_t* get_cached_digest(simple_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); @@ -83,13 +83,14 @@ static int have_cached_basic(simple_context_t* ctx, unsigned char* key) return ret; } -static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec) +static int save_cached_digest(simple_context_t* ctx, ha_context_t* c, + digest_record_t* rec) { int r; - ASSERT(ctx && rec); + ASSERT(ctx && c && rec); - if(ctx->opts->cache_max == 0) + if(c->cache_max == 0) { free_hash_object(NULL, rec); return HA_FALSE; @@ -97,7 +98,7 @@ static int save_cached_digest(simple_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); @@ -114,18 +115,19 @@ static int save_cached_digest(simple_context_t* ctx, digest_record_t* rec) return HA_OK; } -static int add_cached_basic(simple_context_t* ctx, unsigned char* key) +static int add_cached_basic(simple_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); @@ -142,7 +144,7 @@ static int add_cached_basic(simple_context_t* ctx, unsigned char* key) } static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, - ha_buffer_t* buf, const char* user) + const ha_request_t* req, const char* user) { FILE* f; char* t; @@ -151,7 +153,7 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, char line[SIMPLE_MAXLINE]; int ret = HA_FALSE; - ASSERT(ctx && rec && buf && user && user[0]); + ASSERT(ctx && rec && req && user && user[0]); ha_messagex(LOG_DEBUG, "searching password file for user's ha1: %s", user); f = fopen(ctx->filename, "r"); @@ -196,12 +198,12 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, t2++; /* Check the realm */ - if(strcmp(t, ctx->opts->realm) == 0) + if(strcmp(t, req->context->realm) == 0) { len = MD5_LEN; /* Now try antd decode the ha1 */ - t = ha_bufdechex(buf, t2, &len); + t = ha_bufdechex(req->buf, t2, &len); if(t && len == MD5_LEN) { ha_messagex(LOG_DEBUG, "simple: found ha1 for user: %s", user); @@ -220,13 +222,13 @@ static int complete_digest_ha1(simple_context_t* ctx, digest_record_t* rec, fclose(f); - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) return HA_CRITERROR; return ret; } -static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, +static int validate_user_password(simple_context_t* ctx, const ha_request_t* req, const char* user, const char* clearpw) { FILE* f; @@ -237,7 +239,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, size_t len; int ret = HA_FALSE; - ASSERT(ctx && buf); + ASSERT(ctx && req); ASSERT(user && user[0] && clearpw); ha_messagex(LOG_DEBUG, "simple: validating user against password file: %s", user); @@ -248,7 +250,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, return HA_FAILED; } - digest_makeha1(ha1, user, ctx->opts->realm, clearpw); + digest_makeha1(ha1, user, req->context->realm, clearpw); /* * Note: There should be no returns or jumps between @@ -268,12 +270,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, } /* Take white space off end of line */ - t = line + strlen(line); - while(t != line && isspace(*(t - 1))) - { - *(t - 1) = 0; - t--; - } + trim_end(line); t = strchr(line, ':'); if(t) @@ -308,12 +305,12 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, t2++; /* Check the realm */ - if(strcmp(t, ctx->opts->realm) == 0) + if(strcmp(t, req->context->realm) == 0) { len = MD5_LEN; /* Now try antd decode the ha1 */ - t = ha_bufdechex(buf, t2, &len); + t = ha_bufdechex(req->buf, t2, &len); if(t && len == MD5_LEN && memcmp(ha1, t, MD5_LEN) == 0) { ha_messagex(LOG_DEBUG, "simple: found valid ha1 for user: %s", user); @@ -323,7 +320,7 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, } } - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) break; } } @@ -331,23 +328,23 @@ static int validate_user_password(simple_context_t* ctx, ha_buffer_t* buf, fclose(f); - if(ha_buferr(buf)) + if(ha_buferr(req->buf)) return HA_CRITERROR; return ret; } static int simple_basic_response(simple_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; int ret = HA_FALSE; int found = 0; int r; - ASSERT(buf && header && resp && buf); + ASSERT(header && req && resp); - 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 */ @@ -367,7 +364,7 @@ static int simple_basic_response(simple_context_t* ctx, const char* header, goto finally; - ret = validate_user_password(ctx, buf, basic.user, basic.password); + ret = validate_user_password(ctx, req, basic.user, basic.password); if(ret == HA_OK) ha_messagex(LOG_NOTICE, "simple: validated basic user against file: %s", basic.user); @@ -383,26 +380,26 @@ 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 simple_digest_challenge(simple_context_t* ctx, const ha_request_t* req, - ha_response_t* resp, ha_buffer_t* buf, int stale) + ha_response_t* resp, int stale) { const char* nonce_str; const char* header; - ASSERT(ctx && resp && buf); + ASSERT(ctx && req && resp); /* Generate an nonce */ #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, "simple: using debug nonce. security non-existant."); } else @@ -411,15 +408,15 @@ static int simple_digest_challenge(simple_context_t* ctx, const ha_request_t* re unsigned char nonce[DIGEST_NONCE_LEN]; digest_makenonce(nonce, g_simple_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; @@ -433,7 +430,7 @@ static int simple_digest_challenge(simple_context_t* ctx, const ha_request_t* re } static int simple_digest_response(simple_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; @@ -444,18 +441,18 @@ static int simple_digest_response(simple_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, "simple: digest response contains invalid nonce"); @@ -463,7 +460,7 @@ static int simple_digest_response(simple_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); @@ -482,10 +479,10 @@ static int simple_digest_response(simple_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, "simple: nonce expired, sending stale challenge: %s", dg.username); @@ -510,7 +507,7 @@ static int simple_digest_response(simple_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; @@ -524,7 +521,7 @@ static int simple_digest_response(simple_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) @@ -539,8 +536,8 @@ static int simple_digest_response(simple_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, "simple: nonce almost expired, creating new one: %s", dg.username); @@ -549,7 +546,7 @@ static int simple_digest_response(simple_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; @@ -562,7 +559,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header, ha_messagex(LOG_NOTICE, "simple: 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; @@ -576,7 +573,7 @@ finally: /* If nobody above responded then challenge the client again */ if(resp->code == -1) - return simple_digest_challenge(ctx, req, resp, buf, stale); + return simple_digest_challenge(ctx, req, resp, stale); return ret; } @@ -588,7 +585,7 @@ finally: int simple_config(ha_context_t* context, const char* name, const char* value) { - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(context->ctx_data); ASSERT(name && name[0] && value && value[0]); @@ -613,13 +610,13 @@ int simple_init(ha_context_t* context) /* Context specific initialization */ else { - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(context->ctx_data); int fd; 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, "simple: module configured, but does not implement any " "configured authentication type."); @@ -653,9 +650,6 @@ int simple_init(ha_context_t* context) return HA_CRITERROR; } - /* Copy some settings over for easy access */ - ctx->opts = context->opts; - ha_messagex(LOG_INFO, "simple: initialized handler"); } @@ -668,7 +662,7 @@ void simple_destroy(ha_context_t* context) if(context) { /* Note: We don't need to be thread safe here anymore */ - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(context->ctx_data); if(ctx->cache) hash_free(ctx->cache); @@ -677,24 +671,23 @@ void simple_destroy(ha_context_t* context) } } -int simple_process(ha_context_t* context, const ha_request_t* req, - ha_response_t* resp, ha_buffer_t* buf) +int simple_process(const ha_request_t* req, ha_response_t* resp) { - simple_context_t* ctx = (simple_context_t*)(context->data); + simple_context_t* ctx = (simple_context_t*)(req->context->ctx_data); const char* header = NULL; int ret = HA_FALSE; int found = 0; basic_header_t basic; int r; - ASSERT(context && req && resp && buf); + ASSERT(req && resp); ASSERT(req->args[AUTH_ARG_METHOD]); ASSERT(req->args[AUTH_ARG_URI]); ha_lock(NULL); /* Purge the cache */ - r = hash_purge(ctx->cache, time(NULL) - ctx->opts->cache_timeout); + r = hash_purge(ctx->cache, time(NULL) - req->context->cache_timeout); ha_unlock(NULL); @@ -706,26 +699,26 @@ int simple_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, "simple: processing digest auth header"); - ret = simple_digest_response(ctx, header, req, resp, buf); + ret = simple_digest_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) { ha_messagex(LOG_DEBUG, "simple: processing basic auth header"); header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC); if(header) { - ret = simple_basic_response(ctx, header, resp, buf); + ret = simple_basic_response(ctx, header, req, resp); if(ret < 0) return ret; } @@ -737,20 +730,20 @@ int simple_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, "simple: sent basic auth request"); } - if(context->opts->types & HA_TYPE_DIGEST) + if(req->context->allowed_types & HA_TYPE_DIGEST) { - ret = simple_digest_challenge(ctx, req, resp, buf, 0); + ret = simple_digest_challenge(ctx, req, resp, 0); if(ret < 0) return ret; } diff --git a/sample/httpauthd.conf b/sample/httpauthd.conf index f11f48e..c536dcd 100644 --- a/sample/httpauthd.conf +++ b/sample/httpauthd.conf @@ -5,15 +5,14 @@ MaxThreads: 18 CacheTimeout: 300 AuthTypes: Digest # AuthTypes: Basic Digest -Socket: 0.0.0.0:8020 +Socket: 0.0.0.0:8030 DigestIgnoreNC: True -[Simple] +[Simple:Test] Realm: blah PasswordFile: /data/projects/httpauth/sample/passwd.file - [LDAP] Realm: blah LDAPServers: authdev.ws.local @@ -24,6 +23,7 @@ LDAPUser: cn=root,dc=fam LDAPPassword: ldaptest@@password # LDAPHA1Attr: login LDAPPWAttr: clearPassword +DigestDebugNonce: AkCLQA==560f26e24db2d4cecbe5d6e24d958377ab73def9 LDAPFilter: (cn=%u) LDAPBase: dc=fam -- cgit v1.2.3