"Fossies" - the Fresh Open Source Software Archive

Member "src/modules/extra/mod_auth_gss_krb5_org.c" (5 Jun 2003, 19383 Bytes) of package /linux/www/apache_httpd_modules/old/modgssapache-0.0.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* 
    2  * This module implements kerberos5 authentication. Both native kerberos 
    3  * (via GSS API) and password-based methods are supported. Hacked browser is 
    4  * needed if you want to use native kerberos5 protocol (a patch for the Mozilla
    5  * browser can be found at http://meta.cesnet.cz/software/heimdal/)
    6  */
    7 
    8 #include "httpd.h"
    9 #include "http_config.h"
   10 #include "http_core.h"
   11 #include "http_protocol.h"
   12 #include "http_log.h"
   13 
   14 #include <gssapi.h>
   15 
   16 #include <krb5.h>
   17 #include <kafs.h>
   18 
   19 module MODULE_VAR_EXPORT gss_krb5_auth_module;
   20 
   21 extern krb5_keytab gssapi_krb5_keytab;
   22 
   23 typedef struct {
   24   /* Directives for the GSSAPI part */
   25   char  *gss_krb5_keytab;  
   26   int    gss_save_creds;
   27   char  *gss_krb5_cells;
   28   int    use_gss_auth;
   29   char  *gss_krb5_realms;
   30 
   31   /* Directives for the password verification part */
   32   char *krb5_auth_realm;
   33   char *krb5_keytab;
   34   int krb5_save_creds;
   35   int krb5_forwardable;
   36   char *krb5_cells;
   37 } gss_krb5_config_rec;
   38 
   39 static const char *
   40 krb5_save_cells(cmd_parms *, gss_krb5_config_rec *, char *);
   41 
   42 static const char *
   43 gss_save_cells(cmd_parms *, gss_krb5_config_rec *, char *);
   44 
   45 static const char *
   46 gss_save_realms(cmd_parms *, gss_krb5_config_rec *, char *);
   47 
   48 static const char *
   49 krb5_save_realms(cmd_parms *, gss_krb5_config_rec *, char *);
   50 
   51 static const command_rec gss_krb5_cmds[] =
   52 {
   53   /* Directives for the GSSAPI part */ 
   54   { "GssKrb5Keytab", ap_set_file_slot,
   55     (void*)XtOffsetOf(gss_krb5_config_rec, gss_krb5_keytab),
   56     OR_AUTHCFG, TAKE1, "Kerberos v5 keytab." },
   57   { "GssKrb5SaveCredentials", ap_set_flag_slot,
   58     (void*)XtOffsetOf(gss_krb5_config_rec, gss_save_creds),
   59     OR_AUTHCFG, FLAG, "Save the v5 credential cache?" },
   60   { "GssKrb5AFSCells", gss_save_cells, NULL,
   61      OR_AUTHCFG, RAW_ARGS, "Create pag and AFS tokens for cells" },
   62   { "GssSaveCredentials", ap_set_flag_slot,
   63     (void*)XtOffsetOf(gss_krb5_config_rec, gss_save_creds),
   64     OR_AUTHCFG, FLAG, "Save the v5 credential cache?" },
   65   { "GssAuth", ap_set_flag_slot,
   66      (void*)XtOffsetOf(gss_krb5_config_rec, use_gss_auth),
   67      OR_AUTHCFG, FLAG, "Whether to use GSS-API authentication" },
   68   { "GssKrb5AuthRealms", gss_save_realms, NULL,
   69      OR_AUTHCFG, RAW_ARGS, "Kerberos realm(s) in which to authenticate users" },
   70 
   71   /* Directives for the password verification part */
   72   { "KrbAuthRealm", krb5_save_realms, NULL,
   73     OR_AUTHCFG, RAW_ARGS, "Kerberos realm in which to authenticate users." },
   74 
   75    { "Krb5Keytab", ap_set_file_slot,
   76     (void*)XtOffsetOf(gss_krb5_config_rec, krb5_keytab),
   77     OR_AUTHCFG, TAKE1, "Kerberos v5 keytab." },
   78 
   79    { "Krb5SaveCredentials", ap_set_flag_slot,
   80     (void*)XtOffsetOf(gss_krb5_config_rec, krb5_save_creds),
   81     OR_AUTHCFG, FLAG, "Save the v5 credential cache?" },
   82 
   83    { "Krb5Forwardable", ap_set_flag_slot,
   84     (void*)XtOffsetOf(gss_krb5_config_rec, krb5_forwardable),
   85     OR_AUTHCFG, FLAG, "Set tickets to be forwardable?" },
   86 
   87    { "Krb5AFSCells", krb5_save_cells, NULL,
   88     OR_AUTHCFG, RAW_ARGS, "Create pag and AFS tokens for cells" },   
   89 
   90   { NULL, NULL, NULL, 0, 0, NULL}
   91 };
   92 
   93 static const char *
   94 gss_save_cells(cmd_parms *cmd, gss_krb5_config_rec *sec, char *arg)
   95 {
   96    sec->gss_krb5_cells = ap_pstrdup(cmd->pool,arg);
   97    return NULL;
   98 }
   99 
  100 static const char *
  101 krb5_save_cells(cmd_parms *cmd, gss_krb5_config_rec *sec, char *arg)
  102 {
  103    sec->krb5_cells = ap_pstrdup(cmd->pool,arg);
  104    return NULL;
  105 }
  106 
  107 static const char *
  108 gss_save_realms(cmd_parms *cmd, gss_krb5_config_rec *sec, char *arg)
  109 {
  110    sec->gss_krb5_realms = ap_pstrdup(cmd->pool,arg);
  111    return NULL;
  112 }
  113 
  114 static const char *
  115 krb5_save_realms(cmd_parms *cmd, gss_krb5_config_rec *sec, char *arg)
  116 {
  117    sec->krb5_auth_realm = ap_pstrdup(cmd->pool,arg);
  118    return NULL;
  119 }
  120 
  121 static void
  122 krb5_cache_cleanup(void *data)
  123 {
  124    krb5_context context;
  125    krb5_ccache  cache;
  126    krb5_error_code problem;
  127    char *cache_name = (char *) data;
  128 
  129    problem = krb5_init_context(&context);
  130    if (problem) {
  131       ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "krb5_init_context() failed");
  132       return;
  133    }
  134 
  135    problem = krb5_cc_resolve(context, cache_name, &cache);
  136    if (problem) {
  137       ap_log_error(APLOG_MARK, APLOG_ERR, NULL, 
  138                    "krb5_cc_resolve() failed (%s: %s)",
  139                cache_name, krb5_get_err_text(context, problem)); 
  140       return;
  141    }
  142 
  143    krb5_cc_destroy(context, cache);
  144    krb5_free_context(context);
  145 }
  146 
  147 static void krb5_dummy_cleanup(void *data) {}
  148 
  149 static void krb5_unlog_cleanup(void *data)
  150 {
  151    if (k_hasafs())
  152       k_unlog();
  153 }
  154 
  155 static void
  156 note_auth_failure(request_rec *r, const gss_krb5_config_rec *conf)
  157 {
  158    const char *auth_type = NULL;
  159    const char *auth_name = NULL;
  160 
  161    /* get the type specified in .htaccess */
  162    auth_type = ap_auth_type(r);
  163 
  164    /* get the user realm specified in .htaccess */
  165    auth_name = ap_auth_name(r);
  166 
  167    /* XXX should the WWW-Authenticate header be cleared first? */
  168    if (conf->use_gss_auth)
  169       ap_table_add(r->err_headers_out, "WWW-Authenticate", "GSS-Negotiate ");
  170    if (auth_type && strncasecmp(auth_type, "KerberosV5", 10) == 0)
  171       ap_table_add(r->err_headers_out, "WWW-Authenticate",
  172                ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
  173 }
  174 
  175 static const char *
  176 get_gss_error(pool *p, OM_uint32 error_status, char *prefix)
  177 {
  178    OM_uint32 maj_stat, min_stat;
  179    OM_uint32 msg_ctx = 0;
  180    gss_buffer_desc status_string;
  181    char buf[1024];
  182    size_t len;
  183 
  184    snprintf(buf, sizeof(buf), "%s: ", prefix);
  185    len = strlen(buf);
  186    do {
  187       maj_stat = gss_display_status (&min_stat,
  188                                  error_status,
  189                      GSS_C_MECH_CODE,
  190                      GSS_C_NO_OID,
  191                      &msg_ctx,
  192                      &status_string);
  193       if (sizeof(buf) > len + status_string.length + 1) {
  194          sprintf(buf, "%s:", (char*) status_string.value);
  195          len += status_string.length;
  196       }
  197       gss_release_buffer(&min_stat, &status_string);
  198    } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
  199 
  200    return (ap_pstrdup(p, buf));
  201 }
  202 
  203 static void *
  204 gss_krb5_dir_create_config(pool *p, char *dir)
  205 {
  206   gss_krb5_config_rec *rec;
  207 
  208   rec = (gss_krb5_config_rec *) ap_pcalloc(p, sizeof(gss_krb5_config_rec));
  209   return rec;
  210 }
  211 
  212 static void
  213 do_afs_log(krb5_context krb_ctx,
  214            request_rec *r,
  215        krb5_ccache ccache,
  216        char *afs_cells)
  217 {
  218    if (afs_cells && k_hasafs()) {
  219       char *cells = ap_pstrdup(r->pool, afs_cells), *next;
  220 
  221       k_setpag();
  222       for (next=strtok(cells," \t"); next; next = strtok(NULL," \t"))
  223       krb5_afslog(krb_ctx, ccache, next, NULL);
  224       ap_register_cleanup(r->pool, NULL, 
  225                       krb5_unlog_cleanup, krb5_dummy_cleanup);
  226    }
  227 }
  228 static int
  229 store_krb5_creds(krb5_context krb_ctx,
  230                  request_rec *r,
  231                  gss_krb5_config_rec *conf,
  232                  krb5_ccache delegated_cred)
  233 {
  234    krb5_error_code problem;
  235    char *cache_name = NULL;
  236    krb5_ccache ccache = NULL;
  237    krb5_principal principal = NULL;
  238 
  239    if (delegated_cred == NULL)
  240       return OK; /* XXX */
  241 
  242    problem = krb5_cc_gen_new(krb_ctx, &krb5_fcc_ops, &ccache);
  243    if (problem) {
  244       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  245                 "krb5_cc_gen_new() failed (%s)",
  246             krb5_get_err_text(krb_ctx, problem));
  247       goto end;
  248    }
  249 
  250    problem = krb5_cc_get_principal(krb_ctx, delegated_cred, &principal);
  251    if (problem) {
  252       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  253                 "krb5_cc_get_principal() failed (%s)",
  254             krb5_get_err_text(krb_ctx, problem));
  255       goto end;
  256    }
  257 
  258    problem = krb5_cc_initialize(krb_ctx, ccache, principal);
  259    if (problem) {
  260        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  261                  "krb5_cc_initialize() failed (%s)",
  262              krb5_get_err_text(krb_ctx, problem));
  263        goto end;
  264    }
  265 
  266    problem = krb5_cc_copy_cache(krb_ctx, delegated_cred, ccache);
  267    if (problem) {
  268       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  269                 "krb5_cc_copy_cache() failed (%s)",
  270             krb5_get_err_text(krb_ctx, problem));
  271       goto end;
  272    }
  273 
  274    cache_name = ap_pstrdup(r->pool, krb5_cc_get_name(krb_ctx, ccache));
  275    ap_table_setn(r->subprocess_env, "KRB5CCNAME", cache_name);
  276    ap_register_cleanup(r->pool, cache_name, 
  277                    krb5_cache_cleanup, krb5_dummy_cleanup);
  278      
  279    krb5_cc_close(krb_ctx, ccache);
  280 
  281 end:
  282    if (principal)
  283       krb5_free_principal(krb_ctx, principal);
  284    if (ccache && problem)
  285       krb5_cc_destroy(krb_ctx, ccache);
  286 
  287    return (problem ? SERVER_ERROR : OK);
  288 }
  289 
  290 static int 
  291 authenticate_user_gss(request_rec *r, 
  292                       gss_krb5_config_rec *conf,
  293                       const char *auth_line)
  294 {
  295   OM_uint32 major_status, minor_status, minor_status2;
  296   gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
  297   gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
  298   const char *auth_param = NULL;
  299   krb5_context krb_ctx = NULL;
  300   int ret;
  301   gss_name_t client_name = GSS_C_NO_NAME;
  302   gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
  303   gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
  304   char *p;
  305 
  306   krb5_init_context(&krb_ctx);
  307   if (conf->gss_krb5_keytab &&
  308       krb5_kt_resolve(krb_ctx, conf->gss_krb5_keytab, &gssapi_krb5_keytab)) {
  309     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  310                  "krb5_kt_resolve() failed");
  311     ret = SERVER_ERROR;
  312     goto end;
  313   }
  314 
  315   /* ap_getword() shifts parameter */
  316   auth_param = ap_getword_white(r->pool, &auth_line);
  317   if (auth_param == NULL) {
  318      ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  319                "No Authorization parameter from client");
  320      ret = HTTP_UNAUTHORIZED;
  321      goto end;
  322   }
  323 
  324   /* XXX use ap_uudecode() */
  325   input_token.length = ap_base64decode_len(auth_param);
  326   input_token.value = malloc(input_token.length);
  327   if (input_token.value == NULL) {
  328      ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  329            "Not enough memory");
  330      ret = SERVER_ERROR;
  331      goto end;
  332   }
  333   input_token.length = ap_base64decode(input_token.value, auth_param);
  334 
  335   major_status = gss_accept_sec_context(&minor_status,
  336                                     &gss_context,
  337                     GSS_C_NO_CREDENTIAL,
  338                     &input_token,
  339                     GSS_C_NO_CHANNEL_BINDINGS,
  340                     &client_name,
  341                     NULL,
  342                     &output_token,
  343                     NULL,
  344                     NULL,
  345                     &delegated_cred);
  346   if (output_token.length) {
  347      char *token = NULL;
  348      
  349      /* XXX use ap_uuencode() */
  350      token = malloc(ap_base64encode_len(output_token.length));
  351      if (token == NULL) {
  352     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  353                  "Not enough memory");
  354         ret = SERVER_ERROR;
  355     gss_release_buffer(&minor_status2, &output_token);
  356     goto end;
  357      }
  358      ap_base64encode(token, output_token.value, output_token.length);
  359      ap_table_set(r->err_headers_out, "WWW-Authenticate",
  360               ap_pstrcat(r->pool, "GSS-Negotiate ", token, NULL));
  361      free(token);
  362      gss_release_buffer(&minor_status2, &output_token);
  363   }
  364 
  365   if (GSS_ERROR(major_status)) {
  366      ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  367                "%s", get_gss_error(r->pool, minor_status,
  368                                "gss_accept_sec_context() failed"));
  369      ret = HTTP_UNAUTHORIZED;
  370      goto end;
  371   }
  372 
  373   if (major_status & GSS_S_CONTINUE_NEEDED) {
  374      ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  375                "only one authentication iteration allowed"); 
  376      ret = HTTP_UNAUTHORIZED;
  377      goto end;
  378   }
  379 
  380   major_status = gss_export_name(&minor_status, client_name, &output_token);
  381   gss_release_name(&minor_status, &client_name); 
  382   if (GSS_ERROR(major_status)) {
  383     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, r,
  384               "%s", get_gss_error(r->pool, minor_status, 
  385                               "gss_export_name() failed"));
  386     ret = SERVER_ERROR;
  387     goto end;
  388   }
  389 
  390   /* If the user comes from a realm specified by configuration don't include
  391       its realm name in the username so that the authorization routine could
  392       work for both Password-based and Ticket-based authentication. It's
  393       administrators responsibility to include only such realm that have
  394       unified principal instances, i.e. if the same principal name occures in
  395       multiple realms, it must be always assigned to a single user.
  396   */    
  397   r->connection->ap_auth_type = "Negotiate";
  398   r->connection->user = ap_pstrdup(r->pool, output_token.value);
  399   p = strchr(r->connection->user, '@');
  400   if (p != NULL) {
  401      const char *realms = conf->gss_krb5_realms;
  402 
  403      while (realms && *realms) {
  404     if (strcmp(p+1, ap_getword_white(r->pool, &realms)) == 0) {
  405        *p = '\0';
  406        break;
  407     }
  408      }
  409   }
  410 
  411   gss_release_buffer(&minor_status, &output_token);
  412 
  413   /* This should be only done if afs token are requested or gss_save creds is 
  414    * specified */
  415   /* gss_export_cred() from the GGF GSS Extensions could be used */
  416   if (delegated_cred != GSS_C_NO_CREDENTIAL &&
  417       (conf->gss_save_creds || (conf->gss_krb5_cells && k_hasafs()))) { 
  418      do_afs_log(krb_ctx, r, delegated_cred->ccache, conf->gss_krb5_cells);
  419      ret = store_krb5_creds(krb_ctx, r, conf, delegated_cred->ccache);
  420      if (ret)
  421     goto end;
  422   }
  423   ret = OK;
  424 
  425 end:
  426   if (delegated_cred)
  427      gss_release_cred(&minor_status, &delegated_cred);
  428 
  429   if (output_token.length) 
  430      gss_release_buffer(&minor_status, &output_token);
  431 
  432   if (client_name != GSS_C_NO_NAME)
  433      gss_release_name(&minor_status, &client_name);
  434 
  435   if (gss_context != GSS_C_NO_CONTEXT)
  436      gss_delete_sec_context(&minor_status, &gss_context, GSS_C_NO_BUFFER);
  437 
  438   krb5_free_context(krb_ctx);
  439 
  440   if (ret == HTTP_UNAUTHORIZED)
  441      note_auth_failure(r, conf);
  442 
  443   return ret;
  444 }
  445 
  446 static int
  447 authenticate_user_pwd(request_rec *r,
  448                       gss_krb5_config_rec *conf,
  449               const char *auth_line)
  450 {
  451    const char      *sent_pw = NULL;
  452    const char      *realms = NULL;
  453    krb5_context    kcontext;
  454    krb5_error_code code;
  455    krb5_principal  princ = NULL;
  456    char            errstr[512];
  457    krb5_ccache     ccache = NULL;
  458    int             ret;
  459 
  460    krb5_init_context(&kcontext);
  461    
  462    sent_pw = ap_uudecode(r->pool, auth_line);
  463    r->connection->user = ap_getword (r->pool, &sent_pw, ':');
  464    r->connection->ap_auth_type = "Basic";
  465    
  466    /* do not allow user to override realm setting of server */
  467    if (strchr(r->connection->user,'@')) {
  468       ap_log_reason ("specifying realm in user name is prohibited", r->uri, r);
  469       return  HTTP_UNAUTHORIZED;
  470    }
  471 
  472    code = krb5_cc_gen_new(kcontext, &krb5_mcc_ops, &ccache);
  473    if (code) {
  474       snprintf(errstr, sizeof(errstr), "krb5_cc_gen_new(): %.100s",
  475            krb5_get_err_text(kcontext, code));
  476       ap_log_reason (errstr, r->uri, r);
  477       ret = SERVER_ERROR;
  478       goto end;
  479    }
  480 
  481    if (conf->krb5_keytab)
  482       kcontext->default_keytab = conf->krb5_keytab;
  483 
  484    realms = conf->krb5_auth_realm;
  485 
  486    do {
  487       code = 0;
  488       if (realms)
  489      code = krb5_set_default_realm(kcontext,
  490                                    ap_getword_white(r->pool, &realms));
  491       if (code)
  492      continue;
  493 
  494       code = krb5_parse_name(kcontext, r->connection->user, &princ);
  495       if (code)
  496      continue;
  497 
  498       code = krb5_verify_user(kcontext, princ, ccache, sent_pw, 1, "khttp");
  499       if (code == 0)
  500      break;
  501    } while (realms && *realms);
  502 
  503    memset((char *)sent_pw, 0x00, strlen(sent_pw));
  504 
  505    if (code) {
  506       snprintf(errstr, sizeof(errstr), "Verifying krb5 password failed: %s",
  507                krb5_get_err_text(kcontext, code));
  508       ap_log_reason (errstr, r->uri, r);
  509       ret = HTTP_UNAUTHORIZED;
  510       goto end;
  511    }
  512 
  513    if (conf->krb5_save_creds) {
  514       do_afs_log(kcontext, r, ccache, conf->krb5_cells);
  515       ret = store_krb5_creds(kcontext, r, conf, ccache);
  516       if (ret)
  517          goto end;
  518    }
  519 
  520    ret = OK;
  521 
  522 end:
  523    if (princ)
  524       krb5_free_principal(kcontext, princ);
  525    if (ccache)
  526       krb5_cc_destroy(kcontext, ccache);
  527    krb5_free_context(kcontext);
  528 
  529    return ret;
  530 }
  531 
  532 static int
  533 gss_krb5_authenticate_user(request_rec *r)
  534 {
  535   gss_krb5_config_rec *conf =
  536      (gss_krb5_config_rec *) ap_get_module_config(r->per_dir_config,
  537                           &gss_krb5_auth_module);
  538   const char *auth_type = NULL;
  539   const char *auth_line = NULL;
  540   const char *type = NULL;
  541   int ret;
  542 
  543   /* get the type specified in .htaccess */
  544   type = ap_auth_type(r);
  545 
  546   /* Apache doesn't allow multiple values in AuthType within one directory.
  547    * But since we want to support both the method we added a new configuration
  548    * option (UseGSS) to turn on GSS authentication. */
  549   if (!conf->use_gss_auth &&
  550       (type == NULL || strncasecmp(type, "KerberosV5", 10) != 0)) {
  551      return DECLINED;
  552   }
  553 
  554   /* get what the user sent us in the HTTP header */
  555   auth_line = ap_table_get (r->headers_in, "Authorization");
  556   if (!auth_line) {
  557       note_auth_failure(r, conf);
  558       return HTTP_UNAUTHORIZED;
  559   }
  560   auth_type = ap_getword_white(r->pool, &auth_line);
  561 
  562   if (conf->use_gss_auth &&
  563       strncasecmp(auth_type, "GSS-Negotiate", 13) == 0) {
  564      ret = authenticate_user_gss(r, conf, auth_line);
  565   } else
  566      if (type != NULL && strncasecmp(type, "KerberosV5", 10) == 0 &&
  567      strncasecmp(auth_type, "Basic", 5) == 0) {
  568     ret = authenticate_user_pwd(r, conf, auth_line);
  569      }
  570      else {
  571     ret = HTTP_UNAUTHORIZED;
  572      }
  573 
  574   if (ret == HTTP_UNAUTHORIZED)
  575      note_auth_failure(r, conf);
  576 
  577   return ret;
  578 }
  579 
  580 
  581 static int 
  582 gss_krb5_check_user(request_rec *r)
  583 {
  584   gss_krb5_config_rec *conf =
  585      (gss_krb5_config_rec *) ap_get_module_config(r->per_dir_config,
  586                         &gss_krb5_auth_module);
  587   char *user = r->connection->user;
  588   int m = r->method_number;
  589   int method_restricted = 0;
  590   register int x;
  591   const char *t, *w;
  592   const require_line *require;
  593   const array_header *required_users;
  594 
  595   required_users = ap_requires(r);
  596   if (required_users == NULL)
  597     return OK;
  598 
  599   require = (require_line *) required_users->elts;
  600 
  601   for (x = 0; x < required_users->nelts; x++) {
  602      if (! (require[x].method_mask & (1 << m)))
  603     continue;
  604 
  605      method_restricted = 1;
  606 
  607      t = require[x].requirement;
  608      w = ap_getword_white(r->pool, &t);
  609      if (strcmp(w, "valid-user") == 0) {
  610     return OK;
  611      }
  612 
  613      if (strcmp(w, "user") == 0) {
  614     while (t[0] != '\0') {
  615        w = ap_getword_conf(r->pool, &t);
  616            if (strcmp(user, w) == 0) 
  617               return OK;
  618     }
  619      }
  620   }
  621 
  622   if (! method_restricted)
  623      return OK;
  624 
  625   ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  626     "GSS & Krb5 module: access to %s failed, reason: user %s not allowed access",
  627     r->uri, user);
  628 
  629   note_auth_failure(r, conf);
  630 
  631   return AUTH_REQUIRED;
  632 }
  633 
  634 module MODULE_VAR_EXPORT gss_krb5_auth_module =
  635 {
  636   STANDARD_MODULE_STUFF, 
  637   NULL,                       /* initializer */
  638   gss_krb5_dir_create_config, /* dir config creater */
  639   NULL,                       /* dir merger --- default is to override */
  640   NULL,                       /* server config */
  641   NULL,                       /* merge server config */
  642   gss_krb5_cmds,              /* command table */
  643   NULL,                       /* handlers */
  644   NULL,                       /* filename translation */
  645   gss_krb5_authenticate_user, /* check_user_id */
  646   gss_krb5_check_user,        /* check auth */
  647   NULL,                       /* check access */
  648   NULL,                       /* type_checker */
  649   NULL,                       /* fixups */
  650   NULL,                       /* logger */
  651   NULL,                       /* header parser */
  652   NULL,                       /* child_init */
  653   NULL,                       /* child_exit */
  654   NULL                        /* post read-request */
  655 };