/* * mod_auth_sys - use system passwd and group files for authentication * * This module allows you use your system access files (passwd and group) * for www authentication. The following directives have been added which * you can put in a or .htaccess: * * AuthSystem On|Off * Use system files for authentication. Default is Off * AuthSystemAuthorative On|Off * AuthSystemAuthoritative On|Off * If On, the system files are considered authorative, control will not * be passed to other access control modules. Off allows you to use this * with other access modules, to allow access for users defined * in a .htpasswd file as well as other users on the system. * To enable this functionality, this module should be included after * mod_auth in your configuration file. Default is On. * * This module has support for both getting passwd information from * /etc/passwd by default. It can also be configured to use a shadow * passwd file. This requires an external program which runs as root * to read the shadow file. I've included an example checkPasswd in * the distribution. To get shadow support, add the following to * EXTRA_CFLAGS in your Configuration file: * -DSHADOW='"full_path_to_checkPasswd_program"' * The quoting is very important, both pairs are required. * * To enable this module, copy it into your apache source directory and * place the line: * Module sys_auth_module mod_auth_sys.o * in your Configuration file. Rebuild the configuration using * Configure and run the make. * * This module has some rather significant security considerations. * Since the system password file is used, passwords captured during * transit over the internet can be used to break into your system. * Remember, passwords are transferred in clear text for every secure * page that's accessed. This module is (perhaps) only appropriate * for intranet use, and even then the security implications should * be considered. * * copyright (c) 1996-1998 by Howard Fear (hsf@pageplus.com) * * This module is derived from work done by the Apache Group and is * subject to the same terms and conditions as the Apache server. */ #define SHADOW "/usr/sbin/checkPasswd" #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_protocol.h" #if defined(SHADOW) #include "wait.h" #else #include "pwd.h" #endif #include "grp.h" typedef struct mod_sys_auth_config_struct { int sys_auth_flag; int sys_auth_authorative_flag; #if defined(SHADOW) int sys_auth_shadow_flag; #endif } mod_sys_auth_config_rec; void *mod_sys_auth_create_dir_config (pool *p, char *d) { mod_sys_auth_config_rec *sec = (mod_sys_auth_config_rec *) ap_pcalloc (p, sizeof(mod_sys_auth_config_rec)); sec->sys_auth_flag=0; sec->sys_auth_authorative_flag = 1; #if defined(SHADOW) sec->sys_auth_shadow_flag = 1; #endif return(sec); } const char *set_sys_auth_flag(cmd_parms *cmd, mod_sys_auth_config_rec *sec, int arg) { sec->sys_auth_flag=arg; return NULL; } const char *set_sys_auth_authorative_flag (cmd_parms *cmd, mod_sys_auth_config_rec *sec, int arg) { sec->sys_auth_authorative_flag=arg; return NULL; } #if defined(SHADOW) const char *set_sys_auth_shadow_flag (cmd_parms *cmd, mod_sys_auth_config_rec *sec, int arg) { sec->sys_auth_shadow_flag=arg; return NULL; } #endif command_rec mod_sys_auth_cmds[] = { { "AuthSystem", set_sys_auth_flag, (void *) XtOffsetOf(mod_sys_auth_config_rec, sys_auth_flag), OR_AUTHCFG, FLAG, "When 'on' use system passwd and group files." }, { "AuthSystemAuthorative", set_sys_auth_authorative_flag, (void *) XtOffsetOf(mod_sys_auth_config_rec, sys_auth_authorative_flag), OR_AUTHCFG, FLAG, "When 'on' the system access files are taken to be authorative and access control is not passed along to other access modules." }, { "AuthSystemAuthoritative", set_sys_auth_authorative_flag, (void *) XtOffsetOf(mod_sys_auth_config_rec, sys_auth_authorative_flag), OR_AUTHCFG, FLAG, "When 'on' the system access files are taken to be authorative and access control is not passed along to other access modules." }, #if defined(SHADOW) { "AuthSystemShadow", set_sys_auth_shadow_flag, (void *) XtOffsetOf(mod_sys_auth_config_rec, sys_auth_shadow_flag), OR_AUTHCFG, FLAG, "When 'on' the system is assumed to be using Shadow Passwords." }, #endif { NULL } }; module sys_auth_module; int mod_sys_auth_check_passwd(const char *user, const char *passwd, int shadow) { #if defined(SHADOW) FILE *f; char cmdstring[MAX_STRING_LEN]; int status; if (shadow) { sprintf(cmdstring, "%s '%s'", SHADOW, user); if ((f=popen(cmdstring, "w")) == (FILE *)NULL) return(0); fprintf(f, "%s\n", passwd); status = pclose(f); if (!WIFEXITED(status)) return(0); return(!WEXITSTATUS(status)); } else { #endif struct passwd *ptr; if ((ptr=getpwnam(user)) == (struct passwd *)NULL) return(0); return(!strcmp(ptr->pw_passwd,(char *)crypt(passwd,ptr->pw_passwd))); #if defined(SHADOW) } #endif } int mod_sys_auth_in_group(request_rec *r, char *name, char *user) { struct group *group; struct passwd *ptr; int i; if (user == (char *)NULL || *user == '\0') return(0); if (name == (char *)NULL || *name == '\0') return(0); ptr = getpwnam(user); group = getgrnam(name); if (!group) return(0); /* * check if the user base group matches with the group * - Ong Beng Hui */ if (ptr && (ptr->pw_gid == group->gr_gid)) return(1); for (i = 0; group->gr_mem[i] != (char *)NULL; i++) { if(strcmp(group->gr_mem[i], user) == 0) return(1); } return(0); } /* These functions return 0 if client is OK, and proper error status * if not... either AUTH_REQUIRED, if we made a check, and it failed, or * SERVER_ERROR, if things are so totally confused that we couldn't * figure out how to tell if the client is authorized or not. * * If they return DECLINED, and all other modules also decline, that's * treated by the server core as a configuration error, logged and * reported as such. */ /* Determine user ID, and check if it really is that user, for HTTP * basic authentication... */ int mod_sys_auth_authenticate_basic_user (request_rec *r) { mod_sys_auth_config_rec *sec = (mod_sys_auth_config_rec *)ap_get_module_config(r->per_dir_config, &sys_auth_module); conn_rec *c = r->connection; const char *sent_pw; int res; if(!sec->sys_auth_flag) return DECLINED; if ((res = ap_get_basic_auth_pw(r, &sent_pw))) return res; /* If it non-authorative and we don't find the user just pass it on. */ if (!mod_sys_auth_check_passwd(c->user, sent_pw, sec->sys_auth_shadow_flag)) { if (!sec->sys_auth_authorative_flag) return DECLINED; ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Could not validate user %s", c->user); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } return OK; } int mod_sys_auth_check_auth (request_rec *r) { int user_result=DECLINED, group_result=DECLINED; mod_sys_auth_config_rec *sec = (mod_sys_auth_config_rec *)ap_get_module_config (r->per_dir_config, &sys_auth_module); char *user = r->connection->user; int m = r->method_number; const array_header *reqs_arr = ap_requires (r); require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL; register int x; const char *t; char *w; if(!sec->sys_auth_flag) return DECLINED; if (!reqs_arr) { if (sec->sys_auth_authorative_flag) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "User %s denied, no access rules specified (AuthSysAuthorative) ", user); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; }; return DECLINED; } for(x=0; (x < reqs_arr->nelts) ; x++) { if (! (reqs[x].method_mask & (1 << m))) continue; t = reqs[x].requirement; w = ap_getword_white(r->pool, &t); if ((user_result != OK) && (!strcmp(w, "user"))) { while(t[0]) { w = ap_getword_white(r->pool, &t); if (!strcmp(user, w)) { user_result= OK; break; } } if ((sec->sys_auth_authorative_flag) && ( user_result != OK)) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Access for user %s disallowed (AuthSysAuthorative)", user); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } } if ( (group_result != OK) && (!strcmp(w,"group")) ) { /* look up the membership for each of the groups in the table */ while(t[0]) { w = ap_getword_white(r->pool, &t); if (mod_sys_auth_in_group(r, w, user)) { group_result= OK; break; } } if ( (sec->sys_auth_authorative_flag) && (group_result != OK) ) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Access for user %s disallowed (AuthSysAuthorative)", user); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } } if(!strcmp(w,"valid-user")) { user_result= OK; } } return(user_result != DECLINED ? user_result : group_result); } module sys_auth_module = { STANDARD_MODULE_STUFF, NULL, /* initializer */ mod_sys_auth_create_dir_config, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ mod_sys_auth_cmds, /* command table */ NULL, /* handlers */ NULL, /* filename translation */ mod_sys_auth_authenticate_basic_user, /* check_user_id */ mod_sys_auth_check_auth, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL, /* header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* post read-request */ };