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