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