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