swap order of AFS_LIBS and KRB5_LIBS to get the correct libcom_err.a
[hcoop/zz_old/modwaklog.git] / mod_waklog.c
index cc18e54..62aef1c 100644 (file)
 #define MAXNAMELEN 1024
 #endif
 
+#ifdef STANDARD20_MODULE_STUFF
+#define APACHE2
+#endif
+
 /********************* APACHE1 ******************************************************************************/
-#ifndef STANDARD20_MODULE_STUFF
+#ifndef APACHE2
 #include "ap_config.h"
 #if defined(sun)
 #include <sys/ioccom.h>
   { name, func, \
     NULL , \
     RSRC_CONF | ACCESS_CONF , type, usage }
+module waklog_module;
 
 /********************* APACHE2 ******************************************************************************/
 #else
 #include <apr_strings.h>
 #include <apr_base64.h>
-//#include <ap_compat.h>
 #define ap_pcalloc apr_pcalloc
 #define ap_pdupstr apr_pdupstr
 #define ap_pstrdup apr_pstrdup
-
-module AP_MODULE_DECLARE_DATA waklog_module;
-
 #define MK_POOL apr_pool_t
 #define MK_TABLE_GET apr_table_get
 #define MK_TABLE_SET apr_table_set
@@ -62,14 +63,11 @@ extern unixd_config_rec unixd_config;
   AP_INIT_ ## type (name, (void*) func,                 \
         NULL,     \
         RSRC_CONF | ACCESS_CONF, usage)
-typedef struct
-{
-       int dummy;
-}
-child_info;
-
+module AP_MODULE_DECLARE_DATA waklog_module;
+typedef struct { int dummy; } child_info;
 const char *userdata_key = "waklog_init"; 
-#endif /* STANDARD20_MODULE_STUFF */
+
+#endif /* APACHE2 */
 /**************************************************************************************************/
 
 #include <krb5.h>
@@ -81,7 +79,7 @@ const char *userdata_key = "waklog_init";
 #include <rx/rxkad.h>
 
 #define TKT_LIFE  ( 12 * 60 * 60 )
-#define        SLEEP_TIME      ( TKT_LIFE - 5*60 )
+#define SLEEP_TIME      ( TKT_LIFE - 5*60 )
 
 #define WAKLOG_ON 1
 #define WAKLOG_OFF 2
@@ -92,12 +90,6 @@ const char *userdata_key = "waklog_init";
 #define APLOG_DEBUG APLOG_ERR
 #endif
 
-#ifndef CELL_IN_PRINCIPAL
-int cell_in_principal = 1;
-#else
-int cell_in_principal = 0;
-#endif
-
 /* this is used to turn off pag generation for the backround worker child during startup */
 int pag_for_children = 1;
 
@@ -107,11 +99,14 @@ typedef struct
   int configured;
   int protect;
   int usertokens;
+  int cell_in_principal;
+  int disable_token_cache;
   char *keytab;
   char *principal;
   char *default_principal;
   char *default_keytab;
   char *afs_cell;
+  char *afs_cell_realm;
   char *path;
   MK_POOL *p;
 }
@@ -164,7 +159,6 @@ struct renew_ent renewtable[SHARED_TABLE_SIZE];
 
 int renewcount = 0;
 
-module waklog_module;
 
 
 #define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
@@ -181,19 +175,10 @@ module waklog_module;
 #include <afs/ptuser.h>
 #include <rx/rxkad.h>
 
-#define KEYTAB                  "/etc/keytab.wwwserver"
-#define PRINCIPAL        "someplacewwwserver"
-#define AFS_CELL      "someplace.edu" 
-
-/* If there's an error, retry more aggressively */
-#define        ERR_SLEEP_TIME  5*60
-
-
-#define K5PATH         "FILE:/tmp/waklog.creds.k5"
 
 static void
 log_error (const char *file, int line, int level, int status,
-          const server_rec * s, const char *fmt, ...)
+           const server_rec * s, const char *fmt, ...)
 {
   char errstr[4096];
   va_list ap;
@@ -202,7 +187,7 @@ log_error (const char *file, int line, int level, int status,
   vsnprintf (errstr, 1024, fmt, ap);
   va_end (ap);
 
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
   ap_log_error (file, line, level | APLOG_NOERRNO, status, s, "(%d) %s", getpid(), errstr);
 #else
   ap_log_error (file, line, level | APLOG_NOERRNO, s, "(%d) %s", getpid(), errstr);
@@ -261,25 +246,42 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
   int stored = -1;
   time_t mytime;
   int indentical;
+  int cell_in_principal;
+  int attempt;
+  int use_client_credentials = 0;
   
   char k5user[MAXNAMELEN];
   char *k5secret;
+  char *k5path = NULL;
   
+  k5path = !r ? NULL : MK_TABLE_GET( r->subprocess_env, "KRB5CCNAME" );
+
   memset((char *) &increds, 0, sizeof(increds));
-  
   /* init some stuff if it ain't already */
   
   if ( ! child.kcontext ) {
     kerror = krb5_init_context(&child.kcontext);
   }
   
-  if ( ( ! child.ccache ) && ( kerror = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
-    log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", kerror );
+  if (!k5path || !*k5path) {
+    k5path = "MEMORY:tmpcache";
+  }
+  if ( ( ! child.ccache ) && ( kerror = krb5_cc_resolve(child.kcontext, k5path, &child.ccache) ) ) {
+    log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize credentials cache %s err=%d",
+              k5path, kerror );
   }
   
-  
-  log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: %d, %s, %s, %d", self, principal ? principal : "NULL", 
-    keytab ? keytab : "NULL", storeonly);
+  log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: %d, %s, %s, %d, KRB5CC=%s user=%s",
+            self, principal ? principal : "NULL", 
+            keytab ? keytab : "NULL",
+            storeonly,
+            k5path ? k5path : "NULL",
+#ifdef APACHE2
+            (r && r->user) ? r->user : "NULL"
+#else
+            "NULL"
+#endif
+            );
   
   /* pull the server config record that we care about... */
   
@@ -287,7 +289,7 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
     cfg = retrieve_config(r);
   } else {
     log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
-                "mod_waklog: set_auth using no config" );
+                 "mod_waklog: set_auth using no config" );
      getModConfig (cfg, s);
   }
   
@@ -295,7 +297,7 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
     log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: cfg is %d", cfg );
   }
   
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
   if ( self ) {
     /* pull out our principal name and stuff from the environment -- webauth better have sent
        through.  This here is also where you'd suck stuff out of KRB5CCNAME if we were
@@ -303,6 +305,7 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
        
        if ( ! ( r && r->connection && r->user )) {
          log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: self authentication selected, but no data available");
+         log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: r->user=%s", (r->user==NULL ? "null" : r->user==NULL));
          return -1;
        }
        
@@ -317,11 +320,16 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
        /* we'll pick this up later after we've checked the cache and current state */
              
   } else
+  if (r && r->user && !principal) {
+    strncpy(k5user, r->user, sizeof(k5user));
+    keytab = NULL;
+  } else
 #endif
 if ( principal ) {
+ if ( principal ) {
     strncpy( k5user, principal, sizeof(k5user));
   }
   
+  log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: k5user=%s", k5user ? k5user : "NULL");
   mytime = time(0);
   
   /* see if we should just go ahead and ignore this call, since we already should be set to these
@@ -390,9 +398,8 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
     }
   
   }
-  
+
   /* if 'usecached' isn't set, we've got to get our tokens from somewhere... */
-  
   if (( ! usecached ) && ( k5user )) {
 
     /* clear out the creds structure */
@@ -452,27 +459,23 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
       memset(k5secret, 0, sizeof(k5secret));      
       
     } else {
-      
-      /* degenerate case -- we don't have enough information to do anything */
-      
-      log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: no keytab, no self?");
-      kerror = -1;
-      goto cleanup;
-      
+      log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: no keytab, no self; assuming mod_auth_kerb or similar");
+      use_client_credentials = 1;
     } 
     
       /* initialize the credentials cache and store the stuff we just got */
+    if (!use_client_credentials) {
+      if ( kerror = krb5_cc_initialize (child.kcontext, child.ccache, kprinc)) {
+        log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: init credentials cache %s", 
+                  error_message(kerror));
+        goto cleanup;
+      }
       
-    if ( kerror = krb5_cc_initialize (child.kcontext, child.ccache, kprinc)) {
-      log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: init credentials cache %s", 
-      error_message(kerror));
-      goto cleanup;
-    }
-  
-    if ( kerror = krb5_cc_store_cred(child.kcontext, child.ccache, &v5creds) ) {
-       log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot store credentials %s", 
-       error_message(kerror));
-       goto cleanup;
+      if ( kerror = krb5_cc_store_cred(child.kcontext, child.ccache, &v5creds) ) {
+        log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot store credentials %s", 
+                  error_message(kerror));
+        goto cleanup;
+      }
     }
     
     krb5_free_cred_contents(child.kcontext, &v5creds);
@@ -486,40 +489,60 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
   
     /* now, to the 'aklog' portion of our program. */
     
-    strncpy( buf, "afs", sizeof(buf) - 1 );
-    
-    if ( cfg->afs_cell && strcmp( cfg->afs_cell, AFS_CELL ) ) {
-      strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
-      strncat(buf, cfg->afs_cell, sizeof(buf) - strlen(buf) - 1);
-    } else if ( cell_in_principal ) {
-      strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
-      strncat(buf, AFS_CELL, sizeof(buf) - strlen(buf) - 1);
-    }
+    /** we make two attempts here, one for afs@REALM and one for afs/cell@REALM */
+    for(attempt = 0; attempt <= 1; attempt++) {
+      strncpy( buf, "afs", sizeof(buf) - 1 );
+      cell_in_principal = (cfg->cell_in_principal + attempt) % 2;
+
+      log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: cell_in_principal=%d", cell_in_principal );
+      if (cell_in_principal) {
+        strncat(buf, "/",           sizeof(buf) - strlen(buf) - 1);
+        strncat(buf, cfg->afs_cell, sizeof(buf) - strlen(buf) - 1);
+      }
+      if (cfg->afs_cell_realm != WAKLOG_UNSET) {
+        strncat(buf, "@",                 sizeof(buf) - strlen(buf) - 1);
+        strncat(buf, cfg->afs_cell_realm, sizeof(buf) - strlen(buf) - 1);
+      }
+      
+      log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using AFS principal: %s", buf);
+      
+      if ((kerror = krb5_parse_name (child.kcontext, buf, &increds.server))) {
+        log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse name %s", error_message(kerror));
+        goto cleanup;
+      }
 
-    log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using AFS principal: %s", buf);
-    
-    if ((kerror = krb5_parse_name (child.kcontext, buf, &increds.server))) {
-      log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse name %s", error_message(kerror));
-      goto cleanup;
-    }
-  
-    if ((kerror = krb5_cc_get_principal(child.kcontext, child.ccache, &increds.client))) {
-      log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_get_princ %s", error_message(kerror));
-      goto cleanup;
-    }
-    
-    log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: retrieved data from ccache for %s", k5user);
-    
-    increds.times.endtime = 0;
-    
-    increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-    
-    if (kerror = krb5_get_credentials (child.kcontext, 0, child.ccache, &increds, &v5credsp )) {
-      log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
-      error_message(kerror));
-      goto cleanup;
+      if (use_client_credentials) {
+        if (( kerror = krb5_cc_resolve( child.kcontext, k5path, &child.ccache)) != 0 ) {
+          log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_resolve %s", error_message(kerror));          
+          goto cleanup;
+        }
+      } 
+      
+      if ((kerror = krb5_cc_get_principal(child.kcontext, child.ccache, &increds.client))) {
+        log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_get_princ %s", error_message(kerror));
+        goto cleanup;
+      }
+      
+      log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: retrieved data from ccache for %s", k5user);
+      
+      increds.times.endtime = 0;
+      
+      increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+      
+      if (kerror = krb5_get_credentials (child.kcontext, 0, child.ccache, &increds, &v5credsp )) {
+        /* only complain once we've tried both afs@REALM and afs/cell@REALM */
+        if (attempt>=1) {
+          log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
+                    error_message(kerror));
+          goto cleanup;
+        } else {
+          continue;
+        }
+      }
+      cfg->cell_in_principal = cell_in_principal;
+      break;
     }
-    
+
     log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: get_credentials passed for %s", k5user);
     
     if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) {
@@ -561,11 +584,7 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
     strncpy(client.cell, buf, sizeof(client.cell));
     
     /* assemble the server's cell */
-    if ( cfg->afs_cell ) {
-      strncpy(server.cell, cfg->afs_cell, sizeof(server.cell) - 1);
-    } else {
-      strncpy(server.cell, AFS_CELL, sizeof(server.cell) - 1);
-    }
+    strncpy(server.cell, cfg->afs_cell, sizeof(server.cell) - 1);
     
     log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: preparing to init PTS connection for %s", server.cell);
     
@@ -717,16 +736,18 @@ waklog_create_server_config (MK_POOL * p, server_rec * s)
   cfg->path = "(server)";
   cfg->protect = WAKLOG_UNSET;
   cfg->usertokens = WAKLOG_UNSET;
+  cfg->disable_token_cache = WAKLOG_UNSET;
   cfg->keytab = WAKLOG_UNSET;
   cfg->principal = WAKLOG_UNSET;
   cfg->default_principal = WAKLOG_UNSET;
   cfg->default_keytab = WAKLOG_UNSET;
   cfg->afs_cell = WAKLOG_UNSET;
+  cfg->afs_cell_realm = WAKLOG_UNSET;
   cfg->forked = 0;
   cfg->configured = 0;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
-            "mod_waklog: server config created.");
+             "mod_waklog: server config created.");
 
   return (cfg);
 }
@@ -744,11 +765,13 @@ waklog_create_dir_config (MK_POOL * p, char *dir)
   cfg->path = ap_pstrdup(p, dir );
   cfg->protect = WAKLOG_UNSET;
   cfg->usertokens = WAKLOG_UNSET;
+  cfg->disable_token_cache = WAKLOG_UNSET;
   cfg->keytab = WAKLOG_UNSET;
   cfg->principal = WAKLOG_UNSET;
   cfg->default_principal = WAKLOG_UNSET;
   cfg->default_keytab = WAKLOG_UNSET;
   cfg->afs_cell = WAKLOG_UNSET;
+  cfg->afs_cell_realm = WAKLOG_UNSET;
   cfg->forked = 0;
   cfg->configured = 0;
 
@@ -766,6 +789,8 @@ static void *waklog_merge_dir_config(MK_POOL *p, void *parent_conf, void *newloc
   merged->path = child->path != WAKLOG_UNSET ? child->path : parent->path;
   
   merged->usertokens = child->usertokens != WAKLOG_UNSET ? child->usertokens : parent->usertokens;
+
+  merged->disable_token_cache = child->disable_token_cache != WAKLOG_UNSET ? child->disable_token_cache : parent->disable_token_cache;
   
   merged->principal = child->principal != WAKLOG_UNSET ? child->principal : parent->principal;
   
@@ -776,6 +801,8 @@ static void *waklog_merge_dir_config(MK_POOL *p, void *parent_conf, void *newloc
   merged->default_principal = child->default_principal != WAKLOG_UNSET ? child->default_principal : parent->default_principal;
   
   merged->afs_cell = child->afs_cell != WAKLOG_UNSET ? child->afs_cell : parent->afs_cell;
+
+  merged->afs_cell_realm = child->afs_cell_realm != WAKLOG_UNSET ? child->afs_cell_realm : parent->afs_cell_realm;
   
   return (void *) merged;
   
@@ -791,6 +818,8 @@ static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *new
 
   merged->usertokens = nconf->usertokens == WAKLOG_UNSET ? pconf->usertokens : nconf->usertokens;
 
+  merged->disable_token_cache = nconf->disable_token_cache == WAKLOG_UNSET ? pconf->disable_token_cache : nconf->disable_token_cache;
+
   merged->keytab = nconf->keytab ==  WAKLOG_UNSET ? ap_pstrdup(p, pconf->keytab) : 
     ( nconf->keytab == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->keytab) );
     
@@ -800,6 +829,9 @@ static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *new
   merged->afs_cell = nconf->afs_cell  == WAKLOG_UNSET ? ap_pstrdup(p, pconf->afs_cell) : 
       ( nconf->afs_cell == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->afs_cell) );    
   
+  merged->afs_cell_realm = nconf->afs_cell_realm  == WAKLOG_UNSET ? ap_pstrdup(p, pconf->afs_cell_realm) : 
+      ( nconf->afs_cell_realm == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->afs_cell_realm) );    
+  
   merged->default_keytab = nconf->default_keytab ==  WAKLOG_UNSET ? ap_pstrdup(p, pconf->default_keytab) : 
         ( nconf->default_keytab == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->default_keytab) );
 
@@ -812,7 +844,7 @@ static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *new
 }
                                                                                           
 static const char *
-set_waklog_protect (cmd_parms * params, void *mconfig, int flag)
+set_waklog_enabled (cmd_parms * params, void *mconfig, int flag)
 {
   waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig : 
     ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
@@ -820,7 +852,7 @@ set_waklog_protect (cmd_parms * params, void *mconfig, int flag)
   cfg->protect = flag;
   cfg->configured = 1;
   log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
-            "mod_waklog: waklog_protect set on %s", cfg->path ? cfg->path : "NULL");
+             "mod_waklog: waklog_enabled set on %s", cfg->path ? cfg->path : "NULL");
   return (NULL);
 }
 
@@ -854,15 +886,15 @@ void add_to_renewtable(MK_POOL *p, char *keytab, char *principal) {
 }
 
 static const char *
-set_waklog_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
+set_waklog_location_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
 {
   waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig : 
     ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
-            "mod_waklog: configuring principal: %s, keytab: %s", principal, keytab);
-               
-       cfg->principal = ap_pstrdup(params->pool, principal);
+             "mod_waklog: configuring principal: %s, keytab: %s", principal, keytab);
+                
+        cfg->principal = ap_pstrdup(params->pool, principal);
   cfg->keytab = ap_pstrdup (params->pool, keytab);
   
   add_to_renewtable(params->pool, keytab, principal);
@@ -873,16 +905,42 @@ set_waklog_principal (cmd_parms *params, void *mconfig, char *principal, char *k
 }
 
 static const char *
-set_waklog_use_afs_cell (cmd_parms * params, void *mconfig, char *file)
+set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
 {
-  waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig : 
+  waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
+  waklog_config *waklog_srvconfig =
     ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
 
-  log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
-            "mod_waklog: will use afs_cell: %s", file);
+  log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
+             "mod_waklog: will use afs_cell: %s", file);
 
-  cfg->afs_cell = ap_pstrdup (params->pool, file);
-  cfg->configured = 1;
+  waklog_srvconfig->cell_in_principal = 0;
+  waklog_srvconfig->afs_cell = ap_pstrdup (params->pool, file);
+  waklog_srvconfig->configured = 1;
+
+  if (waklog_mconfig != NULL) {
+    waklog_mconfig->cell_in_principal = waklog_srvconfig->cell_in_principal;
+    waklog_mconfig->afs_cell = ap_pstrdup (params->pool, file);
+    waklog_mconfig->configured = 1;
+  }
+  return (NULL);
+}
+
+static const char *
+set_waklog_afs_cell_realm (cmd_parms * params, void *mconfig, char *file)
+{
+  waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
+  waklog_config *waklog_srvconfig =
+    ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
+
+  log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
+             "mod_waklog: will use afs_cell_realm: %s", file);
+
+  waklog_srvconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
+
+  if (waklog_mconfig != NULL) {
+    waklog_mconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
+  }
   return (NULL);
 }
 
@@ -895,7 +953,7 @@ set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal
   waklog_config *srvcfg = ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
-            "mod_waklog: set default princ/keytab: %s, %s for %s", principal, keytab, cfg->path ? cfg->path : "NULL");
+             "mod_waklog: set default princ/keytab: %s, %s for %s", principal, keytab, cfg->path ? cfg->path : "NULL");
 
   cfg->default_principal = ap_pstrdup (params->pool, principal);
   cfg->default_keytab = ap_pstrdup(params->pool, keytab );
@@ -927,12 +985,28 @@ set_waklog_use_usertokens (cmd_parms * params, void *mconfig, int flag)
   cfg->configured = 1;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
-            "mod_waklog: waklog_use_user_tokens set");
+             "mod_waklog: waklog_use_user_tokens set");
+  return (NULL);
+}
+
+
+static const char *
+set_waklog_disable_token_cache (cmd_parms * params, void *mconfig, int flag)
+{
+  waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig : 
+    ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
+
+  cfg->disable_token_cache = flag;
+
+  cfg->configured = 1;
+
+  log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
+             "mod_waklog: waklog_disable_token_cache set");
   return (NULL);
 }
 
 
-#ifndef STANDARD20_MODULE_STUFF
+#ifndef APACHE2
 static void waklog_child_exit( server_rec *s, MK_POOL *p ) {
 #else
 apr_status_t waklog_child_exit( void *sr ) {
@@ -953,16 +1027,16 @@ apr_status_t waklog_child_exit( void *sr ) {
   ktc_ForgetAllTokens ();
   
   log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
-            "mod_waklog: waklog_child_exit complete");
+             "mod_waklog: waklog_child_exit complete");
 
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
   return APR_SUCCESS;
 #endif
   
 }
 
 static void
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
 waklog_child_init (MK_POOL * p, server_rec * s)
 #else
 waklog_child_init (server_rec * s, MK_POOL * p)
@@ -974,8 +1048,6 @@ waklog_child_init (server_rec * s, MK_POOL * p)
   
   char *cell;
   
-  cell = strdup(AFS_CELL);
-  
   log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
   
   if ( !sharedspace ) {
@@ -1006,35 +1078,42 @@ waklog_child_init (server_rec * s, MK_POOL * p)
     set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
   }
 
+  cell = strdup(cfg->afs_cell);
   pr_Initialize(  0, AFSDIR_CLIENT_ETC_DIR, cell );
 
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
   apr_pool_cleanup_register(p, s, waklog_child_exit, apr_pool_cleanup_null);
 #endif
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
-            "mod_waklog: child_init returned");
+             "mod_waklog: child_init returned");
 
   return;
 }
 
 command_rec waklog_cmds[] = {
   
-  command ("WaklogProtected", set_waklog_protect, 0, FLAG,
-          "enable waklog on a location or directory basis"),
+  command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
+           "Use the supplied AFS cell (required)"),
 
-  command ("WaklogPrincipal", set_waklog_principal, 0, TAKE2,
-          "Use the supplied keytab rather than the default"),
+  command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm, 0, TAKE1,
+           "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
 
-  command ("WaklogUseAFSCell", set_waklog_use_afs_cell, 0, TAKE1,
-          "Use the supplied AFS cell rather than the default"),
-
-  command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
-      "Use the requesting user tokens (from webauth)"),
+  command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
+           "enable waklog on a server, location, or directory basis"),
 
   command ("WaklogDefaultPrincipal", set_waklog_default_principal, 0, TAKE2,
-      "Set the default principal that the server runs as"),
-    
+           "Set the default principal that the server runs as"),
+
+  command ("WaklogLocationPrincipal", set_waklog_location_principal, 0, TAKE2,
+           "Set the principal on a <Location>-specific basis"),
+
+  command ("WaklogDisableTokenCache", set_waklog_disable_token_cache, 0, FLAG,
+           "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
+  
+  command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
+           "Use the requesting user tokens (from webauth)"),
+   
   {NULL}
 };
 
@@ -1053,8 +1132,8 @@ token_cleanup (void *data)
       ktc_ForgetAllTokens ();
 
       log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-                "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
-                getpid ());
+                 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
+                 getpid ());
     }
   return 0;
 }
@@ -1086,7 +1165,7 @@ waklog_child_routine (void *data, child_info * pinfo)
   }
   
   /* need to do this so we can make PTS calls */
-  cell = strdup(AFS_CELL); /* stupid */
+  cell = strdup(cfg->afs_cell); /* stupid */
   pr_Initialize(  0, AFSDIR_CLIENT_ETC_DIR, cell );
   
   while(1) {
@@ -1126,10 +1205,10 @@ waklog_child_routine (void *data, child_info * pinfo)
 
 }
 
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
 static int
 waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
-                    apr_pool_t * ptemp, server_rec * s)
+                     apr_pool_t * ptemp, server_rec * s)
 {
   int rv;
   extern char *version;
@@ -1153,15 +1232,23 @@ waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
    * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
   apr_pool_userdata_get (&data, userdata_key, s->process->pool);
 
+
+  if (cfg->afs_cell==NULL) {
+      log_error (APLOG_MARK, APLOG_ERR, 0, s,
+                 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
+      /** clobber apache */
+      exit(-1);
+  }
+
   if (!data)
     {
       apr_pool_userdata_set ((const void *) 1, userdata_key,
-                            apr_pool_cleanup_null, s->process->pool);
+                             apr_pool_cleanup_null, s->process->pool);
     }
   else
     {
       log_error (APLOG_MARK, APLOG_INFO, 0, s,
-                "mod_waklog: version %s initialized.", version);
+                 "mod_waklog: version %s initialized for cell %s", version, cfg->afs_cell);
 
       if ( sharedspace ) {
         log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
@@ -1234,13 +1321,13 @@ waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
       rv = apr_proc_fork (proc, s->process->pool);
 
       if (rv == APR_INCHILD)
-       {
-         waklog_child_routine (s, NULL);
-       }
+        {
+          waklog_child_routine (s, NULL);
+        }
       else
-       {
-         apr_pool_note_subprocess (s->process->pool, proc, APR_KILL_ALWAYS);
-       }
+        {
+          apr_pool_note_subprocess (s->process->pool, proc, APR_KILL_ALWAYS);
+        }
       /* parent and child */
       cfg->forked = proc->pid;
       pag_for_children = 1;
@@ -1276,7 +1363,7 @@ waklog_init (server_rec * s, MK_POOL * p)
 #endif
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
-            "mod_waklog: version %s initialized.", version);
+             "mod_waklog: version %s initialized.", version);
 
   if ( sharedspace ) {
     log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
@@ -1343,18 +1430,18 @@ waklog_init (server_rec * s, MK_POOL * p)
   /* set our default tokens */
   
   getModConfig (cfg, s);
-               
-       oldrenewcount = sharedspace->renewcount;
-               
-       pag_for_children = 0;
-               
-       pid = ap_bspawn_child (p, waklog_child_routine, s, kill_always,
-                        NULL, NULL, NULL);                     
-       
-       pag_for_children = 1;
-       
+                
+        oldrenewcount = sharedspace->renewcount;
+                
+        pag_for_children = 0;
+                
+        pid = ap_bspawn_child (p, waklog_child_routine, s, kill_always,
+                         NULL, NULL, NULL);                     
+        
+        pag_for_children = 1;
+        
   log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
-            "mod_waklog: ap_bspawn_child: %d.", pid);
+             "mod_waklog: ap_bspawn_child: %d.", pid);
   
   if ( use_existing == 0 ) {
     /* wait here until our child process has gone and done it's renewing thing. */
@@ -1377,7 +1464,7 @@ waklog_phase0 (request_rec * r)
   waklog_config *cfg;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase0 called");
+             "mod_waklog: phase0 called");
 
   cfg = retrieve_config(r);
 
@@ -1400,7 +1487,7 @@ waklog_phase1 (request_rec * r)
   waklog_config *cfg;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase1 called");
+             "mod_waklog: phase1 called");
 
   cfg = retrieve_config(r);
 
@@ -1423,7 +1510,7 @@ waklog_phase3 (request_rec * r)
   waklog_config *cfg;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase 3 called");
+             "mod_waklog: phase 3 called");
 
   cfg = retrieve_config(r);
   
@@ -1446,7 +1533,7 @@ waklog_phase6 (request_rec * r)
   waklog_config *cfg;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase6 called");
+             "mod_waklog: phase6 called");
 
   cfg = retrieve_config(r);
   
@@ -1470,7 +1557,7 @@ waklog_phase7 (request_rec * r)
   int rc = 0;
   
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase7 called");
+             "mod_waklog: phase7 called");
 
   cfg = retrieve_config (r);
 
@@ -1483,6 +1570,9 @@ waklog_phase7 (request_rec * r)
   } else if ( cfg->default_principal ) {
     log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using default user %s", cfg->default_principal);
     rc = set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
+  } else {
+    log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using no default principal");
+    set_auth(r->server, r, 0, NULL, NULL, 0);
   }
   
   if ( rc ) {
@@ -1498,7 +1588,7 @@ waklog_phase9 (request_rec * r)
   waklog_config *cfg;
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase9 called");
+             "mod_waklog: phase9 called");
 
   getModConfig (cfg, r->server);
   
@@ -1512,14 +1602,14 @@ waklog_phase9 (request_rec * r)
 
 
 static
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
   int
 #else
   void
 #endif
 waklog_new_connection (conn_rec * c
-#ifdef STANDARD20_MODULE_STUFF
-                      , void *dummy
+#ifdef APACHE2
+                       , void *dummy
 #endif
   )
 {
@@ -1527,19 +1617,19 @@ waklog_new_connection (conn_rec * c
   waklog_config *cfg;
   
   log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
-            "mod_waklog: new_connection called: pid: %d", getpid ());
-       
-       getModConfig(cfg, c->base_server);
-       
-       if ( cfg->default_principal ) {
-         log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
-         cfg->default_principal);
-         set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
-       }     
-            
-            
+             "mod_waklog: new_connection called: pid: %d", getpid ());
+        
+        getModConfig(cfg, c->base_server);
+        
+        if ( cfg->default_principal ) {
+          log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
+          cfg->default_principal);
+          set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
+        }     
+             
+             
   return
-#ifdef STANDARD20_MODULE_STUFF
+#ifdef APACHE2
     0
 #endif
     ;
@@ -1560,7 +1650,7 @@ waklog_phase2 (request_rec * r)
 {
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase2 called");
+             "mod_waklog: phase2 called");
 
   if (child.token.ticketLen)
     {
@@ -1569,42 +1659,42 @@ waklog_phase2 (request_rec * r)
       ktc_ForgetAllTokens ();
 
       log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-                "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
-                getpid ());
+                 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
+                 getpid ());
     }
 
   log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
-            "mod_waklog: phase2 returning");
+             "mod_waklog: phase2 returning");
 
   return DECLINED;
 }
 
-#ifndef STANDARD20_MODULE_STUFF
+#ifndef APACHE2
 module MODULE_VAR_EXPORT waklog_module = {
   STANDARD_MODULE_STUFF,
-  waklog_init,                               /* module initializer                  */
-  waklog_create_dir_config,          /* create per-dir    config structures */
-  waklog_merge_dir_config,                                               /* merge  per-dir    config structures */
-  waklog_create_server_config,   /* create per-server config structures */
-  waklog_merge_dir_config,                                           /* merge  per-server config structures */
-  waklog_cmds,                               /* table of config file commands       */
-  NULL,                                                    /* [#8] MIME-typed-dispatched handlers */
-  waklog_phase1,                                         /* [#1] URI to filename translation    */
-  NULL,                                                    /* [#4] validate user id from request  */
-  NULL,                                                    /* [#5] check if the user is ok _here_ */
-  waklog_phase3,                                         /* [#3] check access by host address   */
-  waklog_phase6,                                         /* [#6] determine MIME type            */
-  waklog_phase7,                       /* [#7] pre-run fixups                 */
-  waklog_phase9,                                   /* [#9] log a transaction              */
-  NULL,                                        /* [#2] header parser                  */
-  waklog_child_init,                   /* child_init                          */
-  waklog_child_exit,                           /* child_exit                          */
-  waklog_phase0                                      /* [#0] post read-request              */
+  waklog_init,                        /* module initializer                  */
+  waklog_create_dir_config,           /* create per-dir    config structures */
+  waklog_merge_dir_config,            /* merge  per-dir    config structures */
+  waklog_create_server_config,        /* create per-server config structures */
+  waklog_merge_dir_config,            /* merge  per-server config structures */
+  waklog_cmds,                        /* table of config file commands       */
+  NULL,                               /* [#8] MIME-typed-dispatched handlers */
+  waklog_phase1,                      /* [#1] URI to filename translation    */
+  NULL,                               /* [#4] validate user id from request  */
+  NULL,                               /* [#5] check if the user is ok _here_ */
+  waklog_phase3,                      /* [#3] check access by host address   */
+  waklog_phase6,                      /* [#6] determine MIME type            */
+  waklog_phase7,                      /* [#7] pre-run fixups                 */
+  waklog_phase9,                      /* [#9] log a transaction              */
+  NULL,                               /* [#2] header parser                  */
+  waklog_child_init,                  /* child_init                          */
+  waklog_child_exit,                  /* child_exit                          */
+  waklog_phase0                       /* [#0] post read-request              */
 #ifdef EAPI
-    , NULL,                              /* EAPI: add_module                    */
-  NULL,                                            /* EAPI: remove_module                 */
-  NULL,                                            /* EAPI: rewrite_command               */
-  waklog_new_connection                /* EAPI: new_connection                */
+    , NULL,                           /* EAPI: add_module                    */
+  NULL,                               /* EAPI: remove_module                 */
+  NULL,                               /* EAPI: rewrite_command               */
+  waklog_new_connection               /* EAPI: new_connection                */
 #endif
 };
 #else
@@ -1626,11 +1716,11 @@ waklog_register_hooks (apr_pool_t * p)
 
 module AP_MODULE_DECLARE_DATA waklog_module = {
   STANDARD20_MODULE_STUFF,
-  waklog_create_dir_config,    /* create per-dir    conf structures  */
-  waklog_merge_dir_config,     /* merge  per-dir    conf structures  */
-  waklog_create_server_config, /* create per-server conf structures  */
-  waklog_merge_dir_config,     /* merge  per-server conf structures  */
-  waklog_cmds,                 /* table of configuration directives  */
-  waklog_register_hooks                /* register hooks                     */
+  waklog_create_dir_config,     /* create per-dir    conf structures  */
+  waklog_merge_dir_config,      /* merge  per-dir    conf structures  */
+  waklog_create_server_config,  /* create per-server conf structures  */
+  waklog_merge_dir_config,      /* merge  per-server conf structures  */
+  waklog_cmds,                  /* table of configuration directives  */
+  waklog_register_hooks         /* register hooks                     */
 };
 #endif