summaryrefslogtreecommitdiff
path: root/daemon/httpauthd.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/httpauthd.c')
-rw-r--r--daemon/httpauthd.c221
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;
}