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