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