diff options
Diffstat (limited to 'daemon/httpauthd.c')
-rw-r--r-- | daemon/httpauthd.c | 221 |
1 files changed, 126 insertions, 95 deletions
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; } |