home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / modules / standard / mod_auth_db.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-01  |  10.8 KB  |  345 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer. 
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission. For written permission, please contact
  24.  *    apache@apache.org.
  25.  *
  26.  * 5. Products derived from this software may not be called "Apache"
  27.  *    nor may "Apache" appear in their names without prior written
  28.  *    permission of the Apache Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  39.  * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Group and was originally based
  51.  * on public domain software written at the National Center for
  52.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53.  * For more information on the Apache Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. /*
  59.  * mod_auth_db: authentication
  60.  * 
  61.  * Original work by Rob McCool & Brian Behlendorf.
  62.  * 
  63.  * Adapted to Apache by rst (mod_auth_dbm)
  64.  *
  65.  * Adapted for Berkeley DB by Andrew Cohen 
  66.  *
  67.  * mod_auth_db was based on mod_auth_dbm.
  68.  * 
  69.  * Warning, this is not a drop in replacement for mod_auth_dbm, 
  70.  * for people wanting to switch from dbm to Berkeley DB.
  71.  * It requires the use of AuthDBUserFile and AuthDBGroupFile
  72.  *           instead of   AuthDBMUserFile    AuthDBMGroupFile
  73.  *
  74.  * Also, in the configuration file you need to specify
  75.  *  db_auth_module rather than dbm_auth_module
  76.  *
  77.  * On some BSD systems (e.g. FreeBSD and NetBSD) dbm is automatically
  78.  * mapped to Berkeley DB. You can use either mod_auth_dbm or
  79.  * mod_auth_db. The latter makes it more obvious that it's Berkeley.
  80.  * On other platforms where you want to use the DB library you
  81.  * usually have to install it first. See http://www.sleepycat.com/
  82.  * for the distribution. The interface this module uses is the
  83.  * one from DB version 1.85 and 1.86, but DB version 2.x
  84.  * can also be used when compatibility mode is enabled.
  85.  *
  86.  * dirkx - Added Authoritative control to allow passing on to lower  
  87.  *         modules if and only if the user-id is not known to this
  88.  *         module. A known user with a faulty or absent password still
  89.  *         causes an AuthRequired. The default is 'Authoritative', i.e.
  90.  *         no control is passed along.
  91.  */
  92.  
  93. #include "httpd.h"
  94. #include "http_config.h"
  95. #include "http_core.h"
  96. #include "http_log.h"
  97. #include "http_protocol.h"
  98. #include <db.h>
  99.  
  100. #if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
  101. #define DB2
  102. #endif
  103.  
  104. typedef struct {
  105.  
  106.     char *auth_dbpwfile;
  107.     char *auth_dbgrpfile;
  108.     int auth_dbauthoritative;
  109. } db_auth_config_rec;
  110.  
  111. static void *create_db_auth_dir_config(pool *p, char *d)
  112. {
  113.     db_auth_config_rec *sec
  114.     = (db_auth_config_rec *) ap_pcalloc(p, sizeof(db_auth_config_rec));
  115.     sec->auth_dbpwfile = NULL;
  116.     sec->auth_dbgrpfile = NULL;
  117.     sec->auth_dbauthoritative = 1;    /* fortress is secure by default */
  118.     return sec;
  119. }
  120.  
  121. static const char *set_db_slot(cmd_parms *cmd, void *offset, char *f, char *t)
  122. {
  123.     if (!t || strcmp(t, "db"))
  124.     return DECLINE_CMD;
  125.  
  126.     return ap_set_file_slot(cmd, offset, f);
  127. }
  128.  
  129. static const command_rec db_auth_cmds[] =
  130. {
  131.     {"AuthDBUserFile", ap_set_file_slot,
  132.      (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile),
  133.      OR_AUTHCFG, TAKE1, NULL},
  134.     {"AuthDBGroupFile", ap_set_file_slot,
  135.      (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile),
  136.      OR_AUTHCFG, TAKE1, NULL},
  137.     {"AuthUserFile", set_db_slot,
  138.      (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile),
  139.      OR_AUTHCFG, TAKE12, NULL},
  140.     {"AuthGroupFile", set_db_slot,
  141.      (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile),
  142.      OR_AUTHCFG, TAKE12, NULL},
  143.     {"AuthDBAuthoritative", ap_set_flag_slot,
  144.      (void *) XtOffsetOf(db_auth_config_rec, auth_dbauthoritative),
  145.      OR_AUTHCFG, FLAG,
  146.      "Set to 'no' to allow access control to be passed along to lower modules if the userID is not known to this module"},
  147.     {NULL}
  148. };
  149.  
  150. module db_auth_module;
  151.  
  152. static char *get_db_pw(request_rec *r, char *user, const char *auth_dbpwfile)
  153. {
  154.     DB *f;
  155.     DBT d, q;
  156.     char *pw = NULL;
  157.  
  158.     memset(&d, 0, sizeof(d));
  159.     memset(&q, 0, sizeof(q));
  160.  
  161.     q.data = user;
  162.     q.size = strlen(q.data);
  163.  
  164. #ifdef DB2
  165.     if (db_open(auth_dbpwfile, DB_HASH, DB_RDONLY, 0664, NULL, NULL, &f) != 0) {
  166. #else
  167.     if (!(f = dbopen(auth_dbpwfile, O_RDONLY, 0664, DB_HASH, NULL))) {
  168. #endif
  169.     ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  170.             "could not open db auth file: %s", auth_dbpwfile);
  171.     return NULL;
  172.     }
  173.  
  174. #ifdef DB2
  175.     if (!((f->get) (f, NULL, &q, &d, 0))) {
  176. #else
  177.     if (!((f->get) (f, &q, &d, 0))) {
  178. #endif
  179.     pw = ap_palloc(r->pool, d.size + 1);
  180.     strncpy(pw, d.data, d.size);
  181.     pw[d.size] = '\0';    /* Terminate the string */
  182.     }
  183.  
  184. #ifdef DB2
  185.     (f->close) (f, 0);
  186. #else
  187.     (f->close) (f);
  188. #endif
  189.     return pw;
  190. }
  191.  
  192. /* We do something strange with the group file.  If the group file
  193.  * contains any : we assume the format is
  194.  *      key=username value=":"groupname [":"anything here is ignored]
  195.  * otherwise we now (0.8.14+) assume that the format is
  196.  *      key=username value=groupname
  197.  * The first allows the password and group files to be the same 
  198.  * physical DB file;   key=username value=password":"groupname[":"anything]
  199.  *
  200.  * mark@telescope.org, 22Sep95
  201.  */
  202.  
  203. static char *get_db_grp(request_rec *r, char *user, const char *auth_dbgrpfile)
  204. {
  205.     char *grp_data = get_db_pw(r, user, auth_dbgrpfile);
  206.     char *grp_colon;
  207.     char *grp_colon2;
  208.  
  209.     if (grp_data == NULL)
  210.     return NULL;
  211.  
  212.     if ((grp_colon = strchr(grp_data, ':')) != NULL) {
  213.     grp_colon2 = strchr(++grp_colon, ':');
  214.     if (grp_colon2)
  215.         *grp_colon2 = '\0';
  216.     return grp_colon;
  217.     }
  218.     return grp_data;
  219. }
  220.  
  221. static int db_authenticate_basic_user(request_rec *r)
  222. {
  223.     db_auth_config_rec *sec =
  224.     (db_auth_config_rec *) ap_get_module_config(r->per_dir_config,
  225.                          &db_auth_module);
  226.     conn_rec *c = r->connection;
  227.     const char *sent_pw;
  228.     char *real_pw, *colon_pw;
  229.     int res;
  230.  
  231.     if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
  232.     return res;
  233.  
  234.     if (!sec->auth_dbpwfile)
  235.     return DECLINED;
  236.  
  237.     if (!(real_pw = get_db_pw(r, c->user, sec->auth_dbpwfile))) {
  238.     if (!(sec->auth_dbauthoritative))
  239.         return DECLINED;
  240.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  241.             "DB user %s not found: %s", c->user, r->filename);
  242.     ap_note_basic_auth_failure(r);
  243.     return AUTH_REQUIRED;
  244.     }
  245.     /* Password is up to first : if exists */
  246.     colon_pw = strchr(real_pw, ':');
  247.     if (colon_pw)
  248.     *colon_pw = '\0';
  249.     /* anyone know where the prototype for crypt is? */
  250.     if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
  251.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  252.             "DB user %s: password mismatch: %s", c->user, r->uri);
  253.     ap_note_basic_auth_failure(r);
  254.     return AUTH_REQUIRED;
  255.     }
  256.     return OK;
  257. }
  258.  
  259. /* Checking ID */
  260.  
  261. static int db_check_auth(request_rec *r)
  262. {
  263.     db_auth_config_rec *sec =
  264.     (db_auth_config_rec *) ap_get_module_config(r->per_dir_config,
  265.                          &db_auth_module);
  266.     char *user = r->connection->user;
  267.     int m = r->method_number;
  268.  
  269.     const array_header *reqs_arr = ap_requires(r);
  270.     require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
  271.  
  272.     register int x;
  273.     const char *t;
  274.     char *w;
  275.  
  276.     if (!sec->auth_dbgrpfile)
  277.     return DECLINED;
  278.     if (!reqs_arr)
  279.     return DECLINED;
  280.  
  281.     for (x = 0; x < reqs_arr->nelts; x++) {
  282.  
  283.     if (!(reqs[x].method_mask & (1 << m)))
  284.         continue;
  285.  
  286.     t = reqs[x].requirement;
  287.     w = ap_getword_white(r->pool, &t);
  288.  
  289.     if (!strcmp(w, "group") && sec->auth_dbgrpfile) {
  290.         const char *orig_groups, *groups;
  291.         char *v;
  292.  
  293.         if (!(groups = get_db_grp(r, user, sec->auth_dbgrpfile))) {
  294.         if (!(sec->auth_dbauthoritative))
  295.             return DECLINED;
  296.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  297.                 "user %s not in DB group file %s: %s",
  298.                 user, sec->auth_dbgrpfile, r->filename);
  299.         ap_note_basic_auth_failure(r);
  300.         return AUTH_REQUIRED;
  301.         }
  302.         orig_groups = groups;
  303.         while (t[0]) {
  304.         w = ap_getword_white(r->pool, &t);
  305.         groups = orig_groups;
  306.         while (groups[0]) {
  307.             v = ap_getword(r->pool, &groups, ',');
  308.             if (!strcmp(v, w))
  309.             return OK;
  310.         }
  311.         }
  312.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  313.             "user %s not in right group: %s", user, r->filename);
  314.         ap_note_basic_auth_failure(r);
  315.         return AUTH_REQUIRED;
  316.     }
  317.     }
  318.  
  319.     return DECLINED;
  320. }
  321.  
  322.  
  323. module db_auth_module =
  324. {
  325.     STANDARD_MODULE_STUFF,
  326.     NULL,            /* initializer */
  327.     create_db_auth_dir_config,    /* dir config creater */
  328.     NULL,            /* dir merger --- default is to override */
  329.     NULL,            /* server config */
  330.     NULL,            /* merge server config */
  331.     db_auth_cmds,        /* command table */
  332.     NULL,            /* handlers */
  333.     NULL,            /* filename translation */
  334.     db_authenticate_basic_user,    /* check_user_id */
  335.     db_check_auth,        /* check auth */
  336.     NULL,            /* check access */
  337.     NULL,            /* type_checker */
  338.     NULL,            /* fixups */
  339.     NULL,            /* logger */
  340.     NULL,            /* header parser */
  341.     NULL,            /* child_init */
  342.     NULL,            /* child_exit */
  343.     NULL            /* post read-request */
  344. };
  345.