0910ec65b0ed130020832e40a671f541890da69d
[hcoop/zz_old/modwaklog.git] / mod_waklog.c
1 #define _LARGEFILE64_SOURCE
2 #define _GNU_SOURCE
3
4 #include "httpd.h"
5 #include "http_config.h"
6 #include "http_log.h"
7 #include "http_protocol.h"
8 #include "http_request.h"
9 #include "http_core.h"
10
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
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
33 module AP_MODULE_DECLARE_DATA waklog_module;
34
35 #define MK_POOL apr_pool_t
36 #define MK_TABLE_GET apr_table_get
37 #define MK_TABLE_SET apr_table_set
38 #include "unixd.h"
39 extern 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, \
45 (void*)APR_OFFSETOF(waklog_commands, var), \
46 OR_AUTHCFG | RSRC_CONF, usage)
47 typedef struct {
48 int dummy;
49 }
50 child_info;
51
52 const char *userdata_key = "waklog_init";
53 #else
54 #include "ap_config.h"
55
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
89 int cell_in_principal = 1;
90 #else
91 int cell_in_principal = 0;
92 #endif
93
94 /* this is used to turn off pag generation for the backround worker child during startup */
95 int pag_for_children = 1;
96
97 typedef 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 }
111 waklog_config;
112
113 typedef 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
124 waklog_child_config child;
125
126 struct 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
137 struct sharedspace_s {
138 int renewcount;
139 struct tokencache_ent sharedtokens[SHARED_TABLE_SIZE];
140 };
141
142 struct sharedspace_s *sharedspace = NULL;
143
144 struct renew_ent {
145 char *keytab;
146 char *principal;
147 int lastrenewed;
148 };
149
150 #ifdef use_pthreads
151 pthread_rwlock_t *sharedlock = NULL;
152 #else
153 rwlock_t *sharedlock = NULL;
154 #endif
155
156 struct renew_ent renewtable[SHARED_TABLE_SIZE];
157
158 int renewcount = 0;
159
160 module 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, \
165 (void*)XtOffsetOf(waklog_commands, var), \
166 OR_AUTHCFG | RSRC_CONF, type, usage }
167 #endif /* STANDARD20_MODULE_STUFF */
168
169 #define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
170
171 #include <krb5.h>
172
173 #if defined(sun)
174 #include <sys/ioccom.h>
175 #endif /* sun */
176 #include <stropts.h>
177 #include <afs/venus.h>
178 #include <afs/auth.h>
179 #include <afs/dirpath.h>
180 #include <afs/ptuser.h>
181 #include <rx/rxkad.h>
182
183 #define KEYTAB "/etc/keytab.wwwserver"
184 #define PRINCIPAL "someplacewwwserver"
185 #define AFS_CELL "someplace.edu"
186
187 /* If there's an error, retry more aggressively */
188 #define ERR_SLEEP_TIME 5*60
189
190
191 #define K5PATH "FILE:/tmp/waklog.creds.k5"
192
193 static void
194 log_error(const char *file, int line, int level, int status,
195 const server_rec *s, const char *fmt, ...)
196 {
197 char errstr[1024];
198 va_list ap;
199
200 va_start(ap, fmt);
201 vsnprintf(errstr, sizeof(errstr), fmt, ap);
202 va_end(ap);
203
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
209
210 }
211
212 static void *
213 waklog_create_server_config( MK_POOL *p, server_rec *s )
214 {
215 waklog_config *cfg;
216
217 cfg = (waklog_config *)ap_pcalloc( p, sizeof( waklog_config ));
218 cfg->p = p;
219 cfg->forked = 0;
220 cfg->configured = 0;
221 cfg->protect = 0;
222 cfg->keytab = KEYTAB;
223 cfg->principal = PRINCIPAL;
224 cfg->afs_cell = AFS_CELL;
225
226 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: server config created." );
227
228 return( cfg );
229 }
230
231
232 static const char *
233 set_waklog_protect( cmd_parms *params, void *mconfig, int flag )
234 {
235 waklog_config *cfg;
236
237 getModConfig(cfg, params->server );
238
239 cfg->protect = flag;
240 cfg->configured = 1;
241 log_error( APLOG_MARK, APLOG_DEBUG, 0, params->server, "mod_waklog: waklog_protect set" );
242 return( NULL );
243 }
244
245
246 static const char *
247 set_waklog_keytab( cmd_parms *params, void *mconfig, char *file )
248 {
249 waklog_config *cfg;
250
251 getModConfig(cfg, params->server );
252
253 log_error( APLOG_MARK, APLOG_INFO, 0, params->server,
254 "mod_waklog: will use keytab: %s", file );
255
256 cfg->keytab = ap_pstrdup ( params->pool, file );
257 cfg->configured = 1;
258 return( NULL );
259 }
260
261
262 static const char *
263 set_waklog_use_principal( cmd_parms *params, void *mconfig, char *file )
264 {
265 waklog_config *cfg;
266
267 getModConfig(cfg, params->server );
268
269 log_error( APLOG_MARK, APLOG_INFO, 0, params->server,
270 "mod_waklog: will use principal: %s", file );
271
272 cfg->principal = ap_pstrdup ( params->pool, file );
273 cfg->configured = 1;
274 return( NULL );
275 }
276
277
278 static const char *
279 set_waklog_use_afs_cell( cmd_parms *params, void *mconfig, char *file )
280 {
281 waklog_config *cfg;
282
283 getModConfig(cfg, params->server );
284
285 log_error( APLOG_MARK, APLOG_INFO, 0, params->server,
286 "mod_waklog: will use afs_cell: %s", file );
287
288 cfg->afs_cell = ap_pstrdup( params->pool, file );
289 cfg->configured = 1;
290 return( NULL );
291 }
292
293
294 static void
295 #ifdef STANDARD20_MODULE_STUFF
296 waklog_child_init(MK_POOL *p, server_rec *s)
297 #else
298 waklog_child_init(server_rec *s, MK_POOL *p)
299 #endif
300 {
301
302 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
303 "mod_waklog: child_init called" );
304
305 memset( &child.token, 0, sizeof( struct ktc_token ) );
306
307 setpag();
308
309 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
310 "mod_waklog: child_init returned" );
311
312 return;
313 }
314
315 typedef struct {
316 int wak_protect;
317 char *wak_keytab;
318 char *wak_ktprinc;
319 char *wak_afscell;
320 } waklog_commands;
321
322 command_rec waklog_cmds[ ] =
323 {
324 command("WaklogProtected", set_waklog_protect, wak_protect, FLAG, "enable waklog on a location or directory basis"),
325
326 command("WaklogKeytab", set_waklog_keytab, wak_keytab, TAKE1, "Use the supplied keytab rather than the default"),
327
328 command("WaklogUseKeytabPrincipal", set_waklog_use_principal, wak_ktprinc, TAKE1, "Use the supplied keytab principal rather than the default"),
329
330 command("WaklogUseAFSCell", set_waklog_use_afs_cell, wak_afscell, TAKE1, "Use the supplied AFS cell rather than the default"),
331
332 { NULL }
333 };
334
335
336 static int
337 token_cleanup( void *data )
338 {
339 request_rec *r = (request_rec *)data;
340
341 if ( child.token.ticketLen ) {
342 memset( &child.token, 0, sizeof( struct ktc_token ) );
343
344 ktc_ForgetAllTokens();
345
346 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
347 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d", getpid() );
348 }
349 return 0;
350 }
351
352
353 static int
354 waklog_kinit( server_rec *s )
355 {
356 krb5_error_code kerror = 0;
357 krb5_context kcontext = NULL;
358 krb5_principal kprinc = NULL;
359 krb5_get_init_creds_opt kopts;
360 krb5_creds v5creds;
361 krb5_ccache kccache = NULL;
362 krb5_keytab keytab = NULL;
363 char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ];
364 int i;
365 waklog_config *cfg;
366
367 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
368 "mod_waklog: waklog_kinit called: pid: %d", getpid() );
369
370 getModConfig(cfg, s);
371
372 if (( kerror = krb5_init_context( &kcontext ))) {
373 log_error( APLOG_MARK, APLOG_ERR, 0, s,
374 "mod_waklog: %s", (char *)error_message( kerror ));
375
376 goto cleanup;
377 }
378
379 /* use the path */
380 if (( kerror = krb5_cc_resolve( kcontext, K5PATH, &kccache )) != 0 ) {
381 log_error( APLOG_MARK, APLOG_ERR, 0, s,
382 "mod_waklog: %s", (char *)error_message( kerror ));
383
384 goto cleanup;
385 }
386
387 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
388 "mod_waklog: principal: %s", cfg->principal );
389
390 if (( kerror = krb5_parse_name( kcontext, cfg->principal, &kprinc ))) {
391 log_error( APLOG_MARK, APLOG_ERR, 0, s,
392 "mod_waklog: %s", (char *)error_message( kerror ));
393
394 goto cleanup;
395 }
396
397 krb5_get_init_creds_opt_init( &kopts );
398 krb5_get_init_creds_opt_set_tkt_life( &kopts, TKT_LIFE );
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 );
402
403 /* keytab from config */
404 strncpy( ktbuf, cfg->keytab, sizeof( ktbuf ) - 1 );
405
406 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
407 "mod_waklog: waklog_kinit using: %s", ktbuf );
408
409 if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) {
410 log_error( APLOG_MARK, APLOG_ERR, 0, s,
411 "mod_waklog:krb5_kt_resolve %s", (char *)error_message( kerror ));
412
413 goto cleanup;
414 }
415
416 memset( (char *)&v5creds, 0, sizeof(v5creds));
417
418 /* get the krbtgt */
419 if (( kerror = krb5_get_init_creds_keytab( kcontext, &v5creds,
420 kprinc, keytab, 0, NULL, &kopts ))) {
421
422 log_error( APLOG_MARK, APLOG_ERR, 0, s,
423 "mod_waklog:krb5_get_init_creds_keytab %s", (char *)error_message( kerror ));
424
425 goto cleanup;
426 }
427
428 if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) {
429 log_error( APLOG_MARK, APLOG_ERR, 0, s,
430 "mod_waklog:krb5_cc_initialize %s", (char *)error_message( kerror ));
431
432 goto cleanup;
433 }
434
435 kerror = krb5_cc_store_cred( kcontext, kccache, &v5creds );
436 krb5_free_cred_contents( kcontext, &v5creds );
437 if ( kerror != 0 ) {
438 log_error( APLOG_MARK, APLOG_ERR, 0, s,
439 "mod_waklog: %s", (char *)error_message( kerror ));
440
441 goto cleanup;
442 }
443
444 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
445 "mod_waklog: waklog_kinit success" );
446
447 cleanup:
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 );
456
457 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
458 "mod_waklog: waklog_kinit: exiting" );
459
460 return( kerror );
461 }
462
463
464 static void
465 waklog_aklog( request_rec *r )
466 {
467 int rc;
468 char buf[ MAXKTCTICKETLEN ];
469 const char *k5path = NULL;
470 krb5_error_code kerror;
471 krb5_context kcontext = NULL;
472 krb5_creds increds;
473 krb5_creds *v5credsp = NULL;
474 krb5_ccache kccache = NULL;
475 struct ktc_principal server = { "afs", "", "" };
476 struct ktc_principal client;
477 struct ktc_token token;
478 waklog_config *cfg;
479 int buflen;
480
481 k5path = MK_TABLE_GET( r->subprocess_env, "KRB5CCNAME" );
482
483 log_error( APLOG_MARK, APLOG_INFO, 0, r->server,
484 "mod_waklog: waklog_aklog called: k5path: %s", k5path );
485
486 if ( k5path == NULL ) {
487 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
488 "mod_waklog: waklog_aklog giving up" );
489 goto cleanup;
490 }
491
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 ) */
498 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
499 (char *)error_message( kerror ));
500
501 goto cleanup;
502 }
503
504 memset( (char *)&increds, 0, sizeof(increds));
505
506 getModConfig(cfg, r->server );
507
508 /* afs/<cell> or afs */
509 strncpy( buf, "afs", sizeof( buf ) - 1 );
510 if ( strcmp( cfg->afs_cell, AFS_CELL ) ) {
511 strncat( buf, "/" , sizeof( buf ) - strlen( buf ) - 1 );
512 strncat( buf, cfg->afs_cell, sizeof( buf ) - strlen( buf ) - 1 );
513 }
514
515 /* set server part */
516 if (( kerror = krb5_parse_name( kcontext, buf, &increds.server ))) {
517 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
518 (char *)error_message( kerror ));
519
520 goto cleanup;
521 }
522
523 if (( kerror = krb5_cc_resolve( kcontext, k5path, &kccache )) != 0 ) {
524 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
525 (char *)error_message( kerror ));
526
527 goto cleanup;
528 }
529
530 /* set client part */
531 krb5_cc_get_principal( kcontext, kccache, &increds.client );
532
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 ) ) ) {
540 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
541 "mod_waklog: krb5_get_credentials: %s", error_message( kerror ));
542 goto cleanup;
543 }
544
545 /* don't overflow */
546 if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) { /* from krb524d.c */
547 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
548 "mod_waklog: ticket size (%d) too big to fake", v5credsp->ticket.length );
549 goto cleanup;
550 }
551
552 /* assemble the token */
553 memset( &token, 0, sizeof( struct ktc_token ) );
554
555 token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime;
556 token.endTime = v5credsp->times.endtime;
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 );
561
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
569 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
570 "mod_waklog: client: %s", buf );
571
572 /* build the name */
573 memmove( buf, v5credsp->client->data[0].data,
574 min( v5credsp->client->data[0].length, MAXKTCNAMELEN - 1 ) );
575 buf[ v5credsp->client->data[0].length ] = '\0';
576 if ( v5credsp->client->length > 1 ) {
577 strncat( buf, ".", sizeof( buf ) - strlen( buf ) - 1 );
578 buflen = strlen( buf );
579 memmove( buf + buflen, v5credsp->client->data[1].data,
580 min( v5credsp->client->data[1].length, MAXKTCNAMELEN - strlen( buf ) - 1 ) );
581 buf[ buflen + v5credsp->client->data[1].length ] = '\0';
582 }
583
584 /* assemble the client */
585 strncpy( client.name, buf, sizeof( client.name ) - 1 );
586 strncpy( client.instance, "", sizeof( client.instance) - 1 );
587 memmove( buf, v5credsp->client->realm.data,
588 min( v5credsp->client->realm.length, MAXKTCNAMELEN - 1 ) );
589 buf[ v5credsp->client->realm.length ] = '\0';
590 strncpy( client.cell, buf, sizeof( client.cell ) - 1 );
591
592 /* assemble the server's cell */
593 strncpy( server.cell, cfg->afs_cell , sizeof( server.cell ) - 1 );
594
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 );
602
603 /* use the path */
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 ) ) ) {
609 log_error( APLOG_MARK, APLOG_ERR, 0, r->server,
610 "mod_waklog: settoken returned %d", rc );
611 goto cleanup;
612 }
613
614 /* save this */
615 memmove( &child.token, &token, sizeof( struct ktc_token ) );
616
617 /* we'll need to unlog when this connection is done. */
618 ap_register_cleanup( r->pool, (void *)r, token_cleanup, ap_null_cleanup );
619 }
620
621 cleanup:
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 );
632
633 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
634 "mod_waklog: finished with waklog_aklog" );
635
636 return;
637
638 }
639
640 static int
641 waklog_child_routine( void *s, child_info *pinfo )
642 {
643 if ( !getuid() ) {
644 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
645 "mod_waklog: waklog_child_routine called as root" );
646
647 /* this was causing the credential file to get owned by root */
648 #ifdef STANDARD20_MODULE_STUFF
649 setgid(ap_group_id);
650 setuid(ap_user_id);
651 #endif
652 }
653
654 while( 1 ) {
655 waklog_kinit( s );
656 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
657 "mod_waklog: child_routine sleeping" );
658 sleep( SLEEP_TIME );
659 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
660 "mod_waklog: slept, calling waklog_kinit" );
661 }
662
663 }
664
665 #ifdef STANDARD20_MODULE_STUFF
666 static int
667 waklog_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;
673 waklog_config *cfg;
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
706 static void
707 waklog_init( server_rec *s, MK_POOL *p )
708 {
709 extern char *version;
710 int pid;
711
712 log_error( APLOG_MARK, APLOG_INFO, 0, s,
713 "mod_waklog: version %s initialized.", version );
714
715 pid = ap_bspawn_child( p, waklog_child_routine, s, kill_always,
716 NULL, NULL, NULL );
717
718 log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
719 "mod_waklog: ap_bspawn_child: %d.", pid );
720 }
721 #endif
722
723 static int
724 waklog_phase0( request_rec *r )
725 {
726 waklog_config *cfg;
727
728 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
729 "mod_waklog: phase0 called" );
730
731 getModConfig(cfg, r->server );
732
733 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
734 "mod_waklog: phase0, checking cfg->protect" );
735 if ( !cfg->protect ) {
736 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
737 "mod_waklog: phase0 declining" );
738 return( DECLINED );
739 }
740
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 );
745
746 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
747 "mod_waklog: phase0, checking child.token.ticketLen" );
748 /* do this only if we are still unauthenticated */
749 if ( !child.token.ticketLen ) {
750
751 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
752 "mod_waklog: phase0, calling waklog_aklog" );
753 /* stuff the credentials into the kernel */
754 waklog_aklog( r );
755 }
756
757 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
758 "mod_waklog: phase0 returning" );
759 return DECLINED;
760 }
761
762
763 static int
764 waklog_phase7( request_rec *r )
765 {
766 waklog_config *cfg;
767
768 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
769 "mod_waklog: phase7 called" );
770
771 getModConfig(cfg, r->server );
772
773 if ( !cfg->protect ) {
774 return( DECLINED );
775 }
776
777 /* stuff the credentials into the kernel */
778
779 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
780 "mod_waklog: phase7, calling waklog_aklog" );
781 waklog_aklog( r );
782
783 log_error( APLOG_MARK, APLOG_DEBUG, 0, r->server,
784 "mod_waklog: phase7 returning" );
785
786 return DECLINED;
787 }
788
789
790 static
791 #ifdef STANDARD20_MODULE_STUFF
792 int
793 #else
794 void
795 #endif
796 waklog_new_connection (conn_rec * c
797 #ifdef STANDARD20_MODULE_STUFF
798 , void *dummy
799 #endif
800 )
801 {
802
803 waklog_commands *cfg;
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
817 return
818 #ifdef STANDARD20_MODULE_STUFF
819 0
820 #endif
821 ;
822 }
823
824
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 */
834 static int
835 waklog_phase2 (request_rec * r)
836 {
837
838 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
839 "mod_waklog: phase2 called");
840
841 if (child.token.ticketLen)
842 {
843 memset (&child.token, 0, sizeof (struct ktc_token));
844
845 ktc_ForgetAllTokens ();
846
847 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
848 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
849 getpid ());
850 }
851
852 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
853 "mod_waklog: phase2 returning");
854
855 return DECLINED;
856 }
857
858 #ifndef STANDARD20_MODULE_STUFF
859 module MODULE_VAR_EXPORT waklog_module = {
860 STANDARD_MODULE_STUFF,
861 waklog_init, /* module initializer */
862 #if 0
863 waklog_create_dir_config, /* create per-dir config structures */
864 #else /* 0 */
865 NULL, /* create per-dir config structures */
866 #endif /* 0 */
867 NULL, /* merge per-dir config structures */
868 waklog_create_server_config, /* create per-server config structures */
869 NULL, /* merge per-server config structures */
870 waklog_cmds, /* table of config file commands */
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 */
877 waklog_phase7, /* [#7] pre-run fixups */
878 NULL, /* [#9] log a transaction */
879 waklog_phase2, /* [#2] header parser */
880 waklog_child_init, /* child_init */
881 NULL, /* child_exit */
882 waklog_phase0 /* [#0] post read-request */
883 #ifdef EAPI
884 ,NULL, /* EAPI: add_module */
885 NULL, /* EAPI: remove_module */
886 NULL, /* EAPI: rewrite_command */
887 waklog_new_connection /* EAPI: new_connection */
888 #endif
889 };
890 #else
891 static void
892 waklog_register_hooks (apr_pool_t * p)
893 {
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);
900 }
901
902
903 module 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
914