rxkad-kdf support
[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;
bd03fc62
CE
536
537 /* Since we're fetching a key for AFS, we have to use single DES
538 and explicitely enable weak crypto using the secret API
539 call */
c8563f50 540 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
bd03fc62 541 krb5_allow_weak_crypto (child.kcontext, 1);
c8563f50 542
c760f0a1 543 if ( ( kerror = krb5_get_credentials (child.kcontext, 0, clientccache, &increds, &v5credsp ) ) ) {
c8563f50 544 /* only complain once we've tried both afs@REALM and afs/cell@REALM */
545 if (attempt>=1) {
546 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
52e434d8 547 afs_error_message(kerror));
c8563f50 548 goto cleanup;
549 } else {
550 continue;
551 }
552 }
553 cfg->cell_in_principal = cell_in_principal;
554 break;
3f4fda20 555 }
c8563f50 556
3f4fda20 557 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: get_credentials passed for %s", k5user);
558
559 if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) {
560 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: ticket size (%d) too big to fake",
561 v5credsp->ticket.length);
562 goto cleanup;
563 }
313dde40 564
3f4fda20 565 memset(&token, 0, sizeof(struct ktc_token));
566
567 token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime;
568 token.endTime = v5credsp->times.endtime;
569
52e434d8
RA
570 if (tkt_DeriveDesKey(v5credsp->keyblock.enctype, v5credsp->keyblock.contents,
571 v5credsp->keyblock.length, &token.sessionKey) != 0) {
572 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: tkt_DeriveDesKey failure (enctype: %d)",
573 v5credsp->keyblock.enctype);
574 goto cleanup;
575 }
3f4fda20 576 token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
577 token.ticketLen = v5credsp->ticket.length;
578 memmove( token.ticket, v5credsp->ticket.data, token.ticketLen);
579
580 /* build the name */
581
582 memmove( buf, v5credsp->client->data[0].data, min(v5credsp->client->data[0].length,
583 MAXKTCNAMELEN -1 ));
584 buf[v5credsp->client->data[0].length] = '\0';
585 if ( v5credsp->client->length > 1 ) {
586 strncat(buf, ".", sizeof(buf) - strlen(buf) - 1);
587 buflen = strlen(buf);
588 memmove(buf + buflen, v5credsp->client->data[1].data,
589 min(v5credsp->client->data[1].length,
590 MAXKTCNAMELEN - strlen(buf) - 1));
591 buf[buflen + v5credsp->client->data[1].length] = '\0';
592 }
593
594 /* assemble the client */
595 strncpy(client.name, buf, sizeof(client.name) - 1 );
596 strncpy(client.instance, "", sizeof(client.instance) - 1 );
597 memmove(buf, v5credsp->client->realm.data, min(v5credsp->client->realm.length,
598 MAXKTCNAMELEN - 1));
599 buf[v5credsp->client->realm.length] = '\0';
600 strncpy(client.cell, buf, sizeof(client.cell));
601
602 /* assemble the server's cell */
891fb458 603 strncpy(server.cell, cfg->afs_cell, sizeof(server.cell) - 1);
3f4fda20 604
605 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: preparing to init PTS connection for %s", server.cell);
606
607 /* fill out the AFS ID in the client name */
608 /* we've done a pr_Initialize in the child_init -- once, per process. If you try to do it more
609 * strange things seem to happen. */
610
611 {
612 afs_int32 viceId = 0;
613
614 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: making PTS call to look up %s", client.name);
615
616 if ( ( rc = pr_SNameToId( client.name, &viceId ) ) == 0 ) {
617 snprintf( client.name, sizeof(client.name), "AFS ID %d", viceId );
618 } else {
619 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: PTS call returned error %d ", rc);
620 }
621
622 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: PTS call returned %s ", client.name);
623
624 }
625
626 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: server: name %s, instance %s, cell %s",
627 server.name, server.instance, server.cell );
628
629 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: client: name %s, instance %s, cell %s",
630 client.name, client.instance, client.cell );
631
632 /* copy the resulting stuff into the child structure */
633
634 strncpy(child.clientprincipal, k5user, sizeof(child.clientprincipal));
635 memcpy(&child.token, &token, sizeof(child.token));
636 memcpy(&child.server, &server, sizeof(child.server));
637 memcpy(&child.client, &client, sizeof(child.client));
638
639 /* stuff the resulting token-related stuff into our shared token cache */
640 /* note, that anything that was set from a keytab is "persistant", and is immune
641 * from LRU-aging. This is because nothing but the process that's running as root
642 * can update these, and it's running every hour or so and renewing these tokens.
643 * and we don't want them aged out.
644 */
645
646 mytime = oldest_time = time(0);
647
648 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waiting for shared space for %s ", k5user);
4e1ae1cd 649
3f4fda20 650#ifdef use_pthreads
651 pthread_rwlock_wrlock(sharedlock);
652#else
653 rw_wrlock(sharedlock);
654#endif
4e1ae1cd 655
3f4fda20 656 for( i = ( SHARED_TABLE_SIZE - 1 ); i >= 0; i-- ) {
657 if ( ( sharedspace->sharedtokens[i].lastused <= oldest_time) &&
658 ( sharedspace->sharedtokens[i].persist == 0 ) ) {
659 oldest = i;
660 oldest_time = sharedspace->sharedtokens[i].lastused;
661 }
662 if ( ! strcmp ( sharedspace->sharedtokens[i].clientprincipal,
663 child.clientprincipal ) ) {
664 memcpy(&sharedspace->sharedtokens[i].token, &child.token, sizeof(child.token) );
665 memcpy(&sharedspace->sharedtokens[i].client, &child.client, sizeof(child.client) );
666 memcpy(&sharedspace->sharedtokens[i].server, &child.server, sizeof(child.server) );
667 sharedspace->sharedtokens[i].lastused = mytime;
668 sharedspace->sharedtokens[i].persist = keytab ? 1 : 0;
669 stored = i;
670 break;
671 }
672 }
673
674 if ( stored == -1 ) {
675 memcpy(&sharedspace->sharedtokens[oldest].token, &child.token, sizeof(child.token) );
676 memcpy(&sharedspace->sharedtokens[oldest].client, &child.client, sizeof(child.client) );
677 memcpy(&sharedspace->sharedtokens[oldest].server, &child.server, sizeof(child.server) );
678 strcpy(sharedspace->sharedtokens[oldest].clientprincipal, child.clientprincipal );
679 sharedspace->sharedtokens[oldest].lastused = mytime;
680 sharedspace->sharedtokens[oldest].persist = keytab ? 1 : 0;
681 stored = oldest;
682 }
3ed1e28a 683
3f4fda20 684#ifdef use_pthreads
685 pthread_rwlock_unlock(sharedlock);
686#else
687 rw_unlock(sharedlock);
688#endif
689
690 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: token stored in slot %d for %s", stored,
691 child.clientprincipal );
692
693 } else if ( ! usecached ) {
694 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth divergent case");
695 }
696
697 if ( storeonly ) {
698 goto cleanup;
699 }
700
701 usecachedtoken:
702
703 /* don't ask. Something about AIX. We're leaving it here.*/
704 /* write(2, "", 0); */
705
706 /* we try twice, because sometimes the first one fails. Dunno why, but it always works the second time */
707
708 if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
709 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: settoken returned %s for %s -- trying again",
52e434d8 710 afs_error_message(rc), k5user);
3f4fda20 711 if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
712 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: settoken2 returned %s for %s",
52e434d8 713 afs_error_message(rc), k5user);
3f4fda20 714 goto cleanup;
715 }
716 }
717
718 cleanup:
c760f0a1 719 if (use_client_credentials)
720 krb5_cc_close(child.kcontext, clientccache);
3f4fda20 721 if ( v5credsp )
722 krb5_free_cred_contents(child.kcontext, v5credsp);
723 if ( increds.client )
724 krb5_free_principal (child.kcontext, increds.client);
725 if ( increds.server )
726 krb5_free_principal (child.kcontext, increds.server);
727 if ( krb5kt )
728 (void) krb5_kt_close(child.kcontext, krb5kt);
729 if ( kprinc )
730 krb5_free_principal (child.kcontext, kprinc);
731
732 if ( rc ) {
733 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with %d", rc );
734 } else if ( kerror ) {
52e434d8 735 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror, afs_error_message(kerror));
3f4fda20 736 } else {
737 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth ending ok");
738 }
739
740 return kerror ? (int) kerror : (int) rc;
741
4e1ae1cd 742}
743
744
4480093f 745int get_cfg_usertokens(waklog_config *cfg)
746{
747 if (cfg->usertokens==WAKLOG_UNSET)
748 return 0; /* default */
749 return cfg->usertokens;
750}
751
752int get_cfg_protect(waklog_config *cfg)
753{
754 if (cfg->protect==WAKLOG_UNSET)
755 return 0; /* default */
756 return cfg->protect;
757}
758
759int get_cfg_disable_token_cache(waklog_config *cfg)
760{
761 if (cfg->disable_token_cache==WAKLOG_UNSET)
762 return 0; /* default */
763 return cfg->disable_token_cache;
764}
765
7193eb01 766
3f4fda20 767static void *
768waklog_create_server_config (MK_POOL * p, server_rec * s)
769{
770 waklog_config *cfg;
771
772 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
773 cfg->p = p;
774 memset(cfg, 0, sizeof(waklog_config));
775 cfg->path = "(server)";
776 cfg->protect = WAKLOG_UNSET;
777 cfg->usertokens = WAKLOG_UNSET;
21a7788b 778 cfg->disable_token_cache = WAKLOG_UNSET;
5d0827ae 779 cfg->keytab = NULL;
780 cfg->principal = NULL;
781 cfg->default_principal = NULL;
782 cfg->default_keytab = NULL;
783 cfg->afs_cell = NULL;
784 cfg->afs_cell_realm = NULL;
3f4fda20 785 cfg->forked = 0;
786 cfg->configured = 0;
787
788 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 789 "mod_waklog: server config created.");
3f4fda20 790
791 return (cfg);
792}
7193eb01 793
3f4fda20 794/* initialize with host-config information */
58bbdc54 795
3f4fda20 796static void *
797waklog_create_dir_config (MK_POOL * p, char *dir)
798{
799 waklog_config *cfg;
800
801 cfg = (waklog_config *) ap_pcalloc (p, sizeof (waklog_config));
802 memset(cfg, 0, sizeof(waklog_config));
803 cfg->p = p;
804 cfg->path = ap_pstrdup(p, dir );
805 cfg->protect = WAKLOG_UNSET;
806 cfg->usertokens = WAKLOG_UNSET;
21a7788b 807 cfg->disable_token_cache = WAKLOG_UNSET;
5d0827ae 808 cfg->keytab = NULL;
809 cfg->principal = NULL;
810 cfg->default_principal = NULL;
811 cfg->default_keytab = NULL;
812 cfg->afs_cell = NULL;
813 cfg->afs_cell_realm = NULL;
3f4fda20 814 cfg->forked = 0;
815 cfg->configured = 0;
816
817 return (cfg);
58bbdc54 818}
819
3f4fda20 820static void *waklog_merge_dir_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 821
3f4fda20 822 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
823 waklog_config *parent = ( waklog_config * ) parent_conf;
824 waklog_config *child = ( waklog_config * ) newloc_conf;
825
826 merged->protect = child->protect != WAKLOG_UNSET ? child->protect : parent->protect;
827
5d0827ae 828 merged->path = child->path != NULL ? child->path : parent->path;
3f4fda20 829
830 merged->usertokens = child->usertokens != WAKLOG_UNSET ? child->usertokens : parent->usertokens;
21a7788b 831
832 merged->disable_token_cache = child->disable_token_cache != WAKLOG_UNSET ? child->disable_token_cache : parent->disable_token_cache;
3f4fda20 833
5d0827ae 834 merged->principal = child->principal != NULL ? child->principal : parent->principal;
3f4fda20 835
5d0827ae 836 merged->keytab = child->keytab != NULL ? child->keytab : parent->keytab;
3f4fda20 837
5d0827ae 838 merged->default_keytab = child->default_keytab != NULL ? child->default_keytab : parent->default_keytab;
3f4fda20 839
5d0827ae 840 merged->default_principal = child->default_principal != NULL ? child->default_principal : parent->default_principal;
3f4fda20 841
5d0827ae 842 merged->afs_cell = child->afs_cell != NULL ? child->afs_cell : parent->afs_cell;
98534230 843
5d0827ae 844 merged->afs_cell_realm = child->afs_cell_realm != NULL ? child->afs_cell_realm : parent->afs_cell_realm;
3f4fda20 845
846 return (void *) merged;
847
848}
58bbdc54 849
3f4fda20 850static void *waklog_merge_server_config(MK_POOL *p, void *parent_conf, void *newloc_conf) {
58bbdc54 851
3f4fda20 852 waklog_config *merged = ( waklog_config * ) ap_pcalloc(p, sizeof(waklog_config ) );
853 waklog_config *pconf = ( waklog_config * ) parent_conf;
854 waklog_config *nconf = ( waklog_config * ) newloc_conf;
855
856 merged->protect = nconf->protect == WAKLOG_UNSET ? pconf->protect : nconf->protect;
58bbdc54 857
3f4fda20 858 merged->usertokens = nconf->usertokens == WAKLOG_UNSET ? pconf->usertokens : nconf->usertokens;
58bbdc54 859
bce7d4d9 860 merged->disable_token_cache = nconf->disable_token_cache == WAKLOG_UNSET ? pconf->disable_token_cache : nconf->disable_token_cache;
21a7788b 861
5d0827ae 862 merged->keytab = nconf->keytab == NULL ? ap_pstrdup(p, pconf->keytab) :
863 ( nconf->keytab == NULL ? NULL : ap_pstrdup(p, nconf->keytab) );
3f4fda20 864
5d0827ae 865 merged->principal = nconf->principal == NULL ? ap_pstrdup(p, pconf->principal) :
866 ( nconf->principal == NULL ? NULL : ap_pstrdup(p, nconf->principal) );
3f4fda20 867
5d0827ae 868 merged->afs_cell = nconf->afs_cell == NULL ? ap_pstrdup(p, pconf->afs_cell) :
869 ( nconf->afs_cell == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell) );
3f4fda20 870
5d0827ae 871 merged->afs_cell_realm = nconf->afs_cell_realm == NULL ? ap_pstrdup(p, pconf->afs_cell_realm) :
872 ( nconf->afs_cell_realm == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell_realm) );
98534230 873
5d0827ae 874 merged->default_keytab = nconf->default_keytab == NULL ? ap_pstrdup(p, pconf->default_keytab) :
875 ( nconf->default_keytab == NULL ? NULL : ap_pstrdup(p, nconf->default_keytab) );
58bbdc54 876
5d0827ae 877 merged->default_principal = nconf->default_principal == NULL ? ap_pstrdup(p, pconf->default_principal) :
878 ( nconf->default_principal == NULL ? NULL : ap_pstrdup(p, nconf->default_principal) );
3f4fda20 879
880
881 return (void *) merged;
882
883}
884
885static const char *
21a7788b 886set_waklog_enabled (cmd_parms * params, void *mconfig, int flag)
58bbdc54 887{
3f4fda20 888 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
889 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
890
891 cfg->protect = flag;
892 cfg->configured = 1;
893 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
21a7788b 894 "mod_waklog: waklog_enabled set on %s", cfg->path ? cfg->path : "NULL");
3f4fda20 895 return (NULL);
896}
58bbdc54 897
7193eb01 898
3f4fda20 899/* this adds a principal/keytab pair to get their tokens renewed by the
900 child process every few centons. */
7193eb01 901
3f4fda20 902void add_to_renewtable(MK_POOL *p, char *keytab, char *principal) {
87822447 903
3f4fda20 904 int i;
905
906 if ( renewcount >= SHARED_TABLE_SIZE ) {
907 log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "mod_waklog: big problem. Increase the SHARED_TABLE_SIZE or \
908 decrease your tokens.");
b74fad73 909 return;
3f4fda20 910 }
911
912 /* check to see if it's already there */
913
914 for ( i = 0; i < renewcount; i++ ) {
915 if ( ! strcmp(renewtable[i].principal, principal ) ) {
916 return;
917 }
918 }
919
920 renewtable[renewcount].keytab = ap_pstrdup(p, keytab);
921 renewtable[renewcount].principal = ap_pstrdup(p, principal);
922 renewtable[renewcount].lastrenewed = 0;
923 ++renewcount;
924
b74fad73 925}
926
3f4fda20 927static const char *
21a7788b 928set_waklog_location_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
3f4fda20 929{
930 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
931 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
932
933 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 934 "mod_waklog: configuring principal: %s, keytab: %s", principal, keytab);
935
936 cfg->principal = ap_pstrdup(params->pool, principal);
3f4fda20 937 cfg->keytab = ap_pstrdup (params->pool, keytab);
938
939 add_to_renewtable(params->pool, keytab, principal);
940
941 cfg->configured = 1;
942
943 return (NULL);
944}
b74fad73 945
3f4fda20 946static const char *
21a7788b 947set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
313dde40 948{
891fb458 949 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
950 waklog_config *waklog_srvconfig =
3f4fda20 951 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
952
891fb458 953 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
42d78dfb 954 "mod_waklog: will use afs_cell: %s", file);
313dde40 955
678051d7 956 // Prefer afs/cell@REALM over afs@REALM, just like the OpenAFS tools
957 waklog_srvconfig->cell_in_principal = 1;
958
891fb458 959 waklog_srvconfig->afs_cell = ap_pstrdup (params->pool, file);
960 waklog_srvconfig->configured = 1;
961
962 if (waklog_mconfig != NULL) {
c8563f50 963 waklog_mconfig->cell_in_principal = waklog_srvconfig->cell_in_principal;
891fb458 964 waklog_mconfig->afs_cell = ap_pstrdup (params->pool, file);
965 waklog_mconfig->configured = 1;
966 }
3f4fda20 967 return (NULL);
968}
58bbdc54 969
98534230 970static const char *
971set_waklog_afs_cell_realm (cmd_parms * params, void *mconfig, char *file)
972{
973 waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
974 waklog_config *waklog_srvconfig =
975 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
976
977 log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
978 "mod_waklog: will use afs_cell_realm: %s", file);
979
980 waklog_srvconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
981
982 if (waklog_mconfig != NULL) {
983 waklog_mconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
984 }
985 return (NULL);
986}
987
3f4fda20 988static const char *
989set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal, char *keytab)
990{
991 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
992 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
58bbdc54 993
3f4fda20 994 waklog_config *srvcfg = ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
4e1ae1cd 995
3f4fda20 996 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 997 "mod_waklog: set default princ/keytab: %s, %s for %s", principal, keytab, cfg->path ? cfg->path : "NULL");
313dde40 998
3f4fda20 999 cfg->default_principal = ap_pstrdup (params->pool, principal);
1000 cfg->default_keytab = ap_pstrdup(params->pool, keytab );
1001
1002 /* this also gets set at the server level */
1003 if ( mconfig && ( ! cfg->path ) ) {
1004 srvcfg->default_principal = ap_pstrdup (params->pool, principal);
1005 srvcfg->default_keytab = ap_pstrdup(params->pool, keytab );
1006 } else {
1007 log_error(APLOG_MARK, APLOG_ERR, 0, params->server, "only able to set default principal on a global level!");
1008 return "Unable to set DefaultPrincipal outside of top level config!";
1009 }
1010
1011 add_to_renewtable( params->pool, keytab, principal );
1012
1013 cfg->configured = 1;
1014
1015 return (NULL);
1016}
313dde40 1017
3f4fda20 1018static const char *
1019set_waklog_use_usertokens (cmd_parms * params, void *mconfig, int flag)
bed98ff9 1020{
3f4fda20 1021 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
1022 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
bed98ff9 1023
3f4fda20 1024 cfg->usertokens = flag;
bed98ff9 1025
3f4fda20 1026 cfg->configured = 1;
bed98ff9 1027
3f4fda20 1028 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
42d78dfb 1029 "mod_waklog: waklog_use_user_tokens set");
3f4fda20 1030 return (NULL);
bed98ff9 1031}
1032
1033
21a7788b 1034static const char *
1035set_waklog_disable_token_cache (cmd_parms * params, void *mconfig, int flag)
1036{
1037 waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
1038 ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
1039
1040 cfg->disable_token_cache = flag;
1041
1042 cfg->configured = 1;
1043
1044 log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
1045 "mod_waklog: waklog_disable_token_cache set");
1046 return (NULL);
1047}
1048
1049
c9d59a9c 1050#ifndef APACHE2
3f4fda20 1051static void waklog_child_exit( server_rec *s, MK_POOL *p ) {
1052#else
1053apr_status_t waklog_child_exit( void *sr ) {
4e1ae1cd 1054
3f4fda20 1055 server_rec *s = (server_rec *) sr;
1056#endif
1057
1058 if ( child.ccache ) {
1059 krb5_cc_close(child.kcontext, child.ccache);
1060 }
1061
1062 if ( child.kcontext ) {
1063 krb5_free_context(child.kcontext);
1064 }
1065
1066 /* forget our tokens */
1067
1068 ktc_ForgetAllTokens ();
1069
1070 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1071 "mod_waklog: waklog_child_exit complete");
4e1ae1cd 1072
c9d59a9c 1073#ifdef APACHE2
3f4fda20 1074 return APR_SUCCESS;
1075#endif
1076
1077}
4e1ae1cd 1078
3f4fda20 1079static void
c9d59a9c 1080#ifdef APACHE2
3f4fda20 1081waklog_child_init (MK_POOL * p, server_rec * s)
1082#else
1083waklog_child_init (server_rec * s, MK_POOL * p)
1084#endif
1085{
b52ccbb1 1086
3f4fda20 1087 krb5_error_code code;
1088 waklog_config *cfg;
1089
1090 char *cell;
1091
3f4fda20 1092 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
1093
1094 if ( !sharedspace ) {
1095 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: child_init called without shared space? %d", getpid());
1096 return;
1097 }
1098
1099 log_error (APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init called for pid %d", getpid());
7193eb01 1100
3f4fda20 1101 memset (&child, 0, sizeof(child));
1102
c760f0a1 1103 if ( ( code = krb5_init_context(&child.kcontext) ) ) {
3f4fda20 1104 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1105 }
1106
c760f0a1 1107 if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
3f4fda20 1108 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1109 }
1110
1111 if ( pag_for_children ) {
8e9df4d2 1112 k_setpag ();
3f4fda20 1113 }
7193eb01 1114
3f4fda20 1115 getModConfig (cfg, s);
7193eb01 1116
5d0827ae 1117 if ( cfg->default_principal != NULL ) {
3f4fda20 1118 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init setting default user %s, %s", cfg->default_principal, cfg->default_keytab);
1119 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1120 }
7193eb01 1121
891fb458 1122 cell = strdup(cfg->afs_cell);
3f4fda20 1123 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
7193eb01 1124
c9d59a9c 1125#ifdef APACHE2
3f4fda20 1126 apr_pool_cleanup_register(p, s, waklog_child_exit, apr_pool_cleanup_null);
1127#endif
7193eb01 1128
3f4fda20 1129 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1130 "mod_waklog: child_init returned");
7193eb01 1131
3f4fda20 1132 return;
1133}
b52ccbb1 1134
3f4fda20 1135command_rec waklog_cmds[] = {
1136
21a7788b 1137 command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
1138 "Use the supplied AFS cell (required)"),
7193eb01 1139
98534230 1140 command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm, 0, TAKE1,
1141 "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
1142
21a7788b 1143 command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
1144 "enable waklog on a server, location, or directory basis"),
7193eb01 1145
21a7788b 1146 command ("WaklogDefaultPrincipal", set_waklog_default_principal, 0, TAKE2,
1147 "Set the default principal that the server runs as"),
7193eb01 1148
21a7788b 1149 command ("WaklogLocationPrincipal", set_waklog_location_principal, 0, TAKE2,
1150 "Set the principal on a <Location>-specific basis"),
7193eb01 1151
21a7788b 1152 command ("WaklogDisableTokenCache", set_waklog_disable_token_cache, 0, FLAG,
1153 "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
1154
1155 command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
1156 "Use the requesting user tokens (from webauth)"),
1157
3f4fda20 1158 {NULL}
1159};
7193eb01 1160
7193eb01 1161
3f4fda20 1162/* not currently using this */
7193eb01 1163
3f4fda20 1164static int
1165token_cleanup (void *data)
1166{
1167 request_rec *r = (request_rec *) data;
e2df6441 1168
3f4fda20 1169 if (child.token.ticketLen)
1170 {
1171 memset (&child.token, 0, sizeof (struct ktc_token));
e21f34f0 1172
3f4fda20 1173 ktc_ForgetAllTokens ();
7193eb01 1174
3f4fda20 1175 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1176 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1177 getpid ());
3f4fda20 1178 }
1179 return 0;
7193eb01 1180}
1181
22782cea
JW
1182/* This function doesn't return anything but is passed to ap_bspawn_child on
1183 * Apache 1 which expects it to return a pid as an int. For want of better
1184 * understanding, err on the side of not changing Apache 1 code while fixing
1185 * the compile warning on Apache 2. */
1186#ifdef APACHE2
1187static void
1188#else
3f4fda20 1189static int
22782cea 1190#endif
3f4fda20 1191waklog_child_routine (void *data, child_info * pinfo)
7193eb01 1192{
3f4fda20 1193 int i;
1194 server_rec *s = (server_rec *) data;
1195 krb5_error_code code;
1196 char *cell;
1197 time_t sleep_time = ( TKT_LIFE / 2 ) ;
1198 time_t when;
1199 time_t left;
1200 waklog_config *cfg;
1201
1202 getModConfig( cfg, s );
1203
1204 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: waklog_child_routine started, running as %d", getuid());
1205
1206 memset (&child, 0, sizeof(child));
1207
c760f0a1 1208 if ( ( code = krb5_init_context(&child.kcontext) ) ) {
3f4fda20 1209 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
1210 }
1211
c760f0a1 1212 if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
3f4fda20 1213 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
1214 }
1215
c760f0a1 1216 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: about to pr_Initialize");
1217
3f4fda20 1218 /* need to do this so we can make PTS calls */
891fb458 1219 cell = strdup(cfg->afs_cell); /* stupid */
3f4fda20 1220 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
c760f0a1 1221
1222 log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: still here");
1223
3f4fda20 1224 while(1) {
1225
1226 for ( i = 0; i < renewcount; ++i ) {
1227 renewtable[i].lastrenewed = time(0);
1228 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: (pid %d) renewing %s / %s", getpid(), renewtable[i].principal,
1229 renewtable[i].keytab);
1230
1231 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 1 );
1232
1233 /* if this is our default token, we want to "stash" it in our current PAG so the parent maintains readability of
1234 things that it needs to read */
1235
1236 if ( cfg && cfg->default_principal && ( ! strcmp(cfg->default_principal, renewtable[i].principal ) ) ) {
1237 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: renewing/setting default tokens" );
1238 set_auth( s, NULL, 0, renewtable[i].principal, renewtable[i].keytab, 0 );
1239 }
1240
4e1ae1cd 1241 }
1242
3f4fda20 1243 sharedspace->renewcount++;
1244
1245 left = sleep_time;
1246
1247 while( left > 5 ) {
1248 when = time(0);
1249
1250 sleep(left);
1251
1252 left -= ( time(0) - when );
4e1ae1cd 1253 }
3f4fda20 1254
1255 }
4e1ae1cd 1256
3f4fda20 1257 pr_End();
403921ef 1258
3f4fda20 1259}
4e1ae1cd 1260
c9d59a9c 1261#ifdef APACHE2
3f4fda20 1262static int
1263waklog_init_handler (apr_pool_t * p, apr_pool_t * plog,
42d78dfb 1264 apr_pool_t * ptemp, server_rec * s)
3f4fda20 1265{
1266 int rv;
1267 extern char *version;
1268 apr_proc_t *proc;
1269 waklog_config *cfg;
1270 void *data;
1271 int fd = -1;
1272 int use_existing = 1;
1273 int oldrenewcount;
1274 char cache_file[MAXNAMELEN];
1275#ifdef use_pthreads
1276 pthread_rwlockattr_t rwlock_attr;
1277#endif
4e1ae1cd 1278
1279
3f4fda20 1280 getModConfig (cfg, s);
4e1ae1cd 1281
3f4fda20 1282 /* initialize_module() will be called twice, and if it's a DSO
1283 * then all static data from the first call will be lost. Only
1284 * set up our static data on the second call.
1285 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
1286 apr_pool_userdata_get (&data, userdata_key, s->process->pool);
7193eb01 1287
891fb458 1288
1289 if (cfg->afs_cell==NULL) {
1290 log_error (APLOG_MARK, APLOG_ERR, 0, s,
21a7788b 1291 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
891fb458 1292 /** clobber apache */
1293 exit(-1);
1294 }
1295
3f4fda20 1296 if (!data)
1297 {
1298 apr_pool_userdata_set ((const void *) 1, userdata_key,
42d78dfb 1299 apr_pool_cleanup_null, s->process->pool);
4e1ae1cd 1300 }
3f4fda20 1301 else
1302 {
1303 log_error (APLOG_MARK, APLOG_INFO, 0, s,
891fb458 1304 "mod_waklog: version %s initialized for cell %s", version, cfg->afs_cell);
3f4fda20 1305
1306 if ( sharedspace ) {
1307 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1308 } else {
1309
1310 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1311
1312 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1313
1314 if ( errno == ENOENT ) {
1315
1316 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1317 use_existing = 0;
1318 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1319 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1320 exit(errno);
1321 }
1322 } else {
1323 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1324 }
1325 }
1326
1327 if ( use_existing == 0 ) {
1328 struct sharedspace_s bob;
1329 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1330 memset( &bob, 0, sizeof(struct sharedspace_s));
24bb0dbf
JW
1331 if ( write(fd, &bob, sizeof(struct sharedspace_s)) != sizeof(struct sharedspace_s) ) {
1332 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: failed to write to our cache file %s (%d)", cache_file, errno );
1333 exit(errno);
1334 }
3f4fda20 1335 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1336 }
1337
1338 /* mmap the region */
1339
1340 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != MAP_FAILED ) {
4cd4a5af 1341 int err = 0;
3f4fda20 1342 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
4cd4a5af 1343 err = unlink(cache_file);
1344 if (err) {
1345 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: unable to delete %s due to %d", cache_file, errno);
1346 } else {
95ad25b8 1347 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared cache unlinked (will be deleted when Apache quits)");
4cd4a5af 1348 }
3f4fda20 1349 } else {
1350 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1351 exit(errno);
1352 }
1353 }
4e1ae1cd 1354
3f4fda20 1355#ifdef use_pthreads
1356#define locktype pthread_rwlock_t
1357#else
1358#define locktype rwlock_t
1359#endif
4e1ae1cd 1360
4521ace1 1361 if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) != NULL ) {
3f4fda20 1362#ifndef use_pthreads
1363 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1364#else
1365 pthread_rwlockattr_init(&rwlock_attr);
1366 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1367 pthread_rwlock_init(sharedlock, &rwlock_attr );
1368#endif
1369 } else {
1370 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1371 }
58bbdc54 1372
3f4fda20 1373#undef locktype
7193eb01 1374
3f4fda20 1375 /* set our default tokens */
403921ef 1376
3f4fda20 1377 oldrenewcount = sharedspace->renewcount;
7193eb01 1378
3f4fda20 1379 pag_for_children = 0;
7193eb01 1380
3f4fda20 1381 proc = (apr_proc_t *) ap_pcalloc (s->process->pool, sizeof (apr_proc_t));
7193eb01 1382
3f4fda20 1383 rv = apr_proc_fork (proc, s->process->pool);
7193eb01 1384
3f4fda20 1385 if (rv == APR_INCHILD)
42d78dfb 1386 {
1387 waklog_child_routine (s, NULL);
1388 }
3f4fda20 1389 else
42d78dfb 1390 {
1391 apr_pool_note_subprocess (s->process->pool, proc, APR_KILL_ALWAYS);
1392 }
3f4fda20 1393 /* parent and child */
1394 cfg->forked = proc->pid;
1395 pag_for_children = 1;
1396
1397 if ( use_existing == 0 ) {
1398 /* wait here until our child process has gone and done it's renewing thing. */
1399 while( sharedspace->renewcount == oldrenewcount ) {
1400 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1401 sleep(2);
1402 }
1403 }
1404
1405 if ( cfg->default_principal ) {
1406 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1407 }
1408 }
1409 return 0;
1410}
ebb1f61c 1411#else
3f4fda20 1412static void
1413waklog_init (server_rec * s, MK_POOL * p)
1414{
1415 extern char *version;
1416 int pid;
1417 waklog_config *cfg;
3f4fda20 1418 int fd = -1;
1419 int use_existing = 1;
1420 int oldrenewcount;
1421 char cache_file[MAXNAMELEN];
1422#ifdef use_pthreads
1423 pthread_rwlockattr_t rwlock_attr;
ebb1f61c 1424#endif
7193eb01 1425
3f4fda20 1426 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1427 "mod_waklog: version %s initialized.", version);
7193eb01 1428
3f4fda20 1429 if ( sharedspace ) {
1430 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: shared memory already allocated." );
1431 } else {
1432
1433 snprintf( cache_file, MAXNAMELEN, "/tmp/waklog_cache.%d", getpid() );
1434
1435 if ( ( fd = open( cache_file, O_RDWR, 0600 ) ) == -1 ) {
1436
1437 if ( errno == ENOENT ) {
1438
1439 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: creating shared token cache file %s", cache_file );
1440 use_existing = 0;
1441 if ( ( fd = open( cache_file, O_RDWR|O_CREAT|O_TRUNC, 0600 ) ) == -1 ) {
1442 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file, errno );
1443 exit(errno);
1444 }
1445 } else {
1446 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file, errno );
1447 }
1448
1449 }
1450
1451 if ( use_existing == 0 ) {
1452 struct sharedspace_s bob;
1453 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
1454 memset( &bob, 0, sizeof(struct sharedspace_s));
1455 write(fd, &bob, sizeof(struct sharedspace_s));
1456 log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
1457 }
4e1ae1cd 1458
3f4fda20 1459 /* mmap the region */
1460
c760f0a1 1461 if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != (void *) -1 ) {
3f4fda20 1462 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
1463 close(fd);
1464 } else {
1465 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
1466 exit(errno);
1467 }
1468 }
e21f34f0 1469
3f4fda20 1470#ifdef use_pthreads
1471#define locktype pthread_rwlock_t
1472#else
1473#define locktype rwlock_t
ea3e8708 1474#endif
e21f34f0 1475
3f4fda20 1476 /* mmap our shared space for our lock */
c760f0a1 1477 if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) ) {
3f4fda20 1478#ifndef use_pthreads
1479 rwlock_init(sharedlock, USYNC_PROCESS, NULL );
1480#else
1481 pthread_rwlockattr_init(&rwlock_attr);
1482 pthread_rwlockattr_setpshared(&rwlock_attr, PTHREAD_PROCESS_SHARED);
1483 pthread_rwlock_init(sharedlock, &rwlock_attr );
1484#endif
1485 } else {
1486 log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: rwlock mmap failed %d", errno );
1487 }
e21f34f0 1488
3f4fda20 1489#undef locktype
e21f34f0 1490
3f4fda20 1491 /* set our default tokens */
1492
1493 getModConfig (cfg, s);
42d78dfb 1494
1495 oldrenewcount = sharedspace->renewcount;
1496
1497 pag_for_children = 0;
1498
1499 pid = ap_bspawn_child (p, waklog_child_routine, s, kill_always,
1500 NULL, NULL, NULL);
1501
1502 pag_for_children = 1;
1503
3f4fda20 1504 log_error (APLOG_MARK, APLOG_DEBUG, 0, s,
42d78dfb 1505 "mod_waklog: ap_bspawn_child: %d.", pid);
3f4fda20 1506
1507 if ( use_existing == 0 ) {
1508 /* wait here until our child process has gone and done it's renewing thing. */
1509 while( sharedspace->renewcount == oldrenewcount ) {
1510 log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: waiting for tokens..." );
1511 sleep(2);
87822447 1512 }
3f4fda20 1513 }
1514
1515 if ( cfg->default_principal ) {
1516 set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1517 }
1518
87822447 1519}
3f4fda20 1520#endif
1521
1522static int
1523waklog_phase0 (request_rec * r)
e21f34f0 1524{
3f4fda20 1525 waklog_config *cfg;
e21f34f0 1526
3f4fda20 1527 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1528 "mod_waklog: phase0 called");
3f4fda20 1529
1530 cfg = retrieve_config(r);
e21f34f0 1531
4480093f 1532 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1533 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using user %s", cfg->principal);
1534 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1535 } else if ( cfg->default_principal ) {
1536 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using default user %s", cfg->default_principal);
1537 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1538 } else {
c760f0a1 1539
1540 if (child.token.ticketLen) {
1541 memset( &child.token, 0, sizeof (struct ktc_token) );
1542 ktc_ForgetAllTokens();
1543 }
1544
3f4fda20 1545 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 not doing nothin.");
1546 }
e21f34f0 1547
3f4fda20 1548 return DECLINED;
e21f34f0 1549}
4e1ae1cd 1550
3f4fda20 1551static int
1552waklog_phase1 (request_rec * r)
bed98ff9 1553{
3f4fda20 1554 waklog_config *cfg;
313dde40 1555
3f4fda20 1556 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1557 "mod_waklog: phase1 called");
7193eb01 1558
3f4fda20 1559 cfg = retrieve_config(r);
313dde40 1560
4480093f 1561 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1562 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using user %s", cfg->principal);
1563 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1564 } else if ( cfg->default_principal ) {
1565 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using default user %s", cfg->default_principal);
1566 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1567 } else {
1568 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 not doing nothin.");
1569 }
4e1ae1cd 1570
3f4fda20 1571 return DECLINED;
7193eb01 1572}
4e1ae1cd 1573
3f4fda20 1574static int
1575waklog_phase3 (request_rec * r)
7193eb01 1576{
3f4fda20 1577 waklog_config *cfg;
1e18ef7d 1578
3f4fda20 1579 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1580 "mod_waklog: phase 3 called");
1e18ef7d 1581
3f4fda20 1582 cfg = retrieve_config(r);
1583
4480093f 1584 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1585 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using user %s", cfg->principal);
1586 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1587 } else if ( cfg->default_principal ) {
1588 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using default user %s", cfg->default_principal);
1589 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1590 } else {
1591 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 not doing nothin.");
1592 }
1593
1594 return DECLINED;
1595}
bed98ff9 1596
3f4fda20 1597static int
1598waklog_phase6 (request_rec * r)
1599{
1600 waklog_config *cfg;
1601
1602 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1603 "mod_waklog: phase6 called");
3f4fda20 1604
1605 cfg = retrieve_config(r);
1606
4480093f 1607 if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1608 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using user %s", cfg->principal);
1609 set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
1610 } else if ( cfg->default_principal ) {
1611 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using default user %s", cfg->default_principal);
1612 set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1613 } else {
1614 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 not doing nothin.");
1615 }
1616
1617 return DECLINED;
1618}
bed98ff9 1619
3f4fda20 1620static int
1621waklog_phase7 (request_rec * r)
1622{
1623 waklog_config *cfg;
1624 int rc = 0;
1625
1626 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1627 "mod_waklog: phase7 called");
3f4fda20 1628
1629 cfg = retrieve_config (r);
1630
4480093f 1631 if ( get_cfg_protect(cfg) && get_cfg_usertokens(cfg) ) {
3f4fda20 1632 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using usertokens");
1633 rc = set_auth( r->server, r, 1, NULL, NULL, 0);
4480093f 1634 } else if ( get_cfg_protect(cfg) && cfg->principal ) {
3f4fda20 1635 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using user %s", cfg->principal);
1636 rc = set_auth( r->server, r, 0, cfg->principal, cfg->keytab, 0);
1637 } else if ( cfg->default_principal ) {
1638 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using default user %s", cfg->default_principal);
1639 rc = set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
d3bea354 1640 } else {
c760f0a1 1641 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: no tokens");
1642 if (child.token.ticketLen) {
1643 memset(&child.token, 0, sizeof(struct ktc_token));
1644 ktc_ForgetAllTokens();
1645 }
3f4fda20 1646 }
1647
1648 if ( rc ) {
1649 return 400;
1650 }
1651
1652 return DECLINED;
1653}
87822447 1654
3f4fda20 1655static int
1656waklog_phase9 (request_rec * r)
1657{
1658 waklog_config *cfg;
bed98ff9 1659
3f4fda20 1660 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1661 "mod_waklog: phase9 called");
bed98ff9 1662
3f4fda20 1663 getModConfig (cfg, r->server);
1664
1665 if ( cfg->default_principal ) {
1666 log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase9 using default user %s", cfg->default_principal);
1667 set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
1668 }
1669
1670 return DECLINED;
bed98ff9 1671}
1672
ff47641b 1673
87822447 1674static
c9d59a9c 1675#ifdef APACHE2
ff47641b 1676 int
87822447 1677#else
ff47641b 1678 void
87822447 1679#endif
ff47641b 1680waklog_new_connection (conn_rec * c
c9d59a9c 1681#ifdef APACHE2
42d78dfb 1682 , void *dummy
87822447 1683#endif
ff47641b 1684 )
1685{
1686
3f4fda20 1687 waklog_config *cfg;
ff47641b 1688
1689 log_error (APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
42d78dfb 1690 "mod_waklog: new_connection called: pid: %d", getpid ());
1691
1692 getModConfig(cfg, c->base_server);
1693
1694 if ( cfg->default_principal ) {
1695 log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server, "mod_waklog: new conn setting default user %s",
1696 cfg->default_principal);
1697 set_auth( c->base_server, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
1698 }
1699
1700
3f4fda20 1701 return
c9d59a9c 1702#ifdef APACHE2
3f4fda20 1703 0
87822447 1704#endif
3f4fda20 1705 ;
7193eb01 1706}
bed98ff9 1707
c4ad0387 1708
1196adfe 1709/*
1710** Here's a quick explaination for phase0 and phase2:
1711** Apache does a stat() on the path between phase0 and
1712** phase2, and must by ACLed rl to succeed. So, at
1713** phase0 we acquire credentials for umweb:servers from
1714** a keytab, and at phase2 we must ensure we remove them.
1715**
1716** Failure to "unlog" would be a security risk.
1717*/
ff47641b 1718static int
1719waklog_phase2 (request_rec * r)
c4ad0387 1720{
161ffd84 1721
ff47641b 1722 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1723 "mod_waklog: phase2 called");
1196adfe 1724
ff47641b 1725 if (child.token.ticketLen)
1726 {
1727 memset (&child.token, 0, sizeof (struct ktc_token));
c4ad0387 1728
ff47641b 1729 ktc_ForgetAllTokens ();
c4ad0387 1730
ff47641b 1731 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1732 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1733 getpid ());
c4ad0387 1734 }
1196adfe 1735
ff47641b 1736 log_error (APLOG_MARK, APLOG_DEBUG, 0, r->server,
42d78dfb 1737 "mod_waklog: phase2 returning");
1196adfe 1738
3f4fda20 1739 return DECLINED;
c4ad0387 1740}
1741
c9d59a9c 1742#ifndef APACHE2
313dde40 1743module MODULE_VAR_EXPORT waklog_module = {
3f4fda20 1744 STANDARD_MODULE_STUFF,
866ccfbd 1745 waklog_init, /* module initializer */
42d78dfb 1746 waklog_create_dir_config, /* create per-dir config structures */
866ccfbd 1747 waklog_merge_dir_config, /* merge per-dir config structures */
1748 waklog_create_server_config, /* create per-server config structures */
1749 waklog_merge_dir_config, /* merge per-server config structures */
1750 waklog_cmds, /* table of config file commands */
1751 NULL, /* [#8] MIME-typed-dispatched handlers */
1752 waklog_phase1, /* [#1] URI to filename translation */
1753 NULL, /* [#4] validate user id from request */
1754 NULL, /* [#5] check if the user is ok _here_ */
1755 waklog_phase3, /* [#3] check access by host address */
1756 waklog_phase6, /* [#6] determine MIME type */
1757 waklog_phase7, /* [#7] pre-run fixups */
1758 waklog_phase9, /* [#9] log a transaction */
c760f0a1 1759 waklog_phase2, /* [#2] header parser */
866ccfbd 1760 waklog_child_init, /* child_init */
1761 waklog_child_exit, /* child_exit */
1762 waklog_phase0 /* [#0] post read-request */
bed98ff9 1763#ifdef EAPI
866ccfbd 1764 , NULL, /* EAPI: add_module */
1765 NULL, /* EAPI: remove_module */
1766 NULL, /* EAPI: rewrite_command */
1767 waklog_new_connection /* EAPI: new_connection */
bed98ff9 1768#endif
1769};
87822447 1770#else
1771static void
ff47641b 1772waklog_register_hooks (apr_pool_t * p)
87822447 1773{
3f4fda20 1774 ap_hook_translate_name (waklog_phase1, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1775 ap_hook_header_parser (waklog_phase2, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1776 ap_hook_access_checker (waklog_phase3, NULL, NULL, APR_HOOK_FIRST);
1777 ap_hook_type_checker (waklog_phase6, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1778 ap_hook_fixups (waklog_phase7, NULL, NULL, APR_HOOK_FIRST);
3f4fda20 1779 ap_hook_log_transaction (waklog_phase9, NULL, NULL, APR_HOOK_FIRST);
ff47641b 1780 ap_hook_child_init (waklog_child_init, NULL, NULL, APR_HOOK_FIRST);
1781 ap_hook_post_read_request (waklog_phase0, NULL, NULL, APR_HOOK_FIRST);
1782 ap_hook_pre_connection (waklog_new_connection, NULL, NULL, APR_HOOK_FIRST);
1783 ap_hook_post_config (waklog_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
87822447 1784}
1785
1786
3f4fda20 1787module AP_MODULE_DECLARE_DATA waklog_module = {
1788 STANDARD20_MODULE_STUFF,
42d78dfb 1789 waklog_create_dir_config, /* create per-dir conf structures */
1790 waklog_merge_dir_config, /* merge per-dir conf structures */
1791 waklog_create_server_config, /* create per-server conf structures */
1792 waklog_merge_dir_config, /* merge per-server conf structures */
1793 waklog_cmds, /* table of configuration directives */
1794 waklog_register_hooks /* register hooks */
87822447 1795};
1796#endif