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