From 670eba73c474230e31d688e9568fcd540b4e3b39 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Mon, 9 Aug 2004 18:35:56 +0000 Subject: - added request parameter to ha_message... - combined ha_request and ha_response --- daemon/ntlm.c | 1156 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 578 insertions(+), 578 deletions(-) (limited to 'daemon/ntlm.c') diff --git a/daemon/ntlm.c b/daemon/ntlm.c index 031e19d..63d4580 100644 --- a/daemon/ntlm.c +++ b/daemon/ntlm.c @@ -19,7 +19,7 @@ */ #define NTLM_HASH_KEY_LEN MD5_LEN -#define NTLM_ESTABLISHED (void*)1 +#define NTLM_ESTABLISHED (void*)1 /* ------------------------------------------------------------------------------- @@ -29,9 +29,9 @@ /* A pending connection */ typedef struct ntlm_connection { - void* handle; - char nonce[NONCE_LEN]; - unsigned int flags; + void* handle; + char nonce[NONCE_LEN]; + unsigned int flags; } ntlm_connection_t; @@ -39,16 +39,16 @@ ntlm_connection_t; /* The main context */ typedef struct ntlm_context { - /* Settings ---------------------------------------------------------- */ - const char* server; /* Server to authenticate against */ - const char* domain; /* NTLM domain to authenticate against */ - const char* backup; /* Backup server if primary is down */ - int pending_max; /* Maximum number of connections at once */ - int pending_timeout; /* Timeout for authentication (in seconds) */ - - /* Context ----------------------------------------------------------- */ - hsh_t* pending; /* Pending connections */ - hsh_t* established; /* Established connections */ + /* Settings ---------------------------------------------------------- */ + const char* server; /* Server to authenticate against */ + const char* domain; /* NTLM domain to authenticate against */ + const char* backup; /* Backup server if primary is down */ + int pending_max; /* Maximum number of connections at once */ + int pending_timeout; /* Timeout for authentication (in seconds) */ + + /* Context ----------------------------------------------------------- */ + hsh_t* pending; /* Pending connections */ + hsh_t* established; /* Established connections */ } ntlm_context_t; @@ -56,8 +56,8 @@ ntlm_context_t; /* The default context settings */ static const ntlm_context_t ntlm_defaults = { - NULL, NULL, NULL, DEFAULT_PENDING_MAX, DEFAULT_PENDING_TIMEOUT, - NULL, NULL + NULL, NULL, NULL, DEFAULT_PENDING_MAX, DEFAULT_PENDING_TIMEOUT, + NULL, NULL }; @@ -70,467 +70,467 @@ static pthread_mutexattr_t g_smblib_mutexattr; * Internal Functions */ -static ntlm_connection_t* makeconnection(ntlm_context_t* ctx) +static ntlm_connection_t* makeconnection(ha_request_t* rq, ntlm_context_t* ctx) { - ntlm_connection_t* conn; - - ASSERT(ctx); - - conn = (ntlm_connection_t*)malloc(sizeof(ntlm_connection_t)); - if(!conn) - { - ha_messagex(LOG_CRIT, "out of memory"); - return NULL; - } - - memset(conn, 0, sizeof(*conn)); - - /* - * Open a connection to to the domain controller. I don't think - * we can cache these connections or use them again as opening - * a connection here results in an nonce being generated. - */ - conn->handle = ntlmssp_connect(ctx->server, ctx->backup, - ctx->domain, conn->nonce); - if(!conn->handle) - { - ha_messagex(LOG_ERR, "ntlm: couldn't connect to the domain server %s (backup: %s)", - ctx->server, ctx->backup ? ctx->backup : "none"); - free(conn); - return NULL; - } + ntlm_connection_t* conn; + + ASSERT(ctx); + + conn = (ntlm_connection_t*)malloc(sizeof(ntlm_connection_t)); + if(!conn) + { + ha_messagex(NULL, LOG_CRIT, "out of memory"); + return NULL; + } + + memset(conn, 0, sizeof(*conn)); + + /* + * Open a connection to to the domain controller. I don't think + * we can cache these connections or use them again as opening + * a connection here results in an nonce being generated. + */ + conn->handle = ntlmssp_connect(ctx->server, ctx->backup, + ctx->domain, conn->nonce); + if(!conn->handle) + { + ha_messagex(rq, LOG_ERR, "couldn't connect to the domain server %s (backup: %s)", + ctx->server, ctx->backup ? ctx->backup : "none"); + free(conn); + return NULL; + } - ha_messagex(LOG_INFO, "ntlm: established connection to server"); - return conn; + ha_messagex(rq, LOG_INFO, "established connection to server"); + return conn; } -static void freeconnection(ntlm_connection_t* conn) +static void freeconnection(ha_request_t* rq, ntlm_connection_t* conn) { - ASSERT(conn); + ASSERT(conn); - if(conn->handle) - { - ha_messagex(LOG_DEBUG, "ntlm: disconnected from server"); - ntlmssp_disconnect(conn->handle); - conn->handle = NULL; - } + if(conn->handle) + { + ha_messagex(rq, LOG_DEBUG, "disconnected from server"); + ntlmssp_disconnect(conn->handle); + conn->handle = NULL; + } - free(conn); + free(conn); } static void free_hash_object(void* arg, void* val) { - if(val) - { - ASSERT(val != NTLM_ESTABLISHED); - freeconnection((ntlm_connection_t*)val); - } + if(val) + { + ASSERT(val != NTLM_ESTABLISHED); + freeconnection(NULL, (ntlm_connection_t*)val); + } } static ntlm_connection_t* getpending(ntlm_context_t* ctx, const void* key) { - ntlm_connection_t* ret; + ntlm_connection_t* ret; - ASSERT(ctx && key); + ASSERT(ctx && key); - ha_lock(NULL); + ha_lock(NULL); - ret = (ntlm_connection_t*)hsh_rem(ctx->pending, key); + ret = (ntlm_connection_t*)hsh_rem(ctx->pending, key); - ha_unlock(NULL); + ha_unlock(NULL); - return ret; + return ret; } static int putpending(ntlm_context_t* ctx, const void* key, ntlm_connection_t* conn) { - int r = 0; + int r = 0; - ASSERT(ctx && key && conn); - ASSERT(conn->handle); + ASSERT(ctx && key && conn); + ASSERT(conn->handle); - if(!hsh_get(ctx->pending, key)) - { - ha_lock(NULL); + if(!hsh_get(ctx->pending, key)) + { + ha_lock(NULL); - if(!hsh_set(ctx->pending, key, (void*)conn)) - { - free_hash_object(NULL, conn); - ha_messagex(LOG_ERR, "out of memory"); - r = -1; - } + if(!hsh_set(ctx->pending, key, (void*)conn)) + { + free_hash_object(NULL, conn); + ha_messagex(NULL, LOG_ERR, "out of memory"); + r = -1; + } - ha_unlock(NULL); - } + ha_unlock(NULL); + } - return r; + return r; } -int ntlm_auth_basic(ntlm_context_t* ctx, char* key, const char* header, - ha_response_t* resp, ha_buffer_t* buf) +int ntlm_auth_basic(ha_request_t* rq, ntlm_context_t* ctx, char* key, + const char* header) { - ntlm_connection_t* conn; - char* t; - basic_header_t basic; - const char* domain = NULL; - int found = 0; - int r; - - ASSERT(ctx && key && header && resp && buf); - - /* - * We're doing basic authentication on the connection - * which invalidates any NTLM authentication we've started - * or done on this connection. - */ - conn = getpending(ctx, key); - if(conn) - { - ha_messagex(LOG_WARNING, "ntlm: basic auth killed a pending ntlm auth in progress"); - freeconnection(conn); - } - - if((r = basic_parse(header, buf, &basic)) < 0) - return r; - - /* Check and see if this connection is in the cache */ - ha_lock(NULL); - - if(hsh_get(ctx->established, basic.key) == NTLM_ESTABLISHED) - found = 1; - - ha_unlock(NULL); - - if(found) - ha_messagex(LOG_NOTICE, "ntlm: validated basic user against cache: %s", basic.user); + ntlm_connection_t* conn; + char* t; + basic_header_t basic; + const char* domain = NULL; + int found = 0; + int r; - else - { - /* Try to find a domain in the user */ - if((t = strchr(basic.user, '\\')) != NULL || - (t = strchr(basic.user, '/')) != NULL) - { - /* Break at the domain */ - domain = basic.user; - basic.user = t + 1; - *t = 0; - - /* Make sure this is our domain */ - if(strcasecmp(domain, ctx->domain) != 0) - domain = NULL; - } + ASSERT(ctx && key && header && rq); - if(!domain) + /* + * We're doing basic authentication on the connection + * which invalidates any NTLM authentication we've started + * or done on this connection. + */ + conn = getpending(ctx, key); + if(conn) { - /* Use the default domain if none specified */ - domain = ctx->domain; + ha_messagex(rq, LOG_WARNING, "basic auth killed a pending ntlm auth in progress"); + freeconnection(rq, conn); } - /* Make sure above did not fail */ - if(basic.user && basic.user[0] && basic.password && - domain && domain[0]) - { - ha_messagex(LOG_DEBUG, "ntlm: checking user against server: %s", basic.user); - - /* We need to lock to go into smblib */ - ha_lock(&g_smblib_mutex); - - /* Found in smbval/valid.h */ - if(ntlmssp_validuser(basic.user, basic.password, ctx->server, - ctx->backup, domain) == NTV_NO_ERROR) - { - /* If valid then we return */ - found = 1; - } - - ha_unlock(&g_smblib_mutex); - } - - if(found) - ha_messagex(LOG_NOTICE, "ntlm: validated basic user against server: %s", basic.user); - } - - if(found) - { - int r; - resp->code = HA_SERVER_OK; - resp->detail = basic.user; + if((r = basic_parse(header, rq->buf, &basic)) < 0) + return r; + /* Check and see if this connection is in the cache */ ha_lock(NULL); - /* We put this connection into the successful connections */ - r = hsh_set(ctx->established, basic.key, NTLM_ESTABLISHED); + if(hsh_get(ctx->established, basic.key) == NTLM_ESTABLISHED) + found = 1; ha_unlock(NULL); - if(!r) - { - ha_messagex(LOG_CRIT, "out of memory"); - return HA_CRITERROR; - } - - return HA_OK; - } - - return HA_FALSE; -} + if(found) + ha_messagex(rq, LOG_NOTICE, "validated basic user against cache: %s", basic.user); -int ntlm_auth_ntlm(ntlm_context_t* ctx, void* key, const char* header, - ha_response_t* resp, ha_buffer_t* buf) -{ - ntlmssp_info_rec ntlmssp; - ntlm_connection_t* conn = NULL; - unsigned int flags = 0; - int ret = HA_FALSE; - size_t len = 0; - void* d; - int r; - - ASSERT(ctx && key && header && resp && buf); - - /* - * Retrieve and remove the connection from the pending bag. - * We add it back again below if that's necessary. - */ - conn = getpending(ctx, key); - - /* - * We use the flags from an already established connection - * if we've been pending and stuff - */ - - if(conn && conn->flags) - flags = conn->flags; - - /* - * First we figure out what kind of message the client - * is sending us. - */ - - d = ha_bufdec64(buf, header, &len); - - if(!d || len == 0) - goto finally; - - r = ntlmssp_decode_msg(&ntlmssp, d, len, &flags); - if(r != 0) - { - ha_messagex(LOG_WARNING, "ntlm: decoding NTLMSSP message failed (error %d)", r); - resp->code = HA_SERVER_BADREQ; - goto finally; - } - - - switch(ntlmssp.msg_type) - { - - /* An initial NTLM request? */ - case 1: + else { - /* Win9x doesn't seem to send a domain or host */ - int win9x = !ntlmssp.host[0] && !ntlmssp.domain[0]; - - /* - * If we already have a connection to the domain controller - * then we're in trouble. Basically this is the second - * type 1 message we've received over this connection. - * - * TODO: Eventually what we want to do here is wait for the - * other authentication request to complete, or something - * like that. - */ - if(conn) - { - /* - * In this case we also add the connection back into the - * pending stack so that the correct request will complete - * properly when it comes through. - */ - r = putpending(ctx, key, conn); - conn = NULL; - - if(r < 0) + /* Try to find a domain in the user */ + if((t = strchr(basic.user, '\\')) != NULL || + (t = strchr(basic.user, '/')) != NULL) { - ret = HA_CRITERROR; + /* Break at the domain */ + domain = basic.user; + basic.user = t + 1; + *t = 0; + + /* Make sure this is our domain */ + if(strcasecmp(domain, ctx->domain) != 0) + domain = NULL; } - else + + if(!domain) { - ha_messagex(LOG_ERR, "ntlm: received out of order NTLM request from client"); - resp->code = HA_SERVER_BADREQ; + /* Use the default domain if none specified */ + domain = ctx->domain; } - goto finally; - } - + /* Make sure above did not fail */ + if(basic.user && basic.user[0] && basic.password && + domain && domain[0]) + { + ha_messagex(rq, LOG_DEBUG, "checking user against server: %s", basic.user); - /* - * Check how many connections we have to the domain controller - * and if too many then cut off here. - */ - if(ctx->pending_max != -1) - { - ha_lock(NULL); + /* We need to lock to go into smblib */ + ha_lock(&g_smblib_mutex); - if(hsh_count(ctx->pending) >= ctx->pending_max) - hsh_bump(ctx->pending); + /* Found in smbval/valid.h */ + if(ntlmssp_validuser(basic.user, basic.password, ctx->server, + ctx->backup, domain) == NTV_NO_ERROR) + { + /* If valid then we return */ + found = 1; + } - ha_unlock(NULL); - } + ha_unlock(&g_smblib_mutex); + } + if(found) + ha_messagex(rq, LOG_NOTICE, "validated basic user against server: %s", basic.user); + } - /* - * Open a connection to to the domain controller. I don't think - * we can cache these connections or use them again as opening - * a connection here results in an nonce being generated. - */ - conn = makeconnection(ctx); + if(found) + { + int r; + rq->resp_code = HA_SERVER_OK; + rq->resp_detail = basic.user; - if(!conn) - { - ret = HA_FAILED; - goto finally; - } - - /* Save away any flags given us by ntlm_decode_msg */ - conn->flags = flags; - - /* Start building the header */ - ha_bufcpy(buf, HA_PREFIX_NTLM); - - if(win9x) - { - struct ntlm_msg2_win9x msg_win9x; - ntlmssp_encode_msg2_win9x(conn->nonce, &msg_win9x, (char*)ctx->domain, flags); - ha_bufjoin(buf); - ha_bufenc64(buf, (unsigned char*)&msg_win9x, sizeof(msg_win9x)); - } - else - { - struct ntlm_msg2 msg; - ntlmssp_encode_msg2(conn->nonce, &msg); - ha_bufjoin(buf); - ha_bufenc64(buf, (unsigned char*)&msg, sizeof(msg)); - } - - if(ha_buferr(buf)) - goto finally; + ha_lock(NULL); - /* - * TODO: Our callers need to be able to keep alive - * connections that have authentication going on. - */ + /* We put this connection into the successful connections */ + r = hsh_set(ctx->established, basic.key, NTLM_ESTABLISHED); - /* Cache this connection in our pending set ... */ - r = putpending(ctx, key, conn); + ha_unlock(NULL); - /* - * By marking this as null, the cleanup code - * won't free the connection since it's been - * cached above. - */ - conn = NULL; + if(!r) + { + ha_messagex(NULL, LOG_CRIT, "out of memory"); + return HA_CRITERROR; + } - if(r < 0) - { - ret = HA_CRITERROR; - } - else - { - ha_messagex(LOG_DEBUG, "ntlm: sending ntlm challenge"); - ha_addheader(resp, "WWW-Authenticate", ha_bufdata(buf)); - resp->code = HA_SERVER_DECLINE; - } - goto finally; + return HA_OK; } - /* A response to a challenge */ - case 3: - { - /* - * We need to have a connection at this point or this whole thing - * has come in in the wrong order. Actually it's a client error - * for stuff to come in wrong. But since some web servers also - * kill keep-alives and stuff, we forgive and just ask the client - * for the authentication info again. - */ - if(!conn || !conn->handle) - { - ha_messagex(LOG_WARNING, "ntlm: received out of order NTLM response from client"); - resp->code = HA_SERVER_BADREQ; - goto finally; - } + return HA_FALSE; +} - if(!ntlmssp.user) - { - ha_messagex(LOG_WARNING, "ntlm: received NTLM response without user name"); - resp->code = HA_SERVER_BADREQ; - goto finally; - } +int ntlm_auth_ntlm(ha_request_t* rq, ntlm_context_t* ctx, void* key, + const char* header) +{ + ntlmssp_info_rec ntlmssp; + ntlm_connection_t* conn = NULL; + unsigned int flags = 0; + int ret = HA_FALSE; + size_t len = 0; + void* d; + int r; - /* We have to lock while going into smblib */ - ha_lock(&g_smblib_mutex); + ASSERT(ctx && key && header && rq); - /* Now authenticate them against the DC */ - r = ntlmssp_auth(conn->handle, ntlmssp.user, ntlmssp.nt, 1, - ntlmssp.domain[0] ? (char*)ntlmssp.domain : (char*)ctx->domain); + /* + * Retrieve and remove the connection from the pending bag. + * We add it back again below if that's necessary. + */ + conn = getpending(ctx, key); - ha_unlock(&g_smblib_mutex); + /* + * We use the flags from an already established connection + * if we've been pending and stuff + */ - /* The connection gets disconnected below */ + if(conn && conn->flags) + flags = conn->flags; - if(r == NTV_LOGON_ERROR) - { - /* - * Note that we don't set a code here. This causes our - * caller to put in all the proper headers for us. - */ - ha_messagex(LOG_WARNING, "ntlm: failed NTLM logon for user '%s'", ntlmssp.user); - ret = HA_FALSE; - } + /* + * First we figure out what kind of message the client + * is sending us. + */ - /* A successful login ends here */ - else - { - int r; - resp->detail = ntlmssp.user; - ha_messagex(LOG_NOTICE, "ntlm: validated ntlm user against server", ntlmssp.user); + d = ha_bufdec64(rq->buf, header, &len); - ha_lock(NULL); + if(!d || len == 0) + goto finally; - /* We put this connection into the successful connections */ - r = hsh_set(ctx->established, key, NTLM_ESTABLISHED); + 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; + } - ha_unlock(NULL); - if(!r) + switch(ntlmssp.msg_type) + { + + /* An initial NTLM request? */ + case 1: { - ha_messagex(LOG_CRIT, "out of memory"); - ret = HA_CRITERROR; + /* Win9x doesn't seem to send a domain or host */ + int win9x = !ntlmssp.host[0] && !ntlmssp.domain[0]; + + /* + * If we already have a connection to the domain controller + * then we're in trouble. Basically this is the second + * type 1 message we've received over this connection. + * + * TODO: Eventually what we want to do here is wait for the + * other authentication request to complete, or something + * like that. + */ + if(conn) + { + /* + * In this case we also add the connection back into the + * pending stack so that the correct request will complete + * properly when it comes through. + */ + r = putpending(ctx, key, conn); + conn = NULL; + + if(r < 0) + { + ret = HA_CRITERROR; + } + else + { + ha_messagex(rq, LOG_ERR, "received out of order NTLM request from client"); + rq->resp_code = HA_SERVER_BADREQ; + } + + goto finally; + } + + + /* + * Check how many connections we have to the domain controller + * and if too many then cut off here. + */ + if(ctx->pending_max != -1) + { + ha_lock(NULL); + + if(hsh_count(ctx->pending) >= ctx->pending_max) + hsh_bump(ctx->pending); + + ha_unlock(NULL); + } + + + /* + * Open a connection to to the domain controller. I don't think + * we can cache these connections or use them again as opening + * a connection here results in an nonce being generated. + */ + conn = makeconnection(rq, ctx); + + if(!conn) + { + ret = HA_FAILED; + goto finally; + } + + /* Save away any flags given us by ntlm_decode_msg */ + conn->flags = flags; + + /* Start building the header */ + ha_bufcpy(rq->buf, HA_PREFIX_NTLM); + + if(win9x) + { + struct ntlm_msg2_win9x msg_win9x; + ntlmssp_encode_msg2_win9x(conn->nonce, &msg_win9x, (char*)ctx->domain, flags); + ha_bufjoin(rq->buf); + ha_bufenc64(rq->buf, (unsigned char*)&msg_win9x, sizeof(msg_win9x)); + } + else + { + struct ntlm_msg2 msg; + ntlmssp_encode_msg2(conn->nonce, &msg); + ha_bufjoin(rq->buf); + ha_bufenc64(rq->buf, (unsigned char*)&msg, sizeof(msg)); + } + + if(ha_buferr(rq->buf)) + goto finally; + + /* + * TODO: Our callers need to be able to keep alive + * connections that have authentication going on. + */ + + /* Cache this connection in our pending set ... */ + r = putpending(ctx, key, conn); + + /* + * By marking this as null, the cleanup code + * won't free the connection since it's been + * cached above. + */ + conn = NULL; + + if(r < 0) + { + ret = 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; + } + goto finally; } - else + + /* A response to a challenge */ + case 3: { - ret = HA_OK; + /* + * We need to have a connection at this point or this whole thing + * has come in in the wrong order. Actually it's a client error + * for stuff to come in wrong. But since some web servers also + * kill keep-alives and stuff, we forgive and just ask the client + * for the authentication info again. + */ + if(!conn || !conn->handle) + { + ha_messagex(rq, LOG_WARNING, "received out of order NTLM response from client"); + rq->resp_code = HA_SERVER_BADREQ; + goto finally; + } + + if(!ntlmssp.user) + { + ha_messagex(rq, LOG_WARNING, "received NTLM response without user name"); + rq->resp_code = HA_SERVER_BADREQ; + goto finally; + } + + /* We have to lock while going into smblib */ + ha_lock(&g_smblib_mutex); + + /* Now authenticate them against the DC */ + r = ntlmssp_auth(conn->handle, ntlmssp.user, ntlmssp.nt, 1, + ntlmssp.domain[0] ? (char*)ntlmssp.domain : (char*)ctx->domain); + + ha_unlock(&g_smblib_mutex); + + /* The connection gets disconnected below */ + + if(r == NTV_LOGON_ERROR) + { + /* + * Note that we don't set a code here. This causes our + * 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; + } + + /* A successful login ends here */ + else + { + int r; + rq->resp_detail = ntlmssp.user; + ha_messagex(rq, LOG_NOTICE, "validated ntlm user against server", ntlmssp.user); + + ha_lock(NULL); + + /* We put this connection into the successful connections */ + r = hsh_set(ctx->established, key, NTLM_ESTABLISHED); + + ha_unlock(NULL); + + if(!r) + { + ha_messagex(NULL, LOG_CRIT, "out of memory"); + ret = HA_CRITERROR; + } + else + { + ret = HA_OK; + } + } + + goto finally; } - } - - goto finally; - } - default: - ha_messagex(LOG_WARNING, "ntlm: received invalid NTLM message (type %d)", ntlmssp.msg_type); - resp->code = HA_SERVER_BADREQ; - goto finally; - }; + default: + ha_messagex(rq, LOG_WARNING, "received invalid NTLM message (type %d)", ntlmssp.msg_type); + rq->resp_code = HA_SERVER_BADREQ; + goto finally; + }; finally: - if(ha_buferr(buf)) - ret = HA_CRITERROR; + if(ha_buferr(rq->buf)) + ret = HA_CRITERROR; - if(conn) - freeconnection(conn); + if(conn) + freeconnection(rq, conn); - return ret; + return ret; } @@ -540,245 +540,245 @@ finally: int ntlm_config(ha_context_t* context, const char* name, const char* value) { - ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); + ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); - ASSERT(name && value && value[0]); + ASSERT(name && value && value[0]); - if(strcmp(name, "ntlmserver") == 0) - { - ctx->server = value; - return HA_OK; - } + if(strcmp(name, "ntlmserver") == 0) + { + ctx->server = value; + return HA_OK; + } - else if(strcmp(name, "ntlmbackup") == 0) - { - ctx->backup = value; - return HA_OK; - } + else if(strcmp(name, "ntlmbackup") == 0) + { + ctx->backup = value; + return HA_OK; + } - else if(strcmp(name, "ntlmdomain") == 0) - { - ctx->domain = value; - return HA_OK; - } + else if(strcmp(name, "ntlmdomain") == 0) + { + ctx->domain = value; + return HA_OK; + } - else if(strcmp(name, "pendingmax") == 0) - { - return ha_confint(name, value, 1, 256, &(ctx->pending_max)); - } + else if(strcmp(name, "pendingmax") == 0) + { + return ha_confint(name, value, 1, 256, &(ctx->pending_max)); + } - else if(strcmp(name, "pendingtimeout") == 0) - { - return ha_confint(name, value, 1, 86400, &(ctx->pending_timeout)); - } + else if(strcmp(name, "pendingtimeout") == 0) + { + return ha_confint(name, value, 1, 86400, &(ctx->pending_timeout)); + } - return HA_FALSE; + return HA_FALSE; } int ntlm_init(ha_context_t* context) { - /* Per context initialization */ - if(context) - { - ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); - hsh_table_calls_t htc; + /* Per context initialization */ + if(context) + { + ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); + hsh_table_calls_t htc; - ASSERT(ctx); + ASSERT(ctx); - /* Make sure there are some types of authentication we can do */ - 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."); - return HA_FAILED; - } + /* Make sure there are some types of authentication we can do */ + if(!(context->allowed_types & (HA_TYPE_BASIC | HA_TYPE_NTLM))) + { + ha_messagex(NULL, LOG_ERR, "NTLM module configured, but does not implement any " + "configured authentication type."); + return HA_FAILED; + } - /* Check for mandatory configuration */ - if(!(ctx->server) || !(ctx->domain)) - { - ha_messagex(LOG_ERR, "NTLM configuration incomplete. " - "Must have NTLMServer and NTLMDomain configured."); - return HA_FAILED; - } + /* Check for mandatory configuration */ + if(!(ctx->server) || !(ctx->domain)) + { + ha_messagex(NULL, LOG_ERR, "NTLM configuration incomplete. " + "Must have NTLMServer and NTLMDomain configured."); + return HA_FAILED; + } - ASSERT(!ctx->pending); - ASSERT(!ctx->established); + ASSERT(!ctx->pending); + ASSERT(!ctx->established); - /* Initialize our tables */ - if(!(ctx->pending = hsh_create(NTLM_HASH_KEY_LEN)) || - !(ctx->established = hsh_create(NTLM_HASH_KEY_LEN))) - { - ha_messagex(LOG_CRIT, "out of memory"); - return HA_CRITERROR; - } + /* Initialize our tables */ + if(!(ctx->pending = hsh_create(NTLM_HASH_KEY_LEN)) || + !(ctx->established = hsh_create(NTLM_HASH_KEY_LEN))) + { + ha_messagex(NULL, LOG_CRIT, "out of memory"); + return HA_CRITERROR; + } - htc.f_freeval = free_hash_object; - htc.arg = NULL; - hsh_set_table_calls(ctx->pending, &htc); + htc.f_freeval = free_hash_object; + htc.arg = NULL; + hsh_set_table_calls(ctx->pending, &htc); - ha_messagex(LOG_INFO, "ntlm: initialized handler"); - } + ha_messagex(NULL, LOG_INFO, "initialized ntlm handler"); + } - /* Global Initialization */ - else - { - /* Create the smblib mutex */ - if(pthread_mutexattr_init(&g_smblib_mutexattr) != 0 || - pthread_mutexattr_settype(&g_smblib_mutexattr, HA_MUTEX_TYPE) || - pthread_mutex_init(&g_smblib_mutex, &g_smblib_mutexattr) != 0) + /* Global Initialization */ + else { - ha_messagex(LOG_CRIT, "threading problem. can't create mutex"); - return HA_CRITERROR; + /* Create the smblib mutex */ + if(pthread_mutexattr_init(&g_smblib_mutexattr) != 0 || + pthread_mutexattr_settype(&g_smblib_mutexattr, HA_MUTEX_TYPE) || + pthread_mutex_init(&g_smblib_mutex, &g_smblib_mutexattr) != 0) + { + ha_messagex(NULL, LOG_CRIT, "threading problem. can't create mutex"); + return HA_CRITERROR; + } } - } - return HA_OK; + return HA_OK; } void ntlm_destroy(ha_context_t* context) { - /* Per context destroy */ - if(context) - { - /* Note: We don't need to be thread safe here anymore */ - ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); + /* Per context destroy */ + if(context) + { + /* Note: We don't need to be thread safe here anymore */ + ntlm_context_t* ctx = (ntlm_context_t*)(context->ctx_data); - if(ctx->pending) - hsh_free(ctx->pending); + if(ctx->pending) + hsh_free(ctx->pending); - if(ctx->established) - hsh_free(ctx->established); + if(ctx->established) + hsh_free(ctx->established); - ha_messagex(LOG_INFO, "ntlm: uninitialized handler"); - } + ha_messagex(NULL, LOG_INFO, "uninitialized handler"); + } - /* Global Destroy */ - else - { - /* Close the mutex */ - pthread_mutex_destroy(&g_smblib_mutex); - pthread_mutexattr_destroy(&g_smblib_mutexattr); - } + /* Global Destroy */ + else + { + /* Close the mutex */ + pthread_mutex_destroy(&g_smblib_mutex); + pthread_mutexattr_destroy(&g_smblib_mutexattr); + } } -int ntlm_process(const ha_request_t* req, ha_response_t* resp) +int ntlm_process(ha_request_t* rq) { - 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; + ntlm_context_t* ctx = (ntlm_context_t*)(rq->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(req && resp); - ASSERT(req->args[AUTH_ARG_CONN]); + ASSERT(rq); + ASSERT(rq->req_args[AUTH_ARG_CONN]); - resp->code = -1; + rq->resp_code = -1; - /* Hash the unique key */ - md5_string(key, req->args[AUTH_ARG_CONN]); + /* Hash the unique key */ + md5_string(key, rq->req_args[AUTH_ARG_CONN]); - ha_lock(NULL); + ha_lock(NULL); - /* - * Purge out stale connection stuff. This includes - * authenticated connections which have expired as - * well as half open connections which expire. - */ - r = hsh_purge(ctx->pending, t - ctx->pending_timeout); - r += hsh_purge(ctx->established, t - req->context->cache_timeout); + /* + * Purge out stale connection stuff. This includes + * authenticated connections which have expired as + * well as half open connections which expire. + */ + r = hsh_purge(ctx->pending, t - ctx->pending_timeout); + r += hsh_purge(ctx->established, t - rq->context->cache_timeout); - ha_unlock(NULL); + ha_unlock(NULL); - if(r > 0) - ha_messagex(LOG_DEBUG, "ntlm: purged info from cache: %d", r); + if(r > 0) + ha_messagex(rq, LOG_DEBUG, "purged info from cache: %d", r); - /* Look for a NTLM header */ - if(req->context->allowed_types & HA_TYPE_NTLM) - { - header = ha_getheader(req, "Authorization", HA_PREFIX_NTLM); - if(header) + /* Look for a NTLM header */ + if(rq->context->allowed_types & HA_TYPE_NTLM) { - /* Trim off for decoding */ - header = trim_start(header); + header = ha_getheader(rq, "Authorization", HA_PREFIX_NTLM); + if(header) + { + /* Trim off for decoding */ + header = trim_start(header); - ha_messagex(LOG_DEBUG, "ntlm: processing ntlm auth header"); - ret = ntlm_auth_ntlm(ctx, key, header, resp, req->buf); - if(ret < 0) - return ret; + ha_messagex(rq, LOG_DEBUG, "processing ntlm auth header"); + ret = ntlm_auth_ntlm(rq, ctx, key, header); + if(ret < 0) + return ret; + } } - } - - /* If basic is enabled, and no NTLM */ - if(!header && req->context->allowed_types & HA_TYPE_BASIC) - { - /* Look for a Basic header */ - header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC); - if(header) + + /* If basic is enabled, and no NTLM */ + if(!header && rq->context->allowed_types & HA_TYPE_BASIC) { - /* Trim off for decoding */ - header = trim_start(header); + /* Look for a Basic header */ + header = ha_getheader(rq, "Authorization", HA_PREFIX_BASIC); + if(header) + { + /* Trim off for decoding */ + header = trim_start(header); - ha_messagex(LOG_DEBUG, "ntlm: processing basic auth header"); - ret = ntlm_auth_basic(ctx, key, header, resp, req->buf); - if(ret < 0) - return ret; + ha_messagex(rq, LOG_DEBUG, "processing basic auth header"); + ret = ntlm_auth_basic(rq, ctx, key, header); + if(ret < 0) + return ret; + } } - } - /* The authorization header was not found */ - else - { - ha_lock(NULL); - - /* - * NTLM trusts a connection after it's been authenticated - * so just pass success for those. Note that we do this - * in the absence of a authorization header so that we - * allow connections to be re-authenticated. - */ + /* The authorization header was not found */ + else + { + ha_lock(NULL); - if(hsh_get(ctx->established, key) == NTLM_ESTABLISHED) - { - hsh_touch(ctx->established, key); - resp->code = HA_SERVER_OK; - } + /* + * NTLM trusts a connection after it's been authenticated + * so just pass success for those. Note that we do this + * in the absence of a authorization header so that we + * allow connections to be re-authenticated. + */ - ha_unlock(NULL); + if(hsh_get(ctx->established, key) == NTLM_ESTABLISHED) + { + hsh_touch(ctx->established, key); + rq->resp_code = HA_SERVER_OK; + } - if(resp->code == HA_SERVER_OK) - ha_messagex(LOG_NOTICE, "ntlm: validated user against connection cache"); + ha_unlock(NULL); - /* TODO: We need to be able to retrieve the user here somehow */ - } + if(rq->resp_code == HA_SERVER_OK) + ha_messagex(rq, LOG_NOTICE, "validated user against connection cache"); + /* TODO: We need to be able to retrieve the user here somehow */ + } - /* If nobody's set any other response then... */ - if(resp->code != -1) - { - /* If authentication failed tell the browser about it */ - resp->code = HA_SERVER_DECLINE; - if(req->context->allowed_types & HA_TYPE_NTLM) + /* If nobody's set any other response then... */ + if(rq->resp_code != -1) { - ha_addheader(resp, "WWW-Authenticate", HA_PREFIX_NTLM); - ha_messagex(LOG_DEBUG, "ntlm: sent ntlm auth request"); - } + /* If authentication failed tell the browser about it */ + rq->resp_code = HA_SERVER_DECLINE; - if(req->context->allowed_types & HA_TYPE_BASIC) - { - ha_bufmcat(req->buf, HA_PREFIX_BASIC, "realm=\"", req->context->realm, "\"", NULL); + if(rq->context->allowed_types & HA_TYPE_NTLM) + { + ha_addheader(rq, "WWW-Authenticate", HA_PREFIX_NTLM); + ha_messagex(rq, LOG_DEBUG, "sent ntlm auth request"); + } - if(ha_buferr(req->buf)) - return HA_CRITERROR; + if(rq->context->allowed_types & HA_TYPE_BASIC) + { + ha_bufmcat(rq->buf, HA_PREFIX_BASIC, "realm=\"", rq->context->realm, "\"", NULL); - ha_addheader(resp, "WWW-Authenticate", ha_bufdata(req->buf)); - ha_messagex(LOG_DEBUG, "ntlm: sent basic auth request"); + if(ha_buferr(rq->buf)) + return HA_CRITERROR; + + ha_addheader(rq, "WWW-Authenticate", ha_bufdata(rq->buf)); + ha_messagex(rq, LOG_DEBUG, "sent basic auth request"); + } } - } - return ret; + return ret; } @@ -789,12 +789,12 @@ int ntlm_process(const ha_request_t* req, ha_response_t* resp) ha_handler_t ntlm_handler = { - "NTLM", /* The type */ - ntlm_init, /* Initialization function */ - ntlm_destroy, /* Uninitialization routine */ - ntlm_config, /* Config routine */ - ntlm_process, /* Processing routine */ - &ntlm_defaults, /* Default settings */ - sizeof(ntlm_context_t) + "NTLM", /* The type */ + ntlm_init, /* Initialization function */ + ntlm_destroy, /* Uninitialization routine */ + ntlm_config, /* Config routine */ + ntlm_process, /* Processing routine */ + &ntlm_defaults, /* Default settings */ + sizeof(ntlm_context_t) }; -- cgit v1.2.3