--- mod_auth_pam-1.1.1/mod_auth_pam.c 2002-08-08 09:47:33.000000000 -0400 +++ mod_auth_pam-1.1.1-debug_nolocal/mod_auth_pam.c 2002-12-05 12:12:05.000000000 -0500 @@ -47,6 +47,14 @@ * provided invaluable development help and ideas. * * Changes: + * 01-Nov-02: Added the AuthPAM_NoLocal directive to allow + * a user without a local account to authenticate + * successfully (of great value when trying to + * use mod_auth_pam in conjunction with + * pam_smb_auth, authenticating against an NT + * domain). + * 01-Nov-02: Added some debugging, and the AuthPAM_Debug + * directive to turn it on and off. * 08-Aug-02: bugfix, supplemental groups are now checked * against correctly. Thanks to Will Holcomb for * the report. @@ -54,7 +62,7 @@ * this doesn't break stranger PAM configs. * 07-Jul-02: License changed to allow redistribution * Performance improvement for group lookup - (many thanks to Fredrik Ohrn for the patch) + * (many thanks to Fredrik Ohrn for the patch) * 06-Dec-99: Special casing for Solaris 2.6 added * Added versioning message to headers * 14-Feb-99: Cleaned up the configuration directives and named them @@ -131,8 +139,24 @@ * Defaults to off * * AuthPAM_Authorative on|off DEPRECATED + * + * AuthPAM_Debug on|off + * If on, debug statements will be spewed using + * syslog (facility AUTHPRIV). The debug statements + * will all begin with the DEBUG_STR macro, so + * if you are using something cool like syslog-ng, + * you can ensure that all AuthPAM debuggery is + * spewed to its own file. + * + * AuthPAM_NoLocal on|off + * If on, the check for a valid account will be + * skipped, allowing any account that can + * authenticate access. This is most likely + * useful in conjuction with pam_smb_auth.so's + * 'nolocal' switch. */ +#include #include #include "httpd.h" @@ -146,6 +170,7 @@ /* change this to 0 on RedHat 4.x */ #define PAM_STRE_NEEDS_PAMH 1 #define VERSION "1.1.1" +#define DEBUG_STR "pam_debug: (mod_auth_pam)" module pam_auth_module; @@ -183,6 +208,8 @@ typedef struct { int + debug, /* 1 to spew debuggery to syslog (defaults to 0) */ + nolocal, /* 1 to bypass local account checks */ fail_delay, /* fail delay in ms -- needs library support */ fall_through, /* 1 to DECLINE instead of AUTH_REQUIRED if we can't find the username (defaults to 0) */ @@ -201,6 +228,8 @@ auth_pam_dir_config *new = (auth_pam_dir_config*) ap_palloc (p, sizeof(auth_pam_dir_config)); + new->debug = 0; /* off */ + new->nolocal = 0; /* require a valid local account */ new->fail_delay = 0; /* 0 ms */ new->fall_through = 0; /* off */ new->enabled = 1; /* on */ @@ -212,6 +241,8 @@ { if(secs) config->fail_delay = atoi(secs); + if(config->debug) + syslog(LOG_AUTHPRIV, "%s Set fail_delay to %d", DEBUG_STR, config->fail_delay); return NULL; } @@ -219,6 +250,8 @@ char* auth_fall_through(cmd_parms *cmd, auth_pam_dir_config *config, int arg) { config->fall_through = arg; + if(config->debug) + syslog(LOG_AUTHPRIV, "%s Set fall_through to %d", DEBUG_STR, config->fall_through); return NULL; } @@ -226,6 +259,26 @@ char* auth_enable(cmd_parms *cmd, auth_pam_dir_config *config, int arg) { config->enabled = arg; + if(config->debug) + syslog(LOG_AUTHPRIV, "%s Set enabled to %d", DEBUG_STR, config->enabled); + return NULL; +} + +static +char* auth_debug(cmd_parms *cmd, auth_pam_dir_config *config, int arg) +{ + config->debug = arg; + if(config->debug) + syslog(LOG_AUTHPRIV, "%s Set debug to %d", DEBUG_STR, config->debug); + return NULL; +} + +static +char* auth_nolocal(cmd_parms *cmd, auth_pam_dir_config *config, int arg) +{ + config->nolocal = arg; + if(config->debug) + syslog(LOG_AUTHPRIV, "%s Set nolocal to %d", DEBUG_STR, config->nolocal); return NULL; } @@ -240,6 +293,10 @@ one fails; default is off" }, { "AuthPAM_Enabled", (const char*(*)())auth_enable, NULL, OR_AUTHCFG, FLAG, "on|off - determines if PAM authentication is enabled; default is on" }, + { "AuthPAM_Debug", (const char*(*)())auth_debug, NULL, OR_AUTHCFG, FLAG, + "on|off - spews debug information via syslog; default is off" }, + { "AuthPAM_NoLocal", (const char*(*)())auth_nolocal, NULL, OR_AUTHCFG, FLAG, + "on|off - allows a non-local account to auth; default is off" }, { 0 } }; @@ -333,22 +390,38 @@ #endif /* enabled? */ - if (!conf->enabled) + if (!conf->enabled) { + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s mod_auth_pam is not enabled", DEBUG_STR); return DECLINED; + } /* read sent pw */ if ((res = ap_get_basic_auth_pw (r, (const char**)&(userinfo.pw)))) + { + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Returning Apache status %d", + DEBUG_STR, res); return res; + } /* this is only set after get_basic_auth_pw was called */ userinfo.name = r->connection->user; + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Trying to authenticate %s/%s", + DEBUG_STR, userinfo.name, userinfo.pw); + /* initialize pam */ if((res = pam_start(pam_servicename, userinfo.name, &conv_info, &pamh)) != PAM_SUCCESS) { + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Init failure: PAM status code %d (%s)", + DEBUG_STR, res, compat_pam_strerror(pamh, res)); + ap_log_reason((char*)compat_pam_strerror(pamh, res), r->uri, r); return DECLINED; } @@ -369,25 +442,42 @@ /* try to authenticate user, log error on failure */ if((res = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS ) { + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Auth failure: PAM status code %d (%s)", + DEBUG_STR, res, compat_pam_strerror(pamh, res)); ap_log_reason((char*)compat_pam_strerror(pamh, res), r->uri, r); if(conf->fall_through && (res == PAM_USER_UNKNOWN)) { /* we don't know about the user, but other auth modules might do */ + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Falling through to other auth modules", + DEBUG_STR); pam_end(pamh, PAM_SUCCESS); return DECLINED; } else { pam_end(pamh, PAM_SUCCESS); ap_note_basic_auth_failure(r); + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Telling Apache AUTH_REQUIRED", DEBUG_STR); return AUTH_REQUIRED; } /* endif fall_through */ } /* endif authenticate */ - /* check that the account is healthy */ - if((res = pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) { - ap_log_reason((char*)compat_pam_strerror(pamh, res), r->uri, r); - pam_end(pamh, PAM_SUCCESS); - return AUTH_REQUIRED; - } - + /* check that the account is healthy, unless AuthPAM_NoLocal was set */ + if( !conf->nolocal ) { + if((res = pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) { + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Account unhealthy: PAM status code %d (%s)", + DEBUG_STR, res, compat_pam_strerror(pamh, res)); + ap_log_reason((char*)compat_pam_strerror(pamh, res), r->uri, r); + pam_end(pamh, PAM_SUCCESS); + return AUTH_REQUIRED; + } /* endif account unhealthy */ + } /* endif health check */ + + if(conf->debug) + syslog(LOG_AUTHPRIV, "%s Authentication succeeded for %s/%s", + DEBUG_STR, userinfo.name, userinfo.pw); + pam_end(pamh, PAM_SUCCESS); return OK; }