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