1 #define _LARGEFILE64_SOURCE
5 #include "http_config.h"
7 #include "http_protocol.h"
8 #include "http_request.h"
16 #include <sys/types.h>
20 #error "make sure you include the right stuff here"
24 #define MAXNAMELEN 1024
27 #ifdef STANDARD20_MODULE_STUFF
31 /********************* APACHE1 ******************************************************************************/
33 #include "ap_config.h"
35 #include <sys/ioccom.h>
37 #include <http_conf_globals.h>
39 #define MK_TABLE_GET ap_table_get
40 #define MK_TABLE_SET ap_table_set
41 #define command(name, func, var, type, usage) \
44 RSRC_CONF | ACCESS_CONF , type, usage }
47 /********************* APACHE2 ******************************************************************************/
49 #include <apr_strings.h>
50 #include <apr_base64.h>
51 #define ap_pcalloc apr_pcalloc
52 #define ap_pdupstr apr_pdupstr
53 #define ap_pstrdup apr_pstrdup
54 #define MK_POOL apr_pool_t
55 #define MK_TABLE_GET apr_table_get
56 #define MK_TABLE_SET apr_table_set
58 extern unixd_config_rec unixd_config
;
59 #define ap_user_id unixd_config.user_id
60 #define ap_group_id unixd_config.group_id
61 #define ap_user_name unixd_config.user_name
62 #define command(name, func, var, type, usage) \
63 AP_INIT_ ## type (name, (void*) func, \
65 RSRC_CONF | ACCESS_CONF, usage)
66 module AP_MODULE_DECLARE_DATA waklog_module
;
67 typedef struct { int dummy
; } child_info
;
68 const char *userdata_key
= "waklog_init";
71 /**************************************************************************************************/
75 #include <afs/venus.h>
77 #include <afs/dirpath.h>
78 #include <afs/ptuser.h>
81 #define TKT_LIFE ( 12 * 60 * 60 )
82 #define SLEEP_TIME ( TKT_LIFE - 5*60 )
86 #define WAKLOG_UNSET 0
90 #define APLOG_DEBUG APLOG_ERR
93 /* this is used to turn off pag generation for the backround worker child during startup */
94 int pag_for_children
= 1;
102 int cell_in_principal
;
103 int disable_token_cache
;
106 char *default_principal
;
107 char *default_keytab
;
116 struct ktc_token token
;
117 char clientprincipal
[MAXNAMELEN
];
118 krb5_context kcontext
;
120 struct ktc_principal server
;
121 struct ktc_principal client
;
123 } waklog_child_config
;
125 waklog_child_config child
;
127 struct tokencache_ent
{
128 char clientprincipal
[MAXNAMELEN
];
129 struct ktc_token token
;
130 struct ktc_principal client
;
131 struct ktc_principal server
;
136 #define SHARED_TABLE_SIZE 512
138 struct sharedspace_s
{
140 struct tokencache_ent sharedtokens
[SHARED_TABLE_SIZE
];
143 struct sharedspace_s
*sharedspace
= NULL
;
152 pthread_rwlock_t
*sharedlock
= NULL
;
154 rwlock_t
*sharedlock
= NULL
;
157 struct renew_ent renewtable
[SHARED_TABLE_SIZE
];
163 #define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
168 #include <sys/ioccom.h>
171 #include <afs/venus.h>
172 #include <afs/auth.h>
173 #include <afs/dirpath.h>
174 #include <afs/ptuser.h>
175 #include <rx/rxkad.h>
179 log_error (const char *file
, int line
, int level
, int status
,
180 const server_rec
* s
, const char *fmt
, ...)
186 vsnprintf (errstr
, 1024, fmt
, ap
);
190 ap_log_error (file
, line
, level
| APLOG_NOERRNO
, status
, s
, "(%d) %s", getpid(), errstr
);
192 ap_log_error (file
, line
, level
| APLOG_NOERRNO
, s
, "(%d) %s", getpid(), errstr
);
197 waklog_config
*retrieve_config(request_rec
*r
) {
202 if ( r
&& r
->main
) {
210 if ( my
&& ( cfg
= (waklog_config
*) ap_get_module_config(my
->per_dir_config
, &waklog_module
) ) ) {
213 getModConfig (cfg
, r
->server
);
220 /* set_auth -- sets the tokens of the current process to this user.
221 if "self" is set, it divines the user from the current requests' environment.
222 otherwise, it's gettng it from principal/keytab */
225 set_auth ( server_rec
*s
, request_rec
*r
, int self
, char *principal
, char *keytab
, int storeonly
) {
229 krb5_error_code kerror
= 0;
230 krb5_principal kprinc
= NULL
;
231 krb5_get_init_creds_opt kopts
;
234 struct ktc_principal server
= { "afs", "", "" };
235 struct ktc_principal client
;
236 struct ktc_token token
;
237 krb5_creds
*v5credsp
= NULL
;
238 krb5_keytab krb5kt
= NULL
;
239 char buf
[MAXNAMELEN
];
243 time_t oldest_time
= 0;
248 int cell_in_principal
;
251 char k5user
[MAXNAMELEN
];
254 memset((char *) &increds
, 0, sizeof(increds
));
256 /* init some stuff if it ain't already */
258 if ( ! child
.kcontext
) {
259 kerror
= krb5_init_context(&child
.kcontext
);
262 if ( ( ! child
.ccache
) && ( kerror
= krb5_cc_resolve(child
.kcontext
, "MEMORY:tmpcache", &child
.ccache
) ) ) {
263 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't initialize in-memory credentials cache %d", kerror
);
267 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: set_auth: %d, %s, %s, %d", self
, principal
? principal
: "NULL",
268 keytab
? keytab
: "NULL", storeonly
);
270 /* pull the server config record that we care about... */
273 cfg
= retrieve_config(r
);
275 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
276 "mod_waklog: set_auth using no config" );
277 getModConfig (cfg
, s
);
281 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: cfg is %d", cfg
);
286 /* pull out our principal name and stuff from the environment -- webauth better have sent
287 through. This here is also where you'd suck stuff out of KRB5CCNAME if we were
288 using something like Cosign */
290 if ( ! ( r
&& r
->connection
&& r
->user
)) {
291 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: self authentication selected, but no data available");
295 strncpy(k5user
, r
->user
, sizeof(k5user
));
297 /* the other thing we need is someone's password */
298 if ( ! ( k5secret
= (char *) MK_TABLE_GET( r
->notes
, "ATTR_PASSWORD" ) ) ) {
299 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cant do self auth without a secret");
303 /* we'll pick this up later after we've checked the cache and current state */
308 strncpy( k5user
, principal
, sizeof(k5user
));
313 /* see if we should just go ahead and ignore this call, since we already should be set to these
319 pthread_rwlock_rdlock( sharedlock
);
321 rw_rdlock( sharedlock
);
324 for ( i
= 0; i
< SHARED_TABLE_SIZE
; ++i
) {
326 /* if it's a token for the principal we're looking for, and it hasn't expired yet */
328 if ( ( !strcmp( k5user
,
329 sharedspace
->sharedtokens
[i
].clientprincipal
) ) &&
330 ( sharedspace
->sharedtokens
[i
].token
.endTime
> mytime
) ) {
332 if ( ! memcmp(&child
.token
, &sharedspace
->sharedtokens
[i
].token
, sizeof(child
.token
) ) ) {
338 /* copy the token out of the cache and into the child object */
340 strcpy(child
.clientprincipal
, sharedspace
->sharedtokens
[i
].clientprincipal
);
341 memcpy(&child
.token
, &sharedspace
->sharedtokens
[i
].token
, sizeof(child
.token
));
342 memcpy(&child
.server
, &sharedspace
->sharedtokens
[i
].server
, sizeof(child
.server
));
343 memcpy(&child
.client
, &sharedspace
->sharedtokens
[i
].client
, sizeof(child
.client
));
345 /* set our last used time thing */
346 sharedspace
->sharedtokens
[i
].lastused
= mytime
;
356 /* release the lock on the token cache */
358 pthread_rwlock_unlock( sharedlock
);
360 rw_unlock( sharedlock
);
364 /* release the lock on the token cache */
365 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
,
366 "mod_waklog: set_auth using shared token %d for %s", i
, k5user
);
370 /* if this is something that was in the cache, and it's the same as the token we already have stored,
371 and we weren't calling this just to renew it... */
373 if ( usecached
&& indentical
) {
374 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: token is identical for %s", k5user
);
380 /* if 'usecached' isn't set, we've got to get our tokens from somewhere... */
382 if (( ! usecached
) && ( k5user
)) {
384 /* clear out the creds structure */
385 memset((void *) &v5creds
, 0, sizeof(v5creds
));
387 /* create a principal out of our k5user string */
389 if ( kerror
= krb5_parse_name (child
.kcontext
, k5user
, &kprinc
) ) {
390 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_parse_name %s", (char *) error_message(kerror
) );
394 /* create the credentials options */
396 krb5_get_init_creds_opt_init ( &kopts
);
397 krb5_get_init_creds_opt_set_tkt_life ( &kopts
, TKT_LIFE
);
398 krb5_get_init_creds_opt_set_renew_life ( &kopts
, 0 );
399 krb5_get_init_creds_opt_set_forwardable ( &kopts
, 0 );
400 krb5_get_init_creds_opt_set_proxiable ( &kopts
, 0 );
404 /* if we've been passed a keytab, we're going to be getting our credentials from it */
406 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: using keytab %s", keytab
);
408 if ( kerror
= krb5_kt_resolve(child
.kcontext
, keytab
, &krb5kt
) ) {
409 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
,
410 "mod_waklog: krb5_kt_resolve %s", error_message(kerror
) );
414 if ((kerror
= krb5_get_init_creds_keytab (child
.kcontext
, &v5creds
,
415 kprinc
, krb5kt
, 0, NULL
, &kopts
) ) ) {
416 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_get_init_creds_keytab %s",
417 error_message(kerror
) );
423 /* if 'self' is set, we're going to use the credentials provided in the credential information */
424 /* if you're using CoSign, you'd actually just set the ccache to the KRB5CCNAME credentials */
425 /* and skip ahead... Our WebSSO is lame, but has a way for us to snarf the password out of */
426 /* the encrypted token for proxy-authentication stuff. We only hand out keys that allow this */
427 /* functionality to VERY special people. */
429 if ((kerror
= krb5_get_init_creds_password ( child
.kcontext
, &v5creds
,
430 kprinc
, k5secret
, NULL
, NULL
, 0, NULL
, &kopts
) ) ) {
431 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_get_init_creds_password %s",
432 error_message(kerror
) );
433 /* nuke the password so it doesn't end up in core files */
434 memset(k5secret
, 0, sizeof(k5secret
));
438 memset(k5secret
, 0, sizeof(k5secret
));
442 /* degenerate case -- we don't have enough information to do anything */
444 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: no keytab, no self?");
450 /* initialize the credentials cache and store the stuff we just got */
452 if ( kerror
= krb5_cc_initialize (child
.kcontext
, child
.ccache
, kprinc
)) {
453 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: init credentials cache %s",
454 error_message(kerror
));
458 if ( kerror
= krb5_cc_store_cred(child
.kcontext
, child
.ccache
, &v5creds
) ) {
459 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot store credentials %s",
460 error_message(kerror
));
464 krb5_free_cred_contents(child
.kcontext
, &v5creds
);
467 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: store cred %s", error_message(kerror
));
471 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: kinit ok for %s", k5user
);
473 /* now, to the 'aklog' portion of our program. */
475 strncpy( buf
, "afs", sizeof(buf
) - 1 );
477 /** we make two attempts here, one for afs@REALM and one for afs/cell@REALM */
478 for(attempt
= 0; attempt
<= 1; attempt
++) {
479 cell_in_principal
= (cfg
->cell_in_principal
+ attempt
) % 2;
481 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: cell_in_principal=%d", cell_in_principal
);
482 if (cell_in_principal
) {
483 strncat(buf
, "/", sizeof(buf
) - strlen(buf
) - 1);
484 strncat(buf
, cfg
->afs_cell
, sizeof(buf
) - strlen(buf
) - 1);
487 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: using AFS principal: %s", buf
);
489 if ((kerror
= krb5_parse_name (child
.kcontext
, buf
, &increds
.server
))) {
490 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_parse name %s", error_message(kerror
));
494 if ((kerror
= krb5_cc_get_principal(child
.kcontext
, child
.ccache
, &increds
.client
))) {
495 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_cc_get_princ %s", error_message(kerror
));
499 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: retrieved data from ccache for %s", k5user
);
501 increds
.times
.endtime
= 0;
503 increds
.keyblock
.enctype
= ENCTYPE_DES_CBC_CRC
;
505 if (kerror
= krb5_get_credentials (child
.kcontext
, 0, child
.ccache
, &increds
, &v5credsp
)) {
506 /* only complain once we've tried both afs@REALM and afs/cell@REALM */
508 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_get_credentials: %s",
509 error_message(kerror
));
515 cfg
->cell_in_principal
= cell_in_principal
;
519 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: get_credentials passed for %s", k5user
);
521 if ( v5credsp
->ticket
.length
>= MAXKTCTICKETLEN
) {
522 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: ticket size (%d) too big to fake",
523 v5credsp
->ticket
.length
);
527 memset(&token
, 0, sizeof(struct ktc_token
));
529 token
.startTime
= v5credsp
->times
.starttime
? v5credsp
->times
.starttime
: v5credsp
->times
.authtime
;
530 token
.endTime
= v5credsp
->times
.endtime
;
532 memmove( &token
.sessionKey
, v5credsp
->keyblock
.contents
, v5credsp
->keyblock
.length
);
533 token
.kvno
= RXKAD_TKT_TYPE_KERBEROS_V5
;
534 token
.ticketLen
= v5credsp
->ticket
.length
;
535 memmove( token
.ticket
, v5credsp
->ticket
.data
, token
.ticketLen
);
539 memmove( buf
, v5credsp
->client
->data
[0].data
, min(v5credsp
->client
->data
[0].length
,
541 buf
[v5credsp
->client
->data
[0].length
] = '\0';
542 if ( v5credsp
->client
->length
> 1 ) {
543 strncat(buf
, ".", sizeof(buf
) - strlen(buf
) - 1);
544 buflen
= strlen(buf
);
545 memmove(buf
+ buflen
, v5credsp
->client
->data
[1].data
,
546 min(v5credsp
->client
->data
[1].length
,
547 MAXKTCNAMELEN
- strlen(buf
) - 1));
548 buf
[buflen
+ v5credsp
->client
->data
[1].length
] = '\0';
551 /* assemble the client */
552 strncpy(client
.name
, buf
, sizeof(client
.name
) - 1 );
553 strncpy(client
.instance
, "", sizeof(client
.instance
) - 1 );
554 memmove(buf
, v5credsp
->client
->realm
.data
, min(v5credsp
->client
->realm
.length
,
556 buf
[v5credsp
->client
->realm
.length
] = '\0';
557 strncpy(client
.cell
, buf
, sizeof(client
.cell
));
559 /* assemble the server's cell */
560 strncpy(server
.cell
, cfg
->afs_cell
, sizeof(server
.cell
) - 1);
562 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: preparing to init PTS connection for %s", server
.cell
);
564 /* fill out the AFS ID in the client name */
565 /* we've done a pr_Initialize in the child_init -- once, per process. If you try to do it more
566 * strange things seem to happen. */
569 afs_int32 viceId
= 0;
571 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: making PTS call to look up %s", client
.name
);
573 if ( ( rc
= pr_SNameToId( client
.name
, &viceId
) ) == 0 ) {
574 snprintf( client
.name
, sizeof(client
.name
), "AFS ID %d", viceId
);
576 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: PTS call returned error %d ", rc
);
579 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: PTS call returned %s ", client
.name
);
583 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: server: name %s, instance %s, cell %s",
584 server
.name
, server
.instance
, server
.cell
);
586 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: client: name %s, instance %s, cell %s",
587 client
.name
, client
.instance
, client
.cell
);
589 /* copy the resulting stuff into the child structure */
591 strncpy(child
.clientprincipal
, k5user
, sizeof(child
.clientprincipal
));
592 memcpy(&child
.token
, &token
, sizeof(child
.token
));
593 memcpy(&child
.server
, &server
, sizeof(child
.server
));
594 memcpy(&child
.client
, &client
, sizeof(child
.client
));
596 /* stuff the resulting token-related stuff into our shared token cache */
597 /* note, that anything that was set from a keytab is "persistant", and is immune
598 * from LRU-aging. This is because nothing but the process that's running as root
599 * can update these, and it's running every hour or so and renewing these tokens.
600 * and we don't want them aged out.
603 mytime
= oldest_time
= time(0);
605 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: waiting for shared space for %s ", k5user
);
608 pthread_rwlock_wrlock(sharedlock
);
610 rw_wrlock(sharedlock
);
613 for( i
= ( SHARED_TABLE_SIZE
- 1 ); i
>= 0; i
-- ) {
614 if ( ( sharedspace
->sharedtokens
[i
].lastused
<= oldest_time
) &&
615 ( sharedspace
->sharedtokens
[i
].persist
== 0 ) ) {
617 oldest_time
= sharedspace
->sharedtokens
[i
].lastused
;
619 if ( ! strcmp ( sharedspace
->sharedtokens
[i
].clientprincipal
,
620 child
.clientprincipal
) ) {
621 memcpy(&sharedspace
->sharedtokens
[i
].token
, &child
.token
, sizeof(child
.token
) );
622 memcpy(&sharedspace
->sharedtokens
[i
].client
, &child
.client
, sizeof(child
.client
) );
623 memcpy(&sharedspace
->sharedtokens
[i
].server
, &child
.server
, sizeof(child
.server
) );
624 sharedspace
->sharedtokens
[i
].lastused
= mytime
;
625 sharedspace
->sharedtokens
[i
].persist
= keytab
? 1 : 0;
631 if ( stored
== -1 ) {
632 memcpy(&sharedspace
->sharedtokens
[oldest
].token
, &child
.token
, sizeof(child
.token
) );
633 memcpy(&sharedspace
->sharedtokens
[oldest
].client
, &child
.client
, sizeof(child
.client
) );
634 memcpy(&sharedspace
->sharedtokens
[oldest
].server
, &child
.server
, sizeof(child
.server
) );
635 strcpy(sharedspace
->sharedtokens
[oldest
].clientprincipal
, child
.clientprincipal
);
636 sharedspace
->sharedtokens
[oldest
].lastused
= mytime
;
637 sharedspace
->sharedtokens
[oldest
].persist
= keytab
? 1 : 0;
642 pthread_rwlock_unlock(sharedlock
);
644 rw_unlock(sharedlock
);
647 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: token stored in slot %d for %s", stored
,
648 child
.clientprincipal
);
650 } else if ( ! usecached
) {
651 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: set_auth divergent case");
660 /* don't ask. Something about AIX. We're leaving it here.*/
661 /* write(2, "", 0); */
663 /* we try twice, because sometimes the first one fails. Dunno why, but it always works the second time */
665 if ((rc
= ktc_SetToken(&child
.server
, &child
.token
, &child
.client
, 0))) {
666 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: settoken returned %s for %s -- trying again",
667 error_message(rc
), k5user
);
668 if ((rc
= ktc_SetToken(&child
.server
, &child
.token
, &child
.client
, 0))) {
669 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: settoken2 returned %s for %s",
670 error_message(rc
), k5user
);
677 krb5_free_cred_contents(child
.kcontext
, v5credsp
);
678 if ( increds
.client
)
679 krb5_free_principal (child
.kcontext
, increds
.client
);
680 if ( increds
.server
)
681 krb5_free_principal (child
.kcontext
, increds
.server
);
683 (void) krb5_kt_close(child
.kcontext
, krb5kt
);
685 krb5_free_principal (child
.kcontext
, kprinc
);
688 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: set_auth ending with %d", rc
);
689 } else if ( kerror
) {
690 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror
, error_message(kerror
));
692 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: set_auth ending ok");
695 return kerror
? (int) kerror
: (int) rc
;
702 waklog_create_server_config (MK_POOL
* p
, server_rec
* s
)
706 cfg
= (waklog_config
*) ap_pcalloc (p
, sizeof (waklog_config
));
708 memset(cfg
, 0, sizeof(waklog_config
));
709 cfg
->path
= "(server)";
710 cfg
->protect
= WAKLOG_UNSET
;
711 cfg
->usertokens
= WAKLOG_UNSET
;
712 cfg
->disable_token_cache
= WAKLOG_UNSET
;
713 cfg
->keytab
= WAKLOG_UNSET
;
714 cfg
->principal
= WAKLOG_UNSET
;
715 cfg
->default_principal
= WAKLOG_UNSET
;
716 cfg
->default_keytab
= WAKLOG_UNSET
;
717 cfg
->afs_cell
= WAKLOG_UNSET
;
721 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
722 "mod_waklog: server config created.");
727 /* initialize with host-config information */
730 waklog_create_dir_config (MK_POOL
* p
, char *dir
)
734 cfg
= (waklog_config
*) ap_pcalloc (p
, sizeof (waklog_config
));
735 memset(cfg
, 0, sizeof(waklog_config
));
737 cfg
->path
= ap_pstrdup(p
, dir
);
738 cfg
->protect
= WAKLOG_UNSET
;
739 cfg
->usertokens
= WAKLOG_UNSET
;
740 cfg
->disable_token_cache
= WAKLOG_UNSET
;
741 cfg
->keytab
= WAKLOG_UNSET
;
742 cfg
->principal
= WAKLOG_UNSET
;
743 cfg
->default_principal
= WAKLOG_UNSET
;
744 cfg
->default_keytab
= WAKLOG_UNSET
;
745 cfg
->afs_cell
= WAKLOG_UNSET
;
752 static void *waklog_merge_dir_config(MK_POOL
*p
, void *parent_conf
, void *newloc_conf
) {
754 waklog_config
*merged
= ( waklog_config
* ) ap_pcalloc(p
, sizeof(waklog_config
) );
755 waklog_config
*parent
= ( waklog_config
* ) parent_conf
;
756 waklog_config
*child
= ( waklog_config
* ) newloc_conf
;
758 merged
->protect
= child
->protect
!= WAKLOG_UNSET
? child
->protect
: parent
->protect
;
760 merged
->path
= child
->path
!= WAKLOG_UNSET
? child
->path
: parent
->path
;
762 merged
->usertokens
= child
->usertokens
!= WAKLOG_UNSET
? child
->usertokens
: parent
->usertokens
;
764 merged
->disable_token_cache
= child
->disable_token_cache
!= WAKLOG_UNSET
? child
->disable_token_cache
: parent
->disable_token_cache
;
766 merged
->principal
= child
->principal
!= WAKLOG_UNSET
? child
->principal
: parent
->principal
;
768 merged
->keytab
= child
->keytab
!= WAKLOG_UNSET
? child
->keytab
: parent
->keytab
;
770 merged
->default_keytab
= child
->default_keytab
!= WAKLOG_UNSET
? child
->default_keytab
: parent
->default_keytab
;
772 merged
->default_principal
= child
->default_principal
!= WAKLOG_UNSET
? child
->default_principal
: parent
->default_principal
;
774 merged
->afs_cell
= child
->afs_cell
!= WAKLOG_UNSET
? child
->afs_cell
: parent
->afs_cell
;
776 return (void *) merged
;
780 static void *waklog_merge_server_config(MK_POOL
*p
, void *parent_conf
, void *newloc_conf
) {
782 waklog_config
*merged
= ( waklog_config
* ) ap_pcalloc(p
, sizeof(waklog_config
) );
783 waklog_config
*pconf
= ( waklog_config
* ) parent_conf
;
784 waklog_config
*nconf
= ( waklog_config
* ) newloc_conf
;
786 merged
->protect
= nconf
->protect
== WAKLOG_UNSET
? pconf
->protect
: nconf
->protect
;
788 merged
->usertokens
= nconf
->usertokens
== WAKLOG_UNSET
? pconf
->usertokens
: nconf
->usertokens
;
790 merged
->disable_token_cache
= nconf
->disable_token_cache
== WAKLOG_UNSET
? pconf
->udisable_token_cache
: nconf
->disable_token_cache
;
792 merged
->keytab
= nconf
->keytab
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->keytab
) :
793 ( nconf
->keytab
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->keytab
) );
795 merged
->principal
= nconf
->principal
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->principal
) :
796 ( nconf
->principal
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->principal
) );
798 merged
->afs_cell
= nconf
->afs_cell
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->afs_cell
) :
799 ( nconf
->afs_cell
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->afs_cell
) );
801 merged
->default_keytab
= nconf
->default_keytab
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->default_keytab
) :
802 ( nconf
->default_keytab
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->default_keytab
) );
804 merged
->default_principal
= nconf
->default_principal
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->default_principal
) :
805 ( nconf
->default_principal
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->default_principal
) );
808 return (void *) merged
;
813 set_waklog_enabled (cmd_parms
* params
, void *mconfig
, int flag
)
815 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
816 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
820 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
821 "mod_waklog: waklog_enabled set on %s", cfg
->path
? cfg
->path
: "NULL");
826 /* this adds a principal/keytab pair to get their tokens renewed by the
827 child process every few centons. */
829 void add_to_renewtable(MK_POOL
*p
, char *keytab
, char *principal
) {
833 if ( renewcount
>= SHARED_TABLE_SIZE
) {
834 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, NULL
, "mod_waklog: big problem. Increase the SHARED_TABLE_SIZE or \
835 decrease your tokens.");
839 /* check to see if it's already there */
841 for ( i
= 0; i
< renewcount
; i
++ ) {
842 if ( ! strcmp(renewtable
[i
].principal
, principal
) ) {
847 renewtable
[renewcount
].keytab
= ap_pstrdup(p
, keytab
);
848 renewtable
[renewcount
].principal
= ap_pstrdup(p
, principal
);
849 renewtable
[renewcount
].lastrenewed
= 0;
855 set_waklog_location_principal (cmd_parms
*params
, void *mconfig
, char *principal
, char *keytab
)
857 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
858 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
860 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
861 "mod_waklog: configuring principal: %s, keytab: %s", principal
, keytab
);
863 cfg
->principal
= ap_pstrdup(params
->pool
, principal
);
864 cfg
->keytab
= ap_pstrdup (params
->pool
, keytab
);
866 add_to_renewtable(params
->pool
, keytab
, principal
);
874 set_waklog_afs_cell (cmd_parms
* params
, void *mconfig
, char *file
)
876 waklog_config
*waklog_mconfig
= ( waklog_config
* ) mconfig
;
877 waklog_config
*waklog_srvconfig
=
878 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
880 log_error (APLOG_MARK
, APLOG_INFO
, 0, params
->server
,
881 "mod_waklog: will use afs_cell: %s", file
);
883 waklog_srvconfig
->cell_in_principal
= 0;
884 waklog_srvconfig
->afs_cell
= ap_pstrdup (params
->pool
, file
);
885 waklog_srvconfig
->configured
= 1;
887 if (waklog_mconfig
!= NULL
) {
888 waklog_mconfig
->cell_in_principal
= waklog_srvconfig
->cell_in_principal
;
889 waklog_mconfig
->afs_cell
= ap_pstrdup (params
->pool
, file
);
890 waklog_mconfig
->configured
= 1;
896 set_waklog_default_principal (cmd_parms
* params
, void *mconfig
, char *principal
, char *keytab
)
898 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
899 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
901 waklog_config
*srvcfg
= ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
903 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
904 "mod_waklog: set default princ/keytab: %s, %s for %s", principal
, keytab
, cfg
->path
? cfg
->path
: "NULL");
906 cfg
->default_principal
= ap_pstrdup (params
->pool
, principal
);
907 cfg
->default_keytab
= ap_pstrdup(params
->pool
, keytab
);
909 /* this also gets set at the server level */
910 if ( mconfig
&& ( ! cfg
->path
) ) {
911 srvcfg
->default_principal
= ap_pstrdup (params
->pool
, principal
);
912 srvcfg
->default_keytab
= ap_pstrdup(params
->pool
, keytab
);
914 log_error(APLOG_MARK
, APLOG_ERR
, 0, params
->server
, "only able to set default principal on a global level!");
915 return "Unable to set DefaultPrincipal outside of top level config!";
918 add_to_renewtable( params
->pool
, keytab
, principal
);
926 set_waklog_use_usertokens (cmd_parms
* params
, void *mconfig
, int flag
)
928 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
929 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
931 cfg
->usertokens
= flag
;
935 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
936 "mod_waklog: waklog_use_user_tokens set");
942 set_waklog_disable_token_cache (cmd_parms
* params
, void *mconfig
, int flag
)
944 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
945 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
947 cfg
->disable_token_cache
= flag
;
951 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
952 "mod_waklog: waklog_disable_token_cache set");
958 static void waklog_child_exit( server_rec
*s
, MK_POOL
*p
) {
960 apr_status_t
waklog_child_exit( void *sr
) {
962 server_rec
*s
= (server_rec
*) sr
;
965 if ( child
.ccache
) {
966 krb5_cc_close(child
.kcontext
, child
.ccache
);
969 if ( child
.kcontext
) {
970 krb5_free_context(child
.kcontext
);
973 /* forget our tokens */
975 ktc_ForgetAllTokens ();
977 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
978 "mod_waklog: waklog_child_exit complete");
988 waklog_child_init (MK_POOL
* p
, server_rec
* s
)
990 waklog_child_init (server_rec
* s
, MK_POOL
* p
)
994 krb5_error_code code
;
999 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: child_init called for pid %d", getpid());
1001 if ( !sharedspace
) {
1002 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: child_init called without shared space? %d", getpid());
1006 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: child_init called for pid %d", getpid());
1008 memset (&child
, 0, sizeof(child
));
1010 if ( code
= krb5_init_context(&child
.kcontext
) ) {
1011 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't init kerberos context %d", code
);
1014 if ( code
= krb5_cc_resolve(child
.kcontext
, "MEMORY:tmpcache", &child
.ccache
) ) {
1015 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't initialize in-memory credentials cache %d", code
);
1018 if ( pag_for_children
) {
1022 getModConfig (cfg
, s
);
1024 if ( cfg
->default_principal
!= WAKLOG_UNSET
) {
1025 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: child_init setting default user %s, %s", cfg
->default_principal
, cfg
->default_keytab
);
1026 set_auth( s
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1029 cell
= strdup(cfg
->afs_cell
);
1030 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR
, cell
);
1033 apr_pool_cleanup_register(p
, s
, waklog_child_exit
, apr_pool_cleanup_null
);
1036 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1037 "mod_waklog: child_init returned");
1042 command_rec waklog_cmds
[] = {
1044 command ("WaklogAFSCell", set_waklog_afs_cell
, 0, TAKE1
,
1045 "Use the supplied AFS cell (required)"),
1047 command ("WaklogEnabled", set_waklog_enabled
, 0, FLAG
,
1048 "enable waklog on a server, location, or directory basis"),
1050 command ("WaklogDefaultPrincipal", set_waklog_default_principal
, 0, TAKE2
,
1051 "Set the default principal that the server runs as"),
1053 command ("WaklogLocationPrincipal", set_waklog_location_principal
, 0, TAKE2
,
1054 "Set the principal on a <Location>-specific basis"),
1056 command ("WaklogDisableTokenCache", set_waklog_disable_token_cache
, 0, FLAG
,
1057 "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
1059 command ("WaklogUseUserTokens", set_waklog_use_usertokens
, 0, FLAG
,
1060 "Use the requesting user tokens (from webauth)"),
1066 /* not currently using this */
1069 token_cleanup (void *data
)
1071 request_rec
*r
= (request_rec
*) data
;
1073 if (child
.token
.ticketLen
)
1075 memset (&child
.token
, 0, sizeof (struct ktc_token
));
1077 ktc_ForgetAllTokens ();
1079 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1080 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1087 waklog_child_routine (void *data
, child_info
* pinfo
)
1090 server_rec
*s
= (server_rec
*) data
;
1091 krb5_error_code code
;
1093 time_t sleep_time
= ( TKT_LIFE
/ 2 ) ;
1098 getModConfig( cfg
, s
);
1100 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: waklog_child_routine started, running as %d", getuid());
1102 memset (&child
, 0, sizeof(child
));
1104 if ( code
= krb5_init_context(&child
.kcontext
) ) {
1105 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't init kerberos context %d", code
);
1108 if ( code
= krb5_cc_resolve(child
.kcontext
, "MEMORY:tmpcache", &child
.ccache
) ) {
1109 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't initialize in-memory credentials cache %d", code
);
1112 /* need to do this so we can make PTS calls */
1113 cell
= strdup(cfg
->afs_cell
); /* stupid */
1114 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR
, cell
);
1118 for ( i
= 0; i
< renewcount
; ++i
) {
1119 renewtable
[i
].lastrenewed
= time(0);
1120 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: (pid %d) renewing %s / %s", getpid(), renewtable
[i
].principal
,
1121 renewtable
[i
].keytab
);
1123 set_auth( s
, NULL
, 0, renewtable
[i
].principal
, renewtable
[i
].keytab
, 1 );
1125 /* if this is our default token, we want to "stash" it in our current PAG so the parent maintains readability of
1126 things that it needs to read */
1128 if ( cfg
&& cfg
->default_principal
&& ( ! strcmp(cfg
->default_principal
, renewtable
[i
].principal
) ) ) {
1129 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: renewing/setting default tokens" );
1130 set_auth( s
, NULL
, 0, renewtable
[i
].principal
, renewtable
[i
].keytab
, 0 );
1135 sharedspace
->renewcount
++;
1144 left
-= ( time(0) - when
);
1155 waklog_init_handler (apr_pool_t
* p
, apr_pool_t
* plog
,
1156 apr_pool_t
* ptemp
, server_rec
* s
)
1159 extern char *version
;
1164 int use_existing
= 1;
1166 char cache_file
[MAXNAMELEN
];
1168 pthread_rwlockattr_t rwlock_attr
;
1172 getModConfig (cfg
, s
);
1174 /* initialize_module() will be called twice, and if it's a DSO
1175 * then all static data from the first call will be lost. Only
1176 * set up our static data on the second call.
1177 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
1178 apr_pool_userdata_get (&data
, userdata_key
, s
->process
->pool
);
1181 if (cfg
->afs_cell
==NULL
) {
1182 log_error (APLOG_MARK
, APLOG_ERR
, 0, s
,
1183 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
1184 /** clobber apache */
1190 apr_pool_userdata_set ((const void *) 1, userdata_key
,
1191 apr_pool_cleanup_null
, s
->process
->pool
);
1195 log_error (APLOG_MARK
, APLOG_INFO
, 0, s
,
1196 "mod_waklog: version %s initialized for cell %s", version
, cfg
->afs_cell
);
1198 if ( sharedspace
) {
1199 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: shared memory already allocated." );
1202 snprintf( cache_file
, MAXNAMELEN
, "/tmp/waklog_cache.%d", getpid() );
1204 if ( ( fd
= open( cache_file
, O_RDWR
, 0600 ) ) == -1 ) {
1206 if ( errno
== ENOENT
) {
1208 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: creating shared token cache file %s", cache_file
);
1210 if ( ( fd
= open( cache_file
, O_RDWR
|O_CREAT
|O_TRUNC
, 0600 ) ) == -1 ) {
1211 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file
, errno
);
1215 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file
, errno
);
1219 if ( use_existing
== 0 ) {
1220 struct sharedspace_s bob
;
1221 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: sizing our cache file %d to %d", fd
, sizeof(struct sharedspace_s
) );
1222 memset( &bob
, 0, sizeof(struct sharedspace_s
));
1223 write(fd
, &bob
, sizeof(struct sharedspace_s
));
1224 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s
) );
1227 /* mmap the region */
1229 if ( ( sharedspace
= (struct sharedspace_s
*) mmap ( NULL
, sizeof(struct sharedspace_s
), PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0 ) ) != MAP_FAILED
) {
1230 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: shared mmap region ok %d", sharedspace
);
1233 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: mmap failed %d", errno
);
1239 #define locktype pthread_rwlock_t
1241 #define locktype rwlock_t
1244 if ( sharedlock
= ( locktype
* ) mmap ( NULL
, sizeof(locktype
), PROT_READ
|PROT_WRITE
, MAP_SHARED
|MAP_ANON
, -1, 0 ) ) {
1245 #ifndef use_pthreads
1246 rwlock_init(sharedlock
, USYNC_PROCESS
, NULL
);
1248 pthread_rwlockattr_init(&rwlock_attr
);
1249 pthread_rwlockattr_setpshared(&rwlock_attr
, PTHREAD_PROCESS_SHARED
);
1250 pthread_rwlock_init(sharedlock
, &rwlock_attr
);
1253 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: rwlock mmap failed %d", errno
);
1258 /* set our default tokens */
1260 oldrenewcount
= sharedspace
->renewcount
;
1262 pag_for_children
= 0;
1264 proc
= (apr_proc_t
*) ap_pcalloc (s
->process
->pool
, sizeof (apr_proc_t
));
1266 rv
= apr_proc_fork (proc
, s
->process
->pool
);
1268 if (rv
== APR_INCHILD
)
1270 waklog_child_routine (s
, NULL
);
1274 apr_pool_note_subprocess (s
->process
->pool
, proc
, APR_KILL_ALWAYS
);
1276 /* parent and child */
1277 cfg
->forked
= proc
->pid
;
1278 pag_for_children
= 1;
1280 if ( use_existing
== 0 ) {
1281 /* wait here until our child process has gone and done it's renewing thing. */
1282 while( sharedspace
->renewcount
== oldrenewcount
) {
1283 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: waiting for tokens..." );
1288 if ( cfg
->default_principal
) {
1289 set_auth( s
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1296 waklog_init (server_rec
* s
, MK_POOL
* p
)
1298 extern char *version
;
1303 int use_existing
= 1;
1305 char cache_file
[MAXNAMELEN
];
1307 pthread_rwlockattr_t rwlock_attr
;
1310 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1311 "mod_waklog: version %s initialized.", version
);
1313 if ( sharedspace
) {
1314 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: shared memory already allocated." );
1317 snprintf( cache_file
, MAXNAMELEN
, "/tmp/waklog_cache.%d", getpid() );
1319 if ( ( fd
= open( cache_file
, O_RDWR
, 0600 ) ) == -1 ) {
1321 if ( errno
== ENOENT
) {
1323 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: creating shared token cache file %s", cache_file
);
1325 if ( ( fd
= open( cache_file
, O_RDWR
|O_CREAT
|O_TRUNC
, 0600 ) ) == -1 ) {
1326 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file
, errno
);
1330 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file
, errno
);
1335 if ( use_existing
== 0 ) {
1336 struct sharedspace_s bob
;
1337 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: sizing our cache file %d to %d", fd
, sizeof(struct sharedspace_s
) );
1338 memset( &bob
, 0, sizeof(struct sharedspace_s
));
1339 write(fd
, &bob
, sizeof(struct sharedspace_s
));
1340 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s
) );
1343 /* mmap the region */
1345 if ( ( sharedspace
= (struct sharedspace_s
*) mmap ( NULL
, sizeof(struct sharedspace_s
), PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0 ) ) != -1 ) {
1346 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: shared mmap region ok %d", sharedspace
);
1349 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: mmap failed %d", errno
);
1355 #define locktype pthread_rwlock_t
1357 #define locktype rwlock_t
1360 /* mmap our shared space for our lock */
1361 if ( sharedlock
= ( locktype
* ) mmap ( NULL
, sizeof(locktype
), PROT_READ
|PROT_WRITE
, MAP_SHARED
|MAP_ANON
, -1, 0 ) ) {
1362 #ifndef use_pthreads
1363 rwlock_init(sharedlock
, USYNC_PROCESS
, NULL
);
1365 pthread_rwlockattr_init(&rwlock_attr
);
1366 pthread_rwlockattr_setpshared(&rwlock_attr
, PTHREAD_PROCESS_SHARED
);
1367 pthread_rwlock_init(sharedlock
, &rwlock_attr
);
1370 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: rwlock mmap failed %d", errno
);
1375 /* set our default tokens */
1377 getModConfig (cfg
, s
);
1379 oldrenewcount
= sharedspace
->renewcount
;
1381 pag_for_children
= 0;
1383 pid
= ap_bspawn_child (p
, waklog_child_routine
, s
, kill_always
,
1386 pag_for_children
= 1;
1388 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1389 "mod_waklog: ap_bspawn_child: %d.", pid
);
1391 if ( use_existing
== 0 ) {
1392 /* wait here until our child process has gone and done it's renewing thing. */
1393 while( sharedspace
->renewcount
== oldrenewcount
) {
1394 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: waiting for tokens..." );
1399 if ( cfg
->default_principal
) {
1400 set_auth( s
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1407 waklog_phase0 (request_rec
* r
)
1411 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1412 "mod_waklog: phase0 called");
1414 cfg
= retrieve_config(r
);
1416 if ( cfg
->protect
&& cfg
->principal
) {
1417 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase0 using user %s", cfg
->principal
);
1418 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1419 } else if ( cfg
->default_principal
) {
1420 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase0 using default user %s", cfg
->default_principal
);
1421 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1423 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase0 not doing nothin.");
1430 waklog_phase1 (request_rec
* r
)
1434 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1435 "mod_waklog: phase1 called");
1437 cfg
= retrieve_config(r
);
1439 if ( cfg
->protect
&& cfg
->principal
) {
1440 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase1 using user %s", cfg
->principal
);
1441 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1442 } else if ( cfg
->default_principal
) {
1443 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase1 using default user %s", cfg
->default_principal
);
1444 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1446 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase1 not doing nothin.");
1453 waklog_phase3 (request_rec
* r
)
1457 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1458 "mod_waklog: phase 3 called");
1460 cfg
= retrieve_config(r
);
1462 if ( cfg
->protect
&& cfg
->principal
) {
1463 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase3 using user %s", cfg
->principal
);
1464 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1465 } else if ( cfg
->default_principal
) {
1466 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase3 using default user %s", cfg
->default_principal
);
1467 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1469 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase3 not doing nothin.");
1476 waklog_phase6 (request_rec
* r
)
1480 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1481 "mod_waklog: phase6 called");
1483 cfg
= retrieve_config(r
);
1485 if ( cfg
->protect
&& cfg
->principal
) {
1486 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase6 using user %s", cfg
->principal
);
1487 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1488 } else if ( cfg
->default_principal
) {
1489 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase6 using default user %s", cfg
->default_principal
);
1490 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1492 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase6 not doing nothin.");
1499 waklog_phase7 (request_rec
* r
)
1504 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1505 "mod_waklog: phase7 called");
1507 cfg
= retrieve_config (r
);
1509 if ( cfg
->protect
&& cfg
->usertokens
) {
1510 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase7 using usertokens");
1511 rc
= set_auth( r
->server
, r
, 1, NULL
, NULL
, 0);
1512 } else if ( cfg
->protect
&& cfg
->principal
) {
1513 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase7 using user %s", cfg
->principal
);
1514 rc
= set_auth( r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1515 } else if ( cfg
->default_principal
) {
1516 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase7 using default user %s", cfg
->default_principal
);
1517 rc
= set_auth( r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1528 waklog_phase9 (request_rec
* r
)
1532 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1533 "mod_waklog: phase9 called");
1535 getModConfig (cfg
, r
->server
);
1537 if ( cfg
->default_principal
) {
1538 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase9 using default user %s", cfg
->default_principal
);
1539 set_auth( r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1552 waklog_new_connection (conn_rec
* c
1561 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, c
->base_server
,
1562 "mod_waklog: new_connection called: pid: %d", getpid ());
1564 getModConfig(cfg
, c
->base_server
);
1566 if ( cfg
->default_principal
) {
1567 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, c
->base_server
, "mod_waklog: new conn setting default user %s",
1568 cfg
->default_principal
);
1569 set_auth( c
->base_server
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1582 ** Here's a quick explaination for phase0 and phase2:
1583 ** Apache does a stat() on the path between phase0 and
1584 ** phase2, and must by ACLed rl to succeed. So, at
1585 ** phase0 we acquire credentials for umweb:servers from
1586 ** a keytab, and at phase2 we must ensure we remove them.
1588 ** Failure to "unlog" would be a security risk.
1591 waklog_phase2 (request_rec
* r
)
1594 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1595 "mod_waklog: phase2 called");
1597 if (child
.token
.ticketLen
)
1599 memset (&child
.token
, 0, sizeof (struct ktc_token
));
1601 ktc_ForgetAllTokens ();
1603 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1604 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1608 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1609 "mod_waklog: phase2 returning");
1615 module MODULE_VAR_EXPORT waklog_module
= {
1616 STANDARD_MODULE_STUFF
,
1617 waklog_init
, /* module initializer */
1618 waklog_create_dir_config
, /* create per-dir config structures */
1619 waklog_merge_dir_config
, /* merge per-dir config structures */
1620 waklog_create_server_config
, /* create per-server config structures */
1621 waklog_merge_dir_config
, /* merge per-server config structures */
1622 waklog_cmds
, /* table of config file commands */
1623 NULL
, /* [#8] MIME-typed-dispatched handlers */
1624 waklog_phase1
, /* [#1] URI to filename translation */
1625 NULL
, /* [#4] validate user id from request */
1626 NULL
, /* [#5] check if the user is ok _here_ */
1627 waklog_phase3
, /* [#3] check access by host address */
1628 waklog_phase6
, /* [#6] determine MIME type */
1629 waklog_phase7
, /* [#7] pre-run fixups */
1630 waklog_phase9
, /* [#9] log a transaction */
1631 NULL
, /* [#2] header parser */
1632 waklog_child_init
, /* child_init */
1633 waklog_child_exit
, /* child_exit */
1634 waklog_phase0
/* [#0] post read-request */
1636 , NULL
, /* EAPI: add_module */
1637 NULL
, /* EAPI: remove_module */
1638 NULL
, /* EAPI: rewrite_command */
1639 waklog_new_connection
/* EAPI: new_connection */
1644 waklog_register_hooks (apr_pool_t
* p
)
1646 ap_hook_translate_name (waklog_phase1
, NULL
, NULL
, APR_HOOK_FIRST
);
1647 ap_hook_header_parser (waklog_phase2
, NULL
, NULL
, APR_HOOK_FIRST
);
1648 ap_hook_access_checker (waklog_phase3
, NULL
, NULL
, APR_HOOK_FIRST
);
1649 ap_hook_type_checker (waklog_phase6
, NULL
, NULL
, APR_HOOK_FIRST
);
1650 ap_hook_fixups (waklog_phase7
, NULL
, NULL
, APR_HOOK_FIRST
);
1651 ap_hook_log_transaction (waklog_phase9
, NULL
, NULL
, APR_HOOK_FIRST
);
1652 ap_hook_child_init (waklog_child_init
, NULL
, NULL
, APR_HOOK_FIRST
);
1653 ap_hook_post_read_request (waklog_phase0
, NULL
, NULL
, APR_HOOK_FIRST
);
1654 ap_hook_pre_connection (waklog_new_connection
, NULL
, NULL
, APR_HOOK_FIRST
);
1655 ap_hook_post_config (waklog_init_handler
, NULL
, NULL
, APR_HOOK_MIDDLE
);
1659 module AP_MODULE_DECLARE_DATA waklog_module
= {
1660 STANDARD20_MODULE_STUFF
,
1661 waklog_create_dir_config
, /* create per-dir conf structures */
1662 waklog_merge_dir_config
, /* merge per-dir conf structures */
1663 waklog_create_server_config
, /* create per-server conf structures */
1664 waklog_merge_dir_config
, /* merge per-server conf structures */
1665 waklog_cmds
, /* table of configuration directives */
1666 waklog_register_hooks
/* register hooks */