summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2008-06-12 03:40:09 +0000
committerStef Walter <stef@memberwebs.com>2008-06-12 03:40:09 +0000
commit3dc8cb104d3392e00514bb829c50390a9598fe3c (patch)
tree945274bf792a923f187a9e83a8c8af9fa3c63942
parentde44fe7893da8d8c9903f1a7268fa6fe03446d36 (diff)
- apache2x module now supports connecting to multiple daemon addresses
and failover between them.
-rw-r--r--ChangeLog2
-rw-r--r--apache1x/Makefile.am2
-rw-r--r--apache1x/mod_httpauth.c4
-rw-r--r--apache2x/Makefile.am8
-rw-r--r--apache2x/mod_httpauth.c571
-rw-r--r--common/sock-any.c506
-rw-r--r--common/sock-any.h (renamed from common/sock_any.h)64
-rw-r--r--common/sock_any.c355
-rw-r--r--common/stringx.c1
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/httpauthd.c2
11 files changed, 980 insertions, 537 deletions
diff --git a/ChangeLog b/ChangeLog
index 1ab0d41..0d0912e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,8 @@
- Build warning fixes.
- Allow better migration of live digest sessions between httpauth
daemons by using the 'stale' flag when things seem out of date.
+ - apache2x module now supports connecting to multiple daemon addresses
+ and failover between them.
0.9.2 [22-05-2008]
- Authenticate sub requests properly in the apache module.
diff --git a/apache1x/Makefile.am b/apache1x/Makefile.am
index d043935..a768b2e 100644
--- a/apache1x/Makefile.am
+++ b/apache1x/Makefile.am
@@ -7,7 +7,7 @@ INC=-I../ -I../common/
all: mod_httpauth.so
-mod_httpauth.so: mod_httpauth.c ../common/sock_any.c
+mod_httpauth.so: mod_httpauth.c ../common/sock-any.c
@APXS@ -c -Wc,-g -Wc,-O0 $(DEF) $(INC) $(LIB) mod_httpauth.c
# install the DSO file into the Apache installation
diff --git a/apache1x/mod_httpauth.c b/apache1x/mod_httpauth.c
index fffaf9d..bb71ea7 100644
--- a/apache1x/mod_httpauth.c
+++ b/apache1x/mod_httpauth.c
@@ -44,7 +44,7 @@
#include <ap_config.h>
#include <ap_alloc.h>
-#include "sock_any.h"
+#include "sock-any.h"
#include "stringx.h"
#define DEFAULT_PORT 8020
@@ -898,5 +898,5 @@ module MODULE_VAR_EXPORT httpauth_module =
* object file, at least when statically compiled.
* so we include this here
*/
-#include "../common/sock_any.c"
+#include "../common/sock-any.c"
#include "../common/stringx.c"
diff --git a/apache2x/Makefile.am b/apache2x/Makefile.am
index a1396c4..6019b06 100644
--- a/apache2x/Makefile.am
+++ b/apache2x/Makefile.am
@@ -1,14 +1,14 @@
EXTRA_DIST = mod_httpauth.c
-DEF=
-INC=-I../ -I../common/
+DEF =
+INC = -I../ -I../common/
all: mod_httpauth.so
-mod_httpauth.so: mod_httpauth.c ../common/sock_any.c
- @APXS@ -c -Wc,-g -Wc,-O0 $(DEF) $(INC) $(LIB) mod_httpauth.c
+mod_httpauth.so: mod_httpauth.c ../common/sock-any.c
+ @APXS@ -c -Wc,-g -Wc,-O0 -Wc,-Wall $(DEF) $(INC) $(LIB) mod_httpauth.c
# install the DSO file into the Apache installation
# and activate it in the Apache configuration
diff --git a/apache2x/mod_httpauth.c b/apache2x/mod_httpauth.c
index d6697ae..58e6f2e 100644
--- a/apache2x/mod_httpauth.c
+++ b/apache2x/mod_httpauth.c
@@ -41,13 +41,23 @@
#include <http_config.h>
#include <http_log.h>
#include <http_protocol.h>
+#include <http_request.h>
#include <ap_config.h>
#include <apr_strings.h>
+#include "apr_file_io.h"
#include <apr_lib.h>
+#include <apr_shm.h>
+
+/* Apache defines these */
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
#include <unistd.h>
-#include "sock_any.h"
+#include "sock-any.h"
#include "stringx.h"
#define DEFAULT_PORT 8020
@@ -60,24 +70,48 @@ static void* conn_current = NULL;
/* And increment this when it goes out of scope */
static unsigned int conn_seen = 0;
-typedef struct httpauth_context
-{
- const char* socketname;
- int socket;
- int types;
- const char* handler;
- const char* domain;
- char* needed_groups;
- int alloced_groups;
- apr_pool_t* child_pool;
-}
-httpauth_context_t;
+/*
+ * Per directory configuration.
+ */
+typedef struct httpauth_context {
+ const char* socketname;
+ int socket;
+ int types;
+ const char* handler;
+ const char* domain;
+ char* needed_groups;
+ int alloced_groups;
+ apr_pool_t* child_pool;
+
+ int address_seed;
+ int retries;
+
+ int shared_version;
+ void *shared_block;
+} httpauth_context_t;
+
+/*
+ * Tagged onto a request once authenticated, used for access
+ * groups and revalidating an already authenticated request.
+ */
typedef struct httpauth_request {
const char *user;
const char *groups;
} httpauth_request_t;
+/*
+ * Shared between all instances of a httpauth_context in
+ * different processes on a server.
+ */
+typedef struct httpauth_shared {
+ int version;
+ struct sockaddr_any address;
+} httpauth_shared_t;
+
+static apr_global_mutex_t *shared_lock = NULL;
+static const char *shared_lock_name = NULL;
+
/* TODO: Support proxy authentication properly */
#define AUTH_PREFIX_BASIC "Basic"
@@ -92,33 +126,197 @@ typedef struct httpauth_request {
#define HTTPAUTH_AUTHTYPE "HTTPAUTH"
/* -------------------------------------------------------------------------------
- * Configuration code
+ * Shared memory
*/
-static void* httpauth_dir_config(apr_pool_t* p, char* dir)
+static int
+httpauth_initialize (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
- httpauth_context_t* ctx;
+ apr_file_t *file = NULL;
+ const char *tmpdir;
+ char *lock_name;
+ int rc;
+
+ /* This may be called more than once */
+ if (shared_lock)
+ return OK;
+
+ rc = apr_temp_dir_get (&tmpdir, p);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, s,
+ "httpauth: couldn't get temporary directory");
+
+ if (rc == APR_SUCCESS) {
+ lock_name = apr_pstrcat (p, tmpdir, "/", "mod-httpauth.lock.XXXXXX", NULL);
+ rc = apr_file_mktemp (&file, lock_name, 0, p);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
+ "httpauth: couldn't create temporary file: %s", lock_name);
+ }
+
+ if (rc == APR_SUCCESS) {
+ rc = apr_global_mutex_create (&shared_lock, lock_name, APR_LOCK_DEFAULT, p);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, s,
+ "httpauth: couldn't create shared memory lock");
+ }
+
+ if (file != NULL)
+ apr_file_close (file);
+ shared_lock_name = lock_name;
+
+ return OK;
+}
+
+static void
+httpauth_child (apr_pool_t *p, server_rec *s)
+{
+ apr_status_t rc;
+
+ if (!shared_lock)
+ return;
+
+ rc = apr_global_mutex_child_init (&shared_lock, shared_lock_name, p);
+ if (rc != APR_SUCCESS) {
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, s,
+ "httpauth: couldn't create lock for shared memory in child");
+ shared_lock = NULL;
+ }
+}
+
+static int
+shared_get_if_changed (httpauth_context_t *ctx, int version, httpauth_shared_t *shared)
+{
+ httpauth_shared_t *block;
+ int ret = 0;
+
+ if (!ctx->shared_block)
+ return 0;
- ctx = (httpauth_context_t*)apr_pcalloc(p, sizeof(*ctx));
- memset(ctx, 0, sizeof(*ctx));
+ apr_global_mutex_lock (shared_lock);
- ctx->socket = -1;
- ctx->types = 0xFFFFFFFF;
- ctx->child_pool = p;
- ctx->needed_groups = NULL;
- ctx->alloced_groups = 0;
- return ctx;
+ block = ctx->shared_block;
+ if (block->version != version) {
+ ret = 1;
+ if (shared)
+ memcpy (shared, block, sizeof (*shared));
+ }
+
+ apr_global_mutex_unlock (shared_lock);
+
+ return ret;
+}
+
+static void
+shared_set_if_changed (httpauth_context_t *ctx, httpauth_shared_t *shared)
+{
+ httpauth_shared_t *block;
+
+ if (!ctx->shared_block)
+ return;
+
+ apr_global_mutex_lock (shared_lock);
+
+ block = ctx->shared_block;
+ if (memcmp (shared, block, sizeof (*shared)) != 0) {
+
+ /* Increment the version beyond all */
+ if (block->version > shared->version)
+ shared->version = block->version;
+ ++shared->version;
+
+ /* And write it out */
+ memcpy (block, shared, sizeof (*shared));
+ }
+
+ apr_global_mutex_unlock (shared_lock);
+}
+
+/* -------------------------------------------------------------------------------
+ * Per Directory Config and Context Code
+ */
+
+static void* httpauth_dir_config (apr_pool_t* p, char* dir)
+{
+ httpauth_context_t* ctx;
+ httpauth_shared_t shared;
+ const char *tmpdir;
+ char *filename;
+ apr_file_t *file;
+ apr_mmap_t *map;
+ void *addr;
+ int rc;
+
+ ctx = (httpauth_context_t*)apr_pcalloc(p, sizeof(*ctx));
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->socket = -1;
+ ctx->types = 0xFFFFFFFF;
+ ctx->child_pool = p;
+ ctx->needed_groups = NULL;
+ ctx->alloced_groups = 0;
+ ctx->shared_version = 0;
+ ctx->retries = 1;
+
+ if (!dir)
+ return ctx;
+
+ /* Get the temp directory */
+ rc = apr_temp_dir_get (&tmpdir, p);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
+ "httpauth: couldn't get temporary directory");
+
+ /* Create the shared file */
+ if (rc == APR_SUCCESS) {
+ filename = apr_pstrcat (p, tmpdir, "/", "mod-httpauth.board.XXXXXX", NULL);
+ rc = apr_file_mktemp (&file, filename, 0, p);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
+ "httpauth: couldn't create temporary file: %s", filename);
+ }
+
+ /* Write a shared block to file */
+ if (rc == APR_SUCCESS) {
+ memset (&shared, 0, sizeof (shared));
+ rc = apr_file_write_full (file, &shared, sizeof (shared), NULL);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
+ "httpauth: couldn't write to temporary file: %s", filename);
+ }
+
+ /* Map the shared file into memory */
+ if (rc == APR_SUCCESS) {
+ rc = apr_mmap_create (&map, file, 0, sizeof (shared),
+ APR_MMAP_READ | APR_MMAP_WRITE, p);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
+ "httpauth: couldn't map temporary file: %s", filename);
+ }
+
+ /* Get the actual address of the mapping */
+ if (rc == APR_SUCCESS) {
+ rc = apr_mmap_offset (&addr, map, 0);
+ if (rc != APR_SUCCESS)
+ ap_log_error (APLOG_MARK, APLOG_ERR, rc, NULL,
+ "httpauth: couldn't get shared memory");
+ }
+
+ if (rc == APR_SUCCESS)
+ ctx->shared_block = addr;
+
+ return ctx;
}
static const char* set_socket(cmd_parms* cmd, void* config, const char* val)
{
- struct sockaddr_any sany;
+ struct sockaddr_any sany;
- if(sock_any_pton(val, &sany, DEFAULT_PORT) == -1)
- return "Invalid socket name or ip in HttpAuthSocket";
+ if (sock_any_pton_n (val, &sany, 1, DEFAULT_PORT | SANY_OPT_NORESOLV) == -1)
+ return "Invalid socket name or ip in HttpAuthSocket";
- ((httpauth_context_t*)config)->socketname = val;
- return NULL;
+ ((httpauth_context_t*)config)->socketname = val;
+ return NULL;
}
static const char* set_handler(cmd_parms* cmd, void* config, const char* val)
@@ -161,7 +359,7 @@ static const char* set_domain(cmd_parms* cmd, void* config, const char* val)
static const command_rec httpauth_cmds[] =
{
- AP_INIT_TAKE1( "HttpAuthSocket", set_socket, NULL, OR_AUTHCFG,
+ AP_INIT_RAW_ARGS( "HttpAuthSocket", set_socket, NULL, OR_AUTHCFG,
"The socket that httpauthd is listening on" ),
AP_INIT_TAKE1( "HttpAuthHandler", set_handler, NULL, OR_AUTHCFG,
"The handler that httpauthd should use to authenticate" ),
@@ -193,6 +391,8 @@ void disconnect_socket(httpauth_context_t* ctx, server_rec* s)
cleanup_socket);
close(ctx->socket);
ctx->socket = -1;
+
+ /* Make sure we send our list of groups to daemon again */
if (ctx->needed_groups)
ctx->needed_groups[0] = 0;
}
@@ -310,63 +510,68 @@ int read_line(httpauth_context_t* ctx, request_rec* r, char** line)
return 0;
}
-int read_response(httpauth_context_t* ctx, request_rec* r,
- int* code, int* ccode, char** details,
- int return_errors)
+int
+read_response (httpauth_context_t *ctx, request_rec *r,
+ int *code, int *ccode, char **details,
+ int return_errors)
{
- int c;
- char* line;
- char* t;
- char* t2;
-
- if(read_line(ctx, r, &line) == -1)
- return -1;
-
- line = trim_space(line);
+ int c, ret = -1;
+ char *line;
+ char *t;
+ char *t2;
+
+ if (read_line (ctx, r, &line) == -1)
+ return -1;
+
+ line = trim_space (line);
+
+ ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
+ "httpauth: received response line from daemon: %s", line);
+
+ /* Get response code */
+ t = ap_getword_nc (r->pool, &line, ' ');
+ c = strtol (t, &t2, 10);
+ if (*t2 || c < 100 || c > 999) {
+ ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
+ "httpauth: protocol error: invalid code: %s", t);
+ goto finally;
+ }
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "httpauth: received response line from daemon: %s", line);
+ if (code)
+ *code = c;
- /* Get response code */
- t = ap_getword_nc(r->pool, &line, ' ');
- c = strtol(t, &t2, 10);
- if(*t2 || c < 100 || c > 999)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: invalid code: %s", t);
- return -1;
- }
+ if (c >= 400 && !return_errors) {
+ ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
+ "httpauth: received error from httpauthd: %d %s", c, line);
+ goto finally;
+ }
- if(code)
- *code = c;
+ /* Get the second response code if we're a 200 */
+ if (c == 200) {
+ t = ap_getword_nc (r->pool, &line, ' ');
+ c = strtol (t, &t2, 10);
+ if (*t2 || c < 100 || c > 999) {
+ ap_log_rerror (APLOG_MARK, APLOG_ERR, 0, r,
+ "httpauth: protocol error: invalid code: %s", t);
+ goto finally;
+ }
- if(c >= 400 && !return_errors)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: received error from httpauthd: %d %s", c, line);
- return -1;
- }
+ if (ccode)
+ *ccode = c;
+ }
- /* Get the second response code if we're a 200 */
- if(c == 200)
- {
- t = ap_getword_nc(r->pool, &line, ' ');
- c = strtol(t, &t2, 10);
- if(*t2 || c < 100 || c > 999)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "httpauth: protocol error: invalid code: %s", t);
- return -1;
- }
+ if (details)
+ *details = trim_space (line);
- if(ccode)
- *ccode = c;
- }
+ ret = 0;
- if(details)
- *details = trim_space(line);
+finally:
+ if (ret < 0 && ctx->socket >= 0) {
+ disconnect_socket (ctx, r->server);
+ ++ctx->address_seed;
+ }
- return 0;
+ return ret;
}
static int
@@ -513,46 +718,94 @@ int write_data(httpauth_context_t* ctx, server_rec* s, const char* data)
return 0;
}
-int connect_socket(httpauth_context_t* ctx, request_rec* r)
+static int
+try_connect_socket (httpauth_context_t *ctx, struct sockaddr_any *sany,
+ request_rec *r)
{
- struct sockaddr_any sany;
- int ret = -1;
+ char peername[256];
+ int rc;
- disconnect_socket(ctx, r->server);
+ if (sock_any_ntop (sany, peername, sizeof (peername), 0) < 0)
+ strcpy (peername, "[unknown]");
- if(sock_any_pton(ctx->socketname, &sany, DEFAULT_PORT) == -1)
- {
- ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
- "httpauth: Invalid socket name or ip.");
- goto finally;
- }
+ ctx->socket = socket (SANY_TYPE (*sany), SOCK_STREAM, 0);
+ if(ctx->socket == -1) {
+ ap_log_rerror (APLOG_MARK, APLOG_CRIT, APR_FROM_OS_ERROR (errno), r,
+ "httpauth: Can't create socket");
+ return -1;
+ }
- ctx->socket = socket(SANY_TYPE(sany), SOCK_STREAM, 0);
- if(ctx->socket == -1)
- {
- ap_log_rerror(APLOG_MARK, APLOG_CRIT, APR_FROM_OS_ERROR(errno), r,
- "httpauth: Can't create socket: %s", ctx->socketname);
- goto finally;
- }
+ if (connect (ctx->socket, &SANY_ADDR (*sany), SANY_LEN(*sany)) != 0) {
+ rc = APR_FROM_OS_ERROR (errno);
+ ap_log_rerror (APLOG_MARK, APLOG_CRIT, rc, r,
+ "httpauth: Can't connect to httpauthd at: %s", peername);
+ close (ctx->socket);
+ ctx->socket = -1;
+ return -1;
+ }
- apr_pool_cleanup_register(ctx->child_pool, (void*)(long)ctx->socket,
- cleanup_socket, cleanup_socket);
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "httpauth: connected to daemon: %s", peername);
- if(connect(ctx->socket, &SANY_ADDR(sany), SANY_LEN(sany)) != 0)
- {
- ap_log_rerror(APLOG_MARK, APLOG_CRIT, APR_FROM_OS_ERROR(errno), r,
- "httpauth: Can't connect to httpauthd");
- goto finally;
- }
+ return 0;
+}
- ret = 0;
+static int
+connect_socket(httpauth_context_t* ctx, request_rec* r)
+{
+ httpauth_shared_t shared;
+ struct sockaddr_any sany[16];
+ int i, which, count = 0;
+ int rc = -1;
+
+ disconnect_socket(ctx, r->server);
+ memset (&shared, 0, sizeof (shared));
+
+ /* Find out what everyone else is connected to */
+ if (shared_get_if_changed (ctx, ctx->shared_version, &shared) && shared.version > 0) {
+ ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
+ "httpauth: trying shared address...");
+ rc = try_connect_socket (ctx, &shared.address, r);
+ }
-finally:
- if(ret == -1)
- disconnect_socket(ctx, r->server);
+ /* Now try to connect to all the other addresses */
+ if (rc < 0) {
+ ap_log_rerror (APLOG_MARK, APLOG_DEBUG, 0, r,
+ "httpauth: resolving daemon address(s)");
+
+ count = sock_any_pton_n (ctx->socketname, sany, 16, DEFAULT_PORT);
+ if (count < 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
+ "httpauth: Invalid socket name or ip: %s", ctx->socketname);
+ rc = -1;
+ }
+
+ /* We know how many addresses we have to retry with */
+ if (count > 0)
+ ctx->retries = count;
- errno = 0;
- return ret;
+ for (i = 0; i != count; ++i) {
+ which = (i + ctx->address_seed) % count;
+ rc = try_connect_socket (ctx, &sany[which], r);
+
+ /* Successful, then let others know we're connected here */
+ if (rc >= 0) {
+ memcpy (&shared.address, &sany[which], sizeof (shared.address));
+ break;
+ }
+ }
+ }
+
+ /* Yay, successful */
+ if (rc >= 0) {
+ shared_set_if_changed (ctx, &shared);
+ ctx->shared_version = shared.version;
+ apr_pool_cleanup_register(ctx->child_pool, (void*)(long)ctx->socket,
+ cleanup_socket, cleanup_socket);
+ errno = 0;
+ }
+
+ return rc;
}
int connect_httpauth(httpauth_context_t* ctx, request_rec* r)
@@ -631,13 +884,15 @@ int connect_httpauth(httpauth_context_t* ctx, request_rec* r)
/* We're cool! */
ret = 0;
- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "httpauth: connected to daemon");
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "httpauth: handshake with daemon completed");
finally:
- if(ret == -1)
- disconnect_socket(ctx, r->server);
+ if(ret == -1 && ctx->socket >= 0) {
+ disconnect_socket(ctx, r->server);
+ ++ctx->address_seed;
+ }
- return ret;
+ return ret;
}
/* Make sure our connection identifier is unique */
@@ -811,6 +1066,7 @@ static int httpauth_authenticate(request_rec* r)
httpauth_request_t* hreq;
const char* authtype;
int code = 0;
+
int ccode = 0;
char *groups = NULL;
char* details = NULL;
@@ -843,43 +1099,60 @@ static int httpauth_authenticate(request_rec* r)
return OK;
}
+ /*
+ * Check if we're in sync with the other processes,
+ * and connected to the same daemon
+ */
+ if (ctx->socket != -1 && shared_get_if_changed (ctx, ctx->shared_version, NULL)) {
+ ap_log_rerror (APLOG_MARK, APLOG_INFO, 0, r,
+ "httpauth: syncing connection with other processes");
+ disconnect_socket (ctx, r->server);
+ }
+
/* For jumping to when a connection has been closed */
retry:
- if(ctx->socket == -1)
- {
- if(connect_httpauth(ctx, r) == -1)
- return HTTP_INTERNAL_SERVER_ERROR;
- }
+ if (ctx->socket == -1) {
+ if (connect_httpauth (ctx, r) == -1) {
- /* Make sure we're starting on a clean slate */
- read_junk(ctx, r);
+ if (ctx->socket == -1 && retried < ctx->retries) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+ "httpauth: trying to connect to daemon again");
+ ++retried;
+ goto retry;
+ }
- /* Send off a request, along with groups, and read response */
- if(write_needed_groups(ctx, r) == -1 ||
- write_request(ctx, r) == -1 ||
- read_response(ctx, r, &code, &ccode, &details, 0) == -1)
- {
- /*
- * If our connection was closed by httpauthd then this
- * is where we get the error. Just do one retry to
- * try and reconnect. This happens often when restarting
- * httpauthd.
- */
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
- if(ctx->socket == -1 && !retried)
- {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
- "httpauth: reconnecting to to httpauthd");
- retried = 1;
- goto retry;
- }
+ /* Make sure we're starting on a clean slate */
+ read_junk (ctx, r);
+
+ /* Send off a request, along with groups, and read response */
+ if (write_needed_groups (ctx, r) == -1 ||
+ write_request (ctx, r) == -1 ||
+ read_response (ctx, r, &code, &ccode, &details, 0) == -1) {
+
+ /*
+ * If our connection was closed by httpauthd then this
+ * is where we get the error. Just do one retry to
+ * try and reconnect. This happens often when restarting
+ * httpauthd.
+ */
+
+ if (ctx->socket == -1 && retried < ctx->retries) {
+ ap_log_rerror (APLOG_MARK, APLOG_WARNING, 0, r,
+ "httpauth: reconnecting to to httpauthd");
+ ++retried;
+ goto retry;
+ }
- ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(errno), r,
- "httpauth: couldn't send request to httpauthd");
+ ap_log_rerror (APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(errno), r,
+ "httpauth: couldn't send request to httpauthd");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
if(code != 200)
{
@@ -951,7 +1224,7 @@ httpauth_access(request_rec *r)
int m = r->method_number;
int method_restricted = 0;
register int x;
- const char *text, *word, *at;
+ const char *text, *word;
const apr_array_header_t *reqs_arr = ap_requires (r);
require_line *reqs;
@@ -1018,10 +1291,10 @@ httpauth_access(request_rec *r)
static void register_hooks(apr_pool_t *p)
{
- /* static const char* cfg_post[] = { "http_core.c", NULL }; */
-
- ap_hook_check_user_id(httpauth_authenticate, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_auth_checker(httpauth_access, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_post_config (httpauth_initialize, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init (httpauth_child, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_check_user_id (httpauth_authenticate, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_auth_checker (httpauth_access, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA httpauth_module =
@@ -1029,7 +1302,7 @@ module AP_MODULE_DECLARE_DATA httpauth_module =
STANDARD20_MODULE_STUFF,
httpauth_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
- NULL, /* server config */
+ NULL, /* server config */
NULL, /* merge server config */
httpauth_cmds, /* command table */
register_hooks /* register hooks */
@@ -1040,5 +1313,5 @@ module AP_MODULE_DECLARE_DATA httpauth_module =
* object file, at least when statically compiled.
* so we include this here
*/
-#include "../common/sock_any.c"
+#include "../common/sock-any.c"
#include "../common/stringx.c"
diff --git a/common/sock-any.c b/common/sock-any.c
new file mode 100644
index 0000000..581ef5b
--- /dev/null
+++ b/common/sock-any.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2004, Stefan Walter
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ *
+ * CONTRIBUTORS
+ * Stef Walter <stef@memberwebs.com>
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "sock-any.h"
+
+#include <arpa/inet.h>
+
+#define LOCALHOST_ADDR 0x7F000001
+#define WHITESPACE " \t\n\r\v"
+
+int
+sock_any_pton(const char* addr, struct sockaddr_any* any, int opts)
+{
+ size_t l;
+ char buf[256];
+ char* t;
+ char* t2;
+ int defport = (opts & 0xFFFF);
+
+ assert (addr);
+ assert (any);
+
+ if (!addr[0]) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(any, 0, sizeof(*any));
+
+ /* Just a port? */
+ do {
+ #define PORT_CHARS "0123456789"
+ #define PORT_MIN 1
+ #define PORT_MAX 5
+
+ int port = 0;
+
+ l = strspn (addr, PORT_CHARS);
+ if (l < PORT_MIN || l > PORT_MAX || addr[l] != 0)
+ break;
+
+ port = strtol (addr, &t2, 10);
+ if (*t2 || port <= 0 || port >= 65536)
+ break;
+
+ any->s.in.sin_port = htons (port);
+
+ /* Fill in the type based on defaults */
+#ifdef HAVE_INET6
+ if (opts & SANY_OPT_DEFINET6)
+ any->s.in.sin_family = AF_INET6;
+ else
+#endif
+ any->s.in.sin_family = AF_INET;
+
+ /* Fill in the address based on defaults */
+ if (opts & SANY_OPT_DEFLOCAL) {
+#ifdef HAVE_INET6
+ if(opts & SANY_OPT_DEFINET6)
+ memcpy(&(any->s.in.sin6_addr), &in6addr_loopback, sizeof(struct in6_addr));
+ else
+ any->s.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
+ }
+
+ /*
+ * Note the 'any' option is the default since we zero out
+ * the entire structure above.
+ */
+
+ any->namelen = sizeof (any->s.in);
+ return AF_INET;
+ }
+ while (0);
+
+ /* Look and see if we can parse an ipv4 address */
+ do
+ {
+ #define IPV4_CHARS "0123456789."
+ #define IPV4_MIN 3
+ #define IPV4_MAX 21
+
+ int port = 0;
+ t = NULL;
+
+ l = strlen (addr);
+ if(l < IPV4_MIN || l > IPV4_MAX)
+ break;
+
+ strcpy (buf, addr);
+
+ /* Find the last set that contains just numbers */
+ l = strspn (buf, IPV4_CHARS);
+ if(l < IPV4_MIN)
+ break;
+
+ /* Either end of string or port */
+ if (buf[l] != 0 && buf[l] != ':')
+ break;
+
+ /* Get the port out */
+ if (buf[l] != 0) {
+ t = buf + l + 1;
+ buf[l] = 0;
+ }
+
+ if (t) {
+ port = strtol(t, &t2, 10);
+ if(*t2 || port <= 0 || port >= 65536)
+ break;
+ }
+
+ any->s.in.sin_family = AF_INET;
+ any->s.in.sin_port = htons ((unsigned short)(port <= 0 ? defport : port));
+
+ if (inet_pton (AF_INET, buf, &(any->s.in.sin_addr)) <= 0)
+ break;
+
+ any->namelen = sizeof(any->s.in);
+ return AF_INET;
+ }
+ while(0);
+
+#ifdef HAVE_INET6
+ do
+ {
+ #define IPV6_CHARS "0123456789:"
+ #define IPV6_MIN 3
+ #define IPV6_MAX 51
+
+ int port = -1;
+ t = NULL;
+
+ l = strlen(addr);
+ if (l < IPV6_MIN || l > IPV6_MAX)
+ break;
+
+ /* If it starts with a '[' then we can get port */
+ if (buf[0] == '[') {
+ port = 0;
+ addr++;
+ }
+
+ strcpy (buf, addr);
+
+ /* Find the last set that contains just numbers */
+ l = strspn(buf, IPV6_CHARS);
+ if (l < IPV6_MIN)
+ break;
+
+ /* Either end of string or port */
+ if (buf[l] != 0) {
+ /* If had bracket, then needs to end with a bracket */
+ if (port != 0 || buf[l] != ']')
+ break;
+
+ /* Get the port out */
+ t = buf + l + 1;
+
+ if(*t = ':')
+ t++;
+ }
+
+ if (t) {
+ port = strtol (t, &t, 10);
+ if (*t || port <= 0 || port >= 65536)
+ break;
+ }
+
+ any->s.in6.sin6_family = AF_INET6;
+ any->s.in6.sin6_port = htons ((unsigned short)port <= 0 : defport : port);
+
+ if (inet_pton(AF_INET6, buf, &(any->s.in6.sin6_addr)) >= 0)
+ break;
+
+ any->namelen = sizeof (any->s.in6);
+ return AF_INET6;
+ } while (0);
+#endif
+
+ /* A unix socket path */
+ do {
+ /* No colon and must have a path component */
+ if (strchr (addr, ':') || !strchr (addr, '/'))
+ break;
+
+ l = strlen(addr);
+ if (l >= sizeof(any->s.un.sun_path))
+ break;
+
+ any->s.un.sun_family = AF_UNIX;
+ strcpy (any->s.un.sun_path, addr);
+
+ any->namelen = sizeof (any->s.un) - (sizeof (any->s.un.sun_path) - l);
+ return AF_UNIX;
+ } while(0);
+
+ /* A DNS name and a port? */
+ do {
+ struct addrinfo* res;
+ int port = 0;
+ int family = 0;
+ t = NULL;
+
+ l = strlen(addr);
+ if (l >= 255 || !isalpha(addr[0]))
+ break;
+
+ /* Some basic illegal character checks */
+ if (strcspn(addr, " /\\") != l)
+ break;
+
+ strcpy (buf, addr);
+
+ /* Find the last set that contains just numbers */
+ t = strchr (buf, ':');
+ if (t) {
+ *t = 0;
+ t++;
+ }
+
+ if (t) {
+ port = strtol (t, &t2, 10);
+ if (*t2 || port <= 0 || port >= 65536)
+ break;
+ }
+
+ if (!(opts & SANY_OPT_NORESOLV)) {
+ /* Try and resolve the domain name */
+ if (getaddrinfo (buf, NULL, NULL, &res) != 0 || !res)
+ break;
+
+ memcpy (&(any->s.a), res->ai_addr, sizeof (struct sockaddr));
+ any->namelen = res->ai_addrlen;
+ family = any->s.a.sa_family;
+ freeaddrinfo (res);
+ } else {
+ family = SANY_AF_DNS;
+#ifdef HAVE_INET6
+ if (opt & SANY_OPT_DEFINET6)
+ {
+ any->s.a.sa_family = AF_INET6;
+ any->namelen = sizeof (any->s.in6);
+ } else
+#endif
+ {
+ any->s.a.sa_family = AF_INET;
+ any->namelen = sizeof(any->s.in);
+ }
+ }
+
+ port = htons ((unsigned short)(port <= 0 ? defport : port));
+
+ switch (any->s.a.sa_family) {
+ case PF_INET:
+ any->s.in.sin_port = port;
+ break;
+#ifdef HAVE_INET6
+ case PF_INET6:
+ any->s.in6.sin6_port = port;
+ break;
+#endif
+ };
+
+ return family;
+ } while (0);
+
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+int
+sock_any_pton_n (const char *string, struct sockaddr_any *addrs, int n_addrs, int opts)
+{
+ struct addrinfo hints, *res, *ai;
+ const char *end;
+ int rc, num;
+ char port[16];
+
+ /*
+ * Can't have a single address that's longer than
+ * sockaddr_any structure when in textual form
+ */
+ char buf[sizeof(struct sockaddr_any)];
+
+ assert (string);
+ assert (addrs);
+
+ num = n_addrs;
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ /*
+ * Not actually limitted to these, just need to specify these
+ * or we'll get multiple results from the resolver.
+ */
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_socktype = SOCK_STREAM;
+
+ while (string && *string && n_addrs) {
+
+ /* Skip initial blanks */
+ while (*string && strchr (WHITESPACE, *string))
+ ++string;
+
+ if (!*string)
+ break;
+
+ /* Find the next word */
+ end = string + strcspn (string, WHITESPACE);
+ assert (end != string);
+ if (end - string >= sizeof (buf)) {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ /* Parse, but not resolve the address */
+ strncpy (buf, string, end - string);
+ buf[end - string] = 0;
+ rc = sock_any_pton (buf, addrs, opts | SANY_OPT_NORESOLV);
+
+ if (rc < 0)
+ return -1;
+
+ /* Parsed to an address */
+ if (rc != SANY_AF_DNS) {
+ ++addrs;
+ --n_addrs;
+
+ /* Needs DNS resolution */
+ } else if (!(opts & SANY_OPT_NORESOLV)) {
+
+ /* Save the port out of the half resolved address */
+ switch (addrs->s.a.sa_family) {
+ case PF_INET:
+ snprintf (port, sizeof (port), "%d", (int)ntohs (addrs->s.in.sin_port));
+ break;
+#ifdef HAVE_INET6
+ case PF_INET6:
+ snprintf (port, sizeof (port), "%d", (int)ntohs (addrs->s.in.sin_port));
+ break;
+#endif
+ default:
+ port[0] = 0;
+ break;
+ };
+
+ if (getaddrinfo (buf, port[0] ? port : NULL, &hints, &res) != 0 || !res)
+ return -1;
+
+ for (ai = res; ai && n_addrs; ai = ai->ai_next) {
+
+ /* Copy in the resolved address */
+ memcpy (&(addrs->s.a), res->ai_addr, res->ai_addrlen);
+ addrs->namelen = res->ai_addrlen;
+
+ ++addrs;
+ --n_addrs;
+ }
+
+ freeaddrinfo (res);
+ }
+
+ string = end;
+ }
+
+
+ /* The number of addrs we used */
+ return num - n_addrs;
+}
+
+int
+sock_any_ntop (const struct sockaddr_any* any, char* addr, size_t addrlen, int opts)
+{
+ int len = 0;
+ int port = 0;
+
+ assert (any);
+ assert (addr);
+
+ switch (any->s.a.sa_family) {
+ case AF_UNIX:
+ len = strlen (any->s.un.sun_path);
+ if (addrlen < len + 1) {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ strcpy (addr, any->s.un.sun_path);
+ break;
+
+ case AF_INET:
+ if (inet_ntop (any->s.a.sa_family, &(any->s.in.sin_addr), addr, addrlen) == NULL)
+ return -1;
+ port = ntohs (any->s.in.sin_port);
+ break;
+
+#ifdef HAVE_INET6
+ case AF_INET6:
+ if (inet_ntop (any->s.a.sa_family, &(any->s.in6.sin6_addr), addr, addrlen) == NULL)
+ return -1;
+ port = ntohs (any->s.in6.sin6_port);
+ break;
+#endif
+
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ if (!(opts & SANY_OPT_NOPORT) && port != 0)
+ {
+ strncat (addr, ":", addrlen);
+ addr[addrlen - 1] = 0;
+
+ len = strlen (addr);
+ addr += len;
+ addrlen -= len;
+
+ snprintf (addr, addrlen, "%d", port);
+ }
+
+ return 0;
+}
+
+int
+sock_any_cmp (const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts)
+{
+ assert (a1);
+ assert (a2);
+
+ if (a1->s.a.sa_family != a2->s.a.sa_family)
+ return -1;
+
+ switch (a1->s.a.sa_family) {
+ case AF_UNIX:
+ return strcmp (a1->s.un.sun_path, a2->s.un.sun_path);
+
+ case AF_INET:
+ if (memcmp (&(a1->s.in.sin_addr), &(a2->s.in.sin_addr), sizeof(a2->s.in.sin_addr)) != 0)
+ return -1;
+ if (!(opts && SANY_OPT_NOPORT) && a1->s.in.sin_port != a2->s.in.sin_port)
+ return -1;
+ return 0;
+#ifdef HAVE_INET6
+ case AF_INET6:
+ if(memcmp(&(a1->s.in6.sin6_addr), &(a2->s.in6.sin6_addr), sizeof(a2->s.in6.sin6_addr)) != 0)
+ return -1;
+ if(!(opts && SANY_OPT_NOPORT) && a1->s.in6.sin6_port != a2->s.in6.sin6_port)
+ return -1;
+ return 0;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+}
diff --git a/common/sock_any.h b/common/sock-any.h
index 27c17cf..c22d1c7 100644
--- a/common/sock_any.h
+++ b/common/sock-any.h
@@ -45,44 +45,60 @@
struct sockaddr_any
{
- union _sockaddr_any
- {
- /* The header */
- struct sockaddr a;
-
- /* The different types */
- struct sockaddr_un un;
- struct sockaddr_in in;
+ union _sockaddr_any {
+ /* The header */
+ struct sockaddr a;
+
+ /* The different types */
+ struct sockaddr_un un;
+ struct sockaddr_in in;
#ifdef HAVE_INET6
- struct sockaddr_in6 in6;
+ struct sockaddr_in6 in6;
#endif
- } s;
- size_t namelen;
+ } s;
+ size_t namelen;
};
-#define SANY_ADDR(any) ((any).s.a)
-#define SANY_LEN(any) ((any).namelen)
-#define SANY_TYPE(any) ((any).s.a.sa_family)
+#define SANY_ADDR(any) ((any).s.a)
+#define SANY_LEN(any) ((any).namelen)
+#define SANY_TYPE(any) ((any).s.a.sa_family)
+
+/* -------------------------------------------------------------------------- */
+
+/* Returns AF_XXX family type or -1 */
+int sock_any_pton (const char *string, struct sockaddr_any *addr, int opts);
-int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts);
+int sock_any_pton_n (const char *string, struct sockaddr_any *addrs, int n_addrs, int opts);
/* The default port to fill in when no IP/IPv6 port specified */
-#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF)
+#define SANY_OPT_DEFPORT(p) (int)((p) & 0xFFFF)
/* When only port specified default to IPANY */
-#define SANY_OPT_DEFANY 0x00000000
+#define SANY_OPT_DEFANY 0x00000000
/* When only port specified default to LOCALHOST */
-#define SANY_OPT_DEFLOCAL 0x00100000
+#define SANY_OPT_DEFLOCAL 0x00100000
/* When only port specified default to IPv6 */
-#ifdef HAVE_INET6
-#define SANY_OPT_DEFINET6 0x00200000
-#endif
+#define SANY_OPT_DEFINET6 0x00200000
+
+/* Don't resolve host name */
+#define SANY_OPT_NORESOLV 0x01000000
+
+/* The family type returned when resolving is needed */
+#define SANY_AF_DNS 0x01000000
+
+/* -------------------------------------------------------------------------- */
+
+/* Returns -1 when failed */
+int sock_any_ntop (const struct sockaddr_any *any, char *addr, size_t addrlen, int opts);
+
+/* Don't print or compare the port */
+#define SANY_OPT_NOPORT 0x01000000
-int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen, int opts);
+/* -------------------------------------------------------------------------- */
-/* Don't print the port */
-#define SANY_OPT_NOPORT 0x01000000
+/* Returns 0 for equal */
+int sock_any_cmp(const struct sockaddr_any *a1, const struct sockaddr_any *a2, int opts);
#endif /* __SOCK_ANY_H__ */
diff --git a/common/sock_any.c b/common/sock_any.c
deleted file mode 100644
index 5972e62..0000000
--- a/common/sock_any.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (c) 2004, Stefan Walter
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * * The names of contributors to this software may not be
- * used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- *
- * CONTRIBUTORS
- * Stef Walter <stef@memberwebs.com>
- *
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <stdlib.h>
-#include <errno.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "sock_any.h"
-
-#include <arpa/inet.h>
-
-#define LOCALHOST_ADDR 0x7F000001
-
-int sock_any_pton(const char* addr, struct sockaddr_any* any, int opts)
-{
- size_t l;
- char buf[256];
- char* t;
- char* t2;
- int defport = (opts & 0xFFFF);
-
- memset(any, 0, sizeof(*any));
-
- /* Just a port? */
- do
- {
- #define PORT_CHARS "0123456789"
- #define PORT_MIN 1
- #define PORT_MAX 5
-
- int port = 0;
-
- l = strspn(addr, PORT_CHARS);
- if(l < PORT_MIN || l > PORT_MAX || addr[l] != 0)
- break;
-
- port = strtol(addr, &t2, 10);
- if(*t2 || port <= 0 || port >= 65536)
- break;
-
- any->s.in.sin_port = htons(port);
-
- /* Fill in the type based on defaults */
-#ifdef HAVE_INET6
- if(opts & SANY_OPT_DEFINET6)
- any->s.in.sin_family = AF_INET6;
- else
-#endif
- any->s.in.sin_family = AF_INET;
-
- /* Fill in the address based on defaults */
- if(opts & SANY_OPT_DEFLOCAL)
- {
-#ifdef HAVE_INET6
- if(opts & SANY_OPT_DEFINET6)
- memcpy(&(any->s.in.sin6_addr), &in6addr_loopback, sizeof(struct in6_addr));
- else
-#endif
- any->s.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- }
-
- /*
- * Note the 'any' option is the default since we zero out
- * the entire structure above.
- */
-
- any->namelen = sizeof(any->s.in);
- return AF_INET;
- }
- while(0);
-
- /* Look and see if we can parse an ipv4 address */
- do
- {
- #define IPV4_PORT_CHARS
- #define IPV4_CHARS "0123456789."
- #define IPV4_MIN 3
- #define IPV4_MAX 18
-
- int port = 0;
- t = NULL;
-
- l = strlen(addr);
- if(l < IPV4_MIN || l > IPV4_MAX)
- break;
-
- strcpy(buf, addr);
-
- /* Find the last set that contains just numbers */
- l = strspn(buf, IPV4_CHARS);
- if(l < IPV4_MIN)
- break;
-
- /* Either end of string or port */
- if(buf[l] != 0 && buf[l] != ':')
- break;
-
- /* Get the port out */
- if(buf[l] != 0)
- {
- t = buf + l + 1;
- buf[l] = 0;
- }
-
- if(t)
- {
- port = strtol(t, &t2, 10);
- if(*t2 || port <= 0 || port >= 65536)
- break;
- }
-
- any->s.in.sin_family = AF_INET;
- any->s.in.sin_port = htons((unsigned short)(port <= 0 ? defport : port));
-
- if(inet_pton(AF_INET, buf, &(any->s.in.sin_addr)) <= 0)
- break;
-
- any->namelen = sizeof(any->s.in);
- return AF_INET;
- }
- while(0);
-
-#ifdef HAVE_INET6
- do
- {
- #define IPV6_CHARS "0123456789:"
- #define IPV6_MIN 3
- #define IPV6_MAX 48
-
- int port = -1;
- t = NULL;
-
- l = strlen(addr);
- if(l < IPV6_MIN || l > IPV6_MAX)
- break;
-
- /* If it starts with a '[' then we can get port */
- if(buf[0] == '[')
- {
- port = 0;
- addr++;
- }
-
- strcpy(buf, addr);
-
- /* Find the last set that contains just numbers */
- l = strspn(buf, IPV6_CHARS);
- if(l < IPV6_MIN)
- break;
-
- /* Either end of string or port */
- if(buf[l] != 0)
- {
- /* If had bracket, then needs to end with a bracket */
- if(port != 0 || buf[l] != ']')
- break;
-
- /* Get the port out */
- t = buf + l + 1;
-
- if(*t = ':')
- t++;
- }
-
- if(t)
- {
- port = strtol(t, &t, 10);
- if(*t || port <= 0 || port >= 65536)
- break;
- }
-
- any->s.in6.sin6_family = AF_INET6;
- any->s.in6.sin6_port = htons((unsigned short)port <= 0 : defport : port);
-
- if(inet_pton(AF_INET6, buf, &(any->s.in6.sin6_addr)) >= 0)
- break;
-
- any->namelen = sizeof(any->s.in6);
- return AF_INET6;
- }
- while(0);
-#endif
-
- /* A unix socket path */
- do
- {
- /* No colon and must have a path component */
- if(strchr(addr, ':') || !strchr(addr, '/'))
- break;
-
- l = strlen(addr);
- if(l >= sizeof(any->s.un.sun_path))
- break;
-
- any->s.un.sun_family = AF_UNIX;
- strcpy(any->s.un.sun_path, addr);
-
- any->namelen = sizeof(any->s.un) - (sizeof(any->s.un.sun_path) - l);
- return AF_UNIX;
- }
- while(0);
-
- /* A DNS name and a port? */
- do
- {
- struct addrinfo* res;
- int port = 0;
- t = NULL;
-
- l = strlen(addr);
- if(l >= 255 || !isalpha(addr[0]))
- break;
-
- /* Some basic illegal character checks */
- if(strcspn(addr, " /\\") != l)
- break;
-
- strcpy(buf, addr);
-
- /* Find the last set that contains just numbers */
- t = strchr(buf, ':');
- if(t)
- {
- *t = 0;
- t++;
- }
-
- if(t)
- {
- port = strtol(t, &t2, 10);
- if(*t2 || port <= 0 || port >= 65536)
- break;
- }
-
- /* Try and resolve the domain name */
- if(getaddrinfo(buf, NULL, NULL, &res) != 0 || !res)
- break;
-
- memcpy(&(any->s.a), res->ai_addr, sizeof(struct sockaddr));
- any->namelen = res->ai_addrlen;
- freeaddrinfo(res);
-
- port = htons((unsigned short)(port <= 0 ? defport : port));
-
- switch(any->s.a.sa_family)
- {
- case PF_INET:
- any->s.in.sin_port = port;
- break;
-#ifdef HAVE_INET6
- case PF_INET6:
- any->s.in6.sin6_port = port;
- break;
-#endif
- };
-
- return any->s.a.sa_family;
- }
- while(0);
-
- return -1;
-}
-
-int sock_any_ntop(struct sockaddr_any* any, char* addr, size_t addrlen, int opts)
-{
- int len = 0;
- int port = 0;
-
- switch(any->s.a.sa_family)
- {
- case AF_UNIX:
- len = strlen(any->s.un.sun_path);
- if(addrlen < len + 1)
- {
- errno = ENOSPC;
- return -1;
- }
-
- strcpy(addr, any->s.un.sun_path);
- break;
-
- case AF_INET:
- if(inet_ntop(any->s.a.sa_family, &(any->s.in.sin_addr), addr, addrlen) == NULL)
- return -1;
- port = ntohs(any->s.in.sin_port);
- break;
-
-#ifdef HAVE_INET6
- case AF_INET6:
- if(inet_ntop(any->s.a.sa_family, &(any->s.in6.sin6_addr), addr, addrlen) == NULL)
- return -1;
- port = ntohs(any->s.in6.sin6_port);
- break;
-#endif
-
- default:
- errno = EAFNOSUPPORT;
- return -1;
- }
-
- if(!(opts & SANY_OPT_NOPORT) && port != 0)
- {
- strncat(addr, ":", addrlen);
- addr[addrlen - 1] = 0;
-
- len = strlen(addr);
- addr += len;
- addrlen -= len;
-
- snprintf(addr, addrlen, "%d", port);
- }
-
- return 0;
-}
diff --git a/common/stringx.c b/common/stringx.c
index 24cf9d1..b48dee9 100644
--- a/common/stringx.c
+++ b/common/stringx.c
@@ -44,6 +44,7 @@
#include <stdarg.h>
#include <stdlib.h>
+#undef WHITESPACE
#define WHITESPACE " \t\r\n\v"
const char* trim_start(const char* data)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index c2fee2a..2e7be2f 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -31,7 +31,7 @@ httpauthd_SOURCES = httpauthd.c httpauthd.h usuals.h bd.h bd.c misc.c basic.h ba
digest.h digest.c defaults.h simple.c dummy.c \
../common/compat.h ../common/compat.c ../common/buffer.h ../common/buffer.c \
../common/hash.h ../common/hash.c ../common/md5.h ../common/md5.c \
- ../common/sha1.h ../common/sha1.c ../common/sock_any.c ../common/sock_any.h \
+ ../common/sha1.h ../common/sha1.c ../common/sock-any.c ../common/sock-any.h \
../common/stringx.c ../common/stringx.h $(EXTRA_SRC)
httpauthd_CFLAGS = -D_THREAD_SAFE -pthread -DLinux \
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c
index 09fb1d7..1adf8db 100644
--- a/daemon/httpauthd.c
+++ b/daemon/httpauthd.c
@@ -37,7 +37,7 @@
#include "usuals.h"
#include "httpauthd.h"
#include "defaults.h"
-#include "sock_any.h"
+#include "sock-any.h"
#include "stringx.h"
/*