summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2004-08-17 20:59:04 +0000
committerStef Walter <stef@memberwebs.com>2004-08-17 20:59:04 +0000
commitd92564c87818157b09ddfbf3314406b765ca390a (patch)
treedc37024dded77c30d769852cce0952f1b886f36c /daemon
parent4af582bf3aa65e0a4ebb5723047c4d1e94d12f15 (diff)
- Changed 'goto finally' to RETURN(xx)
- Added MYSQL support and tested it.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am8
-rw-r--r--daemon/bd.c40
-rw-r--r--daemon/digest.c2
-rw-r--r--daemon/httpauthd.c22
-rw-r--r--daemon/httpauthd.h5
-rw-r--r--daemon/ldap.c65
-rw-r--r--daemon/mysql.c751
-rw-r--r--daemon/ntlm.c43
-rw-r--r--daemon/pgsql.c74
-rw-r--r--daemon/simple.c4
-rw-r--r--daemon/usuals.h2
11 files changed, 878 insertions, 138 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index db83f8b..e4eecde 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -12,6 +12,8 @@ LDAP_SOURCES = ldap.c
PGSQL_SOURCES = pgsql.c
+MYSQL_SOURCES = mysql.c
+
NTLM_SOURCES = ntlm.c ntlmssp.h ntlmssp.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 \
@@ -32,8 +34,12 @@ if WITH_PGSQL
httpauthd_SOURCES += $(PGSQL_SOURCES)
endif
+if WITH_MYSQL
+httpauthd_SOURCES += $(MYSQL_SOURCES)
+endif
+
httpauthd_CFLAGS = -D_THREAD_SAFE -pthread -DLinux \
-I${top_srcdir}/common/ -I${top_srcdir}
httpauthd_LDFLAGS = -pthread
-EXTRA_DIST = $(LDAP_SOURCES) $(NTLM_SOURCES) $(PGSQL_SOURCES)
+EXTRA_DIST = $(LDAP_SOURCES) $(NTLM_SOURCES) $(PGSQL_SOURCES) $(MYSQL_SOURCES)
diff --git a/daemon/bd.c b/daemon/bd.c
index 5519cfa..9c3b429 100644
--- a/daemon/bd.c
+++ b/daemon/bd.c
@@ -174,8 +174,7 @@ static int do_basic_response(ha_request_t* rq, bd_context_t* ctx, const char* he
{
ha_messagex(rq, LOG_NOTICE, "validated basic user against cache: %s",
basic.user);
- ret = HA_OK;
- goto finally;
+ RETURN(HA_OK);
}
/* If we have a user name and password */
@@ -183,8 +182,7 @@ static int do_basic_response(ha_request_t* rq, bd_context_t* ctx, const char* he
!basic.password || !basic.password[0])
{
ha_messagex(rq, LOG_NOTICE, "no valid basic auth info");
- ret = HA_FALSE;
- goto finally;
+ RETURN(HA_FALSE);
}
ASSERT(ctx->f_validate_basic);
@@ -266,7 +264,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
if(!dg.client.username)
{
ha_messagex(rq, LOG_WARNING, "digest response contains no user name");
- goto finally;
+ RETURN(HA_FALSE);
}
#ifdef _DEBUG
@@ -275,7 +273,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
if(dg.client.nonce && strcmp(dg.client.nonce, rq->context->digest_debugnonce) != 0)
{
ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce");
- goto finally;
+ RETURN(HA_FALSE);
}
/* Do a rough hash into the real nonce, for use as a key */
@@ -305,7 +303,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
if(r == HA_FALSE)
ha_messagex(rq, LOG_WARNING, "digest response contains invalid nonce");
- goto finally;
+ RETURN(r);
}
/* Check to see if we're stale */
@@ -315,7 +313,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
dg.client.username);
stale = 1;
- goto finally;
+ RETURN(HA_FALSE);
}
}
@@ -340,7 +338,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
rq->resp_code = HA_SERVER_BADREQ;
}
- goto finally;
+ RETURN(ret);
}
/*
@@ -359,19 +357,13 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
rec = make_digest_rec(nonce, dg.client.username);
if(!rec)
- {
- ret = HA_CRITERROR;
- goto finally;
- }
+ RETURN(HA_CRITERROR);
ASSERT(ctx->f_validate_digest);
r = ctx->f_validate_digest(rq, dg.client.username, &dg);
if(r != HA_OK)
- {
- ret = r;
- goto finally;
- }
+ RETURN(r);
/* Save away pertinent information when successful*/
memcpy(rec->ha1, dg.ha1, MD5_LEN);
@@ -387,8 +379,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
if(md5_strcmp(rec->userhash, dg.client.username) != 0)
{
ha_messagex(NULL, LOG_ERR, "digest response contains invalid username");
- ret = HA_FALSE;
- goto finally;
+ RETURN(HA_FALSE);
}
/* And do the validation ourselves */
@@ -408,7 +399,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
ha_messagex(NULL, LOG_WARNING, "digest re-authentication failed for user: %s",
dg.client.username);
- goto finally;
+ RETURN(ret);
}
}
@@ -429,10 +420,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
t = digest_respond(&dg, rq->buf, stale ? nonce : NULL);
if(!t)
- {
- ret = HA_CRITERROR;
- goto finally;
- }
+ RETURN(HA_CRITERROR);
if(t[0])
ha_addheader(rq, "Authentication-Info", t);
@@ -450,7 +438,7 @@ finally:
free(rec);
/* If nobody above responded then challenge the client again */
- if(rq->resp_code == -1)
+ if(ret == HA_FALSE && rq->resp_code == -1)
return do_digest_challenge(rq, ctx, stale);
return ret;
@@ -552,8 +540,6 @@ int bd_init(ha_context_t* context)
htc.f_freeval = free_hash_object;
htc.arg = NULL;
hsh_set_table_calls(ctx->cache, &htc);
-
- ha_messagex(NULL, LOG_INFO, "initialized handler");
}
return HA_OK;
diff --git a/daemon/digest.c b/daemon/digest.c
index bce588e..968399a 100644
--- a/daemon/digest.c
+++ b/daemon/digest.c
@@ -291,6 +291,8 @@ int digest_pre_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t
/* Validate the nc */
else
{
+ /* TODO: We need to validate the nc properly. Somehow that's not
+ * happening here. */
char* e;
long nc = strtol(dg->client.nc, &e, 16);
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c
index bae758a..4450b7a 100644
--- a/daemon/httpauthd.c
+++ b/daemon/httpauthd.c
@@ -33,6 +33,7 @@ extern ha_handler_t simple_handler;
extern ha_handler_t ldap_handler;
extern ha_handler_t ntlm_handler;
extern ha_handler_t pgsql_handler;
+extern ha_handler_t mysql_handler;
/* This is the list of all available handlers */
ha_handler_t* g_handlerlist[] =
@@ -46,6 +47,9 @@ ha_handler_t* g_handlerlist[] =
#if WITH_PGSQL
&pgsql_handler,
#endif
+#if WITH_MYSQL
+ &mysql_handler,
+#endif
&simple_handler,
};
@@ -115,6 +119,7 @@ int g_console = 0; /* debug mode read write from console
int g_debuglevel = LOG_ERR; /* what gets logged to console */
const char* g_socket = DEFAULT_SOCKET; /* The socket to communicate on */
int g_maxthreads = DEFAULT_MAXTHREADS; /* The maximum number of threads */
+unsigned int g_unique = 0x10000; /* A unique identifier (incremented) */
/* For main loop and signal handlers */
int g_quit = 0;
@@ -251,6 +256,9 @@ int main(int argc, char* argv[])
if(sock < 0)
err(1, "couldn't open socket");
+ i = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&i, sizeof(i));
+
/* Unlink the socket file if it exists */
/* TODO: Is this safe? */
unlink(g_socket);
@@ -970,7 +978,7 @@ static int httpauth_auth(ha_request_t* rq, int ofd)
return HA_OK;
}
-static int httpauth_set(ha_request_t* rq, int ofd)
+static int httpauth_set(ha_request_t* rq, ha_buffer_t* cbuf, int ofd)
{
httpauth_loaded_t* h;
const char* name = rq->req_args[0];
@@ -985,7 +993,8 @@ static int httpauth_set(ha_request_t* rq, int ofd)
if(strcasecmp(name, "Domain") == 0)
{
- rq->digest_domain = value ? value : "";
+ /* We need to copy this string so it doesn't get destroyed on next req */
+ rq->digest_domain = ha_bufcpy(rq->conn_buf, value ? value : "");
}
else if(strcasecmp(name, "Handler") == 0)
@@ -1026,6 +1035,7 @@ static int httpauth_set(ha_request_t* rq, int ofd)
static int httpauth_processor(int ifd, int ofd)
{
+ ha_buffer_t cbuf;
ha_buffer_t buf;
ha_request_t rq;
int result = -1;
@@ -1036,13 +1046,18 @@ static int httpauth_processor(int ifd, int ofd)
/* Initialize the memory buffers */
ha_bufinit(&buf);
+ ha_bufinit(&cbuf);
memset(&rq, 0, sizeof(rq));
/* Set up some context stuff */
rq.digest_domain = "";
rq.buf = &buf;
+ rq.conn_buf = &cbuf;
+ ha_lock(NULL);
+ rq.id = g_unique++;
+ ha_unlock(NULL);
if(httpauth_ready(&rq, ofd) == -1)
{
@@ -1079,7 +1094,7 @@ static int httpauth_processor(int ifd, int ofd)
break;
case REQTYPE_SET:
- r = httpauth_set(&rq, ofd);
+ r = httpauth_set(&rq, &cbuf, ofd);
break;
case REQTYPE_QUIT:
@@ -1121,6 +1136,7 @@ static int httpauth_processor(int ifd, int ofd)
}
finally:
+ ha_buffree(&cbuf);
ha_buffree(&buf);
return result;
}
diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h
index 680994e..1067d8d 100644
--- a/daemon/httpauthd.h
+++ b/daemon/httpauthd.h
@@ -164,9 +164,12 @@ typedef struct ha_request
ha_context_t* context;
const char* digest_domain;
- /* The buffer in use */
+ /* The buffer in use for the request */
ha_buffer_t* buf;
+ /* The buffer in use for the connection */
+ ha_buffer_t* conn_buf;
+
int resp_code; /* The response code */
const char* resp_detail; /* The details for response */
ha_header_t resp_headers[HA_MAX_HEADERS]; /* Headers for the response */
diff --git a/daemon/ldap.c b/daemon/ldap.c
index 1df7651..e3f6a5f 100644
--- a/daemon/ldap.c
+++ b/daemon/ldap.c
@@ -296,7 +296,7 @@ static int validate_ldap_password(const ha_request_t* rq, ldap_context_t* ctx, L
const char* p;
int type;
int res = HA_FALSE;
- int unknown = 0;
+ int foundany = 0;
ASSERT(entry && ld && ctx && clearpw && rq);
@@ -310,6 +310,11 @@ static int validate_ldap_password(const ha_request_t* rq, ldap_context_t* ctx, L
pw = *t;
type = parse_ldap_password(&pw);
+ if(type != LDAP_PW_UNKNOWN)
+ foundany = 1;
+ else
+ continue;
+
switch(type)
{
case LDAP_PW_CLEAR:
@@ -323,7 +328,7 @@ static int validate_ldap_password(const ha_request_t* rq, ldap_context_t* ctx, L
case LDAP_PW_CRYPT:
/* Not sure if crypt is thread safe */
ha_lock(NULL);
- p = crypt(clearpw, pw);
+ p = (const char*)crypt(clearpw, pw);
ha_unlock(NULL);
break;
@@ -331,10 +336,6 @@ static int validate_ldap_password(const ha_request_t* rq, ldap_context_t* ctx, L
p = make_password_sha(rq->buf, clearpw);
break;
- case LDAP_PW_UNKNOWN:
- unknown = 1;
- continue;
-
default:
/* Not reached */
ASSERT(0);
@@ -357,7 +358,7 @@ static int validate_ldap_password(const ha_request_t* rq, ldap_context_t* ctx, L
ldap_value_free(pws);
}
- if(res == HA_FALSE && unknown)
+ if(res == HA_FALSE && !foundany)
ha_messagex(rq, LOG_ERR, "server does not contain any compatible passwords for user: %s", user);
return res;
@@ -596,7 +597,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
LDAPMessage* results = NULL; /* freed in finally */
LDAPMessage* entry = NULL; /* no need to free */
struct berval** ha1s = NULL; /* freed manually */
- const char** pws;
+ const char** pws = NULL; /* freed in finally */
int ret = HA_FALSE;
const char* dn = NULL;
int r;
@@ -606,10 +607,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
ld = get_ldap_connection(rq, ctx);
if(!ld)
- {
- ret = HA_FAILED;
- goto finally;
- }
+ RETURN(HA_FAILED);
/*
* Discover the DN of the user. If there's a DN map string
@@ -621,10 +619,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
/* The map can have %u and %r to denote user and realm */
dn = bd_substitute(rq, user, ctx->dnmap);
if(!dn)
- {
- ret = HA_FAILED;
- goto finally;
- }
+ RETURN(HA_CRITERROR);
ha_messagex(rq, LOG_INFO, "mapped %s to %s", user, dn);
}
@@ -632,10 +627,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
/* Okay now we contact the LDAP server. */
r = retrieve_user_entry(rq, ctx, ld, user, &dn, &entry, &results);
if(r != HA_OK)
- {
- ret = r;
- goto finally;
- }
+ RETURN(r);
/* Figure out the users ha1 */
if(ctx->ha1_attr)
@@ -662,11 +654,11 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
ret = digest_complete_check(dg, rq->buf);
if(ret != HA_FALSE)
- goto finally;
+ RETURN(ret);
}
else if(r < 0)
- goto finally;
+ RETURN(r);
ha1s++;
}
@@ -691,7 +683,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
ret = digest_complete_check(dg, rq->buf);
if(ret != HA_FALSE)
- goto finally;
+ RETURN(ret);
}
}
@@ -730,10 +722,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
ld = get_ldap_connection(rq, ctx);
if(!ld)
- {
- ret = HA_FAILED;
- goto finally;
- }
+ RETURN(HA_FAILED);
/*
@@ -746,10 +735,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
/* The map can have %u and %r to denote user and realm */
dn = bd_substitute(rq, user, ctx->dnmap);
if(!dn)
- {
- ret = HA_CRITERROR;
- goto finally;
- }
+ RETURN(HA_CRITERROR);
ha_messagex(rq, LOG_INFO, "mapped %s to %s", user, dn);
}
@@ -774,10 +760,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
{
r = retrieve_user_entry(rq, ctx, ld, user, &dn, &entry, &results);
if(r != HA_OK)
- {
- ret = r;
- goto finally;
- }
+ RETURN(r);
}
@@ -790,13 +773,15 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
if(r != LDAP_SUCCESS)
{
if(r == LDAP_INVALID_CREDENTIALS)
- ha_messagex(rq, LOG_WARNING, "basic authentication (via bind) failed for user: %s",
- user);
-
+ {
+ ha_messagex(rq, LOG_WARNING, "basic authentication (via bind) failed for user: %s", user);
+ RETURN(HA_FALSE);
+ }
else
+ {
report_ldap(rq, "couldn't bind to LDAP server", r);
-
- goto finally;
+ RETURN(HA_FAILED);
+ }
}
/* It worked! */
diff --git a/daemon/mysql.c b/daemon/mysql.c
new file mode 100644
index 0000000..b6885b0
--- /dev/null
+++ b/daemon/mysql.c
@@ -0,0 +1,751 @@
+
+#include "usuals.h"
+#include "httpauthd.h"
+#include "md5.h"
+#include "sha1.h"
+#include "bd.h"
+
+#include <sys/time.h>
+
+/* Mysql library */
+#include <mysql.h>
+#include <errmsg.h>
+
+/* -------------------------------------------------------------------------------
+ * Structures
+ */
+
+#define DB_PW_CLEAR 0
+#define DB_PW_SHA1 1
+#define DB_PW_MD5 2
+#define DB_PW_CRYPT 3
+
+/* Our hanler context */
+typedef struct mysql_context
+{
+ /* Base Handler ------------------------------------------------------ */
+ bd_context_t bd;
+
+ /* Settings ---------------------------------------------------------- */
+ const char* host; /* The connection host or path */
+ unsigned int port; /* The connection port */
+ const char* user; /* The pgsql user name */
+ const char* password; /* The pgsql password */
+ const char* database; /* The database name */
+ const char* query; /* The query */
+ const char* pw_column; /* The database query to retrieve a password */
+ int pw_type; /* The type of password encoded in database */
+ const char* ha1_column; /* The database query to retrieve a ha1 */
+
+ int mysql_max; /* Number of open connections allowed */
+ int mysql_timeout; /* Maximum amount of time to dedicate to a query */
+ int use_unix_socket;
+
+ /* Context ----------------------------------------------------------- */
+ MYSQL** pool; /* Pool of available connections */
+ int pool_mark; /* Amount of connections allocated */
+}
+mysql_context_t;
+
+/* Forward declarations for callbacks */
+static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg);
+static int validate_basic(ha_request_t* rq, const char* user, const char* password);
+static void escape_mysql(const ha_request_t* rq, ha_buffer_t* buf, const char* value);
+
+/* The defaults for the context */
+static const mysql_context_t mysql_defaults =
+{
+ BD_CALLBACKS(validate_digest,
+ validate_basic, escape_mysql),
+ NULL, /* host */
+ 0, /* port */
+ NULL, /* user */
+ NULL, /* password */
+ NULL, /* database */
+ NULL, /* query */
+ NULL, /* pw_attr */
+ DB_PW_CLEAR, /* pw_type */
+ NULL, /* ha1_attr */
+ 10, /* mysql_max */
+ 30, /* mysql_timeout */
+ 0, /* use_unix_socket */
+ NULL, /* pool */
+ 0 /* pool_mark */
+};
+
+
+/* -------------------------------------------------------------------------------
+ * Internal Functions
+ */
+
+static void escape_mysql(const ha_request_t* rq, ha_buffer_t* buf, const char* value)
+{
+ size_t len;
+ char* t;
+
+ ASSERT(value);
+
+ len = strlen(value);
+
+ t = (char*)malloc((len * 2) + 1);
+ if(t != NULL)
+ {
+ mysql_escape_string(t, value, len);
+ ha_bufcpy(buf, t);
+ free(t);
+ }
+}
+
+static int dec_mysql_binary(const ha_request_t* rq, const char* enc,
+ unsigned char* bytes, size_t len)
+{
+ size_t enclen;
+ void* d;
+
+ ASSERT(rq && enc && bytes && len);
+ enclen = strlen(enc);
+
+ /* Hex encoded */
+ if(enclen == (len * 2))
+ {
+ d = ha_bufdechex(rq->buf, enc, &enclen);
+
+ if(d && enclen == len)
+ {
+ ha_messagex(rq, LOG_DEBUG, "found value in hex encoded format");
+ memcpy(bytes, d, len);
+ return HA_OK;
+ }
+ }
+
+ /* TODO: Does mysql have raw binary encoding? */
+
+ /* B64 Encoded */
+ enclen = strlen(enc);
+ d = ha_bufdec64(rq->buf, enc, &enclen);
+
+ if(d && len == enclen)
+ {
+ ha_messagex(rq, LOG_DEBUG, "found value in b64 encoded format");
+ memcpy(bytes, d, len);
+ return HA_OK;
+ }
+
+ return ha_buferr(rq->buf) ? HA_CRITERROR : HA_FALSE;
+}
+
+static int validate_ha1(ha_request_t* rq, mysql_context_t* ctx, const char* user,
+ const char* clearpw, const char* dbpw)
+{
+ unsigned char dbha1[MD5_LEN];
+ unsigned char ha1[MD5_LEN];
+ const char* p;
+
+ int r = dec_mysql_binary(rq, dbpw, dbha1, MD5_LEN);
+
+ if(r < 0)
+ return r;
+
+ if(r == HA_OK)
+ {
+ digest_makeha1(ha1, user, rq->context->realm, clearpw);
+ if(memcmp(ha1, dbha1, MD5_LEN) == 0)
+ return HA_OK;
+ }
+
+ return HA_FALSE;
+}
+
+static int validate_password(ha_request_t* rq, mysql_context_t* ctx, const char* user,
+ const char* clearpw, const char* dbpw)
+{
+ unsigned char buf[SHA1_LEN];
+ const char* p;
+ int r;
+
+ ASSERT(SHA1_LEN > MD5_LEN);
+
+ switch(ctx->pw_type)
+ {
+
+ /* Clear text */
+ case DB_PW_CLEAR:
+
+ if(strcmp(clearpw, dbpw) == 0)
+ {
+ ha_messagex(rq, LOG_DEBUG, "found matching clear text password");
+ return HA_OK;
+ }
+
+ break;
+
+ /* Crypt pw */
+ case DB_PW_CRYPT:
+
+ ha_lock(NULL);
+ p = (const char*)crypt(clearpw, dbpw);
+ ha_unlock(NULL);
+
+ if(p && strcmp(dbpw, p) == 0)
+ {
+ ha_messagex(rq, LOG_DEBUG, "found matching crypt password");
+ return HA_OK;
+ }
+
+ break;
+
+ /* MD5 */
+ case DB_PW_MD5:
+
+ r = dec_mysql_binary(rq, dbpw, buf, MD5_LEN);
+ if(r < 0) return r;
+
+ if(r == HA_OK && md5_strcmp(buf, clearpw) == 0)
+ {
+ ha_messagex(rq, LOG_DEBUG, "found matching md5 password");
+ return HA_OK;
+ }
+
+ break;
+
+
+ /* SHA1 */
+ case DB_PW_SHA1:
+
+ r = dec_mysql_binary(rq, dbpw, buf, SHA1_LEN);
+ if(r < 0) return r;
+
+ if(r == HA_OK && sha1_strcmp(buf, clearpw) == 0)
+ {
+ ha_messagex(rq, LOG_DEBUG, "found matching sha1 password");
+ return HA_OK;
+ }
+
+ break;
+
+ default:
+ ASSERT(0 && "invalid password type");
+ break;
+ };
+
+ return HA_FALSE;
+}
+
+static MYSQL* get_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx)
+{
+ MYSQL* my;
+ MYSQL* r;
+ int i;
+
+ ASSERT(ctx);
+
+ for(i = 0; i < ctx->mysql_max; i++)
+ {
+ /* An open connection in the pool */
+ if(ctx->pool[i])
+ {
+ ha_messagex(rq, LOG_DEBUG, "using cached mysql connection");
+ my = ctx->pool[i];
+ ctx->pool[i] = NULL;
+ return my;
+ }
+ }
+
+ if(ctx->pool_mark >= ctx->mysql_max)
+ {
+ ha_messagex(rq, LOG_ERR, "too many open mysql connections");
+ return NULL;
+ }
+
+ my = mysql_init(NULL);
+ if(!my)
+ {
+ ha_messagex(rq, LOG_ERR, "out of memory");
+ return NULL;
+ }
+
+ mysql_options(my, MYSQL_OPT_CONNECT_TIMEOUT, (char*)&(ctx->mysql_timeout));
+ /* mysql_options(my, MYSQL_OPT_READ_TIMEOUT, (char*)&(ctx->mysql_timeout));
+ mysql_options(my, MYSQL_OPT_WRITE_TIMEOUT, (char*)&(ctx->mysql_timeout)); */
+
+ /* Apparently mysql_real_connect is not thread safe :( */
+ ha_lock(NULL);
+ r = mysql_real_connect(my, ctx->use_unix_socket ? NULL : ctx->host,
+ ctx->user, ctx->password, ctx->database, ctx->port,
+ ctx->use_unix_socket ? ctx->host : NULL, 0);
+ ha_unlock(NULL);
+
+ if(!r)
+ {
+ ha_messagex(rq, LOG_ERR, "error opening mysql connection: %s", mysql_error(my));
+ mysql_close(my);
+ return NULL;
+ }
+
+ ctx->pool_mark++;
+ ha_messagex(rq, LOG_DEBUG, "opened new mysql connection (total %d)", ctx->pool_mark);
+ return my;
+}
+
+static void discard_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx, MYSQL* my)
+{
+ mysql_close(my);
+ ctx->pool_mark--;
+ ha_messagex(rq, LOG_DEBUG, "discarding mysql connection (total %d)", ctx->pool_mark);
+}
+
+static void save_mysql_connection(const ha_request_t* rq, mysql_context_t* ctx, MYSQL* my)
+{
+ int i, e;
+
+ ASSERT(ctx);
+
+ if(!my)
+ return;
+
+ switch(mysql_errno(my))
+ {
+ case CR_SOCKET_CREATE_ERROR:
+ case CR_CONNECTION_ERROR:
+ case CR_CONN_HOST_ERROR:
+ case CR_IPSOCK_ERROR:
+ case CR_UNKNOWN_HOST:
+ case CR_SERVER_GONE_ERROR:
+ case CR_VERSION_ERROR:
+ case CR_WRONG_HOST_INFO:
+ case CR_LOCALHOST_CONNECTION:
+ case CR_TCP_CONNECTION:
+ case CR_SERVER_HANDSHAKE_ERR:
+ case CR_SERVER_LOST:
+ case CR_COMMANDS_OUT_OF_SYNC:
+ break;
+
+ /* Make sure it's worth saving */
+ default:
+ for(i = 0; i < ctx->mysql_max; i++)
+ {
+ /* An open connection in the pool */
+ if(!ctx->pool[i])
+ {
+ ha_messagex(rq, LOG_DEBUG, "caching mysql connection for later use");
+ ctx->pool[i] = my;
+ my = NULL;
+ break;
+ }
+ }
+ break;
+ };
+
+ if(my != NULL)
+ discard_mysql_connection(rq, ctx, my);
+}
+
+static int resolve_column(MYSQL_RES* res, const char* column)
+{
+ int i, fields;
+
+ if(column)
+ {
+ fields = mysql_num_fields(res);
+ for(i = 0; i < fields; i++)
+ {
+ if(strcasecmp(column, mysql_fetch_field_direct(res, i)->name) == 0)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int retrieve_user_rows(ha_request_t* rq, mysql_context_t* ctx,
+ const char* user, MYSQL_RES** results)
+{
+ MYSQL* my = NULL;
+ MYSQL_RES* res = NULL;
+ const char* query;
+ int ret = HA_OK;
+
+ ASSERT(rq && ctx && user && results);
+ *results = NULL;
+
+ my = get_mysql_connection(rq, ctx);
+ if(!my)
+ RETURN(HA_FAILED);
+
+ ASSERT(ctx->query);
+
+ /* The map can have %u and %r to denote user and realm */
+ query = bd_substitute(rq, user, ctx->query);
+ if(!query)
+ RETURN(HA_CRITERROR);
+
+ ha_messagex(rq, LOG_DEBUG, "executing query: %s", query);
+ if(mysql_query(my, query) != 0)
+ {
+ ha_messagex(rq, LOG_ERR, "error querying database: %s", mysql_error(my));
+ RETURN(HA_FAILED);
+ }
+
+ res = mysql_store_result(my);
+ if(!res)
+ {
+ if(mysql_field_count(my) == 0)
+ ha_messagex(rq, LOG_ERR, "mysql query didn't return results: %s", query);
+ else
+ ha_messagex(rq, LOG_ERR, "error querying database: %s", mysql_error(my));
+
+ RETURN(HA_FAILED);
+ }
+
+ if(mysql_num_rows(res) == 0)
+ {
+ ha_messagex(rq, LOG_WARNING, "login failed. couldn't find user: %s", user);
+ RETURN(HA_FALSE);
+ }
+
+ ha_messagex(rq, LOG_DEBUG, "received %d result rows", mysql_num_rows(res));
+ *results = res;
+ res = NULL;
+
+finally:
+
+ if(res != NULL)
+ mysql_free_result(res);
+
+ /* TODO: Look into what happens if we free a mysql connection
+ * before processing results: */
+ if(my != NULL)
+ save_mysql_connection(rq, ctx, my);
+
+ return ret;
+}
+
+static int validate_digest(ha_request_t* rq, const char* user, digest_context_t* dg)
+{
+ mysql_context_t* ctx = (mysql_context_t*)rq->context->ctx_data;
+ MYSQL_RES* res = NULL;
+ MYSQL_ROW row;
+ int ret = HA_FALSE;
+ int pw_column = -1;
+ int ha1_column = -1;
+ int r, i, foundany = 0;
+ const char* v;
+
+ ASSERT(rq && user && dg);
+
+ ret = retrieve_user_rows(rq, ctx, user, &res);
+ if(ret != HA_OK)
+ RETURN(ret);
+
+ ASSERT(res);
+
+ pw_column = resolve_column(res, ctx->pw_column);
+ ha1_column = resolve_column(res, ctx->ha1_column);
+
+ if(pw_column == -1 && ha1_column == -1)
+ {
+ if(mysql_num_fields(res) > 1)
+ ha_messagex(rq, LOG_WARNING, "query returned more than 1 column, using first as password");
+
+ pw_column = 0;
+ }
+
+ while((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(pw_column != -1 && ctx->pw_type == DB_PW_CLEAR)
+ {
+ v = *(row + pw_column);
+ if(v != NULL)
+ {
+ foundany = 1;
+
+ digest_makeha1(dg->ha1, user, rq->context->realm, v);
+ ha_messagex(rq, LOG_DEBUG, "testing clear text password for digest auth");
+
+ /* Run the actual check */
+ ret = digest_complete_check(dg, rq->buf);
+
+ if(ret != HA_FALSE)
+ RETURN(ret);
+ }
+ }
+
+ if(ha1_column != -1)
+ {
+ v = *(row + ha1_column);
+ if(v != NULL)
+ {
+ ret = dec_mysql_binary(rq, v, dg->ha1, MD5_LEN);
+ if(ret < 0)
+ RETURN(ret)
+ else if(ret == HA_FALSE)
+ continue;
+
+ foundany = 1;
+
+ /* Run the actual check */
+ ret = digest_complete_check(dg, rq->buf);
+
+ if(ret != HA_FALSE)
+ RETURN(ret);
+ }
+ }
+ }
+
+ if(!foundany)
+ ha_messagex(rq, LOG_WARNING, "no clear password or ha1 present for user: %s", user);
+
+finally:
+ if(res)
+ mysql_free_result(res);
+
+ return ret;
+}
+
+static int validate_basic(ha_request_t* rq, const char* user, const char* password)
+{
+ mysql_context_t* ctx = (mysql_context_t*)rq->context->ctx_data;
+ MYSQL_RES* res = NULL;
+ MYSQL_ROW row;
+ int ret = HA_FALSE;
+ int pw_column = -1;
+ int ha1_column = -1;
+ int i, foundany = 0;
+ const char* v;
+
+ ASSERT(rq && user && password);
+
+ ret = retrieve_user_rows(rq, ctx, user, &res);
+ if(ret != HA_OK)
+ RETURN(ret);
+
+ ASSERT(res);
+
+ pw_column = resolve_column(res, ctx->pw_column);
+ ha1_column = resolve_column(res, ctx->ha1_column);
+
+ if(pw_column == -1 && ha1_column == -1)
+ {
+ if(mysql_num_fields(res) > 1)
+ ha_messagex(rq, LOG_WARNING, "query returned more than 1 column, using first as password");
+ pw_column = 0;
+ }
+
+
+ while((row = mysql_fetch_row(res)) != NULL)
+ {
+ if(pw_column != -1)
+ {
+ v = *(row + pw_column);
+ if(v != NULL)
+
+ {
+ foundany = 1;
+ ret = validate_password(rq, ctx, user, password, v);
+ if(ret != HA_FALSE)
+ RETURN(ret);
+ }
+ }
+
+ if(ha1_column != -1)
+ {
+ v = *(row + ha1_column);
+ if(v != NULL)
+ {
+ foundany = 1;
+ ret = validate_ha1(rq, ctx, user, password, v);
+ if(ret != HA_FALSE)
+ RETURN(ret);
+ }
+ }
+ }
+
+ if(!foundany)
+ ha_messagex(rq, LOG_WARNING, "no password present for user: %s", user);
+
+finally:
+ if(res)
+ mysql_free_result(res);
+
+ return ret;
+}
+
+
+/* -------------------------------------------------------------------------------
+ * Handler Functions
+ */
+
+int mysql_config(ha_context_t* context, const char* name, const char* value)
+{
+ mysql_context_t* ctx = (mysql_context_t*)(context->ctx_data);
+
+ ASSERT(name && value && value[0]);
+
+ if(strcmp(name, "dbserver") == 0)
+ {
+ ctx->use_unix_socket = (value[0] == '/');
+ ctx->host = value;
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbport") == 0)
+ {
+ return ha_confint(name, value, 0, 65535, &(ctx->port));
+ }
+
+ if(strcmp(name, "dbuser") == 0)
+ {
+ ctx->user = value;
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbpassword") == 0)
+ {
+ ctx->password = value;
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbdatabase") == 0)
+ {
+ ctx->database = value;
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbquery") == 0)
+ {
+ ctx->query = value;
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbpwcolumn") == 0)
+ {
+ ctx->pw_column = value;
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbpwtype") == 0)
+ {
+ if(strcasecmp(value, "clear") == 0)
+ ctx->pw_type = DB_PW_CLEAR;
+ else if(strcasecmp(value, "crypt") == 0)
+ ctx->pw_type = DB_PW_CRYPT;
+ else if(strcasecmp(value, "md5") == 0)
+ ctx->pw_type = DB_PW_MD5;
+ else if(strcasecmp(value, "sha1") == 0)
+ ctx->pw_type = DB_PW_SHA1;
+ else
+ {
+ ha_messagex(NULL, LOG_ERR, "invalid value for '%s' (must be 'clear', 'crypt', 'md5' or 'sha1')", name);
+ return HA_FAILED;
+ }
+
+ return HA_OK;
+ }
+
+ if(strcmp(name, "dbha1column") == 0)
+ {
+ ctx->ha1_column = value;
+ return HA_OK;
+ }
+
+ else if(strcmp(name, "dbmax") == 0)
+ {
+ return ha_confint(name, value, 1, 256, &(ctx->mysql_max));
+ }
+
+ else if(strcmp(name, "dbtimeout") == 0)
+ {
+ /* TODO: Implement database timeouts */
+ return ha_confint(name, value, 0, 86400, &(ctx->mysql_timeout));
+ }
+
+ return HA_FALSE;
+}
+
+int mysql_initialize(ha_context_t* context)
+{
+ int r;
+
+ if((r = bd_init(context)) != HA_OK)
+ return r;
+
+ /* Context specific initialization */
+ if(context)
+ {
+ mysql_context_t* ctx = (mysql_context_t*)(context->ctx_data);
+ ASSERT(ctx);
+
+ /* Check for mandatory configuration */
+ if(!ctx->database || !ctx->query)
+ {
+ ha_messagex(NULL, LOG_ERR, "mysql configuration incomplete. "
+ "Must have DBDatabase and DBQuery.");
+ return HA_FAILED;
+ }
+
+ ASSERT(!ctx->pool);
+ ASSERT(ctx->mysql_max > 0);
+
+ /*
+ * Our connection pool. It's the size of our maximum
+ * amount of pending connections as that's the max
+ * we'd be able to use at a time anyway.
+ */
+ ctx->pool = (MYSQL**)malloc(sizeof(MYSQL*) * ctx->mysql_max);
+ if(!ctx->pool)
+ {
+ ha_messagex(NULL, LOG_CRIT, "out of memory");
+ return HA_CRITERROR;
+ }
+
+ memset(ctx->pool, 0, sizeof(MYSQL*) * ctx->mysql_max);
+ ha_messagex(NULL, LOG_INFO, "initialized mysql handler");
+ }
+
+ return HA_OK;
+}
+
+void mysql_destroy(ha_context_t* context)
+{
+ if(context)
+ {
+ /* Note: We don't need to be thread safe here anymore */
+ mysql_context_t* ctx = (mysql_context_t*)(context->ctx_data);
+ int i;
+
+ ASSERT(ctx);
+
+ if(ctx->pool)
+ {
+ /* Close any connections we have open */
+ for(i = 0; i < ctx->mysql_max; i++)
+ {
+ if(ctx->pool[i])
+ mysql_close(ctx->pool[i]);
+ }
+
+ /* And free the connection pool */
+ free(ctx->pool);
+ }
+ }
+
+ bd_destroy(context);
+ ha_messagex(NULL, LOG_INFO, "uninitialized mysql handler");
+}
+
+
+
+/* -------------------------------------------------------------------------------
+ * Handler Definition
+ */
+
+ha_handler_t mysql_handler =
+{
+ "MYSQL", /* The type */
+ mysql_initialize, /* Initialization function */
+ mysql_destroy, /* Uninitialization routine */
+ mysql_config, /* Config routine */
+ bd_process, /* Processing routine */
+ &mysql_defaults, /* The context defaults */
+ sizeof(mysql_context_t)
+};
diff --git a/daemon/ntlm.c b/daemon/ntlm.c
index 63d4580..ab6e5e4 100644
--- a/daemon/ntlm.c
+++ b/daemon/ntlm.c
@@ -310,14 +310,14 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
d = ha_bufdec64(rq->buf, header, &len);
if(!d || len == 0)
- goto finally;
+ RETURN(HA_FALSE);
r = ntlmssp_decode_msg(&ntlmssp, d, len, &flags);
if(r != 0)
{
ha_messagex(rq, LOG_WARNING, "decoding NTLMSSP message failed (error %d)", r);
rq->resp_code = HA_SERVER_BADREQ;
- goto finally;
+ RETURN(HA_FALSE);
}
@@ -350,16 +350,13 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
conn = NULL;
if(r < 0)
- {
- ret = HA_CRITERROR;
- }
+ RETURN(HA_CRITERROR);
else
{
ha_messagex(rq, LOG_ERR, "received out of order NTLM request from client");
rq->resp_code = HA_SERVER_BADREQ;
+ RETURN(HA_FALSE);
}
-
- goto finally;
}
@@ -386,10 +383,7 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
conn = makeconnection(rq, ctx);
if(!conn)
- {
- ret = HA_FAILED;
- goto finally;
- }
+ RETURN(HA_FAILED);
/* Save away any flags given us by ntlm_decode_msg */
conn->flags = flags;
@@ -413,7 +407,7 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
}
if(ha_buferr(rq->buf))
- goto finally;
+ RETURN(HA_FALSE);
/*
* TODO: Our callers need to be able to keep alive
@@ -431,16 +425,14 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
conn = NULL;
if(r < 0)
- {
- ret = HA_CRITERROR;
- }
+ RETURN(HA_CRITERROR);
else
{
ha_messagex(rq, LOG_DEBUG, "sending ntlm challenge");
ha_addheader(rq, "WWW-Authenticate", ha_bufdata(rq->buf));
rq->resp_code = HA_SERVER_DECLINE;
+ RETURN(HA_FALSE);
}
- goto finally;
}
/* A response to a challenge */
@@ -457,14 +449,14 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
{
ha_messagex(rq, LOG_WARNING, "received out of order NTLM response from client");
rq->resp_code = HA_SERVER_BADREQ;
- goto finally;
+ RETURN(HA_FALSE);
}
if(!ntlmssp.user)
{
ha_messagex(rq, LOG_WARNING, "received NTLM response without user name");
rq->resp_code = HA_SERVER_BADREQ;
- goto finally;
+ RETURN(HA_FALSE);
}
/* We have to lock while going into smblib */
@@ -485,7 +477,7 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
* caller to put in all the proper headers for us.
*/
ha_messagex(rq, LOG_WARNING, "failed NTLM logon for user '%s'", ntlmssp.user);
- ret = HA_FALSE;
+ RETURN(HA_FALSE);
}
/* A successful login ends here */
@@ -505,21 +497,18 @@ int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key,
if(!r)
{
ha_messagex(NULL, LOG_CRIT, "out of memory");
- ret = HA_CRITERROR;
- }
- else
- {
- ret = HA_OK;
+ RETURN(HA_CRITERROR);
}
- }
- goto finally;
+ RETURN(HA_OK);
+ }
}
+ break;
default:
ha_messagex(rq, LOG_WARNING, "received invalid NTLM message (type %d)", ntlmssp.msg_type);
rq->resp_code = HA_SERVER_BADREQ;
- goto finally;
+ RETURN(HA_FALSE);
};
diff --git a/daemon/pgsql.c b/daemon/pgsql.c
index 225bc65..6ed5658 100644
--- a/daemon/pgsql.c
+++ b/daemon/pgsql.c
@@ -7,7 +7,7 @@
#include <sys/time.h>
-/* LDAP library */
+/* Postgresql library */
#include <libpq-fe.h>
/* -------------------------------------------------------------------------------
@@ -37,7 +37,7 @@ typedef struct pgsql_context
const char* ha1_column; /* The database query to retrieve a ha1 */
int pgsql_max; /* Number of open connections allowed */
- int pgsql_timeout; /* Maximum amount of time to dedicate to an ldap query */
+ int pgsql_timeout; /* Maximum amount of time to dedicate to a query */
/* Context ----------------------------------------------------------- */
PGconn** pool; /* Pool of available connections */
@@ -84,11 +84,12 @@ static void escape_pgsql(const ha_request_t* rq, ha_buffer_t* buf, const char* v
len = strlen(value);
- /* Bit of a hack, we copy the string in twice to give enough room. */
- if((t = (char*)ha_bufmalloc(buf, (len * 2) + 1)) != NULL)
+ t = (char*)malloc((len * 2) + 1);
+ if(t != NULL)
{
PQescapeString(t, value, len);
ha_bufcpy(buf, t);
+ free(t);
}
}
@@ -192,11 +193,11 @@ static int validate_password(ha_request_t* rq, pgsql_context_t* ctx, const char*
/* Crypt pw */
case DB_PW_CRYPT:
- ha_lock();
- p = crypt(clearpw, dbpw);
- ha_unlock();
+ ha_lock(NULL);
+ p = (const char*)crypt(clearpw, dbpw);
+ ha_unlock(NULL);
- if(p && strcmp(clearpw, p) == 0)
+ if(p && strcmp(dbpw, p) == 0)
{
ha_messagex(rq, LOG_DEBUG, "found matching crypt password");
return HA_OK;
@@ -336,11 +337,11 @@ static int check_pgsql_result(ha_request_t* rq, PGresult* res)
ha_messagex(rq, LOG_ERR, "error communicating with pgsql server");
return HA_FAILED;
case PGRES_NONFATAL_ERROR:
+ ha_messagex(rq, LOG_ERR, "warning querying database: %s", PQresultErrorMessage(res));
+ return HA_OK;
+ case PGRES_FATAL_ERROR:
ha_messagex(rq, LOG_ERR, "error querying database: %s", PQresultErrorMessage(res));
return HA_FAILED;
- case PGRES_FATAL_ERROR:
- ha_messagex(rq, LOG_CRIT, "internal error in postgres library");
- return HA_CRITERROR;
case PGRES_COPY_OUT:
case PGRES_COPY_IN:
default:
@@ -375,25 +376,19 @@ static int retrieve_user_rows(ha_request_t* rq, pgsql_context_t* ctx,
const char* query;
int ret = HA_OK;
- ASSERT(rq && ctx && user && res);
+ ASSERT(rq && ctx && user && results);
*results = NULL;
pg = get_pgsql_connection(rq, ctx);
if(!pg)
- {
- ret = HA_FAILED;
- goto finally;
- }
+ RETURN(HA_FAILED);
ASSERT(ctx->query);
/* The map can have %u and %r to denote user and realm */
query = bd_substitute(rq, user, ctx->query);
if(!query)
- {
- ret = HA_CRITERROR;
- goto finally;
- }
+ RETURN(HA_CRITERROR);
ha_messagex(rq, LOG_DEBUG, "executing query: %s", query);
res = PQexec(pg, query);
@@ -401,27 +396,29 @@ static int retrieve_user_rows(ha_request_t* rq, pgsql_context_t* ctx,
ret = check_pgsql_result(rq, res);
if(ret != HA_OK)
- goto finally;
+ RETURN(ret);
if(PQntuples(res) == 0)
{
ha_messagex(rq, LOG_WARNING, "login failed. couldn't find user: %s", user);
- ret = HA_FALSE;
- goto finally;
+ RETURN(HA_FALSE);
}
if(PQnfields(res) <= 0)
{
ha_messagex(rq, LOG_ERR, "query returned 0 columns: %s", query);
- ret = HA_FAILED;
- goto finally;
+ RETURN(HA_FAILED);
}
*results = res;
+ res = NULL;
ha_messagex(rq, LOG_DEBUG, "received %d result rows", PQntuples(res));
finally:
+ if(res != NULL)
+ PQclear(res);
+
/* According to libpg we can close/save the connection
* before the returned results are freed, no worries there */
if(pg != NULL)
@@ -443,7 +440,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
ret = retrieve_user_rows(rq, ctx, user, &res);
if(ret != HA_OK)
- goto finally;
+ RETURN(ret);
ASSERT(res);
@@ -467,12 +464,13 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
foundany = 1;
digest_makeha1(dg->ha1, user, rq->context->realm, PQgetvalue(res, i, pw_column));
+ ha_messagex(rq, LOG_DEBUG, "testing clear text password for digest auth");
/* Run the actual check */
ret = digest_complete_check(dg, rq->buf);
if(ret != HA_FALSE)
- goto finally;
+ RETURN(ret);
}
}
@@ -482,7 +480,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
{
ret = dec_pgsql_binary(rq, PQgetvalue(res, i, ha1_column), dg->ha1, MD5_LEN);
if(ret < 0)
- goto finally;
+ RETURN(ret)
else if(ret == HA_FALSE)
continue;
@@ -492,7 +490,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
ret = digest_complete_check(dg, rq->buf);
if(ret != HA_FALSE)
- goto finally;
+ RETURN(ret);
}
}
}
@@ -520,7 +518,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
ret = retrieve_user_rows(rq, ctx, user, &res);
if(ret != HA_OK)
- goto finally;
+ RETURN(ret);
ASSERT(res);
@@ -544,7 +542,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
foundany = 1;
ret = validate_password(rq, ctx, user, password, PQgetvalue(res, i, pw_column));
if(ret != HA_FALSE)
- goto finally;
+ RETURN(ret);
}
}
@@ -555,7 +553,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
foundany = 1;
ret = validate_ha1(rq, ctx, user, password, PQgetvalue(res, i, ha1_column));
if(ret != HA_FALSE)
- goto finally;
+ RETURN(ret);
}
}
}
@@ -625,19 +623,21 @@ int pgsql_config(ha_context_t* context, const char* name, const char* value)
if(strcmp(name, "dbpwtype") == 0)
{
- if(strcmp(value, "clear") == 0)
+ if(strcasecmp(value, "clear") == 0)
ctx->pw_type = DB_PW_CLEAR;
- else if(strcmp(value, "crypt") == 0)
+ else if(strcasecmp(value, "crypt") == 0)
ctx->pw_type = DB_PW_CRYPT;
- else if(strcmp(value, "md5") == 0)
+ else if(strcasecmp(value, "md5") == 0)
ctx->pw_type = DB_PW_MD5;
- else if(strcmp(value, "sha1") == 0)
+ else if(strcasecmp(value, "sha1") == 0)
ctx->pw_type = DB_PW_SHA1;
else
{
ha_messagex(NULL, LOG_ERR, "invalid value for '%s' (must be 'clear', 'crypt', 'md5' or 'sha1')", name);
return HA_FAILED;
}
+
+ return HA_OK;
}
if(strcmp(name, "dbha1column") == 0)
@@ -676,7 +676,7 @@ int pgsql_init(ha_context_t* context)
/* Check for mandatory configuration */
if(!ctx->database || !ctx->query)
{
- ha_messagex(NULL, LOG_ERR, "configuration incomplete. "
+ ha_messagex(NULL, LOG_ERR, "pgsql configuration incomplete. "
"Must have DBDatabase and DBQuery.");
return HA_FAILED;
}
diff --git a/daemon/simple.c b/daemon/simple.c
index 8e4f8df..fca0e28 100644
--- a/daemon/simple.c
+++ b/daemon/simple.c
@@ -208,7 +208,7 @@ static int validate_basic(ha_request_t* rq, const char* user, const char* passwo
ha_lock(NULL);
/* Check the password */
- t2 = crypt(password, t);
+ t2 = (const char*)crypt(password, t);
ha_unlock(NULL);
@@ -326,7 +326,7 @@ ha_handler_t simple_handler =
bd_destroy, /* Uninitialization routine */
simple_config, /* Config routine */
bd_process, /* Processing routine */
- NULL, /* A default context */
+ &simple_defaults, /* A default context */
sizeof(simple_context_t) /* Size of the context */
};
diff --git a/daemon/usuals.h b/daemon/usuals.h
index 97d355b..020db4a 100644
--- a/daemon/usuals.h
+++ b/daemon/usuals.h
@@ -28,6 +28,8 @@
#define countof(x) (sizeof(x) / sizeof(x[0]))
+#define RETURN(x) { ret = (x); goto finally; }
+
#ifdef _DEBUG
#include "assert.h"
#define ASSERT assert