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