[PATCH] mod_auth_ntlm_winbind - support for REMOTE_USER lookahead
when reverse proxy
Michael Baltaks
mbaltaks at gmail.com
Tue Sep 23 23:39:54 GMT 2008
Hi,
Here is a patch that adds two things to mod_auth_ntlm_winbind, and has
been in production use on my server for over a year.
1) Allows using %{LA-U:REMOTE_USER} in rewrite rules when in reverse
proxy mode and authenticating with mod_auth_ntlm_winbind, useful for
letting httpd handle Active Directory authentication, and then pass the
user name to a backend server like zope/plone.
2) Adds two extra options to the config, [NTLMOmitDomain] allowing the
omission of the domain part of the username, and [NTLMDomainSeparator]
setting a separator for domain and username (so you can match the
winbind separator setting).
-Michael.
-------------- next part --------------
--- /Users/mick/Desktop/mod_auth_ntlm_winbind.c 2008-09-24 09:23:39.000000000 +1000
+++ ./mod_auth_ntlm_winbind.c 2008-08-27 11:25:48.000000000 +1000
@@ -97,6 +97,8 @@
char *ntlm_auth_helper;
char *negotiate_ntlm_auth_helper;
char *ntlm_plaintext_helper;
+ unsigned int omit_domain;
+ char * domain_separator;
} ntlm_config_rec;
/* A structure to hold per-connection information about authentications
@@ -118,6 +120,7 @@
char *auth_type;
apr_pool_t *pool;
int keepalives; /* used to detect redirected auths */
+ request_rec * r_main; /* track the main request if this is a subreq */
};
struct _ntlm_child_stuff {
@@ -194,6 +197,15 @@
(void *) APR_OFFSETOF(ntlm_config_rec, ntlm_basic_realm),
OR_AUTHCFG, "realm to use for Basic authentication" ),
+ AP_INIT_FLAG( "NTLMOmitDomain", ap_set_flag_slot,
+ (void *) APR_OFFSETOF(ntlm_config_rec, omit_domain),
+ OR_AUTHCFG,
+ "set to 'on' to strip the domain name from the user name" ),
+
+ AP_INIT_TAKE1( "NTLMDomainSeparator", ap_set_string_slot,
+ (void *) APR_OFFSETOF(ntlm_config_rec, domain_separator),
+ OR_AUTHCFG, "the separator between domain and user name" ),
+
#else
/* NTLM authentication commands */
@@ -234,11 +246,20 @@
{ "NTLMBasicRealm", ap_set_string_slot,
(void *) XtOffsetOf(ntlm_config_rec, ntlm_basic_realm),
OR_AUTHCFG, TAKE1, "realm to use for Basic authentication" },
+
+ { "NTLMOmitDomain", ap_set_flag_slot,
+ (void *) XtOffsetOf(ntlm_config_rec, omit_domain),
+ OR_AUTHCFG, FLAG, "set to 'on' to strip the domain name from the user name" },
+
+ { "NTLMDomainSeparator", ap_set_string_slot,
+ (void *) XtOffsetOf(ntlm_config_rec, domain_separator),
+ OR_AUTHCFG, TAKE1, "the separator between domain and user name" },
#endif
{ NULL }
};
+
/* both apache1 and apache2 use this to maintain per-child context */
static ntlm_context_t global_ntlm_context;
@@ -290,6 +311,30 @@
}
#endif
+
+/* strip domain name from user name */
+char *
+strip_domain_name(request_rec * r, char * username)
+{
+ char * new_username = username;
+ ntlm_config_rec *crec = (ntlm_config_rec *)
+ ap_get_module_config( r->per_dir_config,
+ &auth_ntlm_winbind_module );
+ if (crec->omit_domain)
+ {
+ RDEBUG( "removing domain name from %s", username);
+ char *s = strstr(username, crec->domain_separator);
+ if (s)
+ {
+ RDEBUG( "user name without domain is %s", s + 1);
+ s++;
+ new_username = s;
+ }
+ }
+ return new_username;
+}
+
+
/* helper function to pull out the context data */
static ntlm_connection_context_t *get_connection_context( struct conn_rec *connection ) {
ntlm_connection_context_t *retval = NULL;
@@ -347,7 +392,7 @@
if ( ctxt->connected_user_authenticated &&
ctxt->connected_user_authenticated->pool ) {
apr_pool_destroy( ctxt->connected_user_authenticated->pool );
- ctxt->connected_user_authenticated = NULL;
+ ctxt->connected_user_authenticated = NULL;
}
return HTTP_UNAUTHORIZED;
@@ -409,7 +454,7 @@
static int
send_auth_reply(request_rec * r, const char *auth_scheme, const char *reply)
{
- RDEBUG( "sending back %s", reply );
+ RDEBUG( "sending to http client: %s", reply );
/* Read negotiate from ntlm_auth */
apr_table_setn(r->err_headers_out,
@@ -496,7 +541,7 @@
char *newline;
char args_to_helper[HUGE_STRING_LEN];
char args_from_helper[HUGE_STRING_LEN];
- size_t bytes_written;
+ apr_size_t bytes_written;
int bytes_read;
if (( global_ntlm_context.ntlm_plaintext_helper = get_auth_helper( r, global_ntlm_context.ntlm_plaintext_helper, crec->ntlm_plaintext_helper, CLEANUP(cleanup_ntlm_plaintext_helper))) == NULL ) {
@@ -506,7 +551,7 @@
if ( ctxt->connected_user_authenticated == NULL ) {
apr_pool_t *pool;
- RDEBUG( "creating auth user" );
+ RDEBUG( "creating auth user for plaintext" );
#ifdef APACHE2
apr_pool_create_ex( &pool, r->connection->pool, NULL, NULL );
@@ -586,7 +631,7 @@
if ( strncmp( args_from_helper, "OK", 2 ) == 0 ) {
RDEBUG( "authentication succeeded!" );
- ctxt->connected_user_authenticated->user = apr_pstrdup(ctxt->connected_user_authenticated->pool, user);
+ ctxt->connected_user_authenticated->user = apr_pstrdup(ctxt->connected_user_authenticated->pool, strip_domain_name(r, user) );
ctxt->connected_user_authenticated->keepalives = r->connection->keepalives;
#ifdef APACHE2
r->user = ctxt->connected_user_authenticated->user;
@@ -625,7 +670,7 @@
char args_to_helper[HUGE_STRING_LEN];
char args_from_helper[HUGE_STRING_LEN];
ntlm_connection_context_t *ctxt = get_connection_context( r->connection );
- size_t bytes_written;
+ apr_size_t bytes_written;
int bytes_read;
struct _ntlm_auth_helper *auth_helper;
@@ -675,6 +720,14 @@
message_type = "KK";
}
+ /* if last time was a subreq, and this isn't, start over */
+ if ( ctxt->connected_user_authenticated->r_main && !r->main )
+ {
+ message_type = "YR";
+ RDEBUG( "resetting NTLM dance" );
+ }
+ ctxt->connected_user_authenticated->r_main = r->main;
+
/* Decode the information the WWW-Authenticate header */
if ((client_msg = get_auth_header(r, crec, auth_type)) == NULL) {
RDEBUG( "client did not return NTLM authentication header");
@@ -701,7 +754,7 @@
#ifdef APACHE2
apr_file_flush( auth_helper->proc->in );
- RDEBUG( "parsing reply from helper to %s", args_to_helper );
+ RDEBUG( "sending to winbind via auth helper: %s", args_to_helper );
if ( apr_file_gets(args_from_helper, HUGE_STRING_LEN, auth_helper->proc->out ) == APR_SUCCESS ) {
bytes_read = strlen( args_from_helper );
@@ -739,7 +792,7 @@
*newline = '\0';
}
- RDEBUG( "got response: %s", args_from_helper );
+ RDEBUG( "read from winbind via auth helper: %s", args_from_helper );
/* inspect message type */
@@ -771,7 +824,7 @@
if (strncmp(args_from_helper, "AF ", 3) == 0) {
ctxt->connected_user_authenticated->user =
apr_pstrdup(ctxt->connected_user_authenticated->pool,
- childarg);
+ strip_domain_name(r, childarg) );
ctxt->connected_user_authenticated->keepalives =
r->connection->keepalives;
#ifdef APACHE2
@@ -887,6 +940,8 @@
crec->ntlm_auth_helper = "ntlm_auth --helper-protocol=squid-2.5-ntlmssp";
crec->negotiate_ntlm_auth_helper = "ntlm_auth --helper-protocol=gss-spnego";
crec->ntlm_plaintext_helper = "ntlm_auth --helper-protocol=squid-2.5-basic";
+ crec->omit_domain = 0;
+ crec->domain_separator = "\\";
return crec;
}
@@ -970,7 +1025,7 @@
#endif
return OK;
} else {
- RDEBUG( "reauth" );
+ RDEBUG( "client wishes to re-authenticate this TCP socket" );
/* client wishes to re-authenticate this TCP socket */
if ( ctxt->connected_user_authenticated->pool ) {
apr_pool_destroy(ctxt->connected_user_authenticated->pool);
@@ -1023,7 +1078,7 @@
if (ctxt->connected_user_authenticated && ctxt->connected_user_authenticated->pool ) {
apr_pool_destroy(ctxt->connected_user_authenticated->pool);
- ctxt->connected_user_authenticated = NULL;
+ ctxt->connected_user_authenticated = NULL;
}
RDEBUG( "declined" );
More information about the samba-technical
mailing list