swap order of AFS_LIBS and KRB5_LIBS to get the correct libcom_err.a
[hcoop/zz_old/modwaklog.git] / mod_waklog.c
index 70b202f..62aef1c 100644 (file)
@@ -106,6 +106,7 @@ typedef struct
   char *default_principal;
   char *default_keytab;
   char *afs_cell;
+  char *afs_cell_realm;
   char *path;
   MK_POOL *p;
 }
@@ -247,25 +248,40 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
   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... */
   
@@ -289,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;
        }
        
@@ -303,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
@@ -376,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 */
@@ -438,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);
@@ -472,17 +489,20 @@ 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 );
-
     /** 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, "/",           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);
       
@@ -490,6 +510,13 @@ set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keyta
         log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse name %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));
@@ -715,6 +742,7 @@ waklog_create_server_config (MK_POOL * p, server_rec * s)
   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;
 
@@ -743,6 +771,7 @@ waklog_create_dir_config (MK_POOL * p, char *dir)
   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;
 
@@ -772,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;
   
@@ -787,7 +818,7 @@ 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->udisable_token_cache : nconf->disable_token_cache;
+  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) );
@@ -798,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) );
 
@@ -892,6 +926,24 @@ set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
   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);
+}
+
 static const char *
 set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal, char *keytab)
 {
@@ -1044,6 +1096,9 @@ command_rec waklog_cmds[] = {
   command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
            "Use the supplied AFS cell (required)"),
 
+  command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm, 0, TAKE1,
+           "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
+
   command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
            "enable waklog on a server, location, or directory basis"),
 
@@ -1515,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 ) {