reinstated pre-umbc behavior to use mod_auth_kerb credentials when available
[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
891fb458 27#ifdef STANDARD20_MODULE_STUFF
c9d59a9c 28#define APACHE2
29#endif
30
31/********************* APACHE1 ******************************************************************************/
32#ifndef APACHE2
ebb1f61c 33#include "ap_config.h"
34#if defined(sun)
35#include <sys/ioccom.h>
36#endif /* sun */
37#include <http_conf_globals.h>
38#define MK_POOL pool
39#define MK_TABLE_GET ap_table_get
40#define MK_TABLE_SET ap_table_set
41#define command(name, func, var, type, usage) \
42 { name, func, \
43 NULL , \
44 RSRC_CONF | ACCESS_CONF , type, usage }
21a7788b 45module waklog_module;
ebb1f61c 46
47/********************* APACHE2 ******************************************************************************/
48#else
87822447 49#include <apr_strings.h>
50#include <apr_base64.h>
ebb1f61c 51#define ap_pcalloc apr_pcalloc
52#define ap_pdupstr apr_pdupstr
53#define ap_pstrdup apr_pstrdup
87822447 54#define MK_POOL apr_pool_t
55#define MK_TABLE_GET apr_table_get
d06251b1 56#define MK_TABLE_SET apr_table_set
87822447 57#include "unixd.h"
58extern unixd_config_rec unixd_config;
59#define ap_user_id unixd_config.user_id
60#define ap_group_id unixd_config.group_id
61#define ap_user_name unixd_config.user_name
62#define command(name, func, var, type, usage) \
63 AP_INIT_ ## type (name, (void*) func, \
ebb1f61c 64 NULL, \
65 RSRC_CONF | ACCESS_CONF, usage)
21a7788b 66module AP_MODULE_DECLARE_DATA waklog_module;
67typedef struct { int dummy; } child_info;
87822447 68const char *userdata_key = "waklog_init";
21a7788b 69
c9d59a9c 70#endif /* APACHE2 */
ebb1f61c 71/**************************************************************************************************/
877d453f 72
73#include <krb5.h>
877d453f 74#include <stropts.h>
75#include <afs/venus.h>
76#include <afs/auth.h>
77#include <afs/dirpath.h>
78#include <afs/ptuser.h>
79#include <rx/rxkad.h>
80
81#define TKT_LIFE ( 12 * 60 * 60 )
42d78dfb 82#define SLEEP_TIME ( TKT_LIFE - 5*60 )
877d453f 83
84#define WAKLOG_ON 1
85#define WAKLOG_OFF 2
86#define WAKLOG_UNSET 0
87
88#ifdef WAKLOG_DEBUG
89#undef APLOG_DEBUG
90#define APLOG_DEBUG APLOG_ERR
91#endif
92
877d453f 93/* this is used to turn off pag generation for the backround worker child during startup */
94int pag_for_children = 1;
95
96typedef struct
97{
98 int forked;
99 int configured;
100 int protect;
101 int usertokens;
c8563f50 102 int cell_in_principal;
21a7788b 103 int disable_token_cache;
877d453f 104 char *keytab;
105 char *principal;
106 char *default_principal;
107 char *default_keytab;
108 char *afs_cell;
109 char *path;
110 MK_POOL *p;
111}
112waklog_config;
113
114typedef struct
115{
116 struct ktc_token token;
117 char clientprincipal[MAXNAMELEN];
118 krb5_context kcontext;
119 krb5_ccache ccache;
120 struct ktc_principal server;
121 struct ktc_principal client;
122 int pr_init;
123} waklog_child_config;
124
125waklog_child_config child;
126
127struct tokencache_ent {
128 char clientprincipal[MAXNAMELEN];
129 struct ktc_token token;
130 struct ktc_principal client;
131 struct ktc_principal server;
132 time_t lastused;
133 int persist;
134};
135
136#define SHARED_TABLE_SIZE 512
137
138struct sharedspace_s {
139 int renewcount;
140 struct tokencache_ent sharedtokens[SHARED_TABLE_SIZE];
141};
142
143struct sharedspace_s *sharedspace = NULL;
144
145struct renew_ent {
146 char *keytab;
147 char *principal;
148 int lastrenewed;
149};
150
151#ifdef use_pthreads
152pthread_rwlock_t *sharedlock = NULL;
153#else
154rwlock_t *sharedlock = NULL;
155#endif
156
157struct renew_ent renewtable[SHARED_TABLE_SIZE];
158
159int renewcount = 0;
160
ebb1f61c 161
87822447 162
c69d952f 163#define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
87822447 164
4e1ae1cd 165#include <krb5.h>
bed98ff9 166
7193eb01 167#if defined(sun)
bed98ff9 168#include <sys/ioccom.h>
7193eb01 169#endif /* sun */
bed98ff9 170#include <stropts.h>
bed98ff9 171#include <afs/venus.h>
7193eb01 172#include <afs/auth.h>
d06251b1 173#include <afs/dirpath.h>
174#include <afs/ptuser.h>
7193eb01 175#include <rx/rxkad.h>
176
58bbdc54 177
87822447 178static void
3f4fda20 179log_error (const char *file, int line, int level, int status,
42d78dfb 180 const server_rec * s, const char *fmt, ...)
4d47a8d9 181{
3f4fda20 182 char errstr[4096];
183 va_list ap;
4d47a8d9 184
3f4fda20 185 va_start (ap, fmt);
186 vsnprintf (errstr, 1024, fmt, ap);
187 va_end (ap);
4d47a8d9 188
c9d59a9c 189#ifdef APACHE2
3f4fda20 190 ap_log_error (file, line, level | APLOG_NOERRNO, status, s, "(%d) %s", getpid(), errstr);
87822447 191#else
3f4fda20 192 ap_log_error (file, line, level | APLOG_NOERRNO, s, "(%d) %s", getpid(), errstr);
87822447 193#endif
4d47a8d9 194
87822447 195}
4d47a8d9 196
3f4fda20 197waklog_config *retrieve_config(request_rec *r) {
198
199 request_rec *my;
200 waklog_config *cfg;
201
202 if ( r && r->main ) {
203 my = r->main;
204 } else if (r) {
205 my = r;
206 } else {
207 return NULL;
208 }
209
210 if ( my && ( cfg = (waklog_config *) ap_get_module_config(my->per_dir_config, &waklog_module ) ) ) {
211 return cfg;
212 } else {
213 getModConfig (cfg, r->server);
214 }
215
216 return cfg;
217
218}
313dde40 219
3f4fda20 220/* set_auth -- sets the tokens of the current process to this user.
221 if "self" is set, it divines the user from the current requests' environment.
222 otherwise, it's gettng it from principal/keytab */
223
224int
225set_auth ( server_rec *s, request_rec *r, int self, char *principal, char *keytab, int storeonly ) {
226
227 int i;
228 int usecached = 0;
229 krb5_error_code kerror = 0;
230 krb5_principal kprinc = NULL;
231 krb5_get_init_creds_opt kopts;
232 krb5_creds v5creds;
233 krb5_creds increds;
234 struct ktc_principal server = { "afs", "", "" };
235 struct ktc_principal client;
236 struct ktc_token token;
237 krb5_creds *v5credsp = NULL;
238 krb5_keytab krb5kt = NULL;
239 char buf[MAXNAMELEN];
240 waklog_config *cfg;
241 int rc = 0;
242 int buflen = 0;
243 time_t oldest_time = 0;
244 int oldest;
245 int stored = -1;
246 time_t mytime;
247 int indentical;
c8563f50 248 int cell_in_principal;
249 int attempt;
7c53b5d0 250 int use_client_credentials = 0;
3f4fda20 251
252 char k5user[MAXNAMELEN];
253 char *k5secret;
7c53b5d0 254 char *k5path = NULL;
3f4fda20 255
7c53b5d0 256 k5path = !r ? NULL : MK_TABLE_GET( r->subprocess_env, "KRB5CCNAME" );
257
3f4fda20 258 memset((char *) &increds, 0, sizeof(increds));
3f4fda20 259 /* init some stuff if it ain't already */
260
261 if ( ! child.kcontext ) {
262 kerror = krb5_init_context(&child.kcontext);
263 }
264
7c53b5d0 265 if (!k5path || !*k5path) {
266 k5path = "MEMORY:tmpcache";
267 }
268 if ( ( ! child.ccache ) && ( kerror = krb5_cc_resolve(child.kcontext, k5path, &child.ccache) ) ) {
269 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize credentials cache %s err=%d",
270 k5path, kerror );
3f4fda20 271 }
272
7c53b5d0 273 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: %d, %s, %s, %d, KRB5CC=%s",
274 self, principal ? principal : "NULL",
275 keytab ? keytab : "NULL", storeonly, k5path ? k5path : "NULL");
3f4fda20 276
277 /* pull the server config record that we care about... */
278
279 if ( r ) {
280 cfg = retrieve_config(r);
281 } else {
282 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 283 "mod_waklog: set_auth using no config" );
3f4fda20 284 getModConfig (cfg, s);
285 }
286
287 if ( ! cfg ) {
288 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: cfg is %d", cfg );
289 }
290
c9d59a9c 291#ifdef APACHE2
3f4fda20 292 if ( self ) {
293 /* pull out our principal name and stuff from the environment -- webauth better have sent
294 through. This here is also where you'd suck stuff out of KRB5CCNAME if we were
295 using something like Cosign */
296
297 if ( ! ( r && r->connection && r->user )) {
298 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: self authentication selected, but no data available");
7c53b5d0 299 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: r->user=%s", (r->user==NULL ? "null" : r->user==NULL));
3f4fda20 300 return -1;
301 }
302
303 strncpy(k5user, r->user, sizeof(k5user));
304
305 /* the other thing we need is someone's password */
306 if ( ! ( k5secret = (char *) MK_TABLE_GET( r->notes, "ATTR_PASSWORD" ) ) ) {
307 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cant do self auth without a secret");
308 return -1;
309 }
310
311 /* we'll pick this up later after we've checked the cache and current state */
312
313 } else
314#endif
7c53b5d0 315 if (r && r->user) {
316 strncpy(k5user, r->user, sizeof(k5user));
317 keytab = NULL;
318 } else if ( principal ) {
3f4fda20 319 strncpy( k5user, principal, sizeof(k5user));
320 }
321
7c53b5d0 322 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: k5user=%s", k5user ? k5user : "NULL");
3f4fda20 323 mytime = time(0);
324
325 /* see if we should just go ahead and ignore this call, since we already should be set to these
326 credentials */
313dde40 327
3f4fda20 328 if ( ! storeonly ) {
313dde40 329
3f4fda20 330#ifdef use_pthreads
331 pthread_rwlock_rdlock( sharedlock );
332#else
333 rw_rdlock( sharedlock );
334#endif
313dde40 335
3f4fda20 336 for ( i = 0; i < SHARED_TABLE_SIZE; ++i ) {
337
338 /* if it's a token for the principal we're looking for, and it hasn't expired yet */
339
340 if ( ( !strcmp( k5user,
341 sharedspace->sharedtokens[i].clientprincipal ) ) &&
342 ( sharedspace->sharedtokens[i].token.endTime > mytime ) ) {
343
344 if ( ! memcmp(&child.token, &sharedspace->sharedtokens[i].token, sizeof(child.token) ) ) {
345 indentical = 1;
346 } else {
347 indentical = 0;
348 }
349
350 /* copy the token out of the cache and into the child object */
351
352 strcpy(child.clientprincipal, sharedspace->sharedtokens[i].clientprincipal );
353 memcpy(&child.token, &sharedspace->sharedtokens[i].token, sizeof(child.token));
354 memcpy(&child.server, &sharedspace->sharedtokens[i].server, sizeof(child.server));
355 memcpy(&child.client, &sharedspace->sharedtokens[i].client, sizeof(child.client));
356
357 /* set our last used time thing */
358 sharedspace->sharedtokens[i].lastused = mytime;
359
360 usecached = 1;
361
362 break;
363
364 }
365
366 }
367
368 /* release the lock on the token cache */
369#ifdef use_pthreads
370 pthread_rwlock_unlock( sharedlock );
371#else
372 rw_unlock( sharedlock );
373#endif
313dde40 374
3f4fda20 375 if ( usecached ) {
376 /* release the lock on the token cache */
377 log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
378 "mod_waklog: set_auth using shared token %d for %s", i, k5user );
379
380 }
381
382 /* if this is something that was in the cache, and it's the same as the token we already have stored,
383 and we weren't calling this just to renew it... */
384
385 if ( usecached && indentical ) {
386 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: token is identical for %s", k5user );
387 return 0;
388 }
389
390 }
7c53b5d0 391
3f4fda20 392 /* if 'usecached' isn't set, we've got to get our tokens from somewhere... */
3f4fda20 393 if (( ! usecached ) && ( k5user )) {
313dde40 394
3f4fda20 395 /* clear out the creds structure */
396 memset((void *) &v5creds, 0, sizeof(v5creds));
397
398 /* create a principal out of our k5user string */
399
400 if ( kerror = krb5_parse_name (child.kcontext, k5user, &kprinc ) ) {
401 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse_name %s", (char *) error_message(kerror) );
402 goto cleanup;
403 }
404
405 /* create the credentials options */
406
407 krb5_get_init_creds_opt_init ( &kopts );
408 krb5_get_init_creds_opt_set_tkt_life ( &kopts, TKT_LIFE );
409 krb5_get_init_creds_opt_set_renew_life ( &kopts, 0 );
410 krb5_get_init_creds_opt_set_forwardable ( &kopts, 0 );
411 krb5_get_init_creds_opt_set_proxiable ( &kopts, 0 );
412
413 if ( keytab ) {
414
415 /* if we've been passed a keytab, we're going to be getting our credentials from it */
416
417 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using keytab %s", keytab);
418
419 if ( kerror = krb5_kt_resolve(child.kcontext, keytab, &krb5kt ) ) {
420 log_error( APLOG_MARK, APLOG_ERR, 0, s,
421 "mod_waklog: krb5_kt_resolve %s", error_message(kerror) );
422 goto cleanup;
423 }
424
425 if ((kerror = krb5_get_init_creds_keytab (child.kcontext, &v5creds,
426 kprinc, krb5kt, 0, NULL, &kopts ) ) ) {
427 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_init_creds_keytab %s",
428 error_message(kerror) );
429 goto cleanup;
430 }
431
432 } else if ( self ) {
433
434 /* if 'self' is set, we're going to use the credentials provided in the credential information */
435 /* if you're using CoSign, you'd actually just set the ccache to the KRB5CCNAME credentials */
436 /* and skip ahead... Our WebSSO is lame, but has a way for us to snarf the password out of */
437 /* the encrypted token for proxy-authentication stuff. We only hand out keys that allow this */
438 /* functionality to VERY special people. */
439
440 if ((kerror = krb5_get_init_creds_password ( child.kcontext, &v5creds,
441 kprinc, k5secret, NULL, NULL, 0, NULL, &kopts ) ) ) {
442 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_init_creds_password %s",
443 error_message(kerror) );
444 /* nuke the password so it doesn't end up in core files */
445 memset(k5secret, 0, sizeof(k5secret));
446 goto cleanup;
447 }
448
449 memset(k5secret, 0, sizeof(k5secret));
450
451 } else {
7c53b5d0 452 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: no keytab, no self; assuming mod_auth_kerb or similar");
453 use_client_credentials = 1;
3f4fda20 454 }
455
456 /* initialize the credentials cache and store the stuff we just got */
7c53b5d0 457 if (!use_client_credentials) {
458 if ( kerror = krb5_cc_initialize (child.kcontext, child.ccache, kprinc)) {
459 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: init credentials cache %s",
460 error_message(kerror));
461 goto cleanup;
462 }
3f4fda20 463
7c53b5d0 464 if ( kerror = krb5_cc_store_cred(child.kcontext, child.ccache, &v5creds) ) {
465 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot store credentials %s",
466 error_message(kerror));
467 goto cleanup;
468 }
3f4fda20 469 }
470
471 krb5_free_cred_contents(child.kcontext, &v5creds);
472
473 if ( kerror ) {
474 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: store cred %s", error_message(kerror));
475 goto cleanup;
476 }
477
478 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: kinit ok for %s", k5user );
479
480 /* now, to the 'aklog' portion of our program. */
481
482 strncpy( buf, "afs", sizeof(buf) - 1 );
313dde40 483
c8563f50 484 /** we make two attempts here, one for afs@REALM and one for afs/cell@REALM */
485 for(attempt = 0; attempt <= 1; attempt++) {
486 cell_in_principal = (cfg->cell_in_principal + attempt) % 2;
487
488 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: cell_in_principal=%d", cell_in_principal );
489 if (cell_in_principal) {
490 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
491 strncat(buf, cfg->afs_cell, sizeof(buf) - strlen(buf) - 1);
492 }
493
494 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using AFS principal: %s", buf);
495
496 if ((kerror = krb5_parse_name (child.kcontext, buf, &increds.server))) {
497 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse name %s", error_message(kerror));
498 goto cleanup;
499 }
7c53b5d0 500
501 if (use_client_credentials) {
502 if (( kerror = krb5_cc_resolve( child.kcontext, k5path, &child.ccache)) != 0 ) {
503 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_resolve %s", error_message(kerror));
504 goto cleanup;
505 }
506 }
c8563f50 507
508 if ((kerror = krb5_cc_get_principal(child.kcontext, child.ccache, &increds.client))) {
509 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_get_princ %s", error_message(kerror));
510 goto cleanup;
511 }
512
513 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: retrieved data from ccache for %s", k5user);
514
515 increds.times.endtime = 0;
516
517 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
518
519 if (kerror = krb5_get_credentials (child.kcontext, 0, child.ccache, &increds, &v5credsp )) {
520 /* only complain once we've tried both afs@REALM and afs/cell@REALM */
521 if (attempt>=1) {
522 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
523 error_message(kerror));
524 goto cleanup;
525 } else {
526 continue;
527 }
528 }
529 cfg->cell_in_principal = cell_in_principal;
530 break;
3f4fda20 531 }
c8563f50 532
3f4fda20 533 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: get_credentials passed for %s", k5user);
534
535 if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) {
536 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: ticket size (%d) too big to fake",
537 v5credsp->ticket.length);
538 goto cleanup;
539 }
313dde40 540
3f4fda20 541 memset(&token, 0, sizeof(struct ktc_token));
542
543 token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime;
544 token.endTime = v5credsp->times.endtime;
545
546 memmove( &token.sessionKey, v5credsp->keyblock.contents, v5credsp->keyblock.length);
547 token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
548 token.ticketLen = v5credsp->ticket.length;
549 memmove( token.ticket, v5credsp->ticket.data, token.ticketLen);
550
551 /* build the name */
552
553 memmove( buf, v5credsp->client->data[0].data, min(v5credsp->client->data[0].length,
554 MAXKTCNAMELEN -1 ));
555 buf[v5credsp->client->data[0].length] = '\0';
556 if ( v5credsp->client->length > 1 ) {
557 strncat(buf, ".", sizeof(buf) - strlen(buf) - 1);
558 buflen = strlen(buf);
559 memmove(buf + buflen, v5credsp->client->data[1].data,
560 min(v5credsp->client->data[1].length,
561 MAXKTCNAMELEN - strlen(buf) - 1));
562 buf[buflen + v5credsp->client->data[1].length] = '\0';
563 }
564
565 /* assemble the client */
566 strncpy(client.name, buf, sizeof(client.name) - 1 );
567 strncpy(client.instance, "", sizeof(client.instance) - 1 );
568 memmove(buf, v5credsp->client->realm.data, min(v5credsp->client->realm.length,
569 MAXKTCNAMELEN - 1));
570 buf[v5credsp->client->realm.length] = '\0';
571 strncpy(client.cell, buf, sizeof(client.cell));
572
573 /* assemble the server's cell */
891fb458 574 strncpy(server.cell, cfg->afs_cell, sizeof(server.cell) - 1);
3f4fda20 575
576 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: preparing to init PTS connection for %s", server.cell);
577
578 /* fill out the AFS ID in the client name */
579 /* we've done a pr_Initialize in the child_init -- once, per process. If you try to do it more
580 * strange things seem to happen. */
581
582 {
583 afs_int32 viceId = 0;
584
585 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: making PTS call to look up %s", client.name);
586
587 if ( ( rc = pr_SNameToId( client.name, &viceId ) ) == 0 ) {
588 snprintf( client.name, sizeof(client.name), "AFS ID %d", viceId );
589 } else {
590 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: PTS call returned error %d ", rc);
591 }
592
593 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: PTS call returned %s ", client.name);
594
595 }
596
597 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: server: name %s, instance %s, cell %s",
598 server.name, server.instance, server.cell );
599
600 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: client: name %s, instance %s, cell %s",
601 client.name, client.instance, client.cell );
602
603 /* copy the resulting stuff into the child structure */
604
605 strncpy(child.clientprincipal, k5user, sizeof(child.clientprincipal));
606 memcpy(&child.token, &token, sizeof(child.token));
607 memcpy(&child.server, &server, sizeof(child.server));
608 memcpy(&child.client, &client, sizeof(child.client));
609
610 /* stuff the resulting token-related stuff into our shared token cache */
611 /* note, that anything that was set from a keytab is "persistant", and is immune
612 * from LRU-aging. This is because nothing but the process that's running as root
613 * can update these, and it's running every hour or so and renewing these tokens.
614 * and we don't want them aged out.
615 */
616
617 mytime = oldest_time = time(0);
618
619 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waiting for shared space for %s ", k5user);
4e1ae1cd 620
3f4fda20 621#ifdef use_pthreads
622 pthread_rwlock_wrlock(sharedlock);
623#else
624 rw_wrlock(sharedlock);
625#endif
4e1ae1cd 626
3f4fda20 627 for( i = ( SHARED_TABLE_SIZE - 1 ); i >= 0; i-- ) {
628 if ( ( sharedspace->sharedtokens[i].lastused <= oldest_time) &&
629 ( sharedspace->sharedtokens[i].persist == 0 ) ) {
630 oldest = i;
631 oldest_time = sharedspace->sharedtokens[i].lastused;
632 }
633 if ( ! strcmp ( sharedspace->sharedtokens[i].clientprincipal,
634 child.clientprincipal ) ) {
635 memcpy(&sharedspace->sharedtokens[i].token, &child.token, sizeof(child.token) );
636 memcpy(&sharedspace->sharedtokens[i].client, &child.client, sizeof(child.client) );
637 memcpy(&sharedspace->sharedtokens[i].server, &child.server, sizeof(child.server) );
638 sharedspace->sharedtokens[i].lastused = mytime;
639 sharedspace->sharedtokens[i].persist = keytab ? 1 : 0;
640 stored = i;
641 break;
642 }
643 }
644
645 if ( stored == -1 ) {
646 memcpy(&sharedspace->sharedtokens[oldest].token, &child.token, sizeof(child.token) );
647 memcpy(&sharedspace->sharedtokens[oldest].client, &child.client, sizeof(child.client) );
648 memcpy(&sharedspace->sharedtokens[oldest].server, &child.server, sizeof(child.server) );
649 strcpy(sharedspace->sharedtokens[oldest].clientprincipal, child.clientprincipal );
650 sharedspace->sharedtokens[oldest].lastused = mytime;
651 sharedspace->sharedtokens[oldest].persist = keytab ? 1 : 0;
652 stored = oldest;
653 }
3ed1e28a 654
3f4fda20 655#ifdef use_pthreads
656 pthread_rwlock_unlock(sharedlock);
657#else
658 rw_unlock(sharedlock);
659#endif
660
661 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: token stored in slot %d for %s", stored,
662 child.clientprincipal );
663
664 } else if ( ! usecached ) {
665 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth divergent case");
666 }
667
668 if ( storeonly ) {
669 goto cleanup;
670 }
671
672 usecachedtoken:
673
674 /* don't ask. Something about AIX. We're leaving it here.*/
675 /* write(2, "", 0); */
676
677 /* we try twice, because sometimes the first one fails. Dunno why, but it always works the second time */
678
679 if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
680 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: settoken returned %s for %s -- trying again",
681 error_message(rc), k5user);
682 if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
683 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: settoken2 returned %s for %s",
684 error_message(rc), k5user);
685 goto cleanup;
686 }
687 }
688
689 cleanup:
690 if ( v5credsp )
691 krb5_free_cred_contents(child.kcontext, v5credsp);
692 if ( increds.client )
693 krb5_free_principal (child.kcontext, increds.client);
694 if ( increds.server )
695 krb5_free_principal (child.kcontext, increds.server);
696 if ( krb5kt )
697 (void) krb5_kt_close(child.kcontext, krb5kt);
698 if ( kprinc )
699 krb5_free_principal (child.kcontext, kprinc);
700
701 if ( rc ) {
702 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with %d", rc );
703 } else if ( kerror ) {
704 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror, error_message(kerror));
705 } else {
706 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth ending ok");
707 }
708
709 return kerror ? (int) kerror : (int) rc;
710
4e1ae1cd 711}
712
713
7193eb01 714
3f4fda20 715static void *
716waklog_create_server_config (MK_POOL * p, server_rec * s)
717{
718 waklog_config *cfg;
719
720 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
721 cfg->p = p;
722 memset(cfg, 0, sizeof(waklog_config));
723 cfg->path = "(server)";
724 cfg->protect = WAKLOG_UNSET;
725 cfg->usertokens = WAKLOG_UNSET;
21a7788b 726 cfg->disable_token_cache = WAKLOG_UNSET;
3f4fda20 727 cfg->keytab = WAKLOG_UNSET;
728 cfg->principal = WAKLOG_UNSET;
729 cfg->default_principal = WAKLOG_UNSET;
730 cfg->default_keytab = WAKLOG_UNSET;
731 cfg->afs_cell = WAKLOG_UNSET;
732 cfg->forked = 0;
733 cfg->configured = 0;
734
735 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 736 "mod_waklog: server config created.");
3f4fda20 737
738 return (cfg);
739}
7193eb01 740
3f4fda20 741/* initialize with host-config information */
58bbdc54 742
3f4fda20 743static void *
744waklog_create_dir_config (MK_POOL * p, char *dir)
745{
746 waklog_config *cfg;
747
748 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
749 memset(cfg, 0, sizeof(waklog_config));
750 cfg->p = p;
751 cfg->path = ap_pstrdup(p, dir );
752 cfg->protect = WAKLOG_UNSET;
753 cfg->usertokens = WAKLOG_UNSET;
21a7788b 754 cfg->disable_token_cache = WAKLOG_UNSET;
3f4fda20 755 cfg->keytab = WAKLOG_UNSET;
756 cfg->principal = WAKLOG_UNSET;
757 cfg->default_principal = WAKLOG_UNSET;
758 cfg->default_keytab = WAKLOG_UNSET;
759 cfg->afs_cell = WAKLOG_UNSET;
760 cfg->forked = 0;
761 cfg->configured = 0;
762
763 return (cfg);
58bbdc54 764}
765
3f4fda20 766static void *waklog_merge_dir_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 767
3f4fda20 768 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
769 waklog_config *parent = ( waklog_config * ) parent_conf;
770 waklog_config *child = ( waklog_config * ) newloc_conf;
771
772 merged->protect = child->protect != WAKLOG_UNSET ? child->protect : parent->protect;
773
774 merged->path = child->path != WAKLOG_UNSET ? child->path : parent->path;
775
776 merged->usertokens = child->usertokens != WAKLOG_UNSET ? child->usertokens : parent->usertokens;
21a7788b 777
778 merged->disable_token_cache = child->disable_token_cache != WAKLOG_UNSET ? child->disable_token_cache : parent->disable_token_cache;
3f4fda20 779
780 merged->principal = child->principal != WAKLOG_UNSET ? child->principal : parent->principal;
781
782 merged->keytab = child->keytab != WAKLOG_UNSET ? child->keytab : parent->keytab;
783
784 merged->default_keytab = child->default_keytab != WAKLOG_UNSET ? child->default_keytab : parent->default_keytab;
785
786 merged->default_principal = child->default_principal != WAKLOG_UNSET ? child->default_principal : parent->default_principal;
787
788 merged->afs_cell = child->afs_cell != WAKLOG_UNSET ? child->afs_cell : parent->afs_cell;
789
790 return (void *) merged;
791
792}
58bbdc54 793
3f4fda20 794static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 795
3f4fda20 796 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
797 waklog_config *pconf = ( waklog_config * ) parent_conf;
798 waklog_config *nconf = ( waklog_config * ) newloc_conf;
799
800 merged->protect = nconf->protect == WAKLOG_UNSET ? pconf->protect : nconf->protect;
58bbdc54 801
3f4fda20 802 merged->usertokens = nconf->usertokens == WAKLOG_UNSET ? pconf->usertokens : nconf->usertokens;
58bbdc54 803
bce7d4d9 804 merged->disable_token_cache = nconf->disable_token_cache == WAKLOG_UNSET ? pconf->disable_token_cache : nconf->disable_token_cache;
21a7788b 805
3f4fda20 806 merged->keytab = nconf->keytab == WAKLOG_UNSET ? ap_pstrdup(p, pconf->keytab) :
807 ( nconf->keytab == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->keytab) );
808
809 merged->principal = nconf->principal == WAKLOG_UNSET ? ap_pstrdup(p, pconf->principal) :
810 ( nconf->principal == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->principal) );
811
812 merged->afs_cell = nconf->afs_cell == WAKLOG_UNSET ? ap_pstrdup(p, pconf->afs_cell) :
813 ( nconf->afs_cell == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->afs_cell) );
814
815 merged->default_keytab = nconf->default_keytab == WAKLOG_UNSET ? ap_pstrdup(p, pconf->default_keytab) :
816 ( nconf->default_keytab == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->default_keytab) );
58bbdc54 817
3f4fda20 818 merged->default_principal = nconf->default_principal == WAKLOG_UNSET ? ap_pstrdup(p, pconf->default_principal) :
819 ( nconf->default_principal == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->default_principal) );
820
821
822 return (void *) merged;
823
824}
825
826static const char *
21a7788b 827set_waklog_enabled (cmd_parms * params, void *mconfig, int flag)
58bbdc54 828{
3f4fda20 829 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
830 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
831
832 cfg->protect = flag;
833 cfg->configured = 1;
834 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
21a7788b 835 "mod_waklog: waklog_enabled set on %s", cfg->path ? cfg->path : "NULL");
3f4fda20 836 return (NULL);
837}
58bbdc54 838
7193eb01 839
3f4fda20 840/* this adds a principal/keytab pair to get their tokens renewed by the
841 child process every few centons. */
7193eb01 842
3f4fda20 843void add_to_renewtable(MK_POOL *p, char *keytab, char *principal) {
87822447 844
3f4fda20 845 int i;
846
847 if ( renewcount >= SHARED_TABLE_SIZE ) {
848 log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "mod_waklog: big problem. Increase the SHARED_TABLE_SIZE or \
849 decrease your tokens.");
b74fad73 850 return;
3f4fda20 851 }
852
853 /* check to see if it's already there */
854
855 for ( i = 0; i < renewcount; i++ ) {
856 if ( ! strcmp(renewtable[i].principal, principal ) ) {
857 return;
858 }
859 }
860
861 renewtable[renewcount].keytab = ap_pstrdup(p, keytab);
862 renewtable[renewcount].principal = ap_pstrdup(p, principal);
863 renewtable[renewcount].lastrenewed = 0;
864 ++renewcount;
865
b74fad73 866}
867
3f4fda20 868static const char *
21a7788b 869set_waklog_location_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
3f4fda20 870{
871 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
872 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
873
874 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 875 "mod_waklog: configuring principal: %s, keytab: %s", principal, keytab);
876
877 cfg->principal = ap_pstrdup(params->pool, principal);
3f4fda20 878 cfg->keytab = ap_pstrdup (params->pool, keytab);
879
880 add_to_renewtable(params->pool, keytab, principal);
881
882 cfg->configured = 1;
883
884 return (NULL);
885}
b74fad73 886
3f4fda20 887static const char *
21a7788b 888set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
313dde40 889{
891fb458 890 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
891 waklog_config *waklog_srvconfig =
3f4fda20 892 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
893
891fb458 894 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
42d78dfb 895 "mod_waklog: will use afs_cell: %s", file);
313dde40 896
c8563f50 897 waklog_srvconfig->cell_in_principal = 0;
891fb458 898 waklog_srvconfig->afs_cell = ap_pstrdup (params->pool, file);
899 waklog_srvconfig->configured = 1;
900
901 if (waklog_mconfig != NULL) {
c8563f50 902 waklog_mconfig->cell_in_principal = waklog_srvconfig->cell_in_principal;
891fb458 903 waklog_mconfig->afs_cell = ap_pstrdup (params->pool, file);
904 waklog_mconfig->configured = 1;
905 }
3f4fda20 906 return (NULL);
907}
58bbdc54 908
3f4fda20 909static const char *
910set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal, char *keytab)
911{
912 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
913 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
58bbdc54 914
3f4fda20 915 waklog_config *srvcfg = ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
4e1ae1cd 916
3f4fda20 917 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 918 "mod_waklog: set default princ/keytab: %s, %s for %s", principal, keytab, cfg->path ? cfg->path : "NULL");
313dde40 919
3f4fda20 920 cfg->default_principal = ap_pstrdup (params->pool, principal);
921 cfg->default_keytab = ap_pstrdup(params->pool, keytab );
922
923 /* this also gets set at the server level */
924 if ( mconfig && ( ! cfg->path ) ) {
925 srvcfg->default_principal = ap_pstrdup (params->pool, principal);
926 srvcfg->default_keytab = ap_pstrdup(params->pool, keytab );
927 } else {
928 log_error(APLOG_MARK, APLOG_ERR, 0, params->server, "only able to set default principal on a global level!");
929 return "Unable to set DefaultPrincipal outside of top level config!";
930 }
931
932 add_to_renewtable( params->pool, keytab, principal );
933
934 cfg->configured = 1;
935
936 return (NULL);
937}
313dde40 938
3f4fda20 939static const char *
940set_waklog_use_usertokens (cmd_parms * params, void *mconfig, int flag)
bed98ff9 941{
3f4fda20 942 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
943 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
bed98ff9 944
3f4fda20 945 cfg->usertokens = flag;
bed98ff9 946
3f4fda20 947 cfg->configured = 1;
bed98ff9 948
3f4fda20 949 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 950 "mod_waklog: waklog_use_user_tokens set");
3f4fda20 951 return (NULL);
bed98ff9 952}
953
954
21a7788b 955static const char *
956set_waklog_disable_token_cache (cmd_parms * params, void *mconfig, int flag)
957{
958 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
959 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
960
961 cfg->disable_token_cache = flag;
962
963 cfg->configured = 1;
964
965 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
966 "mod_waklog: waklog_disable_token_cache set");
967 return (NULL);
968}
969
970
c9d59a9c 971#ifndef APACHE2
3f4fda20 972static void waklog_child_exit( server_rec *s, MK_POOL *p ) {
973#else
974apr_status_t waklog_child_exit( void *sr ) {
4e1ae1cd 975
3f4fda20 976 server_rec *s = (server_rec *) sr;
977#endif
978
979 if ( child.ccache ) {
980 krb5_cc_close(child.kcontext, child.ccache);
981 }
982
983 if ( child.kcontext ) {
984 krb5_free_context(child.kcontext);
985 }
986
987 /* forget our tokens */
988
989 ktc_ForgetAllTokens ();
990
991 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 992 "mod_waklog: waklog_child_exit complete");
4e1ae1cd 993
c9d59a9c 994#ifdef APACHE2
3f4fda20 995 return APR_SUCCESS;
996#endif
997
998}
4e1ae1cd 999
3f4fda20 1000static void
c9d59a9c 1001#ifdef APACHE2
3f4fda20 1002waklog_child_init (MK_POOL * p, server_rec * s)
1003#else
1004waklog_child_init (server_rec * s, MK_POOL * p)
1005#endif
1006{
b52ccbb1 1007
3f4fda20 1008 krb5_error_code code;
1009 waklog_config *cfg;
1010
1011 char *cell;
1012
3f4fda20 1013 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
1014
1015 if ( !sharedspace ) {
1016 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: child_init called without shared space? %d", getpid());
1017 return;
1018 }
1019
1020 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
7193eb01 1021
3f4fda20 1022 memset (&child, 0, sizeof(child));
1023
1024 if ( code = krb5_init_context(&child.kcontext) ) {
1025 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1026 }
1027
1028 if ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) {
1029 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1030 }
1031
1032 if ( pag_for_children ) {
1033 setpag ();
1034 }
7193eb01 1035
3f4fda20 1036 getModConfig (cfg, s);
7193eb01 1037
3f4fda20 1038 if ( cfg->default_principal != WAKLOG_UNSET ) {
1039 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init setting default user %s, %s", cfg->default_principal, cfg->default_keytab);
1040 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1041 }
7193eb01 1042
891fb458 1043 cell = strdup(cfg->afs_cell);
3f4fda20 1044 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
7193eb01 1045
c9d59a9c 1046#ifdef APACHE2
3f4fda20 1047 apr_pool_cleanup_register(p, s, waklog_child_exit, apr_pool_cleanup_null);
1048#endif
7193eb01 1049
3f4fda20 1050 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1051 "mod_waklog: child_init returned");
7193eb01 1052
3f4fda20 1053 return;
1054}
b52ccbb1 1055
3f4fda20 1056command_rec waklog_cmds[] = {
1057
21a7788b 1058 command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
1059 "Use the supplied AFS cell (required)"),
7193eb01 1060
21a7788b 1061 command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
1062 "enable waklog on a server, location, or directory basis"),
7193eb01 1063
21a7788b 1064 command ("WaklogDefaultPrincipal", set_waklog_default_principal, 0, TAKE2,
1065 "Set the default principal that the server runs as"),
7193eb01 1066
21a7788b 1067 command ("WaklogLocationPrincipal", set_waklog_location_principal, 0, TAKE2,
1068 "Set the principal on a <Location>-specific basis"),
7193eb01 1069
21a7788b 1070 command ("WaklogDisableTokenCache", set_waklog_disable_token_cache, 0, FLAG,
1071 "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
1072
1073 command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
1074 "Use the requesting user tokens (from webauth)"),
1075
3f4fda20 1076 {NULL}
1077};
7193eb01 1078
7193eb01 1079
3f4fda20 1080/* not currently using this */
7193eb01 1081
3f4fda20 1082static int
1083token_cleanup (void *data)
1084{
1085 request_rec *r = (request_rec *) data;
e2df6441 1086
3f4fda20 1087 if (child.token.ticketLen)
1088 {
1089 memset (&child.token, 0, sizeof (struct ktc_token));
e21f34f0 1090
3f4fda20 1091 ktc_ForgetAllTokens ();
7193eb01 1092
3f4fda20 1093 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1094 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1095 getpid ());
3f4fda20 1096 }
1097 return 0;
7193eb01 1098}
1099
3f4fda20 1100static int
1101waklog_child_routine (void *data, child_info * pinfo)
7193eb01 1102{
3f4fda20 1103 int i;
1104 server_rec *s = (server_rec *) data;
1105 krb5_error_code code;
1106 char *cell;
1107 time_t sleep_time = ( TKT_LIFE / 2 ) ;
1108 time_t when;
1109 time_t left;
1110 waklog_config *cfg;
1111
1112 getModConfig( cfg, s );
1113
1114 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waklog_child_routine started, running as %d", getuid());
1115
1116 memset (&child, 0, sizeof(child));
1117
1118 if ( code = krb5_init_context(&child.kcontext) ) {
1119 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1120 }
1121
1122 if ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) {
1123 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1124 }
1125
1126 /* need to do this so we can make PTS calls */
891fb458 1127 cell = strdup(cfg->afs_cell); /* stupid */
3f4fda20 1128 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
1129
1130 while(1) {
1131
1132 for ( i = 0; i < renewcount; ++i ) {
1133 renewtable[i].lastrenewed = time(0);
1134 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: (pid %d) renewing %s / %s", getpid(), renewtable[i].principal,
1135 renewtable[i].keytab);
1136
1137 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 1 );
1138
1139 /* if this is our default token, we want to "stash" it in our current PAG so the parent maintains readability of
1140 things that it needs to read */
1141
1142 if ( cfg && cfg->default_principal && ( ! strcmp(cfg->default_principal, renewtable[i].principal ) ) ) {
1143 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: renewing/setting default tokens" );
1144 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 0 );
1145 }
1146
4e1ae1cd 1147 }
1148
3f4fda20 1149 sharedspace->renewcount++;
1150
1151 left = sleep_time;
1152
1153 while( left > 5 ) {
1154 when = time(0);
1155
1156 sleep(left);
1157
1158 left -= ( time(0) - when );
4e1ae1cd 1159 }
3f4fda20 1160
1161 }
4e1ae1cd 1162
3f4fda20 1163 pr_End();
403921ef 1164
3f4fda20 1165}
4e1ae1cd 1166
c9d59a9c 1167#ifdef APACHE2
3f4fda20 1168static int
1169waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
42d78dfb 1170 apr_pool_t * ptemp, server_rec * s)
3f4fda20 1171{
1172 int rv;
1173 extern char *version;
1174 apr_proc_t *proc;
1175 waklog_config *cfg;
1176 void *data;
1177 int fd = -1;
1178 int use_existing = 1;
1179 int oldrenewcount;
1180 char cache_file[MAXNAMELEN];
1181#ifdef use_pthreads
1182 pthread_rwlockattr_t rwlock_attr;
1183#endif
4e1ae1cd 1184
1185
3f4fda20 1186 getModConfig (cfg, s);
4e1ae1cd 1187
3f4fda20 1188 /* initialize_module() will be called twice, and if it's a DSO
1189 * then all static data from the first call will be lost. Only
1190 * set up our static data on the second call.
1191 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
1192 apr_pool_userdata_get (&data, userdata_key, s->process->pool);
7193eb01 1193
891fb458 1194
1195 if (cfg->afs_cell==NULL) {
1196 log_error (APLOG_MARK, APLOG_ERR, 0, s,
21a7788b 1197 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
891fb458 1198 /** clobber apache */
1199 exit(-1);
1200 }
1201
3f4fda20 1202 if (!data)
1203 {
1204 apr_pool_userdata_set ((const void *) 1, userdata_key,
42d78dfb 1205 apr_pool_cleanup_null, s->process->pool);
4e1ae1cd 1206 }
3f4fda20 1207 else
1208 {
1209 log_error (APLOG_MARK, APLOG_INFO, 0, s,
891fb458 1210 "mod_waklog: version %s initialized for cell %s", version, cfg->afs_cell);
3f4fda20 1211
1212 if ( sharedspace ) {
1213 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1214 } else {
1215
1216 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1217
1218 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1219
1220 if ( errno == ENOENT ) {
1221
1222 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1223 use_existing = 0;
1224 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1225 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1226 exit(errno);
1227 }
1228 } else {
1229 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1230 }
1231 }
1232
1233 if ( use_existing == 0 ) {
1234 struct sharedspace_s bob;
1235 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1236 memset( &bob, 0, sizeof(struct sharedspace_s));
1237 write(fd, &bob, sizeof(struct sharedspace_s));
1238 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1239 }
1240
1241 /* mmap the region */
1242
1243 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != MAP_FAILED ) {
1244 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
1245 close(fd);
1246 } else {
1247 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1248 exit(errno);
1249 }
1250 }
4e1ae1cd 1251
3f4fda20 1252#ifdef use_pthreads
1253#define locktype pthread_rwlock_t
1254#else
1255#define locktype rwlock_t
1256#endif
4e1ae1cd 1257
3f4fda20 1258 if ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) {
1259#ifndef use_pthreads
1260 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1261#else
1262 pthread_rwlockattr_init(&rwlock_attr);
1263 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1264 pthread_rwlock_init(sharedlock, &rwlock_attr );
1265#endif
1266 } else {
1267 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1268 }
58bbdc54 1269
3f4fda20 1270#undef locktype
7193eb01 1271
3f4fda20 1272 /* set our default tokens */
403921ef 1273
3f4fda20 1274 oldrenewcount = sharedspace->renewcount;
7193eb01 1275
3f4fda20 1276 pag_for_children = 0;
7193eb01 1277
3f4fda20 1278 proc = (apr_proc_t *) ap_pcalloc (s->process->pool, sizeof (apr_proc_t));
7193eb01 1279
3f4fda20 1280 rv = apr_proc_fork (proc, s->process->pool);
7193eb01 1281
3f4fda20 1282 if (rv == APR_INCHILD)
42d78dfb 1283 {
1284 waklog_child_routine (s, NULL);
1285 }
3f4fda20 1286 else
42d78dfb 1287 {
1288 apr_pool_note_subprocess (s->process->pool, proc, APR_KILL_ALWAYS);
1289 }
3f4fda20 1290 /* parent and child */
1291 cfg->forked = proc->pid;
1292 pag_for_children = 1;
1293
1294 if ( use_existing == 0 ) {
1295 /* wait here until our child process has gone and done it's renewing thing. */
1296 while( sharedspace->renewcount == oldrenewcount ) {
1297 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1298 sleep(2);
1299 }
1300 }
1301
1302 if ( cfg->default_principal ) {
1303 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1304 }
1305 }
1306 return 0;
1307}
ebb1f61c 1308#else
3f4fda20 1309static void
1310waklog_init (server_rec * s, MK_POOL * p)
1311{
1312 extern char *version;
1313 int pid;
1314 waklog_config *cfg;
1315 char *cell;
1316 int fd = -1;
1317 int use_existing = 1;
1318 int oldrenewcount;
1319 char cache_file[MAXNAMELEN];
1320#ifdef use_pthreads
1321 pthread_rwlockattr_t rwlock_attr;
ebb1f61c 1322#endif
7193eb01 1323
3f4fda20 1324 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1325 "mod_waklog: version %s initialized.", version);
7193eb01 1326
3f4fda20 1327 if ( sharedspace ) {
1328 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1329 } else {
1330
1331 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1332
1333 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1334
1335 if ( errno == ENOENT ) {
1336
1337 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1338 use_existing = 0;
1339 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1340 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1341 exit(errno);
1342 }
1343 } else {
1344 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1345 }
1346
1347 }
1348
1349 if ( use_existing == 0 ) {
1350 struct sharedspace_s bob;
1351 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1352 memset( &bob, 0, sizeof(struct sharedspace_s));
1353 write(fd, &bob, sizeof(struct sharedspace_s));
1354 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1355 }
4e1ae1cd 1356
3f4fda20 1357 /* mmap the region */
1358
1359 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != -1 ) {
1360 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
1361 close(fd);
1362 } else {
1363 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1364 exit(errno);
1365 }
1366 }
e21f34f0 1367
3f4fda20 1368#ifdef use_pthreads
1369#define locktype pthread_rwlock_t
1370#else
1371#define locktype rwlock_t
ea3e8708 1372#endif
e21f34f0 1373
3f4fda20 1374 /* mmap our shared space for our lock */
1375 if ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) {
1376#ifndef use_pthreads
1377 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1378#else
1379 pthread_rwlockattr_init(&rwlock_attr);
1380 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1381 pthread_rwlock_init(sharedlock, &rwlock_attr );
1382#endif
1383 } else {
1384 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1385 }
e21f34f0 1386
3f4fda20 1387#undef locktype
e21f34f0 1388
3f4fda20 1389 /* set our default tokens */
1390
1391 getModConfig (cfg, s);
42d78dfb 1392
1393 oldrenewcount = sharedspace->renewcount;
1394
1395 pag_for_children = 0;
1396
1397 pid = ap_bspawn_child (p, waklog_child_routine, s, kill_always,
1398 NULL, NULL, NULL);
1399
1400 pag_for_children = 1;
1401
3f4fda20 1402 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1403 "mod_waklog: ap_bspawn_child: %d.", pid);
3f4fda20 1404
1405 if ( use_existing == 0 ) {
1406 /* wait here until our child process has gone and done it's renewing thing. */
1407 while( sharedspace->renewcount == oldrenewcount ) {
1408 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1409 sleep(2);
87822447 1410 }
3f4fda20 1411 }
1412
1413 if ( cfg->default_principal ) {
1414 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1415 }
1416
87822447 1417}
3f4fda20 1418#endif
1419
1420static int
1421waklog_phase0 (request_rec * r)
e21f34f0 1422{
3f4fda20 1423 waklog_config *cfg;
e21f34f0 1424
3f4fda20 1425 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1426 "mod_waklog: phase0 called");
3f4fda20 1427
1428 cfg = retrieve_config(r);
e21f34f0 1429
3f4fda20 1430 if ( cfg->protect && cfg->principal ) {
1431 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using user %s", cfg->principal);
1432 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1433 } else if ( cfg->default_principal ) {
1434 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using default user %s", cfg->default_principal);
1435 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1436 } else {
1437 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 not doing nothin.");
1438 }
e21f34f0 1439
3f4fda20 1440 return DECLINED;
e21f34f0 1441}
4e1ae1cd 1442
3f4fda20 1443static int
1444waklog_phase1 (request_rec * r)
bed98ff9 1445{
3f4fda20 1446 waklog_config *cfg;
313dde40 1447
3f4fda20 1448 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1449 "mod_waklog: phase1 called");
7193eb01 1450
3f4fda20 1451 cfg = retrieve_config(r);
313dde40 1452
3f4fda20 1453 if ( cfg->protect && cfg->principal ) {
1454 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using user %s", cfg->principal);
1455 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1456 } else if ( cfg->default_principal ) {
1457 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using default user %s", cfg->default_principal);
1458 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1459 } else {
1460 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 not doing nothin.");
1461 }
4e1ae1cd 1462
3f4fda20 1463 return DECLINED;
7193eb01 1464}
4e1ae1cd 1465
3f4fda20 1466static int
1467waklog_phase3 (request_rec * r)
7193eb01 1468{
3f4fda20 1469 waklog_config *cfg;
1e18ef7d 1470
3f4fda20 1471 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1472 "mod_waklog: phase 3 called");
1e18ef7d 1473
3f4fda20 1474 cfg = retrieve_config(r);
1475
1476 if ( cfg->protect && cfg->principal ) {
1477 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using user %s", cfg->principal);
1478 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1479 } else if ( cfg->default_principal ) {
1480 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using default user %s", cfg->default_principal);
1481 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1482 } else {
1483 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 not doing nothin.");
1484 }
1485
1486 return DECLINED;
1487}
bed98ff9 1488
3f4fda20 1489static int
1490waklog_phase6 (request_rec * r)
1491{
1492 waklog_config *cfg;
1493
1494 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1495 "mod_waklog: phase6 called");
3f4fda20 1496
1497 cfg = retrieve_config(r);
1498
1499 if ( cfg->protect && cfg->principal ) {
1500 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using user %s", cfg->principal);
1501 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1502 } else if ( cfg->default_principal ) {
1503 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using default user %s", cfg->default_principal);
1504 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1505 } else {
1506 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 not doing nothin.");
1507 }
1508
1509 return DECLINED;
1510}
bed98ff9 1511
3f4fda20 1512static int
1513waklog_phase7 (request_rec * r)
1514{
1515 waklog_config *cfg;
1516 int rc = 0;
1517
1518 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1519 "mod_waklog: phase7 called");
3f4fda20 1520
1521 cfg = retrieve_config (r);
1522
1523 if ( cfg->protect && cfg->usertokens ) {
1524 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using usertokens");
1525 rc = set_auth( r->server, r, 1, NULL, NULL, 0);
1526 } else if ( cfg->protect && cfg->principal ) {
1527 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using user %s", cfg->principal);
1528 rc = set_auth( r->server, r, 0, cfg->principal, cfg->keytab, 0);
1529 } else if ( cfg->default_principal ) {
1530 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using default user %s", cfg->default_principal);
1531 rc = set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1532 }
1533
1534 if ( rc ) {
1535 return 400;
1536 }
1537
1538 return DECLINED;
1539}
87822447 1540
3f4fda20 1541static int
1542waklog_phase9 (request_rec * r)
1543{
1544 waklog_config *cfg;
bed98ff9 1545
3f4fda20 1546 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1547 "mod_waklog: phase9 called");
bed98ff9 1548
3f4fda20 1549 getModConfig (cfg, r->server);
1550
1551 if ( cfg->default_principal ) {
1552 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase9 using default user %s", cfg->default_principal);
1553 set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1554 }
1555
1556 return DECLINED;
bed98ff9 1557}
1558
ff47641b 1559
87822447 1560static
c9d59a9c 1561#ifdef APACHE2
ff47641b 1562 int
87822447 1563#else
ff47641b 1564 void
87822447 1565#endif
ff47641b 1566waklog_new_connection (conn_rec * c
c9d59a9c 1567#ifdef APACHE2
42d78dfb 1568 , void *dummy
87822447 1569#endif
ff47641b 1570 )
1571{
1572
3f4fda20 1573 waklog_config *cfg;
ff47641b 1574
1575 log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
42d78dfb 1576 "mod_waklog: new_connection called: pid: %d", getpid ());
1577
1578 getModConfig(cfg, c->base_server);
1579
1580 if ( cfg->default_principal ) {
1581 log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
1582 cfg->default_principal);
1583 set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1584 }
1585
1586
3f4fda20 1587 return
c9d59a9c 1588#ifdef APACHE2
3f4fda20 1589 0
87822447 1590#endif
3f4fda20 1591 ;
7193eb01 1592}
bed98ff9 1593
c4ad0387 1594
1196adfe 1595/*
1596** Here's a quick explaination for phase0 and phase2:
1597** Apache does a stat() on the path between phase0 and
1598** phase2, and must by ACLed rl to succeed. So, at
1599** phase0 we acquire credentials for umweb:servers from
1600** a keytab, and at phase2 we must ensure we remove them.
1601**
1602** Failure to "unlog" would be a security risk.
1603*/
ff47641b 1604static int
1605waklog_phase2 (request_rec * r)
c4ad0387 1606{
161ffd84 1607
ff47641b 1608 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1609 "mod_waklog: phase2 called");
1196adfe 1610
ff47641b 1611 if (child.token.ticketLen)
1612 {
1613 memset (&child.token, 0, sizeof (struct ktc_token));
c4ad0387 1614
ff47641b 1615 ktc_ForgetAllTokens ();
c4ad0387 1616
ff47641b 1617 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1618 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1619 getpid ());
c4ad0387 1620 }
1196adfe 1621
ff47641b 1622 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1623 "mod_waklog: phase2 returning");
1196adfe 1624
3f4fda20 1625 return DECLINED;
c4ad0387 1626}
1627
c9d59a9c 1628#ifndef APACHE2
313dde40 1629module MODULE_VAR_EXPORT waklog_module = {
3f4fda20 1630 STANDARD_MODULE_STUFF,
866ccfbd 1631 waklog_init, /* module initializer */
42d78dfb 1632 waklog_create_dir_config, /* create per-dir config structures */
866ccfbd 1633 waklog_merge_dir_config, /* merge per-dir config structures */
1634 waklog_create_server_config, /* create per-server config structures */
1635 waklog_merge_dir_config, /* merge per-server config structures */
1636 waklog_cmds, /* table of config file commands */
1637 NULL, /* [#8] MIME-typed-dispatched handlers */
1638 waklog_phase1, /* [#1] URI to filename translation */
1639 NULL, /* [#4] validate user id from request */
1640 NULL, /* [#5] check if the user is ok _here_ */
1641 waklog_phase3, /* [#3] check access by host address */
1642 waklog_phase6, /* [#6] determine MIME type */
1643 waklog_phase7, /* [#7] pre-run fixups */
1644 waklog_phase9, /* [#9] log a transaction */
1645 NULL, /* [#2] header parser */
1646 waklog_child_init, /* child_init */
1647 waklog_child_exit, /* child_exit */
1648 waklog_phase0 /* [#0] post read-request */
bed98ff9 1649#ifdef EAPI
866ccfbd 1650 , NULL, /* EAPI: add_module */
1651 NULL, /* EAPI: remove_module */
1652 NULL, /* EAPI: rewrite_command */
1653 waklog_new_connection /* EAPI: new_connection */
bed98ff9 1654#endif
1655};
87822447 1656#else
1657static void
ff47641b 1658waklog_register_hooks (apr_pool_t * p)
87822447 1659{
3f4fda20 1660 ap_hook_translate_name (waklog_phase1, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1661 ap_hook_header_parser (waklog_phase2, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1662 ap_hook_access_checker (waklog_phase3, NULL, NULL, APR_HOOK_FIRST);
1663 ap_hook_type_checker (waklog_phase6, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1664 ap_hook_fixups (waklog_phase7, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1665 ap_hook_log_transaction (waklog_phase9, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1666 ap_hook_child_init (waklog_child_init, NULL, NULL, APR_HOOK_FIRST);
1667 ap_hook_post_read_request (waklog_phase0, NULL, NULL, APR_HOOK_FIRST);
1668 ap_hook_pre_connection (waklog_new_connection, NULL, NULL, APR_HOOK_FIRST);
1669 ap_hook_post_config (waklog_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
87822447 1670}
1671
1672
3f4fda20 1673module AP_MODULE_DECLARE_DATA waklog_module = {
1674 STANDARD20_MODULE_STUFF,
42d78dfb 1675 waklog_create_dir_config, /* create per-dir conf structures */
1676 waklog_merge_dir_config, /* merge per-dir conf structures */
1677 waklog_create_server_config, /* create per-server conf structures */
1678 waklog_merge_dir_config, /* merge per-server conf structures */
1679 waklog_cmds, /* table of configuration directives */
1680 waklog_register_hooks /* register hooks */
87822447 1681};
1682#endif