Release
[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>
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;
bd03fc62
CE
548
549 /* Since we're fetching a key for AFS, we have to use single DES
550 and explicitely enable weak crypto using the secret API
551 call */
c8563f50 552 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
bd03fc62 553 krb5_allow_weak_crypto (child.kcontext, 1);
c8563f50 554
c760f0a1 555 if ( ( kerror = krb5_get_credentials (child.kcontext, 0, clientccache, &increds, &v5credsp ) ) ) {
c8563f50 556 /* only complain once we've tried both afs@REALM and afs/cell@REALM */
557 if (attempt>=1) {
558 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
559 error_message(kerror));
560 goto cleanup;
561 } else {
562 continue;
563 }
564 }
565 cfg->cell_in_principal = cell_in_principal;
566 break;
3f4fda20 567 }
c8563f50 568
3f4fda20 569 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: get_credentials passed for %s", k5user);
570
571 if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) {
572 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: ticket size (%d) too big to fake",
573 v5credsp->ticket.length);
574 goto cleanup;
575 }
313dde40 576
3f4fda20 577 memset(&token, 0, sizeof(struct ktc_token));
578
579 token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime;
580 token.endTime = v5credsp->times.endtime;
581
582 memmove( &token.sessionKey, v5credsp->keyblock.contents, v5credsp->keyblock.length);
583 token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
584 token.ticketLen = v5credsp->ticket.length;
585 memmove( token.ticket, v5credsp->ticket.data, token.ticketLen);
586
587 /* build the name */
588
589 memmove( buf, v5credsp->client->data[0].data, min(v5credsp->client->data[0].length,
590 MAXKTCNAMELEN -1 ));
591 buf[v5credsp->client->data[0].length] = '\0';
592 if ( v5credsp->client->length > 1 ) {
593 strncat(buf, ".", sizeof(buf) - strlen(buf) - 1);
594 buflen = strlen(buf);
595 memmove(buf + buflen, v5credsp->client->data[1].data,
596 min(v5credsp->client->data[1].length,
597 MAXKTCNAMELEN - strlen(buf) - 1));
598 buf[buflen + v5credsp->client->data[1].length] = '\0';
599 }
600
601 /* assemble the client */
602 strncpy(client.name, buf, sizeof(client.name) - 1 );
603 strncpy(client.instance, "", sizeof(client.instance) - 1 );
604 memmove(buf, v5credsp->client->realm.data, min(v5credsp->client->realm.length,
605 MAXKTCNAMELEN - 1));
606 buf[v5credsp->client->realm.length] = '\0';
607 strncpy(client.cell, buf, sizeof(client.cell));
608
609 /* assemble the server's cell */
891fb458 610 strncpy(server.cell, cfg->afs_cell, sizeof(server.cell) - 1);
3f4fda20 611
612 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: preparing to init PTS connection for %s", server.cell);
613
614 /* fill out the AFS ID in the client name */
615 /* we've done a pr_Initialize in the child_init -- once, per process. If you try to do it more
616 * strange things seem to happen. */
617
618 {
619 afs_int32 viceId = 0;
620
621 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: making PTS call to look up %s", client.name);
622
623 if ( ( rc = pr_SNameToId( client.name, &viceId ) ) == 0 ) {
624 snprintf( client.name, sizeof(client.name), "AFS ID %d", viceId );
625 } else {
626 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: PTS call returned error %d ", rc);
627 }
628
629 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: PTS call returned %s ", client.name);
630
631 }
632
633 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: server: name %s, instance %s, cell %s",
634 server.name, server.instance, server.cell );
635
636 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: client: name %s, instance %s, cell %s",
637 client.name, client.instance, client.cell );
638
639 /* copy the resulting stuff into the child structure */
640
641 strncpy(child.clientprincipal, k5user, sizeof(child.clientprincipal));
642 memcpy(&child.token, &token, sizeof(child.token));
643 memcpy(&child.server, &server, sizeof(child.server));
644 memcpy(&child.client, &client, sizeof(child.client));
645
646 /* stuff the resulting token-related stuff into our shared token cache */
647 /* note, that anything that was set from a keytab is "persistant", and is immune
648 * from LRU-aging. This is because nothing but the process that's running as root
649 * can update these, and it's running every hour or so and renewing these tokens.
650 * and we don't want them aged out.
651 */
652
653 mytime = oldest_time = time(0);
654
655 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waiting for shared space for %s ", k5user);
4e1ae1cd 656
3f4fda20 657#ifdef use_pthreads
658 pthread_rwlock_wrlock(sharedlock);
659#else
660 rw_wrlock(sharedlock);
661#endif
4e1ae1cd 662
3f4fda20 663 for( i = ( SHARED_TABLE_SIZE - 1 ); i >= 0; i-- ) {
664 if ( ( sharedspace->sharedtokens[i].lastused <= oldest_time) &&
665 ( sharedspace->sharedtokens[i].persist == 0 ) ) {
666 oldest = i;
667 oldest_time = sharedspace->sharedtokens[i].lastused;
668 }
669 if ( ! strcmp ( sharedspace->sharedtokens[i].clientprincipal,
670 child.clientprincipal ) ) {
671 memcpy(&sharedspace->sharedtokens[i].token, &child.token, sizeof(child.token) );
672 memcpy(&sharedspace->sharedtokens[i].client, &child.client, sizeof(child.client) );
673 memcpy(&sharedspace->sharedtokens[i].server, &child.server, sizeof(child.server) );
674 sharedspace->sharedtokens[i].lastused = mytime;
675 sharedspace->sharedtokens[i].persist = keytab ? 1 : 0;
676 stored = i;
677 break;
678 }
679 }
680
681 if ( stored == -1 ) {
682 memcpy(&sharedspace->sharedtokens[oldest].token, &child.token, sizeof(child.token) );
683 memcpy(&sharedspace->sharedtokens[oldest].client, &child.client, sizeof(child.client) );
684 memcpy(&sharedspace->sharedtokens[oldest].server, &child.server, sizeof(child.server) );
685 strcpy(sharedspace->sharedtokens[oldest].clientprincipal, child.clientprincipal );
686 sharedspace->sharedtokens[oldest].lastused = mytime;
687 sharedspace->sharedtokens[oldest].persist = keytab ? 1 : 0;
688 stored = oldest;
689 }
3ed1e28a 690
3f4fda20 691#ifdef use_pthreads
692 pthread_rwlock_unlock(sharedlock);
693#else
694 rw_unlock(sharedlock);
695#endif
696
697 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: token stored in slot %d for %s", stored,
698 child.clientprincipal );
699
700 } else if ( ! usecached ) {
701 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth divergent case");
702 }
703
704 if ( storeonly ) {
705 goto cleanup;
706 }
707
708 usecachedtoken:
709
710 /* don't ask. Something about AIX. We're leaving it here.*/
711 /* write(2, "", 0); */
712
713 /* we try twice, because sometimes the first one fails. Dunno why, but it always works the second time */
714
715 if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
716 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: settoken returned %s for %s -- trying again",
717 error_message(rc), k5user);
718 if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
719 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: settoken2 returned %s for %s",
720 error_message(rc), k5user);
721 goto cleanup;
722 }
723 }
724
725 cleanup:
c760f0a1 726 if (use_client_credentials)
727 krb5_cc_close(child.kcontext, clientccache);
3f4fda20 728 if ( v5credsp )
729 krb5_free_cred_contents(child.kcontext, v5credsp);
730 if ( increds.client )
731 krb5_free_principal (child.kcontext, increds.client);
732 if ( increds.server )
733 krb5_free_principal (child.kcontext, increds.server);
734 if ( krb5kt )
735 (void) krb5_kt_close(child.kcontext, krb5kt);
736 if ( kprinc )
737 krb5_free_principal (child.kcontext, kprinc);
738
739 if ( rc ) {
740 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with %d", rc );
741 } else if ( kerror ) {
742 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror, error_message(kerror));
743 } else {
744 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth ending ok");
745 }
746
747 return kerror ? (int) kerror : (int) rc;
748
4e1ae1cd 749}
750
751
4480093f 752int get_cfg_usertokens(waklog_config *cfg)
753{
754 if (cfg->usertokens==WAKLOG_UNSET)
755 return 0; /* default */
756 return cfg->usertokens;
757}
758
759int get_cfg_protect(waklog_config *cfg)
760{
761 if (cfg->protect==WAKLOG_UNSET)
762 return 0; /* default */
763 return cfg->protect;
764}
765
766int get_cfg_disable_token_cache(waklog_config *cfg)
767{
768 if (cfg->disable_token_cache==WAKLOG_UNSET)
769 return 0; /* default */
770 return cfg->disable_token_cache;
771}
772
7193eb01 773
3f4fda20 774static void *
775waklog_create_server_config (MK_POOL * p, server_rec * s)
776{
777 waklog_config *cfg;
778
779 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
780 cfg->p = p;
781 memset(cfg, 0, sizeof(waklog_config));
782 cfg->path = "(server)";
783 cfg->protect = WAKLOG_UNSET;
784 cfg->usertokens = WAKLOG_UNSET;
21a7788b 785 cfg->disable_token_cache = WAKLOG_UNSET;
5d0827ae 786 cfg->keytab = NULL;
787 cfg->principal = NULL;
788 cfg->default_principal = NULL;
789 cfg->default_keytab = NULL;
790 cfg->afs_cell = NULL;
791 cfg->afs_cell_realm = NULL;
3f4fda20 792 cfg->forked = 0;
793 cfg->configured = 0;
794
795 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 796 "mod_waklog: server config created.");
3f4fda20 797
798 return (cfg);
799}
7193eb01 800
3f4fda20 801/* initialize with host-config information */
58bbdc54 802
3f4fda20 803static void *
804waklog_create_dir_config (MK_POOL * p, char *dir)
805{
806 waklog_config *cfg;
807
808 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
809 memset(cfg, 0, sizeof(waklog_config));
810 cfg->p = p;
811 cfg->path = ap_pstrdup(p, dir );
812 cfg->protect = WAKLOG_UNSET;
813 cfg->usertokens = WAKLOG_UNSET;
21a7788b 814 cfg->disable_token_cache = WAKLOG_UNSET;
5d0827ae 815 cfg->keytab = NULL;
816 cfg->principal = NULL;
817 cfg->default_principal = NULL;
818 cfg->default_keytab = NULL;
819 cfg->afs_cell = NULL;
820 cfg->afs_cell_realm = NULL;
3f4fda20 821 cfg->forked = 0;
822 cfg->configured = 0;
823
824 return (cfg);
58bbdc54 825}
826
3f4fda20 827static void *waklog_merge_dir_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 828
3f4fda20 829 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
830 waklog_config *parent = ( waklog_config * ) parent_conf;
831 waklog_config *child = ( waklog_config * ) newloc_conf;
832
833 merged->protect = child->protect != WAKLOG_UNSET ? child->protect : parent->protect;
834
5d0827ae 835 merged->path = child->path != NULL ? child->path : parent->path;
3f4fda20 836
837 merged->usertokens = child->usertokens != WAKLOG_UNSET ? child->usertokens : parent->usertokens;
21a7788b 838
839 merged->disable_token_cache = child->disable_token_cache != WAKLOG_UNSET ? child->disable_token_cache : parent->disable_token_cache;
3f4fda20 840
5d0827ae 841 merged->principal = child->principal != NULL ? child->principal : parent->principal;
3f4fda20 842
5d0827ae 843 merged->keytab = child->keytab != NULL ? child->keytab : parent->keytab;
3f4fda20 844
5d0827ae 845 merged->default_keytab = child->default_keytab != NULL ? child->default_keytab : parent->default_keytab;
3f4fda20 846
5d0827ae 847 merged->default_principal = child->default_principal != NULL ? child->default_principal : parent->default_principal;
3f4fda20 848
5d0827ae 849 merged->afs_cell = child->afs_cell != NULL ? child->afs_cell : parent->afs_cell;
98534230 850
5d0827ae 851 merged->afs_cell_realm = child->afs_cell_realm != NULL ? child->afs_cell_realm : parent->afs_cell_realm;
3f4fda20 852
853 return (void *) merged;
854
855}
58bbdc54 856
3f4fda20 857static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 858
3f4fda20 859 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
860 waklog_config *pconf = ( waklog_config * ) parent_conf;
861 waklog_config *nconf = ( waklog_config * ) newloc_conf;
862
863 merged->protect = nconf->protect == WAKLOG_UNSET ? pconf->protect : nconf->protect;
58bbdc54 864
3f4fda20 865 merged->usertokens = nconf->usertokens == WAKLOG_UNSET ? pconf->usertokens : nconf->usertokens;
58bbdc54 866
bce7d4d9 867 merged->disable_token_cache = nconf->disable_token_cache == WAKLOG_UNSET ? pconf->disable_token_cache : nconf->disable_token_cache;
21a7788b 868
5d0827ae 869 merged->keytab = nconf->keytab == NULL ? ap_pstrdup(p, pconf->keytab) :
870 ( nconf->keytab == NULL ? NULL : ap_pstrdup(p, nconf->keytab) );
3f4fda20 871
5d0827ae 872 merged->principal = nconf->principal == NULL ? ap_pstrdup(p, pconf->principal) :
873 ( nconf->principal == NULL ? NULL : ap_pstrdup(p, nconf->principal) );
3f4fda20 874
5d0827ae 875 merged->afs_cell = nconf->afs_cell == NULL ? ap_pstrdup(p, pconf->afs_cell) :
876 ( nconf->afs_cell == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell) );
3f4fda20 877
5d0827ae 878 merged->afs_cell_realm = nconf->afs_cell_realm == NULL ? ap_pstrdup(p, pconf->afs_cell_realm) :
879 ( nconf->afs_cell_realm == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell_realm) );
98534230 880
5d0827ae 881 merged->default_keytab = nconf->default_keytab == NULL ? ap_pstrdup(p, pconf->default_keytab) :
882 ( nconf->default_keytab == NULL ? NULL : ap_pstrdup(p, nconf->default_keytab) );
58bbdc54 883
5d0827ae 884 merged->default_principal = nconf->default_principal == NULL ? ap_pstrdup(p, pconf->default_principal) :
885 ( nconf->default_principal == NULL ? NULL : ap_pstrdup(p, nconf->default_principal) );
3f4fda20 886
887
888 return (void *) merged;
889
890}
891
892static const char *
21a7788b 893set_waklog_enabled (cmd_parms * params, void *mconfig, int flag)
58bbdc54 894{
3f4fda20 895 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
896 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
897
898 cfg->protect = flag;
899 cfg->configured = 1;
900 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
21a7788b 901 "mod_waklog: waklog_enabled set on %s", cfg->path ? cfg->path : "NULL");
3f4fda20 902 return (NULL);
903}
58bbdc54 904
7193eb01 905
3f4fda20 906/* this adds a principal/keytab pair to get their tokens renewed by the
907 child process every few centons. */
7193eb01 908
3f4fda20 909void add_to_renewtable(MK_POOL *p, char *keytab, char *principal) {
87822447 910
3f4fda20 911 int i;
912
913 if ( renewcount >= SHARED_TABLE_SIZE ) {
914 log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "mod_waklog: big problem. Increase the SHARED_TABLE_SIZE or \
915 decrease your tokens.");
b74fad73 916 return;
3f4fda20 917 }
918
919 /* check to see if it's already there */
920
921 for ( i = 0; i < renewcount; i++ ) {
922 if ( ! strcmp(renewtable[i].principal, principal ) ) {
923 return;
924 }
925 }
926
927 renewtable[renewcount].keytab = ap_pstrdup(p, keytab);
928 renewtable[renewcount].principal = ap_pstrdup(p, principal);
929 renewtable[renewcount].lastrenewed = 0;
930 ++renewcount;
931
b74fad73 932}
933
3f4fda20 934static const char *
21a7788b 935set_waklog_location_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
3f4fda20 936{
937 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
938 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
939
940 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 941 "mod_waklog: configuring principal: %s, keytab: %s", principal, keytab);
942
943 cfg->principal = ap_pstrdup(params->pool, principal);
3f4fda20 944 cfg->keytab = ap_pstrdup (params->pool, keytab);
945
946 add_to_renewtable(params->pool, keytab, principal);
947
948 cfg->configured = 1;
949
950 return (NULL);
951}
b74fad73 952
3f4fda20 953static const char *
21a7788b 954set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
313dde40 955{
891fb458 956 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
957 waklog_config *waklog_srvconfig =
3f4fda20 958 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
959
891fb458 960 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
42d78dfb 961 "mod_waklog: will use afs_cell: %s", file);
313dde40 962
678051d7 963 // Prefer afs/cell@REALM over afs@REALM, just like the OpenAFS tools
964 waklog_srvconfig->cell_in_principal = 1;
965
891fb458 966 waklog_srvconfig->afs_cell = ap_pstrdup (params->pool, file);
967 waklog_srvconfig->configured = 1;
968
969 if (waklog_mconfig != NULL) {
c8563f50 970 waklog_mconfig->cell_in_principal = waklog_srvconfig->cell_in_principal;
891fb458 971 waklog_mconfig->afs_cell = ap_pstrdup (params->pool, file);
972 waklog_mconfig->configured = 1;
973 }
3f4fda20 974 return (NULL);
975}
58bbdc54 976
98534230 977static const char *
978set_waklog_afs_cell_realm (cmd_parms * params, void *mconfig, char *file)
979{
980 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
981 waklog_config *waklog_srvconfig =
982 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
983
984 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
985 "mod_waklog: will use afs_cell_realm: %s", file);
986
987 waklog_srvconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
988
989 if (waklog_mconfig != NULL) {
990 waklog_mconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
991 }
992 return (NULL);
993}
994
3f4fda20 995static const char *
996set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal, char *keytab)
997{
998 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
999 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
58bbdc54 1000
3f4fda20 1001 waklog_config *srvcfg = ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
4e1ae1cd 1002
3f4fda20 1003 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 1004 "mod_waklog: set default princ/keytab: %s, %s for %s", principal, keytab, cfg->path ? cfg->path : "NULL");
313dde40 1005
3f4fda20 1006 cfg->default_principal = ap_pstrdup (params->pool, principal);
1007 cfg->default_keytab = ap_pstrdup(params->pool, keytab );
1008
1009 /* this also gets set at the server level */
1010 if ( mconfig && ( ! cfg->path ) ) {
1011 srvcfg->default_principal = ap_pstrdup (params->pool, principal);
1012 srvcfg->default_keytab = ap_pstrdup(params->pool, keytab );
1013 } else {
1014 log_error(APLOG_MARK, APLOG_ERR, 0, params->server, "only able to set default principal on a global level!");
1015 return "Unable to set DefaultPrincipal outside of top level config!";
1016 }
1017
1018 add_to_renewtable( params->pool, keytab, principal );
1019
1020 cfg->configured = 1;
1021
1022 return (NULL);
1023}
313dde40 1024
3f4fda20 1025static const char *
1026set_waklog_use_usertokens (cmd_parms * params, void *mconfig, int flag)
bed98ff9 1027{
3f4fda20 1028 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
1029 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
bed98ff9 1030
3f4fda20 1031 cfg->usertokens = flag;
bed98ff9 1032
3f4fda20 1033 cfg->configured = 1;
bed98ff9 1034
3f4fda20 1035 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 1036 "mod_waklog: waklog_use_user_tokens set");
3f4fda20 1037 return (NULL);
bed98ff9 1038}
1039
1040
21a7788b 1041static const char *
1042set_waklog_disable_token_cache (cmd_parms * params, void *mconfig, int flag)
1043{
1044 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
1045 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
1046
1047 cfg->disable_token_cache = flag;
1048
1049 cfg->configured = 1;
1050
1051 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
1052 "mod_waklog: waklog_disable_token_cache set");
1053 return (NULL);
1054}
1055
1056
c9d59a9c 1057#ifndef APACHE2
3f4fda20 1058static void waklog_child_exit( server_rec *s, MK_POOL *p ) {
1059#else
1060apr_status_t waklog_child_exit( void *sr ) {
4e1ae1cd 1061
3f4fda20 1062 server_rec *s = (server_rec *) sr;
1063#endif
1064
1065 if ( child.ccache ) {
1066 krb5_cc_close(child.kcontext, child.ccache);
1067 }
1068
1069 if ( child.kcontext ) {
1070 krb5_free_context(child.kcontext);
1071 }
1072
1073 /* forget our tokens */
1074
1075 ktc_ForgetAllTokens ();
1076
1077 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1078 "mod_waklog: waklog_child_exit complete");
4e1ae1cd 1079
c9d59a9c 1080#ifdef APACHE2
3f4fda20 1081 return APR_SUCCESS;
1082#endif
1083
1084}
4e1ae1cd 1085
3f4fda20 1086static void
c9d59a9c 1087#ifdef APACHE2
3f4fda20 1088waklog_child_init (MK_POOL * p, server_rec * s)
1089#else
1090waklog_child_init (server_rec * s, MK_POOL * p)
1091#endif
1092{
b52ccbb1 1093
3f4fda20 1094 krb5_error_code code;
1095 waklog_config *cfg;
1096
1097 char *cell;
1098
3f4fda20 1099 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
1100
1101 if ( !sharedspace ) {
1102 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: child_init called without shared space? %d", getpid());
1103 return;
1104 }
1105
1106 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
7193eb01 1107
3f4fda20 1108 memset (&child, 0, sizeof(child));
1109
c760f0a1 1110 if ( ( code = krb5_init_context(&child.kcontext) ) ) {
3f4fda20 1111 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1112 }
1113
c760f0a1 1114 if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
3f4fda20 1115 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1116 }
1117
1118 if ( pag_for_children ) {
1119 setpag ();
1120 }
7193eb01 1121
3f4fda20 1122 getModConfig (cfg, s);
7193eb01 1123
5d0827ae 1124 if ( cfg->default_principal != NULL ) {
3f4fda20 1125 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init setting default user %s, %s", cfg->default_principal, cfg->default_keytab);
1126 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1127 }
7193eb01 1128
891fb458 1129 cell = strdup(cfg->afs_cell);
3f4fda20 1130 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
7193eb01 1131
c9d59a9c 1132#ifdef APACHE2
3f4fda20 1133 apr_pool_cleanup_register(p, s, waklog_child_exit, apr_pool_cleanup_null);
1134#endif
7193eb01 1135
3f4fda20 1136 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1137 "mod_waklog: child_init returned");
7193eb01 1138
3f4fda20 1139 return;
1140}
b52ccbb1 1141
3f4fda20 1142command_rec waklog_cmds[] = {
1143
21a7788b 1144 command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
1145 "Use the supplied AFS cell (required)"),
7193eb01 1146
98534230 1147 command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm, 0, TAKE1,
1148 "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
1149
21a7788b 1150 command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
1151 "enable waklog on a server, location, or directory basis"),
7193eb01 1152
21a7788b 1153 command ("WaklogDefaultPrincipal", set_waklog_default_principal, 0, TAKE2,
1154 "Set the default principal that the server runs as"),
7193eb01 1155
21a7788b 1156 command ("WaklogLocationPrincipal", set_waklog_location_principal, 0, TAKE2,
1157 "Set the principal on a <Location>-specific basis"),
7193eb01 1158
21a7788b 1159 command ("WaklogDisableTokenCache", set_waklog_disable_token_cache, 0, FLAG,
1160 "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
1161
1162 command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
1163 "Use the requesting user tokens (from webauth)"),
1164
3f4fda20 1165 {NULL}
1166};
7193eb01 1167
7193eb01 1168
3f4fda20 1169/* not currently using this */
7193eb01 1170
3f4fda20 1171static int
1172token_cleanup (void *data)
1173{
1174 request_rec *r = (request_rec *) data;
e2df6441 1175
3f4fda20 1176 if (child.token.ticketLen)
1177 {
1178 memset (&child.token, 0, sizeof (struct ktc_token));
e21f34f0 1179
3f4fda20 1180 ktc_ForgetAllTokens ();
7193eb01 1181
3f4fda20 1182 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1183 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1184 getpid ());
3f4fda20 1185 }
1186 return 0;
7193eb01 1187}
1188
3f4fda20 1189static int
1190waklog_child_routine (void *data, child_info * pinfo)
7193eb01 1191{
3f4fda20 1192 int i;
1193 server_rec *s = (server_rec *) data;
1194 krb5_error_code code;
1195 char *cell;
1196 time_t sleep_time = ( TKT_LIFE / 2 ) ;
1197 time_t when;
1198 time_t left;
1199 waklog_config *cfg;
1200
1201 getModConfig( cfg, s );
1202
1203 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waklog_child_routine started, running as %d", getuid());
1204
1205 memset (&child, 0, sizeof(child));
1206
c760f0a1 1207 if ( ( code = krb5_init_context(&child.kcontext) ) ) {
3f4fda20 1208 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1209 }
1210
c760f0a1 1211 if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
3f4fda20 1212 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1213 }
1214
c760f0a1 1215 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: about to pr_Initialize");
1216
3f4fda20 1217 /* need to do this so we can make PTS calls */
891fb458 1218 cell = strdup(cfg->afs_cell); /* stupid */
3f4fda20 1219 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
c760f0a1 1220
1221 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: still here");
1222
3f4fda20 1223 while(1) {
1224
1225 for ( i = 0; i < renewcount; ++i ) {
1226 renewtable[i].lastrenewed = time(0);
1227 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: (pid %d) renewing %s / %s", getpid(), renewtable[i].principal,
1228 renewtable[i].keytab);
1229
1230 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 1 );
1231
1232 /* if this is our default token, we want to "stash" it in our current PAG so the parent maintains readability of
1233 things that it needs to read */
1234
1235 if ( cfg && cfg->default_principal && ( ! strcmp(cfg->default_principal, renewtable[i].principal ) ) ) {
1236 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: renewing/setting default tokens" );
1237 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 0 );
1238 }
1239
4e1ae1cd 1240 }
1241
3f4fda20 1242 sharedspace->renewcount++;
1243
1244 left = sleep_time;
1245
1246 while( left > 5 ) {
1247 when = time(0);
1248
1249 sleep(left);
1250
1251 left -= ( time(0) - when );
4e1ae1cd 1252 }
3f4fda20 1253
1254 }
4e1ae1cd 1255
3f4fda20 1256 pr_End();
403921ef 1257
3f4fda20 1258}
4e1ae1cd 1259
c9d59a9c 1260#ifdef APACHE2
3f4fda20 1261static int
1262waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
42d78dfb 1263 apr_pool_t * ptemp, server_rec * s)
3f4fda20 1264{
1265 int rv;
1266 extern char *version;
1267 apr_proc_t *proc;
1268 waklog_config *cfg;
1269 void *data;
1270 int fd = -1;
1271 int use_existing = 1;
1272 int oldrenewcount;
1273 char cache_file[MAXNAMELEN];
1274#ifdef use_pthreads
1275 pthread_rwlockattr_t rwlock_attr;
1276#endif
4e1ae1cd 1277
1278
3f4fda20 1279 getModConfig (cfg, s);
4e1ae1cd 1280
3f4fda20 1281 /* initialize_module() will be called twice, and if it's a DSO
1282 * then all static data from the first call will be lost. Only
1283 * set up our static data on the second call.
1284 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
1285 apr_pool_userdata_get (&data, userdata_key, s->process->pool);
7193eb01 1286
891fb458 1287
1288 if (cfg->afs_cell==NULL) {
1289 log_error (APLOG_MARK, APLOG_ERR, 0, s,
21a7788b 1290 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
891fb458 1291 /** clobber apache */
1292 exit(-1);
1293 }
1294
3f4fda20 1295 if (!data)
1296 {
1297 apr_pool_userdata_set ((const void *) 1, userdata_key,
42d78dfb 1298 apr_pool_cleanup_null, s->process->pool);
4e1ae1cd 1299 }
3f4fda20 1300 else
1301 {
1302 log_error (APLOG_MARK, APLOG_INFO, 0, s,
891fb458 1303 "mod_waklog: version %s initialized for cell %s", version, cfg->afs_cell);
3f4fda20 1304
1305 if ( sharedspace ) {
1306 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1307 } else {
1308
1309 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1310
1311 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1312
1313 if ( errno == ENOENT ) {
1314
1315 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1316 use_existing = 0;
1317 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1318 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1319 exit(errno);
1320 }
1321 } else {
1322 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1323 }
1324 }
1325
1326 if ( use_existing == 0 ) {
1327 struct sharedspace_s bob;
1328 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1329 memset( &bob, 0, sizeof(struct sharedspace_s));
1330 write(fd, &bob, sizeof(struct sharedspace_s));
1331 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1332 }
1333
1334 /* mmap the region */
1335
1336 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != MAP_FAILED ) {
4cd4a5af 1337 int err = 0;
3f4fda20 1338 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
4cd4a5af 1339 err = unlink(cache_file);
1340 if (err) {
1341 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: unable to delete %s due to %d", cache_file, errno);
1342 } else {
95ad25b8 1343 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared cache unlinked (will be deleted when Apache quits)");
4cd4a5af 1344 }
3f4fda20 1345 } else {
1346 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1347 exit(errno);
1348 }
1349 }
4e1ae1cd 1350
3f4fda20 1351#ifdef use_pthreads
1352#define locktype pthread_rwlock_t
1353#else
1354#define locktype rwlock_t
1355#endif
4e1ae1cd 1356
3f4fda20 1357 if ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) {
1358#ifndef use_pthreads
1359 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1360#else
1361 pthread_rwlockattr_init(&rwlock_attr);
1362 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1363 pthread_rwlock_init(sharedlock, &rwlock_attr );
1364#endif
1365 } else {
1366 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1367 }
58bbdc54 1368
3f4fda20 1369#undef locktype
7193eb01 1370
3f4fda20 1371 /* set our default tokens */
403921ef 1372
3f4fda20 1373 oldrenewcount = sharedspace->renewcount;
7193eb01 1374
3f4fda20 1375 pag_for_children = 0;
7193eb01 1376
3f4fda20 1377 proc = (apr_proc_t *) ap_pcalloc (s->process->pool, sizeof (apr_proc_t));
7193eb01 1378
3f4fda20 1379 rv = apr_proc_fork (proc, s->process->pool);
7193eb01 1380
3f4fda20 1381 if (rv == APR_INCHILD)
42d78dfb 1382 {
1383 waklog_child_routine (s, NULL);
1384 }
3f4fda20 1385 else
42d78dfb 1386 {
1387 apr_pool_note_subprocess (s->process->pool, proc, APR_KILL_ALWAYS);
1388 }
3f4fda20 1389 /* parent and child */
1390 cfg->forked = proc->pid;
1391 pag_for_children = 1;
1392
1393 if ( use_existing == 0 ) {
1394 /* wait here until our child process has gone and done it's renewing thing. */
1395 while( sharedspace->renewcount == oldrenewcount ) {
1396 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1397 sleep(2);
1398 }
1399 }
1400
1401 if ( cfg->default_principal ) {
1402 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1403 }
1404 }
1405 return 0;
1406}
ebb1f61c 1407#else
3f4fda20 1408static void
1409waklog_init (server_rec * s, MK_POOL * p)
1410{
1411 extern char *version;
1412 int pid;
1413 waklog_config *cfg;
3f4fda20 1414 int fd = -1;
1415 int use_existing = 1;
1416 int oldrenewcount;
1417 char cache_file[MAXNAMELEN];
1418#ifdef use_pthreads
1419 pthread_rwlockattr_t rwlock_attr;
ebb1f61c 1420#endif
7193eb01 1421
3f4fda20 1422 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1423 "mod_waklog: version %s initialized.", version);
7193eb01 1424
3f4fda20 1425 if ( sharedspace ) {
1426 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1427 } else {
1428
1429 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1430
1431 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1432
1433 if ( errno == ENOENT ) {
1434
1435 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1436 use_existing = 0;
1437 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1438 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1439 exit(errno);
1440 }
1441 } else {
1442 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1443 }
1444
1445 }
1446
1447 if ( use_existing == 0 ) {
1448 struct sharedspace_s bob;
1449 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1450 memset( &bob, 0, sizeof(struct sharedspace_s));
1451 write(fd, &bob, sizeof(struct sharedspace_s));
1452 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1453 }
4e1ae1cd 1454
3f4fda20 1455 /* mmap the region */
1456
c760f0a1 1457 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != (void *) -1 ) {
3f4fda20 1458 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
1459 close(fd);
1460 } else {
1461 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1462 exit(errno);
1463 }
1464 }
e21f34f0 1465
3f4fda20 1466#ifdef use_pthreads
1467#define locktype pthread_rwlock_t
1468#else
1469#define locktype rwlock_t
ea3e8708 1470#endif
e21f34f0 1471
3f4fda20 1472 /* mmap our shared space for our lock */
c760f0a1 1473 if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) ) {
3f4fda20 1474#ifndef use_pthreads
1475 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1476#else
1477 pthread_rwlockattr_init(&rwlock_attr);
1478 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1479 pthread_rwlock_init(sharedlock, &rwlock_attr );
1480#endif
1481 } else {
1482 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1483 }
e21f34f0 1484
3f4fda20 1485#undef locktype
e21f34f0 1486
3f4fda20 1487 /* set our default tokens */
1488
1489 getModConfig (cfg, s);
42d78dfb 1490
1491 oldrenewcount = sharedspace->renewcount;
1492
1493 pag_for_children = 0;
1494
1495 pid = ap_bspawn_child (p, waklog_child_routine, s, kill_always,
1496 NULL, NULL, NULL);
1497
1498 pag_for_children = 1;
1499
3f4fda20 1500 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1501 "mod_waklog: ap_bspawn_child: %d.", pid);
3f4fda20 1502
1503 if ( use_existing == 0 ) {
1504 /* wait here until our child process has gone and done it's renewing thing. */
1505 while( sharedspace->renewcount == oldrenewcount ) {
1506 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1507 sleep(2);
87822447 1508 }
3f4fda20 1509 }
1510
1511 if ( cfg->default_principal ) {
1512 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1513 }
1514
87822447 1515}
3f4fda20 1516#endif
1517
1518static int
1519waklog_phase0 (request_rec * r)
e21f34f0 1520{
3f4fda20 1521 waklog_config *cfg;
e21f34f0 1522
3f4fda20 1523 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1524 "mod_waklog: phase0 called");
3f4fda20 1525
1526 cfg = retrieve_config(r);
e21f34f0 1527
4480093f 1528 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1529 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using user %s", cfg->principal);
1530 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1531 } else if ( cfg->default_principal ) {
1532 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using default user %s", cfg->default_principal);
1533 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1534 } else {
c760f0a1 1535
1536 if (child.token.ticketLen) {
1537 memset( &child.token, 0, sizeof (struct ktc_token) );
1538 ktc_ForgetAllTokens();
1539 }
1540
3f4fda20 1541 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 not doing nothin.");
1542 }
e21f34f0 1543
3f4fda20 1544 return DECLINED;
e21f34f0 1545}
4e1ae1cd 1546
3f4fda20 1547static int
1548waklog_phase1 (request_rec * r)
bed98ff9 1549{
3f4fda20 1550 waklog_config *cfg;
313dde40 1551
3f4fda20 1552 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1553 "mod_waklog: phase1 called");
7193eb01 1554
3f4fda20 1555 cfg = retrieve_config(r);
313dde40 1556
4480093f 1557 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1558 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using user %s", cfg->principal);
1559 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1560 } else if ( cfg->default_principal ) {
1561 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using default user %s", cfg->default_principal);
1562 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1563 } else {
1564 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 not doing nothin.");
1565 }
4e1ae1cd 1566
3f4fda20 1567 return DECLINED;
7193eb01 1568}
4e1ae1cd 1569
3f4fda20 1570static int
1571waklog_phase3 (request_rec * r)
7193eb01 1572{
3f4fda20 1573 waklog_config *cfg;
1e18ef7d 1574
3f4fda20 1575 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1576 "mod_waklog: phase 3 called");
1e18ef7d 1577
3f4fda20 1578 cfg = retrieve_config(r);
1579
4480093f 1580 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1581 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using user %s", cfg->principal);
1582 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1583 } else if ( cfg->default_principal ) {
1584 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using default user %s", cfg->default_principal);
1585 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1586 } else {
1587 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 not doing nothin.");
1588 }
1589
1590 return DECLINED;
1591}
bed98ff9 1592
3f4fda20 1593static int
1594waklog_phase6 (request_rec * r)
1595{
1596 waklog_config *cfg;
1597
1598 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1599 "mod_waklog: phase6 called");
3f4fda20 1600
1601 cfg = retrieve_config(r);
1602
4480093f 1603 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1604 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using user %s", cfg->principal);
1605 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1606 } else if ( cfg->default_principal ) {
1607 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using default user %s", cfg->default_principal);
1608 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1609 } else {
1610 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 not doing nothin.");
1611 }
1612
1613 return DECLINED;
1614}
bed98ff9 1615
3f4fda20 1616static int
1617waklog_phase7 (request_rec * r)
1618{
1619 waklog_config *cfg;
1620 int rc = 0;
1621
1622 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1623 "mod_waklog: phase7 called");
3f4fda20 1624
1625 cfg = retrieve_config (r);
1626
4480093f 1627 if ( get_cfg_protect(cfg) && get_cfg_usertokens(cfg) ) {
3f4fda20 1628 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using usertokens");
1629 rc = set_auth( r->server, r, 1, NULL, NULL, 0);
4480093f 1630 } else if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1631 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using user %s", cfg->principal);
1632 rc = set_auth( r->server, r, 0, cfg->principal, cfg->keytab, 0);
1633 } else if ( cfg->default_principal ) {
1634 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using default user %s", cfg->default_principal);
1635 rc = set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
d3bea354 1636 } else {
c760f0a1 1637 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: no tokens");
1638 if (child.token.ticketLen) {
1639 memset(&child.token, 0, sizeof(struct ktc_token));
1640 ktc_ForgetAllTokens();
1641 }
3f4fda20 1642 }
1643
1644 if ( rc ) {
1645 return 400;
1646 }
1647
1648 return DECLINED;
1649}
87822447 1650
3f4fda20 1651static int
1652waklog_phase9 (request_rec * r)
1653{
1654 waklog_config *cfg;
bed98ff9 1655
3f4fda20 1656 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1657 "mod_waklog: phase9 called");
bed98ff9 1658
3f4fda20 1659 getModConfig (cfg, r->server);
1660
1661 if ( cfg->default_principal ) {
1662 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase9 using default user %s", cfg->default_principal);
1663 set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1664 }
1665
1666 return DECLINED;
bed98ff9 1667}
1668
ff47641b 1669
87822447 1670static
c9d59a9c 1671#ifdef APACHE2
ff47641b 1672 int
87822447 1673#else
ff47641b 1674 void
87822447 1675#endif
ff47641b 1676waklog_new_connection (conn_rec * c
c9d59a9c 1677#ifdef APACHE2
42d78dfb 1678 , void *dummy
87822447 1679#endif
ff47641b 1680 )
1681{
1682
3f4fda20 1683 waklog_config *cfg;
ff47641b 1684
1685 log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
42d78dfb 1686 "mod_waklog: new_connection called: pid: %d", getpid ());
1687
1688 getModConfig(cfg, c->base_server);
1689
1690 if ( cfg->default_principal ) {
1691 log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
1692 cfg->default_principal);
1693 set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1694 }
1695
1696
3f4fda20 1697 return
c9d59a9c 1698#ifdef APACHE2
3f4fda20 1699 0
87822447 1700#endif
3f4fda20 1701 ;
7193eb01 1702}
bed98ff9 1703
c4ad0387 1704
1196adfe 1705/*
1706** Here's a quick explaination for phase0 and phase2:
1707** Apache does a stat() on the path between phase0 and
1708** phase2, and must by ACLed rl to succeed. So, at
1709** phase0 we acquire credentials for umweb:servers from
1710** a keytab, and at phase2 we must ensure we remove them.
1711**
1712** Failure to "unlog" would be a security risk.
1713*/
ff47641b 1714static int
1715waklog_phase2 (request_rec * r)
c4ad0387 1716{
161ffd84 1717
ff47641b 1718 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1719 "mod_waklog: phase2 called");
1196adfe 1720
ff47641b 1721 if (child.token.ticketLen)
1722 {
1723 memset (&child.token, 0, sizeof (struct ktc_token));
c4ad0387 1724
ff47641b 1725 ktc_ForgetAllTokens ();
c4ad0387 1726
ff47641b 1727 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1728 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1729 getpid ());
c4ad0387 1730 }
1196adfe 1731
ff47641b 1732 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1733 "mod_waklog: phase2 returning");
1196adfe 1734
3f4fda20 1735 return DECLINED;
c4ad0387 1736}
1737
c9d59a9c 1738#ifndef APACHE2
313dde40 1739module MODULE_VAR_EXPORT waklog_module = {
3f4fda20 1740 STANDARD_MODULE_STUFF,
866ccfbd 1741 waklog_init, /* module initializer */
42d78dfb 1742 waklog_create_dir_config, /* create per-dir config structures */
866ccfbd 1743 waklog_merge_dir_config, /* merge per-dir config structures */
1744 waklog_create_server_config, /* create per-server config structures */
1745 waklog_merge_dir_config, /* merge per-server config structures */
1746 waklog_cmds, /* table of config file commands */
1747 NULL, /* [#8] MIME-typed-dispatched handlers */
1748 waklog_phase1, /* [#1] URI to filename translation */
1749 NULL, /* [#4] validate user id from request */
1750 NULL, /* [#5] check if the user is ok _here_ */
1751 waklog_phase3, /* [#3] check access by host address */
1752 waklog_phase6, /* [#6] determine MIME type */
1753 waklog_phase7, /* [#7] pre-run fixups */
1754 waklog_phase9, /* [#9] log a transaction */
c760f0a1 1755 waklog_phase2, /* [#2] header parser */
866ccfbd 1756 waklog_child_init, /* child_init */
1757 waklog_child_exit, /* child_exit */
1758 waklog_phase0 /* [#0] post read-request */
bed98ff9 1759#ifdef EAPI
866ccfbd 1760 , NULL, /* EAPI: add_module */
1761 NULL, /* EAPI: remove_module */
1762 NULL, /* EAPI: rewrite_command */
1763 waklog_new_connection /* EAPI: new_connection */
bed98ff9 1764#endif
1765};
87822447 1766#else
1767static void
ff47641b 1768waklog_register_hooks (apr_pool_t * p)
87822447 1769{
3f4fda20 1770 ap_hook_translate_name (waklog_phase1, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1771 ap_hook_header_parser (waklog_phase2, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1772 ap_hook_access_checker (waklog_phase3, NULL, NULL, APR_HOOK_FIRST);
1773 ap_hook_type_checker (waklog_phase6, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1774 ap_hook_fixups (waklog_phase7, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1775 ap_hook_log_transaction (waklog_phase9, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1776 ap_hook_child_init (waklog_child_init, NULL, NULL, APR_HOOK_FIRST);
1777 ap_hook_post_read_request (waklog_phase0, NULL, NULL, APR_HOOK_FIRST);
1778 ap_hook_pre_connection (waklog_new_connection, NULL, NULL, APR_HOOK_FIRST);
1779 ap_hook_post_config (waklog_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
87822447 1780}
1781
1782
3f4fda20 1783module AP_MODULE_DECLARE_DATA waklog_module = {
1784 STANDARD20_MODULE_STUFF,
42d78dfb 1785 waklog_create_dir_config, /* create per-dir conf structures */
1786 waklog_merge_dir_config, /* merge per-dir conf structures */
1787 waklog_create_server_config, /* create per-server conf structures */
1788 waklog_merge_dir_config, /* merge per-server conf structures */
1789 waklog_cmds, /* table of configuration directives */
1790 waklog_register_hooks /* register hooks */
87822447 1791};
1792#endif