home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / modules / standard / mod_auth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-01  |  10.4 KB  |  335 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.  * ITS 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.  * http_auth: authentication
  60.  * 
  61.  * Rob McCool
  62.  * 
  63.  * Adapted to Apache by rst.
  64.  *
  65.  * dirkx - Added Authoritative control to allow passing on to lower
  66.  *         modules if and only if the user-id is not known to this
  67.  *         module. A known user with a faulty or absent password still
  68.  *         causes an AuthRequired. The default is 'Authoritative', i.e.
  69.  *         no control is passed along.
  70.  */
  71.  
  72. #include "httpd.h"
  73. #include "http_config.h"
  74. #include "http_core.h"
  75. #include "http_log.h"
  76. #include "http_protocol.h"
  77. #if defined(HAVE_CRYPT_H)
  78. #include <crypt.h>
  79. #endif
  80.  
  81. typedef struct auth_config_struct {
  82.     char *auth_pwfile;
  83.     char *auth_grpfile;
  84.     int auth_authoritative;
  85. } auth_config_rec;
  86.  
  87. static void *create_auth_dir_config(pool *p, char *d)
  88. {
  89.     auth_config_rec *sec =
  90.     (auth_config_rec *) ap_pcalloc(p, sizeof(auth_config_rec));
  91.     sec->auth_pwfile = NULL;    /* just to illustrate the default really */
  92.     sec->auth_grpfile = NULL;    /* unless you have a broken HP cc */
  93.     sec->auth_authoritative = 1;    /* keep the fortress secure by default */
  94.     return sec;
  95. }
  96.  
  97. static const char *set_auth_slot(cmd_parms *cmd, void *offset, char *f, char *t)
  98. {
  99.     if (t && strcmp(t, "standard"))
  100.     return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
  101.  
  102.     return ap_set_file_slot(cmd, offset, f);
  103. }
  104.  
  105. static const command_rec auth_cmds[] =
  106. {
  107.     {"AuthUserFile", set_auth_slot,
  108.      (void *) XtOffsetOf(auth_config_rec, auth_pwfile), OR_AUTHCFG, TAKE12,
  109.      "text file containing user IDs and passwords"},
  110.     {"AuthGroupFile", set_auth_slot,
  111.      (void *) XtOffsetOf(auth_config_rec, auth_grpfile), OR_AUTHCFG, TAKE12,
  112.      "text file containing group names and member user IDs"},
  113.     {"AuthAuthoritative", ap_set_flag_slot,
  114.      (void *) XtOffsetOf(auth_config_rec, auth_authoritative),
  115.      OR_AUTHCFG, FLAG,
  116.      "Set to 'no' to allow access control to be passed along to lower modules if the UserID is not known to this module"},
  117.     {NULL}
  118. };
  119.  
  120. module MODULE_VAR_EXPORT auth_module;
  121.  
  122. static char *get_pw(request_rec *r, char *user, char *auth_pwfile)
  123. {
  124.     configfile_t *f;
  125.     char l[MAX_STRING_LEN];
  126.     const char *rpw, *w;
  127.  
  128.     if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) {
  129.     ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  130.             "Could not open password file: %s", auth_pwfile);
  131.     return NULL;
  132.     }
  133.     while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
  134.     if ((l[0] == '#') || (!l[0]))
  135.         continue;
  136.     rpw = l;
  137.     w = ap_getword(r->pool, &rpw, ':');
  138.  
  139.     if (!strcmp(user, w)) {
  140.         ap_cfg_closefile(f);
  141.         return ap_getword(r->pool, &rpw, ':');
  142.     }
  143.     }
  144.     ap_cfg_closefile(f);
  145.     return NULL;
  146. }
  147.  
  148. static table *groups_for_user(pool *p, char *user, char *grpfile)
  149. {
  150.     configfile_t *f;
  151.     table *grps = ap_make_table(p, 15);
  152.     pool *sp;
  153.     char l[MAX_STRING_LEN];
  154.     const char *group_name, *ll, *w;
  155.  
  156.     if (!(f = ap_pcfg_openfile(p, grpfile))) {
  157. /*add?    aplog_error(APLOG_MARK, APLOG_ERR, NULL,
  158.             "Could not open group file: %s", grpfile);*/
  159.     return NULL;
  160.     }
  161.  
  162.     sp = ap_make_sub_pool(p);
  163.  
  164.     while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
  165.     if ((l[0] == '#') || (!l[0]))
  166.         continue;
  167.     ll = l;
  168.     ap_clear_pool(sp);
  169.  
  170.     group_name = ap_getword(sp, &ll, ':');
  171.  
  172.     while (ll[0]) {
  173.         w = ap_getword_conf(sp, &ll);
  174.         if (!strcmp(w, user)) {
  175.         ap_table_setn(grps, ap_pstrdup(p, group_name), "in");
  176.         break;
  177.         }
  178.     }
  179.     }
  180.     ap_cfg_closefile(f);
  181.     ap_destroy_pool(sp);
  182.     return grps;
  183. }
  184.  
  185. /* These functions return 0 if client is OK, and proper error status
  186.  * if not... either AUTH_REQUIRED, if we made a check, and it failed, or
  187.  * SERVER_ERROR, if things are so totally confused that we couldn't
  188.  * figure out how to tell if the client is authorized or not.
  189.  *
  190.  * If they return DECLINED, and all other modules also decline, that's
  191.  * treated by the server core as a configuration error, logged and
  192.  * reported as such.
  193.  */
  194.  
  195. /* Determine user ID, and check if it really is that user, for HTTP
  196.  * basic authentication...
  197.  */
  198.  
  199. static int authenticate_basic_user(request_rec *r)
  200. {
  201.     auth_config_rec *sec =
  202.     (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module);
  203.     conn_rec *c = r->connection;
  204.     const char *sent_pw;
  205.     char *real_pw;
  206.     int res;
  207.  
  208.     if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
  209.     return res;
  210.  
  211.     if (!sec->auth_pwfile)
  212.     return DECLINED;
  213.  
  214.     if (!(real_pw = get_pw(r, c->user, sec->auth_pwfile))) {
  215.     if (!(sec->auth_authoritative))
  216.         return DECLINED;
  217.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  218.             "user %s not found: %s", c->user, r->uri);
  219.     ap_note_basic_auth_failure(r);
  220.     return AUTH_REQUIRED;
  221.     }
  222.     /* anyone know where the prototype for crypt is? */
  223.     if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) {
  224.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  225.             "user %s: password mismatch: %s", c->user, r->uri);
  226.     ap_note_basic_auth_failure(r);
  227.     return AUTH_REQUIRED;
  228.     }
  229.     return OK;
  230. }
  231.  
  232. /* Checking ID */
  233.  
  234. static int check_user_access(request_rec *r)
  235. {
  236.     auth_config_rec *sec =
  237.     (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module);
  238.     char *user = r->connection->user;
  239.     int m = r->method_number;
  240.     int method_restricted = 0;
  241.     register int x;
  242.     const char *t, *w;
  243.     table *grpstatus;
  244.     const array_header *reqs_arr = ap_requires(r);
  245.     require_line *reqs;
  246.  
  247.     /* BUG FIX: tadc, 11-Nov-1995.  If there is no "requires" directive, 
  248.      * then any user will do.
  249.      */
  250.     if (!reqs_arr)
  251.     return (OK);
  252.     reqs = (require_line *) reqs_arr->elts;
  253.  
  254.     if (sec->auth_grpfile)
  255.     grpstatus = groups_for_user(r->pool, user, sec->auth_grpfile);
  256.     else
  257.     grpstatus = NULL;
  258.  
  259.     for (x = 0; x < reqs_arr->nelts; x++) {
  260.  
  261.     if (!(reqs[x].method_mask & (1 << m)))
  262.         continue;
  263.  
  264.     method_restricted = 1;
  265.  
  266.     t = reqs[x].requirement;
  267.     w = ap_getword_white(r->pool, &t);
  268.     if (!strcmp(w, "valid-user"))
  269.         return OK;
  270.     if (!strcmp(w, "user")) {
  271.         while (t[0]) {
  272.         w = ap_getword_conf(r->pool, &t);
  273.         if (!strcmp(user, w))
  274.             return OK;
  275.         }
  276.     }
  277.     else if (!strcmp(w, "group")) {
  278.         if (!grpstatus)
  279.         return DECLINED;    /* DBM group?  Something else? */
  280.  
  281.         while (t[0]) {
  282.         w = ap_getword_conf(r->pool, &t);
  283.         if (ap_table_get(grpstatus, w))
  284.             return OK;
  285.         }
  286.     } else if (sec->auth_authoritative) {
  287.         /* if we aren't authoritative, any require directive could be
  288.          * valid even if we don't grok it.  However, if we are 
  289.          * authoritative, we can warn the user they did something wrong.
  290.          * That something could be a missing "AuthAuthoritative off", but
  291.          * more likely is a typo in the require directive.
  292.          */
  293.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  294.         "access to %s failed, reason: unknown require directive:"
  295.         "\"%s\"", r->uri, reqs[x].requirement);
  296.     }
  297.     }
  298.  
  299.     if (!method_restricted)
  300.     return OK;
  301.  
  302.     if (!(sec->auth_authoritative))
  303.     return DECLINED;
  304.  
  305.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  306.     "access to %s failed, reason: user %s not allowed access",
  307.     r->uri, user);
  308.     
  309.     ap_note_basic_auth_failure(r);
  310.     return AUTH_REQUIRED;
  311. }
  312.  
  313. module MODULE_VAR_EXPORT auth_module =
  314. {
  315.     STANDARD_MODULE_STUFF,
  316.     NULL,            /* initializer */
  317.     create_auth_dir_config,    /* dir config creater */
  318.     NULL,            /* dir merger --- default is to override */
  319.     NULL,            /* server config */
  320.     NULL,            /* merge server config */
  321.     auth_cmds,            /* command table */
  322.     NULL,            /* handlers */
  323.     NULL,            /* filename translation */
  324.     authenticate_basic_user,    /* check_user_id */
  325.     check_user_access,        /* check auth */
  326.     NULL,            /* check access */
  327.     NULL,            /* type_checker */
  328.     NULL,            /* fixups */
  329.     NULL,            /* logger */
  330.     NULL,            /* header parser */
  331.     NULL,            /* child_init */
  332.     NULL,            /* child_exit */
  333.     NULL            /* post read-request */
  334. };
  335.