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