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