/* ==================================================================== * 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_passwordstore v0.1 written by John Newbigin * */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_protocol.h" /* * structure to hold the configuration details for the passwords */ typedef struct { char *path; /* the path that is allowed to access the password */ int path_len; /* the length of the path that must match */ char *name; /* the name of the password */ char *password; /* the secret password string */ } password_config_rec; typedef struct { char *filename; int debug_on; pool *p; array_header *password_list; } server_config; module passwordstore_module; static server_config *our_sconfig(server_rec *s) { return (server_config *) ap_get_module_config(s->module_config, &passwordstore_module); } /* static server_config *our_rconfig(request_rec *r) { return (server_config *) ap_get_module_config(r->request_config, &passwordstore_module); }*/ static void load_passwords(server_config *config) { configfile_t *f; char l[MAX_STRING_LEN]; const char *rpw; password_config_rec *rec = NULL; if(!config->filename) { return; } config->password_list = ap_make_array(config->p, 4, sizeof(password_config_rec)); if(!(f = ap_pcfg_openfile(config->p, config->filename))) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, "Could not open password file: %s", config->filename); } else { // read in the passwords... while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { if ((l[0] == '#') || (!l[0])) continue; rpw = l; if(!rec) { rec = (password_config_rec *) ap_push_array(config->password_list); } if(rec) { rec->path = ap_getword(config->p, &rpw, ':'); rec->name = ap_getword(config->p, &rpw, ':'); rec->password = ap_getword(config->p, &rpw, ':'); rec->path_len = strlen(rec->path); if(rec->path_len > 0 && strlen(rec->password) > 0) { rec = NULL; } else { // can we free it? rec->path_len = 0; // 0 = unused } } } ap_cfg_closefile(f); } } static void module_init(server_rec *s, pool *p) { server_config *config = NULL; config = our_sconfig(s); if(config) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, "module_init config file=%s", config->filename); load_passwords(config); } else { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, "module_init no config"); return; } } static int status_handler(request_rec *r) { password_config_rec *rec; int i; int found = 0; server_config *config = our_sconfig(r->server); if(config) { if(r->main) { if(strcmp(r->the_request, r->main->the_request) == 0) { //ap_rputs(r->main->uri, r); // can we assume that r->main->uri has not been tampered with??? for (i = 0; i < config->password_list->nelts; i++) { /*ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, r, "checking: %s-%s-%s", rec->path, rec->name, rec->password);*/ rec = (password_config_rec *)config->password_list->elts; rec = &rec[i]; if(rec->path_len > 0) { if(strncmp(rec->path, r->main->uri, rec->path_len) == 0) { // looks like a match /*ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, r, "match: %s-%s-%s", rec->path, rec->name, rec->password);*/ ap_table_setn(r->main->notes, rec->name, rec->password); } } } return OK; } else { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "the_request does not match %s:%s", r->the_request, r->main->the_request); } } else { if(config->debug_on) { // for testing, lets dump the passwords... this is obviously not secure... r->content_type = "text/plain"; ap_send_http_header(r); ap_rputs("mod_passwordstore configuration\n\n", r); ap_rprintf(r, "PasswordStoreFile: %s\n", config->filename); ap_rprintf(r, "PasswordStoreDebug: %d\n", config->debug_on); for (i = 0; i < config->password_list->nelts; i++) { rec = (password_config_rec *)config->password_list->elts; rec = &rec[i]; if(rec->path_len > 0) { ap_rprintf(r, "path: '%s' name: '%s' password: '%s'\n", rec->path, rec->name, rec->password); found++; } } ap_rprintf(r, "%d password%s available\n", found, found == 1 ? "" : "s"); ap_rputs("\n", r); ap_rputs("mod_passwordstore written by John Newbigin \n", r); ap_rputs("remember to turn debug off once you have confirmed that your installation works\n", r); ap_rputs("(PasswordStoreDebug Off)\n", r); return OK; } else { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "no main request found"); } } } else { // why is there no config? ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "no config found"); } return DECLINED; } static void *create_server_config(pool *p, server_rec *s) { server_config *config; ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, "create_server_config"); config = (server_config *) ap_pcalloc(p, sizeof(server_config)); config->p = p; config->debug_on = 0; config->filename = "passwords.txt"; config->password_list = NULL; return config; } static const char *set_file_slot_server(cmd_parms *cmd, void *offset, char *one) { char *config = ap_get_module_config(cmd->server->module_config, &passwordstore_module); cmd->info = &config[(int)cmd->info]; return ap_set_file_slot(cmd, offset, one); } static const char *set_flag_slot_server(cmd_parms *cmd, void *offset, int flag) { char *config = ap_get_module_config(cmd->server->module_config, &passwordstore_module); cmd->info = &config[(int)cmd->info]; return ap_set_flag_slot(cmd, offset, flag); } static const command_rec password_cmds[] = { {"PasswordStoreFile", set_file_slot_server, (void *)XtOffsetOf(server_config, filename), RSRC_CONF, TAKE1, "file containing secret passwords" }, {"PasswordStoreDebug", set_flag_slot_server, (void *)XtOffsetOf(server_config, debug_on), RSRC_CONF, FLAG, "handler shows config info" }, {NULL} }; static const handler_rec password_handlers[] = { {STATUS_MAGIC_TYPE, status_handler}, {"passwords", status_handler}, {NULL} }; module passwordstore_module = { STANDARD_MODULE_STUFF, module_init, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger --- default is to override */ create_server_config, /* server config */ NULL, /* merge server config */ password_cmds, /* command table */ password_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* 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 */ };