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