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