From 7193eb01f9a9f97a71c55b1c60571d10dfc82d22 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 31 Mar 2004 22:32:06 +0000 Subject: [PATCH] First pass git-svn-id: https://modwaklog.svn.sourceforge.net/svnroot/modwaklog/trunk/modwaklog@12 0d961d1b-a432-0410-8fea-cc29f225fe07 --- Makefile | 8 +- VERSION | 2 +- mod_waklog.c | 621 ++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 466 insertions(+), 165 deletions(-) diff --git a/Makefile b/Makefile index 4667601..5f1a3c6 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,10 @@ CC= gcc INC= -I/usr/local/krb5/include -I/usr/local/openafs/include \ -I/usr/local/apache/include LIB= -L/usr/local/krb5/lib \ - -lkrb4 -lkrb5 -ldes425 -lk5crypto -lcom_err -lsocket -lnsl \ - -L/usr/local/openafs/lib/afs -lsys \ - -L/usr/local/openafs/lib -lrx -llwp -CFLAGS= ${DEF} ${INC} -DEAPI + -lkrb4 -lkrb5 -ldes425 -lk5crypto -lcom_err -lnsl -lkrb524 \ + -L/usr/lib/afs -lsys \ + -lrx -llwp -lauth +CFLAGS= ${DEF} ${INC} -DEAPI -g OBJ= mod_waklog.o lifetime.o version.o all: ${ALL} diff --git a/VERSION b/VERSION index c45feef..b19584c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -20030507 +20040324 diff --git a/mod_waklog.c b/mod_waklog.c index f10475d..5da9a1e 100644 --- a/mod_waklog.c +++ b/mod_waklog.c @@ -1,20 +1,34 @@ #include "httpd.h" #include "http_config.h" -#include "http_protocol.h" +#include "http_conf_globals.h" #include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_core.h" #include "ap_config.h" #include +#if defined(sun) #include +#endif /* sun */ #include #include #include #include +#include +#include + +#include +#include -#define KEYTAB_PATH "/usr/local/users/clunis/keytab.umweb.mysql" -#define PRINCIPAL "umweb/mysql" +#define KEYTAB_PATH "/home/drh/keytab.umweb.drhtest" +#define PRINCIPAL "umweb/drhtest" +#define AFS "afs" #define IN_TKT_SERVICE "krbtgt/UMICH.EDU" +#define K5PATH "FILE:/tmp/waklog.creds.k5" +#define K4PATH "/tmp/waklog.creds.k4" + module waklog_module; struct ClearToken { @@ -29,8 +43,22 @@ typedef struct { int configured; int protect; char *keytab; + char *keytab_principal; + char *afs_instance; } waklog_host_config; +typedef struct { + krb5_timestamp endtime; /* time krbtgt expires */ + int getting_tgt; /* TAS flag, protecting above */ +} waklog_mod_config; +waklog_mod_config *mod = NULL; + +int shmid = -1; + +typedef struct { + struct ktc_token token; +} waklog_child_config; +waklog_child_config *child = NULL; static void * waklog_create_dir_config( pool *p, char *path ) @@ -40,6 +68,9 @@ waklog_create_dir_config( pool *p, char *path ) cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config )); cfg->configured = 0; cfg->protect = 0; + cfg->keytab = 0; + cfg->keytab_principal = 0; + cfg->afs_instance = 0; return( cfg ); } @@ -53,6 +84,9 @@ waklog_create_server_config( pool *p, server_rec *s ) cfg = (waklog_host_config *)ap_pcalloc( p, sizeof( waklog_host_config )); cfg->configured = 0; cfg->protect = 0; + cfg->keytab = 0; + cfg->keytab_principal = 0; + cfg->afs_instance = 0; return( cfg ); } @@ -61,10 +95,60 @@ waklog_create_server_config( pool *p, server_rec *s ) static void waklog_init( server_rec *s, pool *p ) { - extern char *version; + extern char *version; + static key_t shmkey = IPC_PRIVATE; + struct shmid_ds shmbuf; ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, "mod_waklog: version %s initialized.", version ); + + if ( mod == NULL ) { + if (( shmid = shmget( shmkey, sizeof( waklog_mod_config ), + IPC_CREAT | SHM_R | SHM_W )) == -1 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, s, + "mod_waklog: shmget failed" ); + exit ( -1 ); + } + + ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, + "mod_waklog: waklog_init: created shared memory segment %d", shmid ); + + if (( mod = (waklog_mod_config *) shmat( shmid, 0, 0 ) ) == + (waklog_mod_config *) -1 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, s, + "mod_waklog: shmat failed" ); + /* we'll exit after removing the segment */ + + } else { + if ( shmctl( shmid, IPC_STAT, &shmbuf ) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, s, + "mod_waklog: shmctl failed to stat" ); + + } else { + shmbuf.shm_perm.uid = ap_user_id; + shmbuf.shm_perm.gid = ap_group_id; + + if ( shmctl( shmid, IPC_SET, &shmbuf ) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, s, + "mod_waklog: shmctl failed to set" ); + } + } + + } + + if ( shmctl( shmid, IPC_RMID, NULL ) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, s, + "mod_waklog: shmctl failed to remove" ); + } + + if ( mod == (waklog_mod_config *) -1 ) { + exit ( -1 ); + } + } + + mod->endtime = 0; + mod->getting_tgt = 0; + return; } @@ -111,7 +195,18 @@ set_waklog_use_keytab( cmd_parms *params, void *mconfig, char *file ) static void waklog_child_init( server_rec *s, pool *p ) { + + if ( child == NULL ) { + child = (waklog_child_config *) ap_palloc( p, sizeof( waklog_child_config ) ); + } + + memset( &child->token, 0, sizeof( struct ktc_token ) ); + setpag(); + + ap_log_error( APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, s, + "mod_waklog: waklog_child_init: child: 0x%08x", child ); + return; } @@ -134,249 +229,455 @@ command_rec waklog_cmds[ ] = pioctl_cleanup( void *data ) { request_rec *r = (request_rec *)data; - struct ViceIoctl vi; - vi.in = NULL; - vi.in_size = 0; - vi.out = NULL; - vi.out_size = 0; + if ( child->token.ticketLen ) { + memset( &child->token, 0, sizeof( struct ktc_token ) ); - if ( pioctl( 0, VIOCUNPAG, &vi, 0 ) < 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - "mod_waklog: unlog pioctl failed" ); - } + ktc_ForgetAllTokens(); - ap_log_error( APLOG_MARK, APLOG_DEBUG, r->server, - "mod_waklog: unlog pioctl succeeded" ); + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: ktc_ForgetAllTokens succeeded" ); + } return; } static int -waklog_ktinit( request_rec *r ) +waklog_ktinit( request_rec *r, char *keytab_path ) { krb5_error_code kerror; krb5_context kcontext; krb5_principal kprinc; - krb5_principal sprinc; krb5_get_init_creds_opt kopts; - krb5_creds kcreds; + krb5_creds v5creds; + CREDENTIALS v4creds; krb5_ccache kccache; krb5_keytab keytab = 0; char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ]; - char krbpath [ 24 ]; - - if (( kerror = krb5_init_context( &kcontext ))) { - /* Authentication Required ( kerberos error ) */ - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - (char *)error_message( kerror )); + krb5_timestamp now; - return; - } + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: waklog_ktinit called" ); - if (( kerror = krb5_parse_name( kcontext, "PRINCIPAL", &kprinc ))) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - (char *)error_message( kerror )); + /* set our environment variables */ + ap_table_set( r->subprocess_env, "KRB5CCNAME", K5PATH ); + ap_table_set( r->subprocess_env, "KRBTKFILE", K4PATH ); - return; - } + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: KRB5CCNAME: %s, KRBTKFILE: %s", K5PATH, K4PATH ); - snprintf( krbpath, sizeof( krbpath ), "/ticket/waklog" ); +#define SOON 300 - if (( kerror = krb5_cc_resolve( kcontext, krbpath, &kccache )) != 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - (char *)error_message( kerror )); + /* will we need another tgt soon? */ + now = time( NULL ); + if ( !mod->getting_tgt && mod->endtime < now + SOON ) { - return; - } + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: mod->endtime: %u, now: %u", mod->endtime, now ); + + /* + ** Only one process will get into the critical region below and + ** replace the soon-to-be-expired credential; the rest will just + ** use the still-good credential until the new one shows up. + ** + ** The TAS flag will stop other processes from entering the + ** first half of the conditional above, and the critical region + ** below will not exit until mod->endtime has been updated to + ** reflect that of the new credentials (or fail). + ** + ** (While it is possible for all child processes to get past the + ** first half of the conditional above, and then for one + ** process to get into the critical region below and run to the + ** end (clearing the TAS flag), a fair scheduler would not + ** do this; but even so, it really wouldn't kill us if ALL of + ** the child processes got credentials, anyway. + */ + if ( !test_and_set_bit( 0, &mod->getting_tgt ) ) { + + if (( kerror = krb5_init_context( &kcontext ))) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup1; + } + + /* use the path */ + if (( kerror = krb5_cc_resolve( kcontext, K5PATH, &kccache )) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); - krb5_get_init_creds_opt_init( &kopts ); - krb5_get_init_creds_opt_set_tkt_life( &kopts, 10*60*60 ); - krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); - krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); - krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); + goto cleanup2; + } - if ( KEYTAB_PATH == '\0' ) { - if (( kerror = krb5_kt_default_name( - kcontext, ktbuf, MAX_KEYTAB_NAME_LEN )) != 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + if (( kerror = krb5_parse_name( kcontext, PRINCIPAL, &kprinc ))) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, (char *)error_message( kerror )); - return; - } - } else { - if ( strlen( KEYTAB_PATH ) > MAX_KEYTAB_NAME_LEN ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + goto cleanup3; + } + + krb5_get_init_creds_opt_init( &kopts ); + krb5_get_init_creds_opt_set_tkt_life( &kopts, 10*60*60 ); + krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); + krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); + krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); + + /* which keytab should we use? */ + strcpy( ktbuf, keytab_path ? keytab_path : KEYTAB_PATH ); + + if ( strlen( ktbuf ) > MAX_KEYTAB_NAME_LEN ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, "server configuration error" ); - return; + goto cleanup4; + } + + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: waklog_ktinit using: %s", ktbuf ); + + if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup4; + } + + /* get the krbtgt */ + if (( kerror = krb5_get_init_creds_keytab( kcontext, &v5creds, + kprinc, keytab, 0, IN_TKT_SERVICE, &kopts ))) { + + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup5; + } + + if (( kerror = krb5_verify_init_creds( kcontext, &v5creds, + kprinc, keytab, NULL, NULL )) != 0 ) { + + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup6; + } + + if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup6; + } + + if (( kerror = krb5_cc_store_cred( kcontext, kccache, &v5creds )) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup6; + } + + /* convert K5 => K4 */ + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: before krb524_convert_creds" ); + + if (( kerror = krb524_convert_creds_kdc( kcontext, + &v5creds, &v4creds )) != 0 ) { + + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup6; + } + + /* use the path */ + krb_set_tkt_string( (char *)K4PATH ); + + /* initialize ticket cache */ + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: before in_tkt" ); + + if (( kerror = in_tkt( v4creds.pname, v4creds.pinst )) != KSUCCESS ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup6; + } + + /* stash, ticket, session key, etc for future use */ + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: before krb_save_credentials" ); + + if (( kerror = krb_save_credentials( v4creds.service, + v4creds.instance, + v4creds.realm, + v4creds.session, + v4creds.lifetime, + v4creds.kvno, + &(v4creds.ticket_st), + v4creds.issue_date )) != 0 ) { + + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + goto cleanup6; + } + + /* save this */ + mod->endtime = v5creds.times.endtime; + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: mod->endtime: %u, mod->getting_tgt: %d", + mod->endtime, mod->getting_tgt ); + +cleanup6: krb5_free_cred_contents( kcontext, &v5creds ); +cleanup5: (void)krb5_kt_close( kcontext, keytab ); +cleanup4: krb5_free_principal( kcontext, kprinc ); +cleanup3: krb5_cc_close( kcontext, kccache ); +cleanup2: krb5_free_context( kcontext ); + + /* exit the critical region */ +cleanup1: mod->getting_tgt = 0; } - strcpy( ktbuf, KEYTAB_PATH ); + } - if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - (char *)error_message( kerror )); - + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: waklog_ktinit: exiting" ); + + return( 0 ); +} + + + static void +waklog_aklog( request_rec *r ) +{ + int rc; + char buf[ 1024 ]; + const char *k4path = NULL; + const char *k5path = NULL; + krb5_error_code kerror; + krb5_context kcontext; + krb5_creds increds; + krb5_creds *v5credsp = NULL; + CREDENTIALS v4creds; + krb5_ccache kccache; + struct ktc_principal server = { "afs", "", "umich.edu" }; + struct ktc_principal client; + struct ktc_token token; + + 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, + "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, + "mod_waklog: waklog_aklog giving up" ); return; } - if (( kerror = krb5_sname_to_principal( kcontext, NULL, "cosign", - KRB5_NT_SRV_HST, &sprinc )) != 0 ) { + /* + ** Get/build creds from file/tgs, then see if we need to SetToken + */ + + if (( kerror = krb5_init_context( &kcontext ))) { + /* Authentication Required ( kerberos error ) */ ap_log_error( APLOG_MARK, APLOG_ERR, r->server, (char *)error_message( kerror )); - + return; } - if (( kerror = krb5_get_init_creds_keytab( kcontext, &kcreds, - kprinc, keytab, NULL, IN_TKT_SERVICE, &kopts ))) { + memset( (char *)&increds, 0, sizeof(increds)); + /* set server part */ + if (( kerror = krb5_parse_name( kcontext, AFS, &increds.server ))) { ap_log_error( APLOG_MARK, APLOG_ERR, r->server, (char *)error_message( kerror )); return; } + if (( kerror = krb5_cc_resolve( kcontext, k5path, &kccache )) != 0 ) { + ap_log_error( APLOG_MARK, APLOG_ERR, r->server, + (char *)error_message( kerror )); + + return; + } - (void)krb5_kt_close( kcontext, keytab ); - krb5_free_principal( kcontext, sprinc ); + /* set client part */ + krb5_cc_get_principal( kcontext, kccache, &increds.client ); - if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - (char *)error_message( kerror )); - + increds.times.endtime = 0; + /* Ask for DES since that is what V4 understands */ + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + + /* get the V5 credentials */ + if (( kerror = krb5_get_credentials( kcontext, 0, kccache, + &increds, &v5credsp ) ) ) { + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: krb5_get_credentials: %s", krb_err_txt[ kerror ] ); return; } - if (( kerror = krb5_cc_store_cred( kcontext, kccache, &kcreds )) != 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - (char *)error_message( kerror )); - + /* get the V4 credentials */ + if (( kerror = krb524_convert_creds_kdc( kcontext, v5credsp, &v4creds ) ) ) { + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: krb524_convert_creds_kdc: %s", krb_err_txt[ kerror ] ); return; } - krb5_free_cred_contents( kcontext, &kcreds ); - krb5_free_principal( kcontext, kprinc ); + /* assemble the token */ + token.kvno = v4creds.kvno; + token.startTime = v4creds.issue_date; + token.endTime = v5credsp->times.endtime; + memmove( &token.sessionKey, v4creds.session, 8 ); + token.ticketLen = v4creds.ticket_st.length ; + memmove( token.ticket, v4creds.ticket_st.dat, token.ticketLen ); + + /* make sure we have to do this */ + if ( child->token.kvno != token.kvno || + child->token.ticketLen != token.ticketLen || + memcmp( &child->token.sessionKey, &token.sessionKey, + sizeof( token.sessionKey ) ) || + memcmp( child->token.ticket, token.ticket, token.ticketLen ) ) { + + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: %s.%s@%s", v4creds.service, v4creds.instance, + v4creds.realm ); + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: %d %d %d", v4creds.lifetime, v4creds.kvno, + v4creds.issue_date ); + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: %s %s", v4creds.pname, v4creds.pinst ); + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: %d", v4creds.ticket_st.length ); + + /* build the name */ + strcpy( buf, v4creds.pname ); + if ( v4creds.pinst[ 0 ] ) { + strcat( buf, "." ); + strcat( buf, v4creds.pinst ); + } + + /* assemble the client */ + strncpy( client.name, buf, MAXKTCNAMELEN - 1 ); + strcpy( client.instance, "" ); + strncpy( client.cell, v4creds.realm, MAXKTCNAMELEN - 1 ); + + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 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, + "mod_waklog: client: name=%s, instance=%s, cell=%s", + client.name, client.instance, client.cell ); + + /* use the path */ + krb_set_tkt_string( (char *)k4path ); + + /* rumor: we have to do this for AIX 4.1.4 with AFS 3.4+ */ + write( 2, "", 0 ); + + if ( ( rc = ktc_SetToken( &server, &token, &client, 0 ) ) ) { + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: settoken returned %d", rc ); + } + + /* save this */ + memmove( &child->token, &token, sizeof( struct ktc_token ) ); + + /* we'll need to unlog when this connection is done. */ + ap_register_cleanup( r->pool, (void *)r, pioctl_cleanup, ap_null_cleanup ); + } + + krb5_free_cred_contents( kcontext, v5credsp ); + krb5_free_principal( kcontext, increds.client ); krb5_cc_close( kcontext, kccache ); krb5_free_context( kcontext ); - return( 0 ); + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: finished with waklog_aklog" ); + } static int -waklog_get_tokens( request_rec *r ) +waklog_phase0( request_rec *r ) { - CREDENTIALS cr; - struct ViceIoctl vi; - struct ClearToken ct; - int i, rc; - char buf[ 1024 ], *s; - char *urealm = "UMICH.EDU"; - char *lrealm = "umich.edu"; waklog_host_config *cfg; + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: phase0 called" ); + /* directory config? */ cfg = (waklog_host_config *)ap_get_module_config( r->per_dir_config, &waklog_module); /* server config? */ if ( !cfg->configured ) { - cfg = (waklog_host_config *)ap_get_module_config( - r->server->module_config, &waklog_module); + cfg = (waklog_host_config *)ap_get_module_config( + r->server->module_config, &waklog_module); } - if ( cfg->keytab != NULL ) { + if ( !cfg->protect ) { ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, - "mod_waklog: keytab is configured: %s", cfg->keytab ); + "mod_waklog: phase0 declining" ); + return( DECLINED ); + } - /* authenticate using keytab file */ - waklog_ktinit( r ); + /* do this only if we are still unauthenticated */ + if ( !child->token.ticketLen ) { - return OK; - } else { - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, - "mod_waklog: keytab is not configured" ); - } + /* authenticate using keytab file */ + waklog_ktinit( r , cfg->keytab ); - if ( !cfg->protect ) { - return( DECLINED ); + /* stuff the credentials into the kernel */ + waklog_aklog( r ); } + + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: phase0 returning" ); + return DECLINED; +} - if (( rc = krb_get_cred( "afs", "", urealm, &cr )) != KSUCCESS ) { - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, - "mod_waklog: krb_get_cred: %s", krb_err_txt[ rc ] ); - if (( rc = get_ad_tkt( "afs", "", urealm, 255 )) != KSUCCESS ) { - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, - "mod_waklog: get_ad_tkt: %s", krb_err_txt[ rc ] ); + static int +waklog_phase7( request_rec *r ) +{ + waklog_host_config *cfg; - /* fail here or just let AFS deny permission? */ + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: phase7 called" ); - return OK; - } + /* directory config? */ + cfg = (waklog_host_config *)ap_get_module_config( + r->per_dir_config, &waklog_module); - if (( rc = krb_get_cred( "afs", "", urealm, &cr )) != KSUCCESS ) { - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, - "mod_waklog: krb_get_cred: %s", krb_err_txt[ rc ] ); - return OK; - } + /* server config? */ + if ( !cfg->configured ) { + cfg = (waklog_host_config *)ap_get_module_config( + r->server->module_config, &waklog_module); } - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, - "mod_waklog: %s.%s@%s", cr.service, cr.instance, cr.realm ); - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, - "mod_waklog: %d %d %d", cr.lifetime, cr.kvno, cr.issue_date ); - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, - "mod_waklog: %s %s", cr.pname, cr.pinst ); - ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r->server, - "mod_waklog: %d", cr.ticket_st.length ); - - s = buf; - memmove( s, &cr.ticket_st.length, sizeof( int )); - s += sizeof( int ); - memmove( s, cr.ticket_st.dat, cr.ticket_st.length ); - s += cr.ticket_st.length; - - ct.AuthHandle = cr.kvno; - memmove( ct.HandShakeKey, cr.session, sizeof( cr.session )); - ct.ViceId = 0; - ct.BeginTimestamp = cr.issue_date; - ct.EndTimestamp = krb_life_to_time( cr.issue_date, cr.lifetime ); - - i = sizeof( struct ClearToken ); - memmove( s, &i, sizeof( int )); - s += sizeof( int ); - memmove( s, &ct, sizeof( struct ClearToken )); - s += sizeof( struct ClearToken ); - - i = 0; - memmove( s, &i, sizeof( int )); - s += sizeof( int ); - - strcpy( s, lrealm ); - s += strlen( lrealm ) + 1; - - vi.in = buf; - vi.in_size = s - buf; - vi.out = buf; - vi.out_size = sizeof( buf ); - - if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) { - ap_log_error( APLOG_MARK, APLOG_ERR, r->server, - "mod_waklog: pioctl failed" ); + if ( !cfg->protect ) { + return( DECLINED ); } - /* we'll need to unlog when this connection is done. */ - ap_register_cleanup( r->pool, (void *)r, pioctl_cleanup, ap_null_cleanup ); + /* stuff the credentials into the kernel */ + waklog_aklog( r ); - ap_log_error( APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, - "mod_waklog: finished with get_token" ); + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_waklog: phase7 returning" ); - return OK; + return DECLINED; } + static void +waklog_new_connection( conn_rec *c ) { + ap_log_error( APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, c->server, + "mod_waklog: new_connection called: conn_rec: 0x%08x pid: %d", c, getpid() ); + return; +} module MODULE_VAR_EXPORT waklog_module = { STANDARD_MODULE_STUFF, @@ -392,16 +693,16 @@ module MODULE_VAR_EXPORT waklog_module = { NULL, /* [#5] check if the user is ok _here_ */ NULL, /* [#3] check access by host address */ NULL, /* [#6] determine MIME type */ - waklog_get_tokens, /* [#7] pre-run fixups */ + waklog_phase7, /* [#7] pre-run fixups */ NULL, /* [#9] log a transaction */ NULL, /* [#2] header parser */ waklog_child_init, /* child_init */ NULL, /* child_exit */ - NULL /* [#0] post read-request */ + waklog_phase0 /* [#0] post read-request */ #ifdef EAPI ,NULL, /* EAPI: add_module */ NULL, /* EAPI: remove_module */ NULL, /* EAPI: rewrite_command */ - NULL /* EAPI: new_connection */ + waklog_new_connection /* EAPI: new_connection */ #endif }; -- 2.20.1