Update ap_log_error usage for Apache 2.4
[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>
2779b42e 13#include <stropts.h>
6dfa6ea5 14#include <sys/ioccom.h>
ff47641b 15#elif linux
16#define use_pthreads
17#include <features.h>
18#include <sys/types.h>
19#include <sys/mman.h>
20#include <pthread.h>
21#else
22#error "make sure you include the right stuff here"
23#endif
24
25#ifndef MAXNAMELEN
26#define MAXNAMELEN 1024
27#endif
28
891fb458 29#ifdef STANDARD20_MODULE_STUFF
c9d59a9c 30#define APACHE2
31#endif
32
33/********************* APACHE1 ******************************************************************************/
34#ifndef APACHE2
ebb1f61c 35#include "ap_config.h"
ebb1f61c 36#include <http_conf_globals.h>
37#define MK_POOL pool
38#define MK_TABLE_GET ap_table_get
39#define MK_TABLE_SET ap_table_set
40#define command(name, func, var, type, usage) \
41 { name, func, \
42 NULL , \
43 RSRC_CONF | ACCESS_CONF , type, usage }
21a7788b 44module waklog_module;
ebb1f61c 45
46/********************* APACHE2 ******************************************************************************/
47#else
c3d579d6 48#include "http_connection.h"
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#define command(name, func, var, type, usage) \
58 AP_INIT_ ## type (name, (void*) func, \
ebb1f61c 59 NULL, \
60 RSRC_CONF | ACCESS_CONF, usage)
21a7788b 61module AP_MODULE_DECLARE_DATA waklog_module;
62typedef struct { int dummy; } child_info;
87822447 63const char *userdata_key = "waklog_init";
21a7788b 64
5427406a
JW
65/* Apache 2.4 */
66#ifdef APLOG_USE_MODULE
67APLOG_USE_MODULE(waklog);
68#endif
69
c9d59a9c 70#endif /* APACHE2 */
ebb1f61c 71/**************************************************************************************************/
877d453f 72
73#include <krb5.h>
8e9df4d2 74#include <kopenafs.h>
3cb7bdb7
RJH
75
76#include <afs/param.h>
77
877d453f 78#include <afs/venus.h>
79#include <afs/auth.h>
80#include <afs/dirpath.h>
81#include <afs/ptuser.h>
82#include <rx/rxkad.h>
83
84#define TKT_LIFE ( 12 * 60 * 60 )
42d78dfb 85#define SLEEP_TIME ( TKT_LIFE - 5*60 )
877d453f 86
5d0827ae 87#define WAKLOG_UNSET -1
877d453f 88
89#ifdef WAKLOG_DEBUG
90#undef APLOG_DEBUG
91#define APLOG_DEBUG APLOG_ERR
92#endif
93
877d453f 94/* this is used to turn off pag generation for the backround worker child during startup */
95int pag_for_children = 1;
96
97typedef struct
98{
99 int forked;
100 int configured;
101 int protect;
102 int usertokens;
c8563f50 103 int cell_in_principal;
21a7788b 104 int disable_token_cache;
877d453f 105 char *keytab;
106 char *principal;
107 char *default_principal;
108 char *default_keytab;
109 char *afs_cell;
98534230 110 char *afs_cell_realm;
877d453f 111 char *path;
112 MK_POOL *p;
113}
114waklog_config;
115
116typedef struct
117{
118 struct ktc_token token;
119 char clientprincipal[MAXNAMELEN];
120 krb5_context kcontext;
121 krb5_ccache ccache;
122 struct ktc_principal server;
123 struct ktc_principal client;
124 int pr_init;
125} waklog_child_config;
126
127waklog_child_config child;
128
129struct tokencache_ent {
130 char clientprincipal[MAXNAMELEN];
131 struct ktc_token token;
132 struct ktc_principal client;
133 struct ktc_principal server;
134 time_t lastused;
135 int persist;
136};
137
138#define SHARED_TABLE_SIZE 512
139
140struct sharedspace_s {
141 int renewcount;
142 struct tokencache_ent sharedtokens[SHARED_TABLE_SIZE];
143};
144
145struct sharedspace_s *sharedspace = NULL;
146
147struct renew_ent {
148 char *keytab;
149 char *principal;
150 int lastrenewed;
151};
152
153#ifdef use_pthreads
154pthread_rwlock_t *sharedlock = NULL;
155#else
156rwlock_t *sharedlock = NULL;
157#endif
158
159struct renew_ent renewtable[SHARED_TABLE_SIZE];
160
161int renewcount = 0;
162
ebb1f61c 163
87822447 164
c69d952f 165#define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
87822447 166
58bbdc54 167
5427406a
JW
168#ifdef APLOG_USE_MODULE
169static void
170log_error (const char *file, int line, int module_index, int level, int status,
171 const server_rec * s, const char *fmt, ...)
172#else
87822447 173static void
3f4fda20 174log_error (const char *file, int line, int level, int status,
42d78dfb 175 const server_rec * s, const char *fmt, ...)
5427406a 176#endif
4d47a8d9 177{
3f4fda20 178 char errstr[4096];
179 va_list ap;
4d47a8d9 180
3f4fda20 181 va_start (ap, fmt);
182 vsnprintf (errstr, 1024, fmt, ap);
183 va_end (ap);
4d47a8d9 184
c9d59a9c 185#ifdef APACHE2
5427406a
JW
186 #ifdef APLOG_USE_MODULE
187 /* Apache 2.4 */
188 ap_log_error (file, line, module_index, level | APLOG_NOERRNO, status, s, "%s", errstr);
189 #else
3f4fda20 190 ap_log_error (file, line, level | APLOG_NOERRNO, status, s, "(%d) %s", getpid(), errstr);
5427406a 191 #endif
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");
5220a4ef 313 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: r->user=%s", (r->user==NULL ? "null" : r->user));
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
8f0b039f 348 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: k5user=%s", k5user);
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... */
8f0b039f 419 if ( ! usecached ) {
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 }
5d0827ae 523 if (cfg->afs_cell_realm != NULL) {
98534230 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
4480093f 747int get_cfg_usertokens(waklog_config *cfg)
748{
749 if (cfg->usertokens==WAKLOG_UNSET)
750 return 0; /* default */
751 return cfg->usertokens;
752}
753
754int get_cfg_protect(waklog_config *cfg)
755{
756 if (cfg->protect==WAKLOG_UNSET)
757 return 0; /* default */
758 return cfg->protect;
759}
760
761int get_cfg_disable_token_cache(waklog_config *cfg)
762{
763 if (cfg->disable_token_cache==WAKLOG_UNSET)
764 return 0; /* default */
765 return cfg->disable_token_cache;
766}
767
7193eb01 768
3f4fda20 769static void *
770waklog_create_server_config (MK_POOL * p, server_rec * s)
771{
772 waklog_config *cfg;
773
774 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
775 cfg->p = p;
776 memset(cfg, 0, sizeof(waklog_config));
777 cfg->path = "(server)";
778 cfg->protect = WAKLOG_UNSET;
779 cfg->usertokens = WAKLOG_UNSET;
21a7788b 780 cfg->disable_token_cache = WAKLOG_UNSET;
5d0827ae 781 cfg->keytab = NULL;
782 cfg->principal = NULL;
783 cfg->default_principal = NULL;
784 cfg->default_keytab = NULL;
785 cfg->afs_cell = NULL;
786 cfg->afs_cell_realm = NULL;
3f4fda20 787 cfg->forked = 0;
788 cfg->configured = 0;
789
790 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 791 "mod_waklog: server config created.");
3f4fda20 792
793 return (cfg);
794}
7193eb01 795
3f4fda20 796/* initialize with host-config information */
58bbdc54 797
3f4fda20 798static void *
799waklog_create_dir_config (MK_POOL * p, char *dir)
800{
801 waklog_config *cfg;
802
803 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
804 memset(cfg, 0, sizeof(waklog_config));
805 cfg->p = p;
806 cfg->path = ap_pstrdup(p, dir );
807 cfg->protect = WAKLOG_UNSET;
808 cfg->usertokens = WAKLOG_UNSET;
21a7788b 809 cfg->disable_token_cache = WAKLOG_UNSET;
5d0827ae 810 cfg->keytab = NULL;
811 cfg->principal = NULL;
812 cfg->default_principal = NULL;
813 cfg->default_keytab = NULL;
814 cfg->afs_cell = NULL;
815 cfg->afs_cell_realm = NULL;
3f4fda20 816 cfg->forked = 0;
817 cfg->configured = 0;
818
819 return (cfg);
58bbdc54 820}
821
3f4fda20 822static void *waklog_merge_dir_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 823
3f4fda20 824 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
825 waklog_config *parent = ( waklog_config * ) parent_conf;
826 waklog_config *child = ( waklog_config * ) newloc_conf;
827
828 merged->protect = child->protect != WAKLOG_UNSET ? child->protect : parent->protect;
829
5d0827ae 830 merged->path = child->path != NULL ? child->path : parent->path;
3f4fda20 831
832 merged->usertokens = child->usertokens != WAKLOG_UNSET ? child->usertokens : parent->usertokens;
21a7788b 833
834 merged->disable_token_cache = child->disable_token_cache != WAKLOG_UNSET ? child->disable_token_cache : parent->disable_token_cache;
3f4fda20 835
5d0827ae 836 merged->principal = child->principal != NULL ? child->principal : parent->principal;
3f4fda20 837
5d0827ae 838 merged->keytab = child->keytab != NULL ? child->keytab : parent->keytab;
3f4fda20 839
5d0827ae 840 merged->default_keytab = child->default_keytab != NULL ? child->default_keytab : parent->default_keytab;
3f4fda20 841
5d0827ae 842 merged->default_principal = child->default_principal != NULL ? child->default_principal : parent->default_principal;
3f4fda20 843
5d0827ae 844 merged->afs_cell = child->afs_cell != NULL ? child->afs_cell : parent->afs_cell;
98534230 845
5d0827ae 846 merged->afs_cell_realm = child->afs_cell_realm != NULL ? child->afs_cell_realm : parent->afs_cell_realm;
3f4fda20 847
848 return (void *) merged;
849
850}
58bbdc54 851
3f4fda20 852static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 853
3f4fda20 854 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
855 waklog_config *pconf = ( waklog_config * ) parent_conf;
856 waklog_config *nconf = ( waklog_config * ) newloc_conf;
857
858 merged->protect = nconf->protect == WAKLOG_UNSET ? pconf->protect : nconf->protect;
58bbdc54 859
3f4fda20 860 merged->usertokens = nconf->usertokens == WAKLOG_UNSET ? pconf->usertokens : nconf->usertokens;
58bbdc54 861
bce7d4d9 862 merged->disable_token_cache = nconf->disable_token_cache == WAKLOG_UNSET ? pconf->disable_token_cache : nconf->disable_token_cache;
21a7788b 863
5d0827ae 864 merged->keytab = nconf->keytab == NULL ? ap_pstrdup(p, pconf->keytab) :
865 ( nconf->keytab == NULL ? NULL : ap_pstrdup(p, nconf->keytab) );
3f4fda20 866
5d0827ae 867 merged->principal = nconf->principal == NULL ? ap_pstrdup(p, pconf->principal) :
868 ( nconf->principal == NULL ? NULL : ap_pstrdup(p, nconf->principal) );
3f4fda20 869
5d0827ae 870 merged->afs_cell = nconf->afs_cell == NULL ? ap_pstrdup(p, pconf->afs_cell) :
871 ( nconf->afs_cell == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell) );
3f4fda20 872
5d0827ae 873 merged->afs_cell_realm = nconf->afs_cell_realm == NULL ? ap_pstrdup(p, pconf->afs_cell_realm) :
874 ( nconf->afs_cell_realm == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell_realm) );
98534230 875
5d0827ae 876 merged->default_keytab = nconf->default_keytab == NULL ? ap_pstrdup(p, pconf->default_keytab) :
877 ( nconf->default_keytab == NULL ? NULL : ap_pstrdup(p, nconf->default_keytab) );
58bbdc54 878
5d0827ae 879 merged->default_principal = nconf->default_principal == NULL ? ap_pstrdup(p, pconf->default_principal) :
880 ( nconf->default_principal == NULL ? NULL : ap_pstrdup(p, nconf->default_principal) );
3f4fda20 881
882
883 return (void *) merged;
884
885}
886
887static const char *
21a7788b 888set_waklog_enabled (cmd_parms * params, void *mconfig, int flag)
58bbdc54 889{
3f4fda20 890 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
891 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
892
893 cfg->protect = flag;
894 cfg->configured = 1;
895 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
21a7788b 896 "mod_waklog: waklog_enabled set on %s", cfg->path ? cfg->path : "NULL");
3f4fda20 897 return (NULL);
898}
58bbdc54 899
7193eb01 900
3f4fda20 901/* this adds a principal/keytab pair to get their tokens renewed by the
902 child process every few centons. */
7193eb01 903
3f4fda20 904void add_to_renewtable(MK_POOL *p, char *keytab, char *principal) {
87822447 905
3f4fda20 906 int i;
907
908 if ( renewcount >= SHARED_TABLE_SIZE ) {
909 log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "mod_waklog: big problem. Increase the SHARED_TABLE_SIZE or \
910 decrease your tokens.");
b74fad73 911 return;
3f4fda20 912 }
913
914 /* check to see if it's already there */
915
916 for ( i = 0; i < renewcount; i++ ) {
917 if ( ! strcmp(renewtable[i].principal, principal ) ) {
918 return;
919 }
920 }
921
922 renewtable[renewcount].keytab = ap_pstrdup(p, keytab);
923 renewtable[renewcount].principal = ap_pstrdup(p, principal);
924 renewtable[renewcount].lastrenewed = 0;
925 ++renewcount;
926
b74fad73 927}
928
3f4fda20 929static const char *
21a7788b 930set_waklog_location_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
3f4fda20 931{
932 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
933 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
934
935 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 936 "mod_waklog: configuring principal: %s, keytab: %s", principal, keytab);
937
938 cfg->principal = ap_pstrdup(params->pool, principal);
3f4fda20 939 cfg->keytab = ap_pstrdup (params->pool, keytab);
940
941 add_to_renewtable(params->pool, keytab, principal);
942
943 cfg->configured = 1;
944
945 return (NULL);
946}
b74fad73 947
3f4fda20 948static const char *
21a7788b 949set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
313dde40 950{
891fb458 951 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
952 waklog_config *waklog_srvconfig =
3f4fda20 953 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
954
891fb458 955 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
42d78dfb 956 "mod_waklog: will use afs_cell: %s", file);
313dde40 957
678051d7 958 // Prefer afs/cell@REALM over afs@REALM, just like the OpenAFS tools
959 waklog_srvconfig->cell_in_principal = 1;
960
891fb458 961 waklog_srvconfig->afs_cell = ap_pstrdup (params->pool, file);
962 waklog_srvconfig->configured = 1;
963
964 if (waklog_mconfig != NULL) {
c8563f50 965 waklog_mconfig->cell_in_principal = waklog_srvconfig->cell_in_principal;
891fb458 966 waklog_mconfig->afs_cell = ap_pstrdup (params->pool, file);
967 waklog_mconfig->configured = 1;
968 }
3f4fda20 969 return (NULL);
970}
58bbdc54 971
98534230 972static const char *
973set_waklog_afs_cell_realm (cmd_parms * params, void *mconfig, char *file)
974{
975 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
976 waklog_config *waklog_srvconfig =
977 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
978
979 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
980 "mod_waklog: will use afs_cell_realm: %s", file);
981
982 waklog_srvconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
983
984 if (waklog_mconfig != NULL) {
985 waklog_mconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
986 }
987 return (NULL);
988}
989
3f4fda20 990static const char *
991set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal, char *keytab)
992{
993 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
994 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
58bbdc54 995
3f4fda20 996 waklog_config *srvcfg = ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
4e1ae1cd 997
3f4fda20 998 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 999 "mod_waklog: set default princ/keytab: %s, %s for %s", principal, keytab, cfg->path ? cfg->path : "NULL");
313dde40 1000
3f4fda20 1001 cfg->default_principal = ap_pstrdup (params->pool, principal);
1002 cfg->default_keytab = ap_pstrdup(params->pool, keytab );
1003
1004 /* this also gets set at the server level */
1005 if ( mconfig && ( ! cfg->path ) ) {
1006 srvcfg->default_principal = ap_pstrdup (params->pool, principal);
1007 srvcfg->default_keytab = ap_pstrdup(params->pool, keytab );
1008 } else {
1009 log_error(APLOG_MARK, APLOG_ERR, 0, params->server, "only able to set default principal on a global level!");
1010 return "Unable to set DefaultPrincipal outside of top level config!";
1011 }
1012
1013 add_to_renewtable( params->pool, keytab, principal );
1014
1015 cfg->configured = 1;
1016
1017 return (NULL);
1018}
313dde40 1019
3f4fda20 1020static const char *
1021set_waklog_use_usertokens (cmd_parms * params, void *mconfig, int flag)
bed98ff9 1022{
3f4fda20 1023 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
1024 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
bed98ff9 1025
3f4fda20 1026 cfg->usertokens = flag;
bed98ff9 1027
3f4fda20 1028 cfg->configured = 1;
bed98ff9 1029
3f4fda20 1030 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 1031 "mod_waklog: waklog_use_user_tokens set");
3f4fda20 1032 return (NULL);
bed98ff9 1033}
1034
1035
21a7788b 1036static const char *
1037set_waklog_disable_token_cache (cmd_parms * params, void *mconfig, int flag)
1038{
1039 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
1040 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
1041
1042 cfg->disable_token_cache = flag;
1043
1044 cfg->configured = 1;
1045
1046 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
1047 "mod_waklog: waklog_disable_token_cache set");
1048 return (NULL);
1049}
1050
1051
c9d59a9c 1052#ifndef APACHE2
3f4fda20 1053static void waklog_child_exit( server_rec *s, MK_POOL *p ) {
1054#else
1055apr_status_t waklog_child_exit( void *sr ) {
4e1ae1cd 1056
3f4fda20 1057 server_rec *s = (server_rec *) sr;
1058#endif
1059
1060 if ( child.ccache ) {
1061 krb5_cc_close(child.kcontext, child.ccache);
1062 }
1063
1064 if ( child.kcontext ) {
1065 krb5_free_context(child.kcontext);
1066 }
1067
1068 /* forget our tokens */
1069
1070 ktc_ForgetAllTokens ();
1071
1072 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1073 "mod_waklog: waklog_child_exit complete");
4e1ae1cd 1074
c9d59a9c 1075#ifdef APACHE2
3f4fda20 1076 return APR_SUCCESS;
1077#endif
1078
1079}
4e1ae1cd 1080
3f4fda20 1081static void
c9d59a9c 1082#ifdef APACHE2
3f4fda20 1083waklog_child_init (MK_POOL * p, server_rec * s)
1084#else
1085waklog_child_init (server_rec * s, MK_POOL * p)
1086#endif
1087{
b52ccbb1 1088
3f4fda20 1089 krb5_error_code code;
1090 waklog_config *cfg;
1091
1092 char *cell;
1093
3f4fda20 1094 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
1095
1096 if ( !sharedspace ) {
1097 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: child_init called without shared space? %d", getpid());
1098 return;
1099 }
1100
1101 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
7193eb01 1102
3f4fda20 1103 memset (&child, 0, sizeof(child));
1104
c760f0a1 1105 if ( ( code = krb5_init_context(&child.kcontext) ) ) {
3f4fda20 1106 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1107 }
1108
c760f0a1 1109 if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
3f4fda20 1110 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1111 }
1112
1113 if ( pag_for_children ) {
8e9df4d2 1114 k_setpag ();
3f4fda20 1115 }
7193eb01 1116
3f4fda20 1117 getModConfig (cfg, s);
7193eb01 1118
5d0827ae 1119 if ( cfg->default_principal != NULL ) {
3f4fda20 1120 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init setting default user %s, %s", cfg->default_principal, cfg->default_keytab);
1121 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1122 }
7193eb01 1123
891fb458 1124 cell = strdup(cfg->afs_cell);
3f4fda20 1125 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
7193eb01 1126
c9d59a9c 1127#ifdef APACHE2
3f4fda20 1128 apr_pool_cleanup_register(p, s, waklog_child_exit, apr_pool_cleanup_null);
1129#endif
7193eb01 1130
3f4fda20 1131 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1132 "mod_waklog: child_init returned");
7193eb01 1133
3f4fda20 1134 return;
1135}
b52ccbb1 1136
3f4fda20 1137command_rec waklog_cmds[] = {
1138
21a7788b 1139 command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
1140 "Use the supplied AFS cell (required)"),
7193eb01 1141
98534230 1142 command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm, 0, TAKE1,
1143 "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
1144
21a7788b 1145 command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
1146 "enable waklog on a server, location, or directory basis"),
7193eb01 1147
21a7788b 1148 command ("WaklogDefaultPrincipal", set_waklog_default_principal, 0, TAKE2,
1149 "Set the default principal that the server runs as"),
7193eb01 1150
21a7788b 1151 command ("WaklogLocationPrincipal", set_waklog_location_principal, 0, TAKE2,
1152 "Set the principal on a <Location>-specific basis"),
7193eb01 1153
21a7788b 1154 command ("WaklogDisableTokenCache", set_waklog_disable_token_cache, 0, FLAG,
1155 "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
1156
1157 command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
1158 "Use the requesting user tokens (from webauth)"),
1159
3f4fda20 1160 {NULL}
1161};
7193eb01 1162
7193eb01 1163
3f4fda20 1164/* not currently using this */
7193eb01 1165
3f4fda20 1166static int
1167token_cleanup (void *data)
1168{
1169 request_rec *r = (request_rec *) data;
e2df6441 1170
3f4fda20 1171 if (child.token.ticketLen)
1172 {
1173 memset (&child.token, 0, sizeof (struct ktc_token));
e21f34f0 1174
3f4fda20 1175 ktc_ForgetAllTokens ();
7193eb01 1176
3f4fda20 1177 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1178 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1179 getpid ());
3f4fda20 1180 }
1181 return 0;
7193eb01 1182}
1183
22782cea
JW
1184/* This function doesn't return anything but is passed to ap_bspawn_child on
1185 * Apache 1 which expects it to return a pid as an int. For want of better
1186 * understanding, err on the side of not changing Apache 1 code while fixing
1187 * the compile warning on Apache 2. */
1188#ifdef APACHE2
1189static void
1190#else
3f4fda20 1191static int
22782cea 1192#endif
3f4fda20 1193waklog_child_routine (void *data, child_info * pinfo)
7193eb01 1194{
3f4fda20 1195 int i;
1196 server_rec *s = (server_rec *) data;
1197 krb5_error_code code;
1198 char *cell;
1199 time_t sleep_time = ( TKT_LIFE / 2 ) ;
1200 time_t when;
1201 time_t left;
1202 waklog_config *cfg;
1203
1204 getModConfig( cfg, s );
1205
1206 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waklog_child_routine started, running as %d", getuid());
1207
1208 memset (&child, 0, sizeof(child));
1209
c760f0a1 1210 if ( ( code = krb5_init_context(&child.kcontext) ) ) {
3f4fda20 1211 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1212 }
1213
c760f0a1 1214 if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
3f4fda20 1215 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1216 }
1217
c760f0a1 1218 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: about to pr_Initialize");
1219
3f4fda20 1220 /* need to do this so we can make PTS calls */
891fb458 1221 cell = strdup(cfg->afs_cell); /* stupid */
3f4fda20 1222 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
c760f0a1 1223
1224 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: still here");
1225
3f4fda20 1226 while(1) {
1227
1228 for ( i = 0; i < renewcount; ++i ) {
1229 renewtable[i].lastrenewed = time(0);
1230 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: (pid %d) renewing %s / %s", getpid(), renewtable[i].principal,
1231 renewtable[i].keytab);
1232
1233 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 1 );
1234
1235 /* if this is our default token, we want to "stash" it in our current PAG so the parent maintains readability of
1236 things that it needs to read */
1237
1238 if ( cfg && cfg->default_principal && ( ! strcmp(cfg->default_principal, renewtable[i].principal ) ) ) {
1239 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: renewing/setting default tokens" );
1240 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 0 );
1241 }
1242
4e1ae1cd 1243 }
1244
3f4fda20 1245 sharedspace->renewcount++;
1246
1247 left = sleep_time;
1248
1249 while( left > 5 ) {
1250 when = time(0);
1251
1252 sleep(left);
1253
1254 left -= ( time(0) - when );
4e1ae1cd 1255 }
3f4fda20 1256
1257 }
4e1ae1cd 1258
3f4fda20 1259 pr_End();
403921ef 1260
3f4fda20 1261}
4e1ae1cd 1262
c9d59a9c 1263#ifdef APACHE2
3f4fda20 1264static int
1265waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
42d78dfb 1266 apr_pool_t * ptemp, server_rec * s)
3f4fda20 1267{
1268 int rv;
1269 extern char *version;
1270 apr_proc_t *proc;
1271 waklog_config *cfg;
1272 void *data;
1273 int fd = -1;
1274 int use_existing = 1;
1275 int oldrenewcount;
1276 char cache_file[MAXNAMELEN];
1277#ifdef use_pthreads
1278 pthread_rwlockattr_t rwlock_attr;
1279#endif
4e1ae1cd 1280
1281
3f4fda20 1282 getModConfig (cfg, s);
4e1ae1cd 1283
3f4fda20 1284 /* initialize_module() will be called twice, and if it's a DSO
1285 * then all static data from the first call will be lost. Only
1286 * set up our static data on the second call.
1287 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
1288 apr_pool_userdata_get (&data, userdata_key, s->process->pool);
7193eb01 1289
891fb458 1290
1291 if (cfg->afs_cell==NULL) {
1292 log_error (APLOG_MARK, APLOG_ERR, 0, s,
21a7788b 1293 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
891fb458 1294 /** clobber apache */
1295 exit(-1);
1296 }
1297
3f4fda20 1298 if (!data)
1299 {
1300 apr_pool_userdata_set ((const void *) 1, userdata_key,
42d78dfb 1301 apr_pool_cleanup_null, s->process->pool);
4e1ae1cd 1302 }
3f4fda20 1303 else
1304 {
1305 log_error (APLOG_MARK, APLOG_INFO, 0, s,
891fb458 1306 "mod_waklog: version %s initialized for cell %s", version, cfg->afs_cell);
3f4fda20 1307
1308 if ( sharedspace ) {
1309 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1310 } else {
1311
1312 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1313
1314 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1315
1316 if ( errno == ENOENT ) {
1317
1318 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1319 use_existing = 0;
1320 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1321 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1322 exit(errno);
1323 }
1324 } else {
1325 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1326 }
1327 }
1328
1329 if ( use_existing == 0 ) {
1330 struct sharedspace_s bob;
1331 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1332 memset( &bob, 0, sizeof(struct sharedspace_s));
24bb0dbf
JW
1333 if ( write(fd, &bob, sizeof(struct sharedspace_s)) != sizeof(struct sharedspace_s) ) {
1334 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: failed to write to our cache file %s (%d)", cache_file, errno );
1335 exit(errno);
1336 }
3f4fda20 1337 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1338 }
1339
1340 /* mmap the region */
1341
1342 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != MAP_FAILED ) {
4cd4a5af 1343 int err = 0;
3f4fda20 1344 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
4cd4a5af 1345 err = unlink(cache_file);
1346 if (err) {
1347 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: unable to delete %s due to %d", cache_file, errno);
1348 } else {
95ad25b8 1349 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared cache unlinked (will be deleted when Apache quits)");
4cd4a5af 1350 }
3f4fda20 1351 } else {
1352 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1353 exit(errno);
1354 }
1355 }
4e1ae1cd 1356
3f4fda20 1357#ifdef use_pthreads
1358#define locktype pthread_rwlock_t
1359#else
1360#define locktype rwlock_t
1361#endif
4e1ae1cd 1362
4521ace1 1363 if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) != NULL ) {
3f4fda20 1364#ifndef use_pthreads
1365 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1366#else
1367 pthread_rwlockattr_init(&rwlock_attr);
1368 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1369 pthread_rwlock_init(sharedlock, &rwlock_attr );
1370#endif
1371 } else {
1372 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1373 }
58bbdc54 1374
3f4fda20 1375#undef locktype
7193eb01 1376
3f4fda20 1377 /* set our default tokens */
403921ef 1378
3f4fda20 1379 oldrenewcount = sharedspace->renewcount;
7193eb01 1380
3f4fda20 1381 pag_for_children = 0;
7193eb01 1382
3f4fda20 1383 proc = (apr_proc_t *) ap_pcalloc (s->process->pool, sizeof (apr_proc_t));
7193eb01 1384
3f4fda20 1385 rv = apr_proc_fork (proc, s->process->pool);
7193eb01 1386
3f4fda20 1387 if (rv == APR_INCHILD)
42d78dfb 1388 {
1389 waklog_child_routine (s, NULL);
1390 }
3f4fda20 1391 else
42d78dfb 1392 {
1393 apr_pool_note_subprocess (s->process->pool, proc, APR_KILL_ALWAYS);
1394 }
3f4fda20 1395 /* parent and child */
1396 cfg->forked = proc->pid;
1397 pag_for_children = 1;
1398
1399 if ( use_existing == 0 ) {
1400 /* wait here until our child process has gone and done it's renewing thing. */
1401 while( sharedspace->renewcount == oldrenewcount ) {
1402 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1403 sleep(2);
1404 }
1405 }
1406
1407 if ( cfg->default_principal ) {
1408 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1409 }
1410 }
1411 return 0;
1412}
ebb1f61c 1413#else
3f4fda20 1414static void
1415waklog_init (server_rec * s, MK_POOL * p)
1416{
1417 extern char *version;
1418 int pid;
1419 waklog_config *cfg;
3f4fda20 1420 int fd = -1;
1421 int use_existing = 1;
1422 int oldrenewcount;
1423 char cache_file[MAXNAMELEN];
1424#ifdef use_pthreads
1425 pthread_rwlockattr_t rwlock_attr;
ebb1f61c 1426#endif
7193eb01 1427
3f4fda20 1428 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1429 "mod_waklog: version %s initialized.", version);
7193eb01 1430
3f4fda20 1431 if ( sharedspace ) {
1432 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1433 } else {
1434
1435 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1436
1437 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1438
1439 if ( errno == ENOENT ) {
1440
1441 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1442 use_existing = 0;
1443 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1444 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1445 exit(errno);
1446 }
1447 } else {
1448 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1449 }
1450
1451 }
1452
1453 if ( use_existing == 0 ) {
1454 struct sharedspace_s bob;
1455 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1456 memset( &bob, 0, sizeof(struct sharedspace_s));
1457 write(fd, &bob, sizeof(struct sharedspace_s));
1458 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1459 }
4e1ae1cd 1460
3f4fda20 1461 /* mmap the region */
1462
c760f0a1 1463 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != (void *) -1 ) {
3f4fda20 1464 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
1465 close(fd);
1466 } else {
1467 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1468 exit(errno);
1469 }
1470 }
e21f34f0 1471
3f4fda20 1472#ifdef use_pthreads
1473#define locktype pthread_rwlock_t
1474#else
1475#define locktype rwlock_t
ea3e8708 1476#endif
e21f34f0 1477
3f4fda20 1478 /* mmap our shared space for our lock */
c760f0a1 1479 if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) ) {
3f4fda20 1480#ifndef use_pthreads
1481 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1482#else
1483 pthread_rwlockattr_init(&rwlock_attr);
1484 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1485 pthread_rwlock_init(sharedlock, &rwlock_attr );
1486#endif
1487 } else {
1488 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1489 }
e21f34f0 1490
3f4fda20 1491#undef locktype
e21f34f0 1492
3f4fda20 1493 /* set our default tokens */
1494
1495 getModConfig (cfg, s);
42d78dfb 1496
1497 oldrenewcount = sharedspace->renewcount;
1498
1499 pag_for_children = 0;
1500
1501 pid = ap_bspawn_child (p, waklog_child_routine, s, kill_always,
1502 NULL, NULL, NULL);
1503
1504 pag_for_children = 1;
1505
3f4fda20 1506 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1507 "mod_waklog: ap_bspawn_child: %d.", pid);
3f4fda20 1508
1509 if ( use_existing == 0 ) {
1510 /* wait here until our child process has gone and done it's renewing thing. */
1511 while( sharedspace->renewcount == oldrenewcount ) {
1512 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1513 sleep(2);
87822447 1514 }
3f4fda20 1515 }
1516
1517 if ( cfg->default_principal ) {
1518 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1519 }
1520
87822447 1521}
3f4fda20 1522#endif
1523
1524static int
1525waklog_phase0 (request_rec * r)
e21f34f0 1526{
3f4fda20 1527 waklog_config *cfg;
e21f34f0 1528
3f4fda20 1529 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1530 "mod_waklog: phase0 called");
3f4fda20 1531
1532 cfg = retrieve_config(r);
e21f34f0 1533
4480093f 1534 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1535 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using user %s", cfg->principal);
1536 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1537 } else if ( cfg->default_principal ) {
1538 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using default user %s", cfg->default_principal);
1539 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1540 } else {
c760f0a1 1541
1542 if (child.token.ticketLen) {
1543 memset( &child.token, 0, sizeof (struct ktc_token) );
1544 ktc_ForgetAllTokens();
1545 }
1546
3f4fda20 1547 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 not doing nothin.");
1548 }
e21f34f0 1549
3f4fda20 1550 return DECLINED;
e21f34f0 1551}
4e1ae1cd 1552
3f4fda20 1553static int
1554waklog_phase1 (request_rec * r)
bed98ff9 1555{
3f4fda20 1556 waklog_config *cfg;
313dde40 1557
3f4fda20 1558 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1559 "mod_waklog: phase1 called");
7193eb01 1560
3f4fda20 1561 cfg = retrieve_config(r);
313dde40 1562
4480093f 1563 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1564 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using user %s", cfg->principal);
1565 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1566 } else if ( cfg->default_principal ) {
1567 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using default user %s", cfg->default_principal);
1568 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1569 } else {
1570 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 not doing nothin.");
1571 }
4e1ae1cd 1572
3f4fda20 1573 return DECLINED;
7193eb01 1574}
4e1ae1cd 1575
3f4fda20 1576static int
1577waklog_phase3 (request_rec * r)
7193eb01 1578{
3f4fda20 1579 waklog_config *cfg;
1e18ef7d 1580
3f4fda20 1581 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1582 "mod_waklog: phase 3 called");
1e18ef7d 1583
3f4fda20 1584 cfg = retrieve_config(r);
1585
4480093f 1586 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1587 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using user %s", cfg->principal);
1588 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1589 } else if ( cfg->default_principal ) {
1590 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using default user %s", cfg->default_principal);
1591 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1592 } else {
1593 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 not doing nothin.");
1594 }
1595
1596 return DECLINED;
1597}
bed98ff9 1598
3f4fda20 1599static int
1600waklog_phase6 (request_rec * r)
1601{
1602 waklog_config *cfg;
1603
1604 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1605 "mod_waklog: phase6 called");
3f4fda20 1606
1607 cfg = retrieve_config(r);
1608
4480093f 1609 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1610 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using user %s", cfg->principal);
1611 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1612 } else if ( cfg->default_principal ) {
1613 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using default user %s", cfg->default_principal);
1614 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1615 } else {
1616 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 not doing nothin.");
1617 }
1618
1619 return DECLINED;
1620}
bed98ff9 1621
3f4fda20 1622static int
1623waklog_phase7 (request_rec * r)
1624{
1625 waklog_config *cfg;
1626 int rc = 0;
1627
1628 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1629 "mod_waklog: phase7 called");
3f4fda20 1630
1631 cfg = retrieve_config (r);
1632
4480093f 1633 if ( get_cfg_protect(cfg) && get_cfg_usertokens(cfg) ) {
3f4fda20 1634 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using usertokens");
1635 rc = set_auth( r->server, r, 1, NULL, NULL, 0);
4480093f 1636 } else if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1637 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using user %s", cfg->principal);
1638 rc = set_auth( r->server, r, 0, cfg->principal, cfg->keytab, 0);
1639 } else if ( cfg->default_principal ) {
1640 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using default user %s", cfg->default_principal);
1641 rc = set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
d3bea354 1642 } else {
c760f0a1 1643 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: no tokens");
1644 if (child.token.ticketLen) {
1645 memset(&child.token, 0, sizeof(struct ktc_token));
1646 ktc_ForgetAllTokens();
1647 }
3f4fda20 1648 }
1649
1650 if ( rc ) {
1651 return 400;
1652 }
1653
1654 return DECLINED;
1655}
87822447 1656
3f4fda20 1657static int
1658waklog_phase9 (request_rec * r)
1659{
1660 waklog_config *cfg;
bed98ff9 1661
3f4fda20 1662 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1663 "mod_waklog: phase9 called");
bed98ff9 1664
3f4fda20 1665 getModConfig (cfg, r->server);
1666
1667 if ( cfg->default_principal ) {
1668 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase9 using default user %s", cfg->default_principal);
1669 set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1670 }
1671
1672 return DECLINED;
bed98ff9 1673}
1674
ff47641b 1675
87822447 1676static
c9d59a9c 1677#ifdef APACHE2
ff47641b 1678 int
87822447 1679#else
ff47641b 1680 void
87822447 1681#endif
ff47641b 1682waklog_new_connection (conn_rec * c
c9d59a9c 1683#ifdef APACHE2
42d78dfb 1684 , void *dummy
87822447 1685#endif
ff47641b 1686 )
1687{
1688
3f4fda20 1689 waklog_config *cfg;
ff47641b 1690
1691 log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
42d78dfb 1692 "mod_waklog: new_connection called: pid: %d", getpid ());
1693
1694 getModConfig(cfg, c->base_server);
1695
1696 if ( cfg->default_principal ) {
1697 log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
1698 cfg->default_principal);
1699 set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1700 }
1701
1702
3f4fda20 1703 return
c9d59a9c 1704#ifdef APACHE2
3f4fda20 1705 0
87822447 1706#endif
3f4fda20 1707 ;
7193eb01 1708}
bed98ff9 1709
c4ad0387 1710
1196adfe 1711/*
1712** Here's a quick explaination for phase0 and phase2:
1713** Apache does a stat() on the path between phase0 and
1714** phase2, and must by ACLed rl to succeed. So, at
1715** phase0 we acquire credentials for umweb:servers from
1716** a keytab, and at phase2 we must ensure we remove them.
1717**
1718** Failure to "unlog" would be a security risk.
1719*/
ff47641b 1720static int
1721waklog_phase2 (request_rec * r)
c4ad0387 1722{
161ffd84 1723
ff47641b 1724 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1725 "mod_waklog: phase2 called");
1196adfe 1726
ff47641b 1727 if (child.token.ticketLen)
1728 {
1729 memset (&child.token, 0, sizeof (struct ktc_token));
c4ad0387 1730
ff47641b 1731 ktc_ForgetAllTokens ();
c4ad0387 1732
ff47641b 1733 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1734 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1735 getpid ());
c4ad0387 1736 }
1196adfe 1737
ff47641b 1738 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1739 "mod_waklog: phase2 returning");
1196adfe 1740
3f4fda20 1741 return DECLINED;
c4ad0387 1742}
1743
c9d59a9c 1744#ifndef APACHE2
313dde40 1745module MODULE_VAR_EXPORT waklog_module = {
3f4fda20 1746 STANDARD_MODULE_STUFF,
866ccfbd 1747 waklog_init, /* module initializer */
42d78dfb 1748 waklog_create_dir_config, /* create per-dir config structures */
866ccfbd 1749 waklog_merge_dir_config, /* merge per-dir config structures */
1750 waklog_create_server_config, /* create per-server config structures */
1751 waklog_merge_dir_config, /* merge per-server config structures */
1752 waklog_cmds, /* table of config file commands */
1753 NULL, /* [#8] MIME-typed-dispatched handlers */
1754 waklog_phase1, /* [#1] URI to filename translation */
1755 NULL, /* [#4] validate user id from request */
1756 NULL, /* [#5] check if the user is ok _here_ */
1757 waklog_phase3, /* [#3] check access by host address */
1758 waklog_phase6, /* [#6] determine MIME type */
1759 waklog_phase7, /* [#7] pre-run fixups */
1760 waklog_phase9, /* [#9] log a transaction */
c760f0a1 1761 waklog_phase2, /* [#2] header parser */
866ccfbd 1762 waklog_child_init, /* child_init */
1763 waklog_child_exit, /* child_exit */
1764 waklog_phase0 /* [#0] post read-request */
bed98ff9 1765#ifdef EAPI
866ccfbd 1766 , NULL, /* EAPI: add_module */
1767 NULL, /* EAPI: remove_module */
1768 NULL, /* EAPI: rewrite_command */
1769 waklog_new_connection /* EAPI: new_connection */
bed98ff9 1770#endif
1771};
87822447 1772#else
1773static void
ff47641b 1774waklog_register_hooks (apr_pool_t * p)
87822447 1775{
3f4fda20 1776 ap_hook_translate_name (waklog_phase1, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1777 ap_hook_header_parser (waklog_phase2, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1778 ap_hook_access_checker (waklog_phase3, NULL, NULL, APR_HOOK_FIRST);
1779 ap_hook_type_checker (waklog_phase6, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1780 ap_hook_fixups (waklog_phase7, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1781 ap_hook_log_transaction (waklog_phase9, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1782 ap_hook_child_init (waklog_child_init, NULL, NULL, APR_HOOK_FIRST);
1783 ap_hook_post_read_request (waklog_phase0, NULL, NULL, APR_HOOK_FIRST);
1784 ap_hook_pre_connection (waklog_new_connection, NULL, NULL, APR_HOOK_FIRST);
1785 ap_hook_post_config (waklog_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
87822447 1786}
1787
1788
3f4fda20 1789module AP_MODULE_DECLARE_DATA waklog_module = {
1790 STANDARD20_MODULE_STUFF,
42d78dfb 1791 waklog_create_dir_config, /* create per-dir conf structures */
1792 waklog_merge_dir_config, /* merge per-dir conf structures */
1793 waklog_create_server_config, /* create per-server conf structures */
1794 waklog_merge_dir_config, /* merge per-server conf structures */
1795 waklog_cmds, /* table of configuration directives */
1796 waklog_register_hooks /* register hooks */
87822447 1797};
1798#endif