"Fossies" - the Fresh Open Source Software Archive

Member "mod_auth_dce-3.4/auth_dce/mod_auth_dce.c" (10 Aug 2006, 30720 Bytes) of package /linux/www/apache_httpd_modules/old/mod_auth_dce-3.4.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  * DCE Authentication Module for Apache HTTP Server
    3  *
    4  * Paul B. Henson <henson@acm.org>
    5  *
    6  * Copyright (c) 1996-2003 Paul B. Henson -- see COPYRIGHT file for details
    7  *
    8  */
    9 
   10 /* MODULE-DEFINITION-START
   11  * Name: auth_dce
   12  * ConfigStart
   13 
   14     case "$PLAT" in
   15     
   16       *-ibm-aix4.*)
   17         echo "  mod_auth_dce: Note - context caching not supported on this platform."
   18         CC=xlC_r4
   19     CFLAGS="$CFLAGS -DNO_CACHING"
   20         LDFLAGS="$LDFLAGS -ldce -lm"
   21         ;;
   22 
   23       *-dec-osf*)
   24         echo "  mod_auth_dce: Note - context caching not supported on this platform."
   25     CFLAGS="$CFLAGS -std -threads -DNO_CACHING"
   26     LDFLAGS="$LDFLAGS -threads"
   27         LIBS="$LIBS -ldce -lm"
   28         ;;
   29       
   30       *-solaris2*)
   31         CFLAGS="$CFLAGS -D_REENTRANT"
   32         case "$PLATOSVERS" in
   33             2[012345]*)
   34                 LIBS="$LIBS -ldce -lthread -lsocket -lnsl -lm"
   35                 ;;
   36             2[678]*)
   37                 LIBS="$LIBS -ldce -lpthread -lsocket -lnsl"
   38                 ;;
   39         *)
   40             echo "  mod_auth_dce: This version of Solaris is not currently supported."
   41         exit 1
   42         ;;
   43         esac
   44     ;;
   45 
   46       *)
   47     echo "  mod_auth_dce: I don't know how to compile DCE applications on this platform."
   48     exit 1
   49     ;;
   50     
   51     esac
   52 
   53  * ConfigEnd
   54  * MODULE-DEFINITION-END
   55  */
   56 
   57 #if defined(HPUX) || defined(HPUX10) || defined(HPUX11) /* I guess HPSUX just had to be different */
   58 #include <pthread.h>
   59 #else
   60 #include <dce/pthread.h>
   61 #endif
   62 
   63 #include <dce/dce_error.h>
   64 #include <dce/sec_login.h>
   65 #include <dce/binding.h>
   66 #include <dce/pgo.h>
   67 #include "httpd.h"
   68 #include "http_config.h"
   69 #include "http_core.h"
   70 #include "http_log.h"
   71 #include "http_main.h"
   72 #include "http_protocol.h"
   73 #include "util_script.h"
   74 #include "mod_auth_dce.h"
   75 
   76 
   77 #ifndef NO_CACHING
   78 #ifdef SOLARIS2
   79 static char krb5_env[] = "KRB5CCNAME=FILE:/opt/dcelocal/var/security/creds/dcecred_XXXXXXXX";
   80 static char *krb5_env_pag = krb5_env+57;
   81 #else
   82 #error Credential cache directory not known for this platform.
   83 #endif
   84 static unsigned32 server_pag = 0;
   85 #endif
   86 
   87 #ifndef WITH_DFS
   88 static unsigned long sec_login_inq_pag_no_dfs(void *dummy, error_status_t *dce_st)
   89 {
   90   char *krb5ccname = getenv("KRB5CCNAME");
   91   *dce_st = 0;
   92   
   93   if (krb5ccname)
   94     {
   95       int len = strlen(krb5ccname);
   96       if (len >= 8)
   97     return (unsigned long)strtol(krb5ccname + len - 8, (char **)NULL, 16);
   98     }
   99   
  100   return 0;
  101 }
  102 #define sec_login_inq_pag(X, Y) sec_login_inq_pag_no_dfs(X, Y)
  103 #define installpag(X)
  104 #define resetpag()
  105 #endif
  106 
  107 static sec_login_handle_t server_context = NULL;
  108 
  109 
  110 server_config_rec auth_dce_server_config = {
  111   NULL,  /* default user */
  112   NULL,  /* default keytab */
  113   0,     /* default certify_identity */
  114 #ifndef NO_CACHING
  115   1000,  /* default cache_buckets */
  116   7200,  /* default cache_graceperiod */
  117   21600, /* default cache_lifetime */
  118   14400, /* default cache_max_idle */
  119   1800   /* default cache_sweep_interval */
  120 #endif
  121 };
  122 
  123 
  124 static pthread_addr_t refresh_context(pthread_addr_t arg)
  125 {
  126   signed32 expiration_time;
  127   time_t now;
  128   struct timespec sleep_interval;
  129   error_status_t dce_st;
  130   dce_error_string_t dce_error;
  131   int dce_error_st;
  132   sec_login_auth_src_t auth_src;
  133   unsigned32 kvno_worked;
  134   boolean32 reset_passwd;
  135   server_rec *s = (server_rec *)arg;
  136 
  137   DEBUG_S("auth_dce.refresh_context: beginning context refresh loop");
  138   
  139   while (1)
  140     {
  141       now = time(NULL);
  142 
  143       sec_login_get_expiration(server_context, &expiration_time, &dce_st);
  144       if (dce_st && (dce_st != sec_login_s_not_certified))
  145     {
  146       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  147       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
  148                "auth_dce.refresh_context: sec_login_get_expiration failed - %s (%d)", dce_error, dce_st);
  149       expiration_time = now + 20 * 60;
  150     }
  151 
  152       DEBUG_S("auth_dce.refresh_context: context expires at time %d", expiration_time);
  153       
  154       sleep_interval.tv_sec = expiration_time - now - 10 * 60;
  155       sleep_interval.tv_nsec = 0;
  156       
  157       DEBUG_S("auth_dce.refresh_context: sleeping %d seconds", sleep_interval.tv_sec);
  158 
  159       pthread_delay_np(&sleep_interval);
  160     
  161       DEBUG_S("auth_dce.refresh_context: calling sec_login_refresh_identity");
  162 
  163       sec_login_refresh_identity(server_context, &dce_st);
  164       if (dce_st)
  165     {
  166       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  167       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
  168                "auth_dce.refresh_context: sec_login_refresh_identity failed - %s (%d)", dce_error, dce_st);
  169     }
  170       
  171       DEBUG_S("auth_dce.refresh_context: calling sec_login_valid_from_keytable");
  172 
  173       sec_login_valid_from_keytable(server_context, rpc_c_authn_dce_secret, auth_dce_server_config.keytab, (unsigned32) NULL, &kvno_worked,
  174                     &reset_passwd, &auth_src, &dce_st);
  175       if (dce_st)
  176     {
  177       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  178       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
  179                "auth_dce.refresh_context: sec_login_valid_from_keytable failed - %s (%d)", dce_error, dce_st);
  180     }
  181 
  182       DEBUG_S("auth_dce.refresh_context: context refreshed");
  183     }          
  184   return 0;
  185 }
  186 
  187 #ifndef NO_CACHING
  188 void auth_dce_purge_context(server_rec *s, unsigned long pag)
  189 {
  190   sec_login_handle_t login_context;
  191   error_status_t dce_st;
  192   dce_error_string_t dce_error;
  193   int dce_error_st;
  194 
  195   DEBUG_S("auth_dce.purge_context called for pag %08x", pag);
  196   
  197   sec_login_context_from_pag(pag, &login_context, &dce_st);
  198   if (dce_st)
  199     {
  200       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  201       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
  202            "auth_dce.purge_context: sec_login_context_from_pag failed - %s (%d)", dce_error, dce_st);
  203       return;
  204     }
  205   
  206   sec_login_purge_context(&login_context, &dce_st);
  207 }   
  208 #endif
  209 
  210 static void *create_server_config(pool *p, server_rec *s)
  211 {
  212   return ap_pcalloc (p, sizeof(server_config_rec));
  213 }
  214 
  215 static void *merge_server_configs(pool *p, void *basev, void *addv)
  216 {
  217   server_config_rec *new = (server_config_rec*)ap_pcalloc(p, sizeof(server_config_rec));
  218   server_config_rec *base = (server_config_rec *)basev;
  219   server_config_rec *add = (server_config_rec *)addv;
  220   
  221   return new;
  222 }
  223 
  224 static const char *set_user(cmd_parms *cmd, void *dv, char *word1)
  225 {
  226   auth_dce_server_config.user = (word1) ? ap_pstrdup(cmd->pool, word1) : NULL;
  227   return NULL;
  228 }
  229 
  230 static const char *set_keytab(cmd_parms *cmd, void *dv, char *word1)
  231 {
  232   auth_dce_server_config.keytab = ap_pstrcat(cmd->pool, "FILE:", word1, NULL);
  233   return NULL;
  234 }
  235 
  236 static const char *set_certify_identity(cmd_parms *cmd, void *mconfig, int bool)
  237 {
  238   auth_dce_server_config.certify_identity = bool;
  239   return NULL;
  240 }
  241 
  242 #ifndef NO_CACHING
  243 static const char *set_cache_buckets(cmd_parms *cmd, void *dv, char *word1)
  244 {
  245   auth_dce_server_config.cache_buckets = atoi(word1);
  246   if (auth_dce_server_config.cache_buckets < 1 || auth_dce_server_config.cache_buckets > 50000)
  247     return "auth_dce: invalid cache_buckets value";
  248   
  249   return NULL;
  250 }
  251 
  252 static const char *set_cache_graceperiod(cmd_parms *cmd, void *dv, char *word1)
  253 {
  254   auth_dce_server_config.cache_graceperiod = atoi(word1);
  255   if (auth_dce_server_config.cache_graceperiod < 0)
  256     return "auth_dce: invalid negative cache_graceperiod";
  257   
  258   return NULL;
  259 }
  260 
  261 static const char *set_cache_lifetime(cmd_parms *cmd, void *dv, char *word1)
  262 {
  263   auth_dce_server_config.cache_lifetime = atoi(word1);
  264   if (auth_dce_server_config.cache_lifetime < 3600)
  265     return "auth_dce: invalid cache_buckets value < 3600 seconds";
  266   
  267   return NULL;
  268 }
  269 
  270 static const char *set_cache_max_idle(cmd_parms *cmd, void *dv, char *word1)
  271 {
  272   auth_dce_server_config.cache_max_idle = atoi(word1);
  273   if (auth_dce_server_config.cache_max_idle < 0)
  274     return "auth_dce: invalid cache_max_idle < 0";
  275   
  276   return NULL;
  277 }
  278 
  279 static const char *set_cache_sweep_interval(cmd_parms *cmd, void *dv, char *word1)
  280 {
  281   auth_dce_server_config.cache_sweep_interval = atoi(word1);
  282   if (auth_dce_server_config.cache_sweep_interval < 300)
  283     return "auth_dce: invalid cache_sweep_interval < 300 seconds";
  284   
  285   return NULL;
  286 }
  287 #endif
  288 
  289 static const char *set_indexes(cmd_parms *cmd, void *dv, const char *args)
  290 {
  291   dir_config_rec *dir_config = (dir_config_rec *)dv;
  292   dir_config->index_names = ap_pstrcat(cmd->pool, args, NULL);
  293   return NULL;
  294 }
  295 
  296 static void *create_dir_config(pool *p, char *d)
  297 {
  298     dir_config_rec *new = (dir_config_rec*)ap_pcalloc(p, sizeof(dir_config_rec));
  299     new->impersonate_browser = 1;
  300     new->authoritative = 1;
  301     
  302     return new;
  303 }
  304 
  305 static void *merge_dir_configs(pool *p, void *basev, void *addv)
  306 {
  307   dir_config_rec *new = (dir_config_rec*)ap_pcalloc(p, sizeof(dir_config_rec));
  308   dir_config_rec *base = (dir_config_rec *)basev;
  309   dir_config_rec *add = (dir_config_rec *)addv;
  310 
  311   new->active = add->active;
  312 #ifdef WITH_DFS
  313   new->dfs_authorization = add->dfs_authorization;
  314 #endif
  315   new->include_pw = add->include_pw;
  316   new->impersonate_browser = add->impersonate_browser;
  317   new->authoritative = add->authoritative;
  318   new->index_names = (add->index_names) ? (add->index_names) : (base->index_names);
  319   
  320   return new;
  321 }
  322 
  323 
  324 static command_rec cmds[] = {
  325   { "AuthDCE", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, active), OR_AUTHCFG, FLAG,
  326     "Perform DCE authentication in this directory?" },
  327 
  328 #ifdef WITH_DFS
  329   { "AuthDCEDFSAuthorization", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, dfs_authorization), OR_AUTHCFG, FLAG,
  330     "Use DFS ACLs for authorization in this directory?" },
  331 #endif
  332   
  333   { "AuthDCEIncludePW", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, include_pw), OR_AUTHCFG, FLAG,
  334     "Include DCE password for CGIs run in this directory?" },
  335   
  336   { "AuthDCEImpersonateBrowser", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, impersonate_browser), OR_AUTHCFG, FLAG,
  337     "Attach browser's credentials when accessing files or running CGIs?" },
  338   
  339   { "AuthDCEUser", set_user, NULL, RSRC_CONF, TAKE1,
  340     "DCE identity to run web server as" },
  341   
  342   { "AuthDCEKeytab", set_keytab, NULL, RSRC_CONF, TAKE1,
  343     "Keytab to use if different than default" },
  344   
  345   { "AuthDCEAuthoritative", ap_set_flag_slot, (void *) XtOffsetOf(dir_config_rec, authoritative), OR_AUTHCFG, FLAG,
  346     "Make DCE Authoritative" },
  347   
  348   { "AuthDCEDirectoryIndex", set_indexes, NULL, OR_INDEXES, RAW_ARGS,
  349     "Set this identical to DirectoryIndex if set" },
  350   
  351   { "AuthDCECertifyIdentity", set_certify_identity, NULL, RSRC_CONF, FLAG,
  352     "Certify DCE Identity" },
  353 
  354 #ifndef NO_CACHING
  355   { "AuthDCECacheBuckets", set_cache_buckets, NULL, RSRC_CONF, TAKE1,
  356     "Number of buckets in credential hash table" },
  357   
  358   { "AuthDCECacheGracePeriod", set_cache_graceperiod, NULL, RSRC_CONF, TAKE1,
  359     "Time in seconds" },
  360  
  361   { "AuthDCECacheLifetime", set_cache_lifetime, NULL, RSRC_CONF, TAKE1,
  362     "Time in seconds after which credentials are removed" },
  363   
  364   { "AuthDCECacheMaxIdle", set_cache_max_idle, NULL, RSRC_CONF, TAKE1,
  365     "Time in seconds after which unused credentials are considered idle" },
  366   
  367   { "AuthDCECacheSweepInterval", set_cache_sweep_interval, NULL, RSRC_CONF, TAKE1,
  368     "Frequency in seconds to sweep cache for credential removal" },
  369 #endif
  370   
  371   { NULL }
  372 };
  373 
  374 
  375 module auth_dce_module;
  376 
  377 static int authenticate(request_rec *r)
  378 {
  379   char *sent_pw;
  380   sec_login_handle_t login_context;
  381   error_status_t dce_st;
  382   dce_error_string_t dce_error;
  383   int dce_error_st;
  384   sec_login_auth_src_t auth_src;
  385   sec_passwd_rec_t pw_entry;
  386   sec_passwd_str_t dce_pw;
  387   boolean32 reset_passwd;
  388   request_config_rec *request_config;
  389   
  390   dir_config_rec *dir_config = (dir_config_rec *)ap_get_module_config(r->per_dir_config, &auth_dce_module);
  391 
  392   DEBUG_R("auth_dce.authenticate: called for URI %s", r->uri);
  393   DEBUG_R("auth_dce.authenticate: called for filename %s", r->filename);
  394 
  395   if (!dir_config->active)
  396     {
  397       if (server_context)
  398     ap_table_set(r->subprocess_env, "KRB5CCNAME", getenv("KRB5CCNAME"));
  399       
  400       DEBUG_R("auth_dce.authenticate: active not set, returning DECLINED");
  401       
  402       return DECLINED;
  403     }
  404 
  405 #ifdef WITH_DFS
  406   if (dir_config->dfs_authorization)
  407     {
  408       struct stat statbuf;
  409       int accessible = 1;
  410 
  411       if(stat(r->filename, &statbuf))
  412     accessible = (errno != EACCES);
  413       else
  414     {
  415       int access_required = R_OK;
  416       
  417       if (S_ISDIR(statbuf.st_mode))
  418         if (r->uri[strlen(r->uri)-1] == '/')
  419           {
  420         const char *indexes = (dir_config->index_names) ? (dir_config->index_names) : (DEFAULT_INDEX);
  421         char *slash = (r->filename[strlen(r->filename)-1] == '/') ? "" : "/";
  422         access_required |= X_OK;
  423         
  424         while (*indexes)
  425           {
  426             char *index = ap_getword_conf(r->pool, &indexes);
  427             char *filename = ap_pstrcat(r->pool, r->filename, slash, index, NULL);
  428             
  429             if (!stat(filename, &statbuf))
  430               {
  431             r->filename = filename;
  432             access_required = R_OK;
  433             break;
  434               }
  435           }
  436           }
  437         else
  438           return OK; /* request for directory with no trailing slash, allow redirect without authentication */
  439 
  440       if (access(r->filename, access_required))
  441         accessible = (errno != EACCES);
  442     }
  443 
  444       if (accessible)
  445     {
  446       DEBUG_R("auth_dce.authenticate: file is accessible, returning OK");
  447       ap_set_module_config(r->request_config, &auth_dce_module, NULL);
  448 
  449       if (server_context)
  450         ap_table_set(r->subprocess_env, "KRB5CCNAME", getenv("KRB5CCNAME"));
  451 
  452       return OK;
  453     }
  454     }
  455 #endif
  456   
  457   if (!(ap_table_get(r->headers_in, r->proxyreq != STD_PROXY ? "Authorization" : "Proxy-Authorization")))
  458     { 
  459       DEBUG_R("auth_dce.authenticate: authorization not provided, returning AUTH_REQUIRED");
  460       ap_note_basic_auth_failure(r);
  461       
  462       return AUTH_REQUIRED;
  463     }
  464 
  465   ap_set_module_config(r->request_config, &auth_dce_module, (void *)ap_pcalloc(r->pool, sizeof(request_config_rec)));
  466   request_config = (request_config_rec *)ap_get_module_config(r->request_config, &auth_dce_module);
  467   
  468   ap_get_basic_auth_pw(r, (const char **)&sent_pw);
  469 
  470   DEBUG_R("auth_dce.authenticate: request made by user %s", r->connection->user);
  471   
  472 #ifndef NO_CACHING
  473   auth_dce_find_cached_context(r, request_config, r->connection->user, sent_pw);
  474 
  475   if (!request_config->pag)
  476     {
  477 #endif
  478 
  479       DEBUG_R("auth_dce.authenticate: calling sec_login_setup_identity");
  480   
  481       if (!sec_login_setup_identity((unsigned_char_p_t)r->connection->user, sec_login_no_flags,
  482                                     &login_context, &dce_st))
  483         {
  484           dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  485           ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  486             "auth_dce.authenticate: sec_login_setup_identity failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
  487       
  488       if (dir_config->authoritative)
  489         {
  490           ap_note_basic_auth_failure(r);
  491           DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  492           
  493           return AUTH_REQUIRED;
  494         }
  495       else
  496         {
  497           DEBUG_R("auth_dce.authenticate: AuthDCEAuthoritative off, returning DECLINED");
  498           
  499           return DECLINED;
  500         }
  501     }
  502 
  503       pw_entry.version_number = sec_passwd_c_version_none;
  504       pw_entry.pepper = NULL;
  505       pw_entry.key.key_type = sec_passwd_plain;
  506           
  507       strncpy( (char *)dce_pw, sent_pw, sec_passwd_str_max_len);
  508       dce_pw[sec_passwd_str_max_len] = '\0';
  509       pw_entry.key.tagged_union.plain = &(dce_pw[0]);
  510 
  511       DEBUG_R("auth_dce.authenticate: calling sec_login_validate_identity");
  512       
  513       if (!sec_login_validate_identity(login_context, &pw_entry, &reset_passwd,
  514                                        &auth_src, &dce_st))
  515         {
  516           dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  517           ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  518             "auth_dce.authenticate: sec_login_validate_identity failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
  519       
  520           sec_login_purge_context(&login_context, &dce_st);
  521           ap_note_basic_auth_failure(r);
  522           DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  523       
  524           return AUTH_REQUIRED;
  525         }
  526         
  527       if (auth_dce_server_config.certify_identity)
  528     {
  529       DEBUG_R("auth_dce.authenticate: calling sec_login_certify_identity");
  530       
  531       if (!sec_login_certify_identity(login_context, &dce_st))
  532         {
  533           dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  534           ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  535                 "auth_dce.authenticate: sec_login_certify_identity failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
  536           
  537           sec_login_purge_context(&login_context, &dce_st);
  538           ap_note_basic_auth_failure(r);
  539           DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  540           
  541           return AUTH_REQUIRED;
  542         }
  543     }
  544           
  545       if (auth_src != sec_login_auth_src_network)
  546         {
  547           ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  548             "auth_dce.authenticate: no network credentials for %s", r->connection->user);
  549 
  550           sec_login_purge_context(&login_context, &dce_st);
  551           ap_note_basic_auth_failure(r);
  552       DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  553       
  554           return AUTH_REQUIRED;
  555         }
  556           
  557 
  558 #ifndef NO_CACHING
  559       DEBUG_R("auth_dce.authenticate: acquiring context pag");
  560       
  561       if (server_pag)
  562     krb5_env[0] = 'X';
  563 
  564       sec_login_set_context(login_context, &dce_st);
  565       if (dce_st)
  566     {
  567       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  568       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  569             "auth_dce.authenticate: sec_login_set_context failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
  570       
  571       sec_login_purge_context(&login_context, &dce_st);
  572       
  573       if (server_pag)
  574         {
  575           krb5_env[0] = 'K';
  576           installpag(server_pag);
  577         }
  578       
  579       ap_note_basic_auth_failure(r);
  580       DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  581       
  582       return AUTH_REQUIRED;
  583     }
  584 
  585       request_config->pag = sec_login_inq_pag(login_context, &dce_st);
  586       if (dce_st || !request_config->pag)
  587     {
  588       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  589       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  590             "auth_dce.authenticate: sec_login_inq_pag failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
  591       
  592       sec_login_purge_context(&login_context, &dce_st);
  593       
  594       if (server_pag)
  595         {
  596           krb5_env[0] = 'K';
  597           installpag(server_pag);
  598         }
  599       
  600       ap_note_basic_auth_failure(r);
  601       DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  602       
  603       return AUTH_REQUIRED;
  604     }
  605 
  606       sec_login_release_context(&login_context, &dce_st);
  607       if (server_pag)
  608     {
  609       krb5_env[0] = 'K';
  610       installpag(server_pag);
  611     }
  612       
  613       auth_dce_add_cached_context(r, request_config);
  614     }
  615 #else
  616   request_config->login_context = login_context;
  617 #endif
  618 
  619   if (dir_config->impersonate_browser)
  620     {
  621 
  622       DEBUG_R("auth_dce.authenticate: impersonating browser");
  623       
  624 #ifndef NO_CACHING
  625       krb5_env[0] = 'K';
  626       sprintf(krb5_env_pag, "%08x", request_config->pag);
  627       installpag(request_config->pag);
  628 #else
  629 
  630       if (server_context)
  631     unlink(getenv("KRB5CCNAME")+5);
  632       
  633       DEBUG_R("auth_dce.authenticate: calling sec_login_set_context");
  634       sec_login_set_context(request_config->login_context, &dce_st);
  635       if (dce_st)
  636     {
  637       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  638       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  639             "auth_dce.authenticate: sec_login_set_context failed for %s - %s (%d)", r->connection->user, dce_error, dce_st);
  640       
  641       sec_login_purge_context(&request_config->login_context, &dce_st);
  642       
  643       if (server_context)
  644         sec_login_set_context(server_context, &dce_st);
  645       
  646       ap_note_basic_auth_failure(r);
  647       DEBUG_R("auth_dce.authenticate: returning AUTH_REQUIRED");
  648       
  649       return AUTH_REQUIRED;
  650     }
  651 #endif
  652     }
  653                     
  654 
  655   /* The server might have failed to fill in the request_rec
  656    * structure due to permission errors. If the structure hasn't been
  657    * filled in, call the function (from http_request.c) again.
  658    */
  659   if (r->finfo.st_mode == 0)
  660     get_path_info(r);
  661           
  662   DEBUG_R("auth_dce.authenticate: setting CGI environment variables");
  663 
  664   ap_table_set(r->subprocess_env, "KRB5CCNAME", getenv("KRB5CCNAME"));
  665 
  666   if (dir_config->include_pw)
  667     ap_table_set(r->subprocess_env, "DCEPW", sent_pw);  
  668 
  669 /* requested feature to remove authorization header for requests where
  670    include_pw not set, currently disabled pending debugging of strange
  671    side effects
  672 
  673   else
  674     ap_table_set(r->headers_in, r->proxyreq != STD_PROXY ? "Authorization" : "Proxy-Authorization",
  675          ap_pstrcat(r->pool, "Basic ",
  676                             ap_pbase64encode(r->pool, ap_pstrcat(r->pool, r->connection->user, ":<censored>", NULL)),
  677                             NULL));
  678 */
  679   
  680   DEBUG_R("auth_dce.authenticate: returning OK");
  681 
  682   return OK;
  683 }
  684 
  685 
  686 static int authorize(request_rec *r)
  687 {
  688   dir_config_rec *dir_config = (dir_config_rec *)ap_get_module_config(r->per_dir_config, &auth_dce_module);
  689 
  690   error_status_t dce_st;
  691   dce_error_string_t dce_error;
  692   int dce_error_st;
  693 
  694   const char *require_list;
  695   char *require_type, *entity;
  696   const array_header *requires_array = ap_requires(r);
  697   require_line *require_lines;
  698 
  699   int index;
  700 
  701   DEBUG_R("auth_dce.authorize: called for URI %s", r->uri);
  702   DEBUG_R("auth_dce.authorize: called for filename %s", r->filename);
  703   
  704   if (!dir_config->active)
  705     {
  706       DEBUG_R("auth_dce.authorize: active not set, returning DECLINED");
  707       
  708       return DECLINED;
  709     }
  710 
  711   if (!ap_get_module_config(r->request_config, &auth_dce_module))
  712     {
  713       DEBUG_R("auth_dce.authorize: request_config not set, returning OK");
  714 
  715       return OK;
  716     }
  717 
  718   DEBUG_R("auth_dce.authorize: called for user %s", r->connection->user);
  719   
  720   if (!requires_array)
  721     {
  722       /* Assume no require information is the same as "require valid-user" and return OK. */
  723       DEBUG_R("auth_dce.authorize: no requires line, returning OK");
  724       
  725       return OK;
  726     }
  727 
  728   require_lines = (require_line *)requires_array->elts;
  729   for(index = 0; index < requires_array->nelts; index++)
  730     {
  731       if (!(require_lines[index].method_mask & (1 << r->method_number)))
  732     continue;
  733 
  734       require_list = require_lines[index].requirement;
  735       require_type = ap_getword_white(r->pool, &require_list);
  736 
  737       if(!strcmp(require_type, "valid-user"))
  738     {
  739       DEBUG_R("auth_dce.authorize: matched valid-user, returning OK");
  740       
  741       return OK;
  742     }
  743 
  744       if(!strcmp(require_type, "user"))
  745     while(*require_list)
  746       {
  747         entity = ap_getword_conf(r->pool, &require_list);
  748         if(!strcmp(entity, r->connection->user))
  749           {
  750         DEBUG_R("auth_dce.authorize: matched listed user, returning OK");
  751         
  752         return OK;
  753           }
  754       }
  755 
  756       if(!strcmp(require_type, "group"))
  757     while(*require_list)
  758       {
  759         entity = ap_getword_conf(r->pool, &require_list);
  760         if(sec_rgy_pgo_is_member(sec_rgy_default_handle, sec_rgy_domain_group, (unsigned_char_p_t)entity,
  761                      (unsigned_char_p_t)r->connection->user, &dce_st))
  762           {
  763         DEBUG_R("auth_dce.authorize: matched listed group %s, returning OK", entity);
  764         
  765         return OK;
  766           }
  767       }
  768     }
  769 
  770   return ((dir_config->authoritative) ? FORBIDDEN : DECLINED);
  771 }
  772 
  773 
  774 static int request_cleanup(request_rec *orig)
  775 {
  776   sec_login_handle_t login_context;
  777   error_status_t dce_st;
  778   dce_error_string_t dce_error;
  779   int dce_error_st;
  780     
  781   request_rec *r = orig;
  782   dir_config_rec *dir_config;
  783   request_config_rec *request_config;
  784 
  785   while (r)
  786     {
  787       DEBUG_R("auth_dce.request_cleanup: processing URI %s", r->uri);
  788       DEBUG_R("auth_dce.request_cleanup: processing filename %s", r->filename);
  789   
  790       dir_config = (dir_config_rec *)ap_get_module_config(r->per_dir_config, &auth_dce_module);
  791       
  792       if (dir_config->active && dir_config->impersonate_browser &&
  793       (request_config = (request_config_rec *)ap_get_module_config(r->request_config, &auth_dce_module)))
  794     {
  795       
  796 #ifndef NO_CACHING
  797       if (memcmp(request_config->hash_key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
  798         {
  799           if (request_config->pag) 
  800         {
  801               DEBUG_R("auth_dce.request_cleanup: releasing cached context");
  802               auth_dce_release_cached_context(r, request_config);
  803         }
  804         }
  805       else
  806         {
  807           DEBUG_R("auth_dce.request_cleanup: no cache state in request, purging context");
  808           sec_login_context_from_pag(request_config->pag, &login_context, &dce_st);
  809           if (dce_st)
  810         {
  811           dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  812           ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  813                 "auth_dce.request_cleanup: sec_login_context_from_pag failed - %s (%d)", dce_error, dce_st);
  814         }
  815           else
  816         sec_login_purge_context(&login_context, &dce_st);
  817         }
  818       
  819       if (server_pag)
  820         {
  821           sprintf(krb5_env_pag, "%08x", server_pag);
  822           installpag(server_pag);
  823         }
  824       else
  825         {
  826           krb5_env[0] = 'X';
  827           resetpag();
  828         }
  829 #else
  830       if (request_config->login_context)
  831         {
  832           DEBUG_R("auth_dce.request_cleanup: purging context");
  833           sec_login_purge_context(&request_config->login_context, &dce_st);
  834         }
  835       
  836       if (server_context)
  837         {
  838           sec_login_set_context(server_context, &dce_st);
  839           if (dce_st)
  840         {
  841           dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  842           ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  843                 "auth_dce.request_cleanup: sec_login_set_context failed - %s (%d)", dce_error, dce_st);
  844         }
  845         }
  846 #endif
  847     }
  848       r = r->next;
  849     }
  850   
  851   return OK;
  852 }
  853 
  854 static void initialize(server_rec *s, pool *p)
  855 {
  856 
  857 #ifndef NO_CACHING
  858   DEBUG_S("auth_dce.initialize: cache_buckets = %d", auth_dce_server_config.cache_buckets);
  859   DEBUG_S("auth_dce.initialize: cache_graceperiod = %d", auth_dce_server_config.cache_graceperiod);
  860   DEBUG_S("auth_dce.initialize: cache_lifetime = %d", auth_dce_server_config.cache_lifetime);
  861   DEBUG_S("auth_dce.initialize: cache_max_idle = %d", auth_dce_server_config.cache_max_idle);
  862   DEBUG_S("auth_dce.initialize: cache_sweep_interval = %d", auth_dce_server_config.cache_sweep_interval);
  863   DEBUG_S("auth_dce.initialize: calling cache initialization");
  864   
  865   auth_dce_initialize_cache(s, p);
  866 #endif
  867 }
  868 
  869 
  870 static void process_initialize(server_rec *s, pool *p)
  871 {
  872   error_status_t dce_st;
  873   dce_error_string_t dce_error;
  874   int dce_error_st;
  875   sec_login_auth_src_t auth_src;
  876   boolean32 reset_passwd;
  877   unsigned32 kvno_worked;
  878   pthread_t refresh_thread;
  879 
  880   DEBUG_S("auth_dce.process_initialize: user = %s", (auth_dce_server_config.user ? auth_dce_server_config.user : "NULL")); 
  881   DEBUG_S("auth_dce.process_initialize: keytab = %s", (auth_dce_server_config.keytab ? auth_dce_server_config.keytab : "NULL")); 
  882   DEBUG_S("auth_dce.process_initialize: certify_identity = %d", auth_dce_server_config.certify_identity);
  883 
  884 #ifndef NO_CACHING
  885   putenv(krb5_env);
  886   krb5_env[0] = 'X';
  887 #endif
  888   
  889   if (auth_dce_server_config.user)
  890     {
  891       DEBUG_S("auth_dce.initialize: calling sec_login_setup_identity");
  892 
  893       if (!sec_login_setup_identity((unsigned_char_p_t)auth_dce_server_config.user,
  894                     sec_login_no_flags, &server_context, &dce_st))
  895     {
  896       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  897       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  898                "auth_dce.initialize: sec_login_setup_identity failed for %s - %s (%d)", auth_dce_server_config.user, dce_error, dce_st);
  899       exit(1);
  900     }
  901 
  902       DEBUG_S("auth_dce.initialize: calling sec_login_valid_from_keytable");
  903       
  904       sec_login_valid_from_keytable(server_context, rpc_c_authn_dce_secret, auth_dce_server_config.keytab, (unsigned32) NULL, &kvno_worked,
  905                     &reset_passwd, &auth_src, &dce_st);
  906       if (dce_st)
  907     {
  908       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  909       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  910                "auth_dce.initialize: sec_login_valid_from_keytable failed for %s - %s (%d)", auth_dce_server_config.user, dce_error, dce_st);
  911       sec_login_purge_context(&server_context, &dce_st);
  912       exit(1);
  913     }
  914       
  915       if (auth_dce_server_config.certify_identity)
  916     {
  917       DEBUG_S("auth_dce.initialize: calling sec_login_certify_identity");
  918 
  919       if (!sec_login_certify_identity(server_context, &dce_st))
  920         {
  921           dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  922           ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  923                "auth_dce.initialize: sec_login_certify_identity failed for %s - %s (%d)", auth_dce_server_config.user, dce_error, dce_st);
  924           sec_login_purge_context(&server_context, &dce_st);
  925           exit(1);
  926         }
  927     }
  928       
  929       if (auth_src != sec_login_auth_src_network)
  930     {
  931       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  932                "auth_dce.initialize: no network credentials for %s", auth_dce_server_config.user);
  933       sec_login_purge_context(&server_context, &dce_st);
  934       exit(1);
  935     }
  936 
  937 
  938       DEBUG_S("auth_dce.process_initialize: calling sec_login_set_context");
  939 
  940       sec_login_set_context(server_context, &dce_st);
  941       if (dce_st)
  942     {
  943       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  944       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  945                "auth_dce.process_initialize: sec_login_set_context failed - %s (%d)", dce_error, dce_st);
  946       
  947       exit(1);
  948     }
  949 
  950       DEBUG_S("auth_dce.initialize: spawning server credential refresh thread");
  951       
  952       if (pthread_create(&refresh_thread, pthread_attr_default, refresh_context, (pthread_addr_t) s))
  953     {
  954       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  955                "auth_dce.initialize: pthread_create failed");
  956       exit(1);
  957     }
  958     
  959       pthread_detach(&refresh_thread);
  960 
  961 #ifndef NO_CACHING
  962       server_pag = sec_login_inq_pag(server_context, &dce_st);
  963       if (dce_st)
  964     {
  965       dce_error_inq_text(dce_st, dce_error, &dce_error_st);
  966       ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, s,
  967                "auth_dce.process_initialize: sec_login_inq_pag failed - %s (%d)", dce_error, dce_st);
  968       
  969       exit(1);
  970     }
  971 
  972       krb5_env[0] = 'K';
  973       sprintf(krb5_env_pag, "%08x", server_pag);
  974       installpag(server_pag);          
  975 #endif
  976     }
  977 
  978 #ifdef CACHE_TEST_LEVEL
  979   srand48(getpid() ^ time(NULL));
  980 #endif
  981 }
  982 
  983 
  984 module auth_dce_module = {
  985    STANDARD_MODULE_STUFF,
  986    initialize,              /* initializer */
  987    create_dir_config,       /* dir config creater */
  988    merge_dir_configs,       /* dir merger --- default is to override */
  989    create_server_config,    /* server config */
  990    merge_server_configs,    /* merge server config */
  991    cmds,                /* command table */
  992    NULL,            /* handlers */
  993    NULL,            /* filename translation */
  994    authenticate,            /* check_user_id */
  995    authorize,                   /* check auth */
  996    NULL,            /* check access */
  997    NULL,            /* type_checker */
  998    NULL,            /* fixups */
  999    request_cleanup,     /* logger */
 1000    NULL,                        /* [3] header parser */
 1001    process_initialize,          /* process initializer */
 1002    NULL,                        /* process exit/cleanup */
 1003    NULL                         /* [1] post read_request handling */
 1004 };