"Hard-coded paths made more generic. These will soon be configurable with configure...
[hcoop/zz_old/modwaklog.git] / mod_waklog.c
index 820a178..65fb9fa 100644 (file)
@@ -16,8 +16,8 @@
 #include <afs/auth.h>
 #include <rx/rxkad.h>
 
-#define KEYTAB                 "/home/drh/keytab.itdwww"
-#define KEYTAB_PRINCIPAL       "itdwww"
+#define KEYTAB                 "/path/to/keytab.www"
+#define KEYTAB_PRINCIPAL       "principalwww"
 
 #define TKT_LIFE       10*60*60
 #define        SLEEP_TIME      TKT_LIFE - 5*60
@@ -221,7 +221,7 @@ token_cleanup( void *data )
 
        ktc_ForgetAllTokens();
 
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
            "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() );
     }
     return;
@@ -242,7 +242,7 @@ waklog_kinit( server_rec *s )
     waklog_host_config         *cfg;
     int                                i;
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: waklog_kinit called: pid: %d", getpid() );
 
     cfg = (waklog_host_config *) ap_get_module_config( s->module_config,
@@ -263,7 +263,7 @@ waklog_kinit( server_rec *s )
        goto cleanup;
     }
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: keytab_principal: %s", cfg->keytab_principal );
 
     if (( kerror = krb5_parse_name( kcontext, cfg->keytab_principal, &kprinc ))) {
@@ -274,13 +274,13 @@ waklog_kinit( server_rec *s )
     }
 
 #if 0
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: kprinc->realm: %.*s", kprinc->realm.length, kprinc->realm.data );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: kprinc->length: %d", kprinc->length );
     for ( i = 0; i < kprinc->length; i++ ) {
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
                "mod_waklog: kprinc->data[%d].data: %.*s", i, kprinc->data[i].length, kprinc->data[i].data );
     }
 #endif /* 0 */
@@ -294,7 +294,7 @@ waklog_kinit( server_rec *s )
     /* keytab from config */
     strncpy( ktbuf, cfg->keytab, sizeof( ktbuf ) - 1 );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
            "mod_waklog: waklog_kinit using: %s", ktbuf );
 
     if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) {
@@ -317,32 +317,32 @@ waklog_kinit( server_rec *s )
     }
 
 #if 0
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: v5creds.client->realm: %.*s", v5creds.client->realm.length, v5creds.client->realm.data );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
            "mod_waklog: v5creds.client->length: %d", v5creds.client->length );
     for ( i = 0; i < v5creds.client->length; i++ ) {
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
                "mod_waklog: v5creds.client->data[%d].data: %.*s",
                i, v5creds.client->data[i].length, v5creds.client->data[i].data );
     }
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: v5creds.server->realm: %.*s", v5creds.server->realm.length, v5creds.server->realm.data );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: v5creds.server->length: %d", v5creds.server->length );
     for ( i = 0; i < v5creds.server->length; i++ ) {
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
                "mod_waklog: v5creds.server->data[%d].data: %.*s",
                i, v5creds.server->data[i].length, v5creds.server->data[i].data );
     }
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: waklog_kinit #4" );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
            "mod_waklog: waklog_kinit kprinc==v5creds.server: %s", 
            krb5_principal_compare( kcontext, kprinc, v5creds.server ) ? "true" : "false" );
 #endif /* 0 */
@@ -375,7 +375,7 @@ waklog_kinit( server_rec *s )
        goto cleanup;
     }
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: waklog_kinit success" );
 
 cleanup:
@@ -388,7 +388,7 @@ cleanup:
     if ( kcontext )
        krb5_free_context( kcontext );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s,
        "mod_waklog: waklog_kinit: exiting" );
 
     return( 0 );
@@ -399,7 +399,7 @@ cleanup:
 waklog_aklog( request_rec *r )
 {
     int                                rc;
-    char                       buf[ 2048 ];
+    char                       buf[ MAXKTCTICKETLEN ];
     const char                 *k4path = NULL;
     const char                 *k5path = NULL;
     krb5_error_code            kerror;
@@ -416,11 +416,11 @@ waklog_aklog( request_rec *r )
     k5path = ap_table_get( r->subprocess_env, "KRB5CCNAME" );
     k4path = ap_table_get( r->subprocess_env, "KRBTKFILE" );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
        "mod_waklog: waklog_aklog called: k5path: %s, k4path: %s", k5path, k4path );
 
-    if ( !k5path || !k4path ) {   
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    if ( !k5path || !k4path || !*k5path || !*k4path ) {
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
                "mod_waklog: waklog_aklog giving up" );
        goto cleanup;
     }
@@ -479,10 +479,10 @@ waklog_aklog( request_rec *r )
        goto cleanup;
     }
 
-    /* don't overflor */
-    if ( v5credsp->ticket.length >= 344 ) {    /* from krb524d.c */
+    /* don't overflow */
+    if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) {        /* from krb524d.c */
        ap_log_error( APLOG_MARK, APLOG_ERR, r->server,
-           "mod_waklog: ticket size (%d) to big to fake", v5credsp->ticket.length );
+           "mod_waklog: ticket size (%d) too big to fake", v5credsp->ticket.length );
        goto cleanup;
     }
 
@@ -503,34 +503,37 @@ waklog_aklog( request_rec *r )
                    sizeof( token.sessionKey ) )) ||
            (memcmp( child.token.ticket, token.ticket, token.ticketLen )) ) {
 
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
                "mod_waklog: client: %s", buf );
 
        /* build the name */
-       memmove( buf, v5credsp->client->data[0].data, v5credsp->client->data[0].length );
+       memmove( buf, v5credsp->client->data[0].data,
+               min( v5credsp->client->data[0].length, MAXKTCNAMELEN - 1 ) );
        buf[ v5credsp->client->data[0].length ] = '\0';
        if ( v5credsp->client->length > 1 ) {
                strncat( buf, ".", sizeof( buf ) - strlen( buf ) - 1 );
                buflen = strlen( buf );
-               memmove( buf + buflen, v5credsp->client->data[1].data, v5credsp->client->data[1].length );
+               memmove( buf + buflen, v5credsp->client->data[1].data,
+                       min( v5credsp->client->data[1].length, MAXKTCNAMELEN - strlen( buf ) - 1 ) );
                buf[ buflen + v5credsp->client->data[1].length ] = '\0';
        }
 
        /* assemble the client */
        strncpy( client.name, buf,              sizeof( client.name ) - 1 );
        strncpy( client.instance, "",           sizeof( client.instance) - 1 );
-       memmove( buf, v5credsp->client->realm.data, v5credsp->client->realm.length );
+       memmove( buf, v5credsp->client->realm.data, 
+               min( v5credsp->client->realm.length, MAXKTCNAMELEN - 1 ) );
        buf[ v5credsp->client->realm.length ] = '\0';
        strncpy( client.cell, buf,              sizeof( client.cell ) - 1 );
 
        /* assemble the server's cell */
        strncpy( server.cell, cfg->afs_cell ,   sizeof( server.cell ) - 1 );
 
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
                "mod_waklog: server: name=%s, instance=%s, cell=%s",
                server.name, server.instance, server.cell );
 
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
                "mod_waklog: client: name=%s, instance=%s, cell=%s",
                 client.name, client.instance, client.cell );
 
@@ -565,7 +568,7 @@ cleanup:
     if ( kcontext )
        krb5_free_context( kcontext );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
                "mod_waklog: finished with waklog_aklog" );
 
     return;
@@ -576,7 +579,7 @@ cleanup:
 waklog_child_routine( void *s, child_info *pinfo )
 {
     if ( !getuid() ) {
-       ap_log_error( APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s,
+       ap_log_error( APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, s,
                "mod_waklog: waklog_child_routine called as root" );
 
        /* this was causing the credential file to get owned by root */
@@ -604,7 +607,7 @@ waklog_init( server_rec *s, pool *p )
     pid = ap_bspawn_child( p, waklog_child_routine, s, kill_always,
            NULL, NULL, NULL );
 
-    ap_log_error( APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s,
+    ap_log_error( APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, s,
            "mod_waklog: ap_bspawn_child: %d.", pid );
 }
 
@@ -614,7 +617,7 @@ waklog_phase0( request_rec *r )
 {
     waklog_host_config  *cfg;
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
        "mod_waklog: phase0 called" );
 
 #if 0
@@ -633,7 +636,7 @@ waklog_phase0( request_rec *r )
 #endif /* 0 */
 
     if ( !cfg->protect ) {
-       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
            "mod_waklog: phase0 declining" );
         return( DECLINED );
     }
@@ -649,7 +652,7 @@ waklog_phase0( request_rec *r )
        waklog_aklog( r );
     }
     
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
        "mod_waklog: phase0 returning" );
     return DECLINED;
 }
@@ -660,7 +663,7 @@ waklog_phase7( request_rec *r )
 {
     waklog_host_config *cfg;
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
        "mod_waklog: phase7 called" );
 
 #if 0
@@ -684,7 +687,7 @@ waklog_phase7( request_rec *r )
     /* stuff the credentials into the kernel */
     waklog_aklog( r );
 
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
        "mod_waklog: phase7 returning" );
 
     return DECLINED;
@@ -692,11 +695,80 @@ waklog_phase7( request_rec *r )
 
     static void
 waklog_new_connection( conn_rec *c ) {
-    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, c->server,
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, c->server,
        "mod_waklog: new_connection called: pid: %d", getpid() );
     return;
 }
 
+
+/*
+**  Here's a quick explaination for phase0 and phase2:
+**  Apache does a stat() on the path between phase0 and
+**  phase2, and must by ACLed rl to succeed.  So, at
+**  phase0 we acquire credentials for umweb:servers from
+**  a keytab, and at phase2 we must ensure we remove them.
+**
+**  Failure to "unlog" would be a security risk.
+*/
+    static int
+waklog_phase2( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_waklog: phase2 called" );
+
+    if ( child.token.ticketLen ) {
+       memset( &child.token, 0, sizeof( struct ktc_token ) );
+
+       ktc_ForgetAllTokens();
+
+       ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() );
+    }
+
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server,
+           "mod_waklog: phase2 returning" );
+
+    return DECLINED;
+}
+
+#if 0
+static int waklog_phase1( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase1 returning" );
+    return DECLINED;
+}
+static int waklog_phase3( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase3 returning" );
+    return DECLINED;
+}
+static int waklog_phase4( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase4 returning" );
+    return DECLINED;
+}
+static int waklog_phase5( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase5 returning" );
+    return DECLINED;
+}
+static int waklog_phase6( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase6 returning" );
+    return DECLINED;
+}
+static void waklog_phase8( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase8 returning" );
+    return;
+}
+static int waklog_phase9( request_rec *r )
+{
+    ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, "mod_waklog: phase9 returning" );
+    return DECLINED;
+}
+#endif /* 0 */
+
 module MODULE_VAR_EXPORT waklog_module = {
     STANDARD_MODULE_STUFF, 
     waklog_init,           /* module initializer                  */
@@ -717,7 +789,7 @@ module MODULE_VAR_EXPORT waklog_module = {
     NULL,                  /* [#6] determine MIME type            */
     waklog_phase7,         /* [#7] pre-run fixups                 */
     NULL,                  /* [#9] log a transaction              */
-    NULL,                  /* [#2] header parser                  */
+    waklog_phase2,         /* [#2] header parser                  */
     waklog_child_init,     /* child_init                          */
     NULL,                  /* child_exit                          */
     waklog_phase0          /* [#0] post read-request              */