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