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