/* ==================================================================== * Copyright (c) 1995 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see . * */ /******** Mod_Auth_External version 2.0.1 Add to Configuration file: Module external_auth_module mod_auth_external.o Add to server configuration file: AddExternalAuth AddExternalGroup SetExternalAuthMethod SetExternalGroupMethod The SetExternalMethod directive specifies how the data is to be passed to the external routine. There are currently three possible methods: environment - pass in environment variables (default) pipe - pass name=value pairs via stdin function - handle as an internal function For environment and pipe, the option specifies a path to a program to run. For function, the option specifies a special internal keyword that indicates which internal function is to be used. To Use your own Hard Coded function use: AddExternalAuth : Usage in auth config files: AuthExternal AuthExternal afs GroupExternal GroupExternal unix AuthExternals are passed the userid and passwd in the USER and PASS environment variables, and return a success code of 0 to indicate successful authentication. Non-zero result indicates either a failure to authenticate, or a failure to execute the authenticator. GroupExternals are passed the userid and desired group in the USER and GROUP environment variables, and return a success code of 0 to indicate successful authentication. Non-zero result indicates non-membersip or a failure to execute the group checker. The need for this module arises from difficulties I have had linking apache with other libraries (such as AFS, and database access libs). Comments/questions/etc. to nneul@umr.edu Comments/questions about HARDCODE (or) RADIUS to allison@nas.nasa.gov ********/ /* Uncomment if you want to use a HARDCODE'd check (default off) */ /* #define _HARDCODE_ */ #ifdef _HARDCODE_ /* Uncomment if you want to use your own Hardcode (default off) */ /* MUST HAVE _HARDCODE_ defined above! */ /* #include "your_function_here.c" */ #endif /* * Origional External authentication module by nneul@umr.edu * Maintained by */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_protocol.h" #include #define null ((void*)0) /* NULL is already defined but wont catch everything */ /* * Structure for the module itself */ module external_auth_module; /* * Data types for per-dir and server configuration */ typedef struct { char *auth_extname; char *group_extname; } extauth_dir_config_rec; typedef struct { table *auth_extpath; table *auth_extmethod; table *group_extpath; table *group_extmethod; } extauth_server_config_rec; /* * Creators for per-dir and server configurations */ static void *create_extauth_dir_config (pool *p, char *d) { return ap_pcalloc (p, sizeof(extauth_dir_config_rec)); } static void *create_extauth_server_config ( pool *p, server_rec *s) { extauth_server_config_rec *scr; scr = (extauth_server_config_rec *) ap_palloc(p, sizeof(extauth_server_config_rec) ); scr->auth_extmethod = ap_make_table(p, 4); scr->auth_extpath = ap_make_table(p, 4); scr->group_extmethod = ap_make_table(p, 4); scr->group_extpath = ap_make_table(p, 4); return (void *)scr; } /* * Handler for a server config line - add a external type to the * server configuration */ static const char *add_extauth(cmd_parms *cmd, void *dummy, char *keyword, char *path) { extauth_server_config_rec *sc_rec; sc_rec = ap_get_module_config( cmd->server->module_config, &external_auth_module); ap_table_set ( sc_rec->auth_extpath, keyword, path ); ap_table_set ( sc_rec->auth_extmethod, keyword, "environment" ); return NULL; } /* * Handler for a server config line - add a external type to the * server configuration */ static const char *add_extgroup(cmd_parms *cmd, void *dummy, char *keyword, char *path) { extauth_server_config_rec *sc_rec; sc_rec = ap_get_module_config( cmd->server->module_config, &external_auth_module); ap_table_set ( sc_rec->group_extpath, keyword, path ); ap_table_set ( sc_rec->group_extmethod, keyword, "environment" ); return NULL; } static const char *set_extgroup_method(cmd_parms *cmd, void *dummy, char *keyword, char *method) { extauth_server_config_rec *sc_rec; sc_rec = ap_get_module_config( cmd->server->module_config, &external_auth_module); ap_table_set ( sc_rec->group_extmethod, keyword, method ); return NULL; } static const char *set_extauth_method(cmd_parms *cmd, void *dummy, char *keyword, char *method) { extauth_server_config_rec *sc_rec; sc_rec = ap_get_module_config( cmd->server->module_config, &external_auth_module); ap_table_set ( sc_rec->auth_extmethod, keyword, method ); return NULL; } /* * Commands that this module can handle */ command_rec extauth_cmds[] = { { "AuthExternal", ap_set_string_slot, (void*)XtOffsetOf(extauth_dir_config_rec,auth_extname), OR_AUTHCFG, TAKE1, "a keyword indicating which authenticator to use" }, { "AddExternalAuth", add_extauth, NULL, RSRC_CONF, TAKE2, "a keyword followed by a path to the authenticator program" }, { "SetExternalAuthMethod", set_extauth_method, NULL, RSRC_CONF, TAKE2, "a keyword followed by the method by which the data is passed" }, { "GroupExternal", ap_set_string_slot, (void*)XtOffsetOf(extauth_dir_config_rec,group_extname), OR_AUTHCFG, TAKE1, "a keyword indicating which group checker to use" }, { "AddExternalGroup", add_extgroup, NULL, RSRC_CONF, TAKE2, "a keyword followed by a path to the group check program" }, { "SetExternalGroupMethod", set_extgroup_method, NULL, RSRC_CONF, TAKE2, "a keyword followed by the method by which the data is passed" }, { NULL } }; /* * Authenticate a user */ static int extauth_basic_user (request_rec *r) { extauth_dir_config_rec *dir_config_rec = (extauth_dir_config_rec *)ap_get_module_config (r->per_dir_config, &external_auth_module); extauth_server_config_rec *server_config_rec = (extauth_server_config_rec *)ap_get_module_config (r->server->module_config, &external_auth_module); const char *sent_pw; #ifdef _HARDCODE_ char *check_type; /* Pointer to HARDCODE type check */ char *config_file; /* Pointer to HARDCODE config file */ char config_line[256]; /* Where we store extpath locally */ int standard_auth = 0; #endif char errstr[MAX_STRING_LEN]; char env_user[MAX_STRING_LEN]; char env_pass[MAX_STRING_LEN]; int res, code=1, status; const char *extname; const char *extpath, *extmethod; int pipe_to_auth[2]; int pid; conn_rec *c = r->connection; /* Get the password, exit if can't get */ if ((res = ap_get_basic_auth_pw (r, &sent_pw))) return res; /* Extract which external was chosen */ extname = dir_config_rec->auth_extname; /* Check if we are supposed to handle this authentication */ if ( !extname ) { return DECLINED; } /* Get the Method requested */ extmethod = ap_table_get (server_config_rec->auth_extmethod, extname); /* Make the default Method environment */ if ( !extmethod ) { extmethod=strdup("environment"); } /* Get the path associated with that external */ if ((extpath = ap_table_get (server_config_rec->auth_extpath, extname))) { if ( !strcasecmp(extmethod, "environment") ) { /* Set envir vars for the userid and password */ sprintf(env_user, "%s=%s", "USER", c->user); sprintf(env_pass, "%s=%s", "PASS", sent_pw); putenv(env_user); putenv(env_pass); status = system(extpath); code = WEXITSTATUS(status); } else if ( !strcasecmp(extmethod, "pipe") ) { pipe(pipe_to_auth); pid = fork(); if ( pid < 0 ) { sprintf(errstr, "External Auth (%s): Failed (%d) for user %s", extname, errno, c->user); ap_log_reason(errstr, r->filename, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } else if ( pid == 0 ) { dup2(pipe_to_auth[0], 0); /* stdin */ close(1); /* stdout */ ap_error_log2stderr(r->server); /* stderr */ close(pipe_to_auth[1]); status = system(extpath); code = WEXITSTATUS(status); exit(code); } else { close(pipe_to_auth[0]); /* Send the user */ write(pipe_to_auth[1], "user=", 5); write(pipe_to_auth[1], c->user, strlen(c->user)); write(pipe_to_auth[1], "\n", 1); /* Send the password */ write(pipe_to_auth[1], "pass=", 5); write(pipe_to_auth[1], sent_pw, strlen(sent_pw)); write(pipe_to_auth[1], "\n", 1); /* Read responses */ waitpid(pid, &status, 0); code = WEXITSTATUS(status); /* Close output */ close(pipe_to_auth[1]); } } else if ( !strcasecmp(extmethod, "function") ) { #ifdef _HARDCODE_ strcpy(config_line,extpath); /* Dont mess with extpath cause it's */ /* shared between httpd's, make a copy */ check_type = config_line; /* type is at the beginning */ config_file = strchr(config_line, ':');/* Find the colon seperator */ if (config_file == null) { /* No colon! srm.conf is wrong */ sprintf(errstr, "Problem parsing srm.conf: (%s) directive. You must have a ':' seperator!\n",check_type); ap_log_reason(errstr, r->filename, r); return SERVER_ERROR; } else { /* Hey! We found the colon! */ *config_file = '\0'; /* Put newline where the colon is */ config_file++; /* Point to next character */ /* This is where you make your function call. */ /* Here is an example of what one looks like. */ /* */ /* if (strcmp(check_type,"RADIUS")==0) { */ /* code = radcheck(c->user,sent_pw,config_file); */ /* } */ /* */ /* Replace 'RADIUS' with whatever you are using as */ /* the in: */ /* AddExternalAuth : */ /* */ /* Replace radcheck with whatever the name of your */ /* function is. */ /* Note: If you dont use a config_file you must at */ /* least include the ':'..for example..at a minimum */ /* you must have 'RADIUS:' in the srm.conf for your */ /* function to be called. */ else { sprintf(errstr, "Problem parsing srm.conf: (%s) directive (%s) config_file\n",check_type,config_file); ap_log_reason(errstr, r->filename, r); return SERVER_ERROR; } } } #else /* If _HARDCODE_ is not defined than no mater what the user says */ /* about wanting to use a function we fail!! */ code = 1; } #endif if(code) { sprintf(errstr, "External Auth (%s): Failed (%d) for user %s [%s]", extname, code, c->user, extpath); ap_log_reason(errstr, r->filename, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } return OK; } else { sprintf(errstr, "External Auth: Invalid external keyword (%s)", extname); ap_log_reason(errstr, r->filename, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } /* shouldn't get here */ return SERVER_ERROR; } static int extauth_check_auth(request_rec *r) { extauth_dir_config_rec *dir_config_rec = (extauth_dir_config_rec *)ap_get_module_config (r->per_dir_config, &external_auth_module); extauth_server_config_rec *server_config_rec = (extauth_server_config_rec *)ap_get_module_config (r->server->module_config, &external_auth_module); conn_rec *c = r->connection; int m = r->method_number; char errstr[MAX_STRING_LEN]; char env_user[MAX_STRING_LEN]; char env_group[MAX_STRING_LEN]; int code; char *extname; const char *extpath; const array_header *reqs_arr = ap_requires(r); require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL; int x; const char *t; char *w; /* Extract which external was chosen */ extname = dir_config_rec->group_extname; /* Check if we are supposed to handle this authentication */ if ( !extname ) { return DECLINED; } if (!reqs_arr) 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(r->pool, &t, ' '); if(!strcmp(w,"valid-user")) return OK; if(!strcmp(w,"user")) { while(t[0]) { w = ap_getword_conf (r->pool, &t); if(!strcmp(c->user,w)) return OK; } } else if( !strcmp(w,"group") ) { while(t[0]) { w = ap_getword(r->pool, &t, ' '); /* Get the path associated with that external */ if ((extpath = ap_table_get (server_config_rec->group_extpath, extname))) { /* Set envir vars for the userid and password */ sprintf(env_user, "%s=%s", "USER", c->user); sprintf(env_group, "%s=%s", "GROUP", w); putenv(env_user); putenv(env_group); code = system(extpath); if ( !code ) return OK; } else { sprintf(errstr, "External Group: Invalid external keyword (%s)", extname); ap_log_reason(errstr, r->filename, r); ap_note_basic_auth_failure(r); return AUTH_REQUIRED; } } } } return DECLINED; } module external_auth_module = { STANDARD_MODULE_STUFF, NULL, /* initializer */ create_extauth_dir_config, /* dir config creater */ NULL, /* dir merger --- default is to override */ create_extauth_server_config, /* server config */ NULL, /* merge server config */ extauth_cmds, /* command table */ NULL, /* handlers */ NULL, /* filename translation */ extauth_basic_user, /* check_user_id */ extauth_check_auth, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL /* logger */ };