summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/basic.c7
-rw-r--r--daemon/digest.c23
-rw-r--r--daemon/digest.h2
-rw-r--r--daemon/httpauthd.c221
-rw-r--r--daemon/httpauthd.h48
-rw-r--r--daemon/ldap.c179
-rw-r--r--daemon/ntlm.c42
-rw-r--r--daemon/simple.c151
9 files changed, 341 insertions, 334 deletions
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 <syslog.h>
@@ -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 <syslog.h>
@@ -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;
}