fifth set of UMBC merges; still all inert changes (added data structures but not...
[hcoop/zz_old/modwaklog.git] / mod_waklog.c
CommitLineData
87822447 1#define _LARGEFILE64_SOURCE
ff47641b 2#define _GNU_SOURCE
87822447 3
bed98ff9 4#include "httpd.h"
5#include "http_config.h"
bed98ff9 6#include "http_log.h"
7193eb01 7#include "http_protocol.h"
8#include "http_request.h"
9#include "http_core.h"
87822447 10
ff47641b 11#ifdef sun
12#include <synch.h>
13#elif linux
14#define use_pthreads
15#include <features.h>
16#include <sys/types.h>
17#include <sys/mman.h>
18#include <pthread.h>
19#else
20#error "make sure you include the right stuff here"
21#endif
22
23#ifndef MAXNAMELEN
24#define MAXNAMELEN 1024
25#endif
26
87822447 27#ifdef STANDARD20_MODULE_STUFF
28#include <apr_strings.h>
29#include <apr_base64.h>
30#include <apr_compat.h>
31#include <apu_compat.h>
32
33module AP_MODULE_DECLARE_DATA waklog_module;
34
35#define MK_POOL apr_pool_t
36#define MK_TABLE_GET apr_table_get
d06251b1 37#define MK_TABLE_SET apr_table_set
87822447 38#include "unixd.h"
39extern unixd_config_rec unixd_config;
40#define ap_user_id unixd_config.user_id
41#define ap_group_id unixd_config.group_id
42#define ap_user_name unixd_config.user_name
43#define command(name, func, var, type, usage) \
44 AP_INIT_ ## type (name, (void*) func, \
c69d952f 45 (void*)APR_OFFSETOF(waklog_commands, var), \
87822447 46 OR_AUTHCFG | RSRC_CONF, usage)
47typedef struct {
48 int dummy;
877d453f 49}
50child_info;
87822447 51
52const char *userdata_key = "waklog_init";
53#else
bed98ff9 54#include "ap_config.h"
87822447 55
877d453f 56#define MK_POOL pool
57#define MK_TABLE_GET ap_table_get
58#define MK_TABLE_SET ap_table_set
59
60
61
62
63#include <krb5.h>
64
65#if defined(sun)
66#include <sys/ioccom.h>
67#endif /* sun */
68
69#include <stropts.h>
70#include <afs/venus.h>
71#include <afs/auth.h>
72#include <afs/dirpath.h>
73#include <afs/ptuser.h>
74#include <rx/rxkad.h>
75
76#define TKT_LIFE ( 12 * 60 * 60 )
77#define SLEEP_TIME ( TKT_LIFE - 5*60 )
78
79#define WAKLOG_ON 1
80#define WAKLOG_OFF 2
81#define WAKLOG_UNSET 0
82
83#ifdef WAKLOG_DEBUG
84#undef APLOG_DEBUG
85#define APLOG_DEBUG APLOG_ERR
86#endif
87
88#ifndef CELL_IN_PRINCIPAL
89int cell_in_principal = 1;
90#else
91int cell_in_principal = 0;
92#endif
93
94/* this is used to turn off pag generation for the backround worker child during startup */
95int pag_for_children = 1;
96
97typedef struct
98{
99 int forked;
100 int configured;
101 int protect;
102 int usertokens;
103 char *keytab;
104 char *principal;
105 char *default_principal;
106 char *default_keytab;
107 char *afs_cell;
108 char *path;
109 MK_POOL *p;
110}
111waklog_config;
112
113typedef struct
114{
115 struct ktc_token token;
116 char clientprincipal[MAXNAMELEN];
117 krb5_context kcontext;
118 krb5_ccache ccache;
119 struct ktc_principal server;
120 struct ktc_principal client;
121 int pr_init;
122} waklog_child_config;
123
124waklog_child_config child;
125
126struct tokencache_ent {
127 char clientprincipal[MAXNAMELEN];
128 struct ktc_token token;
129 struct ktc_principal client;
130 struct ktc_principal server;
131 time_t lastused;
132 int persist;
133};
134
135#define SHARED_TABLE_SIZE 512
136
137struct sharedspace_s {
138 int renewcount;
139 struct tokencache_ent sharedtokens[SHARED_TABLE_SIZE];
140};
141
142struct sharedspace_s *sharedspace = NULL;
143
144struct renew_ent {
145 char *keytab;
146 char *principal;
147 int lastrenewed;
148};
149
150#ifdef use_pthreads
151pthread_rwlock_t *sharedlock = NULL;
152#else
153rwlock_t *sharedlock = NULL;
154#endif
155
156struct renew_ent renewtable[SHARED_TABLE_SIZE];
157
158int renewcount = 0;
159
87822447 160module waklog_module;
161#define MK_POOL pool
162#define MK_TABLE_GET ap_table_get
163#define command(name, func, var, type, usage) \
164 { name, func, \
c69d952f 165 (void*)XtOffsetOf(waklog_commands, var), \
87822447 166 OR_AUTHCFG | RSRC_CONF, type, usage }
167#endif /* STANDARD20_MODULE_STUFF */
168
c69d952f 169#define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
87822447 170
4e1ae1cd 171#include <krb5.h>
bed98ff9 172
7193eb01 173#if defined(sun)
bed98ff9 174#include <sys/ioccom.h>
7193eb01 175#endif /* sun */
bed98ff9 176#include <stropts.h>
bed98ff9 177#include <afs/venus.h>
7193eb01 178#include <afs/auth.h>
d06251b1 179#include <afs/dirpath.h>
180#include <afs/ptuser.h>
7193eb01 181#include <rx/rxkad.h>
182
87822447 183#define KEYTAB "/etc/keytab.wwwserver"
ad1d1967 184#define PRINCIPAL "someplacewwwserver"
87822447 185#define AFS_CELL "someplace.edu"
4e1ae1cd 186
87822447 187/* If there's an error, retry more aggressively */
188#define ERR_SLEEP_TIME 5*60
58bbdc54 189
58bbdc54 190
191#define K5PATH "FILE:/tmp/waklog.creds.k5"
7193eb01 192
87822447 193static void
194log_error(const char *file, int line, int level, int status,
195 const server_rec *s, const char *fmt, ...)
4d47a8d9 196{
87822447 197 char errstr[1024];
198 va_list ap;
4d47a8d9 199
87822447 200 va_start(ap, fmt);
201 vsnprintf(errstr, sizeof(errstr), fmt, ap);
202 va_end(ap);
4d47a8d9 203
87822447 204#ifdef STANDARD20_MODULE_STUFF
205 ap_log_error(file, line, level | APLOG_NOERRNO, status, s, "%s", errstr);
206#else
207 ap_log_error(file, line, level | APLOG_NOERRNO, s, "%s", errstr);
208#endif
4d47a8d9 209
87822447 210}
4d47a8d9 211
313dde40 212 static void *
87822447 213waklog_create_server_config( MK_POOL *p, server_rec *s )
313dde40 214{
c69d952f 215 waklog_config *cfg;
313dde40 216
c69d952f 217 cfg = (waklog_config *)ap_pcalloc( p, sizeof( waklog_config ));
87822447 218 cfg->p = p;
219 cfg->forked = 0;
313dde40 220 cfg->configured = 0;
221 cfg->protect = 0;
58bbdc54 222 cfg->keytab = KEYTAB;
ad1d1967 223 cfg->principal = PRINCIPAL;
58bbdc54 224 cfg->afs_cell = AFS_CELL;
313dde40 225
87822447 226 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: server config created." );
227
313dde40 228 return( cfg );
229}
230
231
313dde40 232 static const char *
233set_waklog_protect( cmd_parms *params, void *mconfig, int flag )
234{
c69d952f 235 waklog_config *cfg;
313dde40 236
87822447 237 getModConfig(cfg, params->server );
313dde40 238
239 cfg->protect = flag;
240 cfg->configured = 1;
87822447 241 log_error( APLOG_MARK, APLOG_DEBUG, 0, params->server, "mod_waklog: waklog_protect set" );
313dde40 242 return( NULL );
243}
244
245
4e1ae1cd 246 static const char *
161ffd84 247set_waklog_keytab( cmd_parms *params, void *mconfig, char *file )
4e1ae1cd 248{
c69d952f 249 waklog_config *cfg;
4e1ae1cd 250
87822447 251 getModConfig(cfg, params->server );
4e1ae1cd 252
87822447 253 log_error( APLOG_MARK, APLOG_INFO, 0, params->server,
254 "mod_waklog: will use keytab: %s", file );
3ed1e28a 255
b52ccbb1 256 cfg->keytab = ap_pstrdup ( params->pool, file );
4e1ae1cd 257 cfg->configured = 1;
258 return( NULL );
259}
260
261
58bbdc54 262 static const char *
ad1d1967 263set_waklog_use_principal( cmd_parms *params, void *mconfig, char *file )
b74fad73 264{
c69d952f 265 waklog_config *cfg;
7193eb01 266
87822447 267 getModConfig(cfg, params->server );
7193eb01 268
87822447 269 log_error( APLOG_MARK, APLOG_INFO, 0, params->server,
ad1d1967 270 "mod_waklog: will use principal: %s", file );
58bbdc54 271
ad1d1967 272 cfg->principal = ap_pstrdup ( params->pool, file );
58bbdc54 273 cfg->configured = 1;
274 return( NULL );
275}
276
277
278 static const char *
279set_waklog_use_afs_cell( cmd_parms *params, void *mconfig, char *file )
280{
c69d952f 281 waklog_config *cfg;
58bbdc54 282
87822447 283 getModConfig(cfg, params->server );
58bbdc54 284
87822447 285 log_error( APLOG_MARK, APLOG_INFO, 0, params->server,
286 "mod_waklog: will use afs_cell: %s", file );
58bbdc54 287
b52ccbb1 288 cfg->afs_cell = ap_pstrdup( params->pool, file );
58bbdc54 289 cfg->configured = 1;
290 return( NULL );
291}
292
293
294 static void
87822447 295#ifdef STANDARD20_MODULE_STUFF
296waklog_child_init(MK_POOL *p, server_rec *s)
297#else
298waklog_child_init(server_rec *s, MK_POOL *p)
299#endif
58bbdc54 300{
301
87822447 302 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
303 "mod_waklog: child_init called" );
304
58bbdc54 305 memset( &child.token, 0, sizeof( struct ktc_token ) );
7193eb01 306
b74fad73 307 setpag();
7193eb01 308
87822447 309 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
310 "mod_waklog: child_init returned" );
311
b74fad73 312 return;
313}
314
87822447 315typedef struct {
316 int wak_protect;
317 char *wak_keytab;
318 char *wak_ktprinc;
319 char *wak_afscell;
c69d952f 320} waklog_commands;
b74fad73 321
313dde40 322command_rec waklog_cmds[ ] =
323{
87822447 324 command("WaklogProtected", set_waklog_protect, wak_protect, FLAG, "enable waklog on a location or directory basis"),
313dde40 325
87822447 326 command("WaklogKeytab", set_waklog_keytab, wak_keytab, TAKE1, "Use the supplied keytab rather than the default"),
58bbdc54 327
ad1d1967 328 command("WaklogUseKeytabPrincipal", set_waklog_use_principal, wak_ktprinc, TAKE1, "Use the supplied keytab principal rather than the default"),
58bbdc54 329
87822447 330 command("WaklogUseAFSCell", set_waklog_use_afs_cell, wak_afscell, TAKE1, "Use the supplied AFS cell rather than the default"),
4e1ae1cd 331
313dde40 332 { NULL }
333};
334
335
87822447 336 static int
e2df6441 337token_cleanup( void *data )
bed98ff9 338{
339 request_rec *r = (request_rec *)data;
bed98ff9 340
58bbdc54 341 if ( child.token.ticketLen ) {
342 memset( &child.token, 0, sizeof( struct ktc_token ) );
bed98ff9 343
7193eb01 344 ktc_ForgetAllTokens();
bed98ff9 345
87822447 346 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
347 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() );
7193eb01 348 }
87822447 349 return 0;
bed98ff9 350}
351
352
4e1ae1cd 353 static int
e2df6441 354waklog_kinit( server_rec *s )
4e1ae1cd 355{
87822447 356 krb5_error_code kerror = 0;
e2df6441 357 krb5_context kcontext = NULL;
358 krb5_principal kprinc = NULL;
4e1ae1cd 359 krb5_get_init_creds_opt kopts;
7193eb01 360 krb5_creds v5creds;
e2df6441 361 krb5_ccache kccache = NULL;
362 krb5_keytab keytab = NULL;
4e1ae1cd 363 char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ];
b52ccbb1 364 int i;
c69d952f 365 waklog_config *cfg;
4e1ae1cd 366
87822447 367 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
368 "mod_waklog: waklog_kinit called: pid: %d", getpid() );
4e1ae1cd 369
87822447 370 getModConfig(cfg, s);
58bbdc54 371
e21f34f0 372 if (( kerror = krb5_init_context( &kcontext ))) {
87822447 373 log_error( APLOG_MARK, APLOG_ERR, 0, s,
374 "mod_waklog: %s", (char *)error_message( kerror ));
4e1ae1cd 375
e2df6441 376 goto cleanup;
e21f34f0 377 }
4e1ae1cd 378
e21f34f0 379 /* use the path */
380 if (( kerror = krb5_cc_resolve( kcontext, K5PATH, &kccache )) != 0 ) {
87822447 381 log_error( APLOG_MARK, APLOG_ERR, 0, s,
382 "mod_waklog: %s", (char *)error_message( kerror ));
4e1ae1cd 383
e2df6441 384 goto cleanup;
e21f34f0 385 }
4e1ae1cd 386
87822447 387 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
ad1d1967 388 "mod_waklog: principal: %s", cfg->principal );
b52ccbb1 389
ad1d1967 390 if (( kerror = krb5_parse_name( kcontext, cfg->principal, &kprinc ))) {
87822447 391 log_error( APLOG_MARK, APLOG_ERR, 0, s,
392 "mod_waklog: %s", (char *)error_message( kerror ));
7193eb01 393
e2df6441 394 goto cleanup;
e21f34f0 395 }
7193eb01 396
e21f34f0 397 krb5_get_init_creds_opt_init( &kopts );
58bbdc54 398 krb5_get_init_creds_opt_set_tkt_life( &kopts, TKT_LIFE );
e21f34f0 399 krb5_get_init_creds_opt_set_renew_life( &kopts, 0 );
400 krb5_get_init_creds_opt_set_forwardable( &kopts, 1 );
401 krb5_get_init_creds_opt_set_proxiable( &kopts, 0 );
7193eb01 402
58bbdc54 403 /* keytab from config */
404 strncpy( ktbuf, cfg->keytab, sizeof( ktbuf ) - 1 );
7193eb01 405
87822447 406 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
407 "mod_waklog: waklog_kinit using: %s", ktbuf );
7193eb01 408
e21f34f0 409 if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) {
87822447 410 log_error( APLOG_MARK, APLOG_ERR, 0, s,
411 "mod_waklog:krb5_kt_resolve %s", (char *)error_message( kerror ));
7193eb01 412
e2df6441 413 goto cleanup;
e21f34f0 414 }
7193eb01 415
b52ccbb1 416 memset( (char *)&v5creds, 0, sizeof(v5creds));
417
e21f34f0 418 /* get the krbtgt */
419 if (( kerror = krb5_get_init_creds_keytab( kcontext, &v5creds,
403921ef 420 kprinc, keytab, 0, NULL, &kopts ))) {
7193eb01 421
87822447 422 log_error( APLOG_MARK, APLOG_ERR, 0, s,
423 "mod_waklog:krb5_get_init_creds_keytab %s", (char *)error_message( kerror ));
7193eb01 424
e2df6441 425 goto cleanup;
e21f34f0 426 }
7193eb01 427
e21f34f0 428 if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) {
87822447 429 log_error( APLOG_MARK, APLOG_ERR, 0, s,
430 "mod_waklog:krb5_cc_initialize %s", (char *)error_message( kerror ));
7193eb01 431
e2df6441 432 goto cleanup;
e21f34f0 433 }
7193eb01 434
e2df6441 435 kerror = krb5_cc_store_cred( kcontext, kccache, &v5creds );
436 krb5_free_cred_contents( kcontext, &v5creds );
437 if ( kerror != 0 ) {
87822447 438 log_error( APLOG_MARK, APLOG_ERR, 0, s,
439 "mod_waklog: %s", (char *)error_message( kerror ));
7193eb01 440
e2df6441 441 goto cleanup;
e21f34f0 442 }
7193eb01 443
87822447 444 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
445 "mod_waklog: waklog_kinit success" );
e2df6441 446
447cleanup:
448 if ( keytab )
449 (void)krb5_kt_close( kcontext, keytab );
450 if ( kprinc )
451 krb5_free_principal( kcontext, kprinc );
452 if ( kccache )
453 krb5_cc_close( kcontext, kccache );
454 if ( kcontext )
455 krb5_free_context( kcontext );
e21f34f0 456
87822447 457 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
458 "mod_waklog: waklog_kinit: exiting" );
7193eb01 459
87822447 460 return( kerror );
7193eb01 461}
462
463
464 static void
465waklog_aklog( request_rec *r )
466{
467 int rc;
bd173fe7 468 char buf[ MAXKTCTICKETLEN ];
7193eb01 469 const char *k5path = NULL;
470 krb5_error_code kerror;
e2df6441 471 krb5_context kcontext = NULL;
7193eb01 472 krb5_creds increds;
473 krb5_creds *v5credsp = NULL;
e2df6441 474 krb5_ccache kccache = NULL;
403921ef 475 struct ktc_principal server = { "afs", "", "" };
7193eb01 476 struct ktc_principal client;
477 struct ktc_token token;
c69d952f 478 waklog_config *cfg;
58bbdc54 479 int buflen;
7193eb01 480
87822447 481 k5path = MK_TABLE_GET( r->subprocess_env, "KRB5CCNAME" );
7193eb01 482
87822447 483 log_error( APLOG_MARK, APLOG_INFO, 0, r->server,
484 "mod_waklog: waklog_aklog called: k5path: %s", k5path );
7193eb01 485
161ffd84 486 if ( k5path == NULL ) {
87822447 487 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
488 "mod_waklog: waklog_aklog giving up" );
e2df6441 489 goto cleanup;
4e1ae1cd 490 }
491
7193eb01 492 /*
493 ** Get/build creds from file/tgs, then see if we need to SetToken
494 */
495
496 if (( kerror = krb5_init_context( &kcontext ))) {
497 /* Authentication Required ( kerberos error ) */
87822447 498 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
499 (char *)error_message( kerror ));
500
e2df6441 501 goto cleanup;
4e1ae1cd 502 }
503
7193eb01 504 memset( (char *)&increds, 0, sizeof(increds));
4e1ae1cd 505
87822447 506 getModConfig(cfg, r->server );
403921ef 507
508 /* afs/<cell> or afs */
509 strncpy( buf, "afs", sizeof( buf ) - 1 );
58bbdc54 510 if ( strcmp( cfg->afs_cell, AFS_CELL ) ) {
403921ef 511 strncat( buf, "/" , sizeof( buf ) - strlen( buf ) - 1 );
512 strncat( buf, cfg->afs_cell, sizeof( buf ) - strlen( buf ) - 1 );
513 }
514
7193eb01 515 /* set server part */
403921ef 516 if (( kerror = krb5_parse_name( kcontext, buf, &increds.server ))) {
87822447 517 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
518 (char *)error_message( kerror ));
4e1ae1cd 519
e2df6441 520 goto cleanup;
4e1ae1cd 521 }
522
7193eb01 523 if (( kerror = krb5_cc_resolve( kcontext, k5path, &kccache )) != 0 ) {
87822447 524 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
525 (char *)error_message( kerror ));
7193eb01 526
e2df6441 527 goto cleanup;
7193eb01 528 }
4e1ae1cd 529
7193eb01 530 /* set client part */
531 krb5_cc_get_principal( kcontext, kccache, &increds.client );
4e1ae1cd 532
7193eb01 533 increds.times.endtime = 0;
534 /* Ask for DES since that is what V4 understands */
535 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
536
537 /* get the V5 credentials */
538 if (( kerror = krb5_get_credentials( kcontext, 0, kccache,
539 &increds, &v5credsp ) ) ) {
87822447 540 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
541 "mod_waklog: krb5_get_credentials: %s", error_message( kerror ));
e2df6441 542 goto cleanup;
4e1ae1cd 543 }
544
c4ad0387 545 /* don't overflow */
546 if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) { /* from krb524d.c */
87822447 547 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
548 "mod_waklog: ticket size (%d) too big to fake", v5credsp->ticket.length );
e2df6441 549 goto cleanup;
4e1ae1cd 550 }
551
7193eb01 552 /* assemble the token */
58bbdc54 553 memset( &token, 0, sizeof( struct ktc_token ) );
554
555 token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime;
7193eb01 556 token.endTime = v5credsp->times.endtime;
58bbdc54 557 memmove( &token.sessionKey, v5credsp->keyblock.contents, v5credsp->keyblock.length );
558 token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
559 token.ticketLen = v5credsp->ticket.length;
560 memmove( token.ticket, v5credsp->ticket.data, token.ticketLen );
7193eb01 561
58bbdc54 562 /* make sure we have to do this */
563 if ( child.token.kvno != token.kvno ||
564 child.token.ticketLen != token.ticketLen ||
565 (memcmp( &child.token.sessionKey, &token.sessionKey,
566 sizeof( token.sessionKey ) )) ||
567 (memcmp( child.token.ticket, token.ticket, token.ticketLen )) ) {
568
87822447 569 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
570 "mod_waklog: client: %s", buf );
7193eb01 571
572 /* build the name */
bd173fe7 573 memmove( buf, v5credsp->client->data[0].data,
574 min( v5credsp->client->data[0].length, MAXKTCNAMELEN - 1 ) );
58bbdc54 575 buf[ v5credsp->client->data[0].length ] = '\0';
576 if ( v5credsp->client->length > 1 ) {
8258901d 577 strncat( buf, ".", sizeof( buf ) - strlen( buf ) - 1 );
58bbdc54 578 buflen = strlen( buf );
bd173fe7 579 memmove( buf + buflen, v5credsp->client->data[1].data,
580 min( v5credsp->client->data[1].length, MAXKTCNAMELEN - strlen( buf ) - 1 ) );
58bbdc54 581 buf[ buflen + v5credsp->client->data[1].length ] = '\0';
7193eb01 582 }
583
584 /* assemble the client */
403921ef 585 strncpy( client.name, buf, sizeof( client.name ) - 1 );
586 strncpy( client.instance, "", sizeof( client.instance) - 1 );
bd173fe7 587 memmove( buf, v5credsp->client->realm.data,
588 min( v5credsp->client->realm.length, MAXKTCNAMELEN - 1 ) );
58bbdc54 589 buf[ v5credsp->client->realm.length ] = '\0';
590 strncpy( client.cell, buf, sizeof( client.cell ) - 1 );
403921ef 591
58bbdc54 592 /* assemble the server's cell */
403921ef 593 strncpy( server.cell, cfg->afs_cell , sizeof( server.cell ) - 1 );
7193eb01 594
87822447 595 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
596 "mod_waklog: server: name=%s, instance=%s, cell=%s",
597 server.name, server.instance, server.cell );
598
599 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
600 "mod_waklog: client: name=%s, instance=%s, cell=%s",
601 client.name, client.instance, client.cell );
7193eb01 602
603 /* use the path */
7193eb01 604
605 /* rumor: we have to do this for AIX 4.1.4 with AFS 3.4+ */
606 write( 2, "", 0 );
607
608 if ( ( rc = ktc_SetToken( &server, &token, &client, 0 ) ) ) {
87822447 609 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
610 "mod_waklog: settoken returned %d", rc );
58bbdc54 611 goto cleanup;
7193eb01 612 }
613
614 /* save this */
58bbdc54 615 memmove( &child.token, &token, sizeof( struct ktc_token ) );
7193eb01 616
617 /* we'll need to unlog when this connection is done. */
e2df6441 618 ap_register_cleanup( r->pool, (void *)r, token_cleanup, ap_null_cleanup );
7193eb01 619 }
620
e2df6441 621cleanup:
622 if ( v5credsp )
623 krb5_free_cred_contents( kcontext, v5credsp );
624 if ( increds.client )
625 krb5_free_principal( kcontext, increds.client );
626 if ( increds.server )
627 krb5_free_principal( kcontext, increds.server );
628 if ( kccache )
629 krb5_cc_close( kcontext, kccache );
630 if ( kcontext )
631 krb5_free_context( kcontext );
3ed1e28a 632
87822447 633 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
634 "mod_waklog: finished with waklog_aklog" );
7193eb01 635
e2df6441 636 return;
637
4e1ae1cd 638}
639
e21f34f0 640 static int
641waklog_child_routine( void *s, child_info *pinfo )
642{
e21f34f0 643 if ( !getuid() ) {
87822447 644 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
645 "mod_waklog: waklog_child_routine called as root" );
e21f34f0 646
647 /* this was causing the credential file to get owned by root */
ea3e8708 648#ifdef STANDARD20_MODULE_STUFF
e21f34f0 649 setgid(ap_group_id);
650 setuid(ap_user_id);
ea3e8708 651#endif
e21f34f0 652 }
653
654 while( 1 ) {
e2df6441 655 waklog_kinit( s );
87822447 656 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
657 "mod_waklog: child_routine sleeping" );
58bbdc54 658 sleep( SLEEP_TIME );
87822447 659 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
660 "mod_waklog: slept, calling waklog_kinit" );
e21f34f0 661 }
662
663}
664
87822447 665#ifdef STANDARD20_MODULE_STUFF
666static int
667waklog_init_handler(apr_pool_t *p, apr_pool_t *plog,
668 apr_pool_t *ptemp, server_rec *s)
669{
670 int rv;
671 extern char *version;
672 apr_proc_t *proc;
c69d952f 673 waklog_config *cfg;
87822447 674 void *data;
675
676 getModConfig(cfg, s);
677
678 /* initialize_module() will be called twice, and if it's a DSO
679 * then all static data from the first call will be lost. Only
680 * set up our static data on the second call.
681 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
682 apr_pool_userdata_get(&data, userdata_key, s->process->pool);
683
684 if (!data) {
685 apr_pool_userdata_set((const void *)1, userdata_key,
686 apr_pool_cleanup_null, s->process->pool);
687 } else {
688 log_error( APLOG_MARK, APLOG_INFO, 0, s,
689 "mod_waklog: version %s initialized.", version );
690
691 proc = (apr_proc_t *)ap_pcalloc( s->process->pool, sizeof(apr_proc_t));
692
693 rv = apr_proc_fork(proc, s->process->pool);
694
695 if (rv == APR_INCHILD) {
696 waklog_child_routine(s, NULL);
697 } else {
698 apr_pool_note_subprocess(s->process->pool, proc, APR_KILL_ALWAYS);
699 }
700 /* parent and child */
701 cfg->forked = proc->pid;
702 }
703 return 0;
704}
705#else
e21f34f0 706 static void
87822447 707waklog_init( server_rec *s, MK_POOL *p )
e21f34f0 708{
709 extern char *version;
710 int pid;
711
87822447 712 log_error( APLOG_MARK, APLOG_INFO, 0, s,
713 "mod_waklog: version %s initialized.", version );
e21f34f0 714
715 pid = ap_bspawn_child( p, waklog_child_routine, s, kill_always,
716 NULL, NULL, NULL );
717
87822447 718 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
719 "mod_waklog: ap_bspawn_child: %d.", pid );
e21f34f0 720}
87822447 721#endif
4e1ae1cd 722
bed98ff9 723 static int
7193eb01 724waklog_phase0( request_rec *r )
bed98ff9 725{
c69d952f 726 waklog_config *cfg;
313dde40 727
87822447 728 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
729 "mod_waklog: phase0 called" );
7193eb01 730
87822447 731 getModConfig(cfg, r->server );
313dde40 732
87822447 733 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
734 "mod_waklog: phase0, checking cfg->protect" );
7193eb01 735 if ( !cfg->protect ) {
87822447 736 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
737 "mod_waklog: phase0 declining" );
7193eb01 738 return( DECLINED );
739 }
4e1ae1cd 740
87822447 741 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
742 "mod_waklog: phase0, NOT setting environment variable" );
743 /* set our environment variable */
744 apr_table_set( r->subprocess_env, "KRB5CCNAME", K5PATH );
b52ccbb1 745
87822447 746 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
747 "mod_waklog: phase0, checking child.token.ticketLen" );
7193eb01 748 /* do this only if we are still unauthenticated */
58bbdc54 749 if ( !child.token.ticketLen ) {
87822447 750
751 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
752 "mod_waklog: phase0, calling waklog_aklog" );
7193eb01 753 /* stuff the credentials into the kernel */
754 waklog_aklog( r );
4e1ae1cd 755 }
7193eb01 756
87822447 757 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
758 "mod_waklog: phase0 returning" );
7193eb01 759 return DECLINED;
760}
4e1ae1cd 761
1e18ef7d 762
7193eb01 763 static int
764waklog_phase7( request_rec *r )
765{
c69d952f 766 waklog_config *cfg;
1e18ef7d 767
87822447 768 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
769 "mod_waklog: phase7 called" );
1e18ef7d 770
87822447 771 getModConfig(cfg, r->server );
bed98ff9 772
7193eb01 773 if ( !cfg->protect ) {
774 return( DECLINED );
bed98ff9 775 }
776
7193eb01 777 /* stuff the credentials into the kernel */
87822447 778
779 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
780 "mod_waklog: phase7, calling waklog_aklog" );
7193eb01 781 waklog_aklog( r );
bed98ff9 782
87822447 783 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
784 "mod_waklog: phase7 returning" );
bed98ff9 785
7193eb01 786 return DECLINED;
bed98ff9 787}
788
ff47641b 789
87822447 790static
791#ifdef STANDARD20_MODULE_STUFF
ff47641b 792 int
87822447 793#else
ff47641b 794 void
87822447 795#endif
ff47641b 796waklog_new_connection (conn_rec * c
87822447 797#ifdef STANDARD20_MODULE_STUFF
798 , void *dummy
799#endif
ff47641b 800 )
801{
802
c69d952f 803 waklog_commands *cfg;
ff47641b 804
805 log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
806 "mod_waklog: new_connection called: pid: %d", getpid ());
807 /*
808 getModConfig(cfg, c->base_server);
809
810 if ( cfg->default_principal ) {
811 log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
812 cfg->default_principal);
813 set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
814 }
815 */
816
87822447 817 return
818#ifdef STANDARD20_MODULE_STUFF
819 0
820#endif
821 ;
7193eb01 822}
bed98ff9 823
c4ad0387 824
1196adfe 825/*
826** Here's a quick explaination for phase0 and phase2:
827** Apache does a stat() on the path between phase0 and
828** phase2, and must by ACLed rl to succeed. So, at
829** phase0 we acquire credentials for umweb:servers from
830** a keytab, and at phase2 we must ensure we remove them.
831**
832** Failure to "unlog" would be a security risk.
833*/
ff47641b 834static int
835waklog_phase2 (request_rec * r)
c4ad0387 836{
161ffd84 837
ff47641b 838 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
839 "mod_waklog: phase2 called");
1196adfe 840
ff47641b 841 if (child.token.ticketLen)
842 {
843 memset (&child.token, 0, sizeof (struct ktc_token));
c4ad0387 844
ff47641b 845 ktc_ForgetAllTokens ();
c4ad0387 846
ff47641b 847 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
848 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
849 getpid ());
c4ad0387 850 }
1196adfe 851
ff47641b 852 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
853 "mod_waklog: phase2 returning");
1196adfe 854
c4ad0387 855 return DECLINED;
856}
857
87822447 858#ifndef STANDARD20_MODULE_STUFF
313dde40 859module MODULE_VAR_EXPORT waklog_module = {
bed98ff9 860 STANDARD_MODULE_STUFF,
003832b1 861 waklog_init, /* module initializer */
b52ccbb1 862#if 0
4d47a8d9 863 waklog_create_dir_config, /* create per-dir config structures */
b52ccbb1 864#else /* 0 */
865 NULL, /* create per-dir config structures */
866#endif /* 0 */
bed98ff9 867 NULL, /* merge per-dir config structures */
313dde40 868 waklog_create_server_config, /* create per-server config structures */
bed98ff9 869 NULL, /* merge per-server config structures */
313dde40 870 waklog_cmds, /* table of config file commands */
bed98ff9 871 NULL, /* [#8] MIME-typed-dispatched handlers */
872 NULL, /* [#1] URI to filename translation */
873 NULL, /* [#4] validate user id from request */
874 NULL, /* [#5] check if the user is ok _here_ */
875 NULL, /* [#3] check access by host address */
876 NULL, /* [#6] determine MIME type */
7193eb01 877 waklog_phase7, /* [#7] pre-run fixups */
bed98ff9 878 NULL, /* [#9] log a transaction */
c4ad0387 879 waklog_phase2, /* [#2] header parser */
313dde40 880 waklog_child_init, /* child_init */
bed98ff9 881 NULL, /* child_exit */
7193eb01 882 waklog_phase0 /* [#0] post read-request */
bed98ff9 883#ifdef EAPI
884 ,NULL, /* EAPI: add_module */
885 NULL, /* EAPI: remove_module */
886 NULL, /* EAPI: rewrite_command */
7193eb01 887 waklog_new_connection /* EAPI: new_connection */
bed98ff9 888#endif
889};
87822447 890#else
891static void
ff47641b 892waklog_register_hooks (apr_pool_t * p)
87822447 893{
ff47641b 894 ap_hook_header_parser (waklog_phase2, NULL, NULL, APR_HOOK_FIRST);
895 ap_hook_fixups (waklog_phase7, NULL, NULL, APR_HOOK_FIRST);
896 ap_hook_child_init (waklog_child_init, NULL, NULL, APR_HOOK_FIRST);
897 ap_hook_post_read_request (waklog_phase0, NULL, NULL, APR_HOOK_FIRST);
898 ap_hook_pre_connection (waklog_new_connection, NULL, NULL, APR_HOOK_FIRST);
899 ap_hook_post_config (waklog_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
87822447 900}
901
902
903module AP_MODULE_DECLARE_DATA waklog_module =
904{
905 STANDARD20_MODULE_STUFF,
906 NULL, /* create per-dir conf structures */
907 NULL, /* merge per-dir conf structures */
908 waklog_create_server_config, /* create per-server conf structures */
909 NULL, /* merge per-server conf structures */
910 waklog_cmds, /* table of configuration directives */
911 waklog_register_hooks /* register hooks */
912};
913#endif
161ffd84 914