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
;
109 char *afs_cell_realm
;
117 struct ktc_token token
;
118 char clientprincipal
[MAXNAMELEN
];
119 krb5_context kcontext
;
121 struct ktc_principal server
;
122 struct ktc_principal client
;
124 } waklog_child_config
;
126 waklog_child_config child
;
128 struct tokencache_ent
{
129 char clientprincipal
[MAXNAMELEN
];
130 struct ktc_token token
;
131 struct ktc_principal client
;
132 struct ktc_principal server
;
137 #define SHARED_TABLE_SIZE 512
139 struct sharedspace_s
{
141 struct tokencache_ent sharedtokens
[SHARED_TABLE_SIZE
];
144 struct sharedspace_s
*sharedspace
= NULL
;
153 pthread_rwlock_t
*sharedlock
= NULL
;
155 rwlock_t
*sharedlock
= NULL
;
158 struct renew_ent renewtable
[SHARED_TABLE_SIZE
];
164 #define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
169 #include <sys/ioccom.h>
172 #include <afs/venus.h>
173 #include <afs/auth.h>
174 #include <afs/dirpath.h>
175 #include <afs/ptuser.h>
176 #include <rx/rxkad.h>
180 log_error (const char *file
, int line
, int level
, int status
,
181 const server_rec
* s
, const char *fmt
, ...)
187 vsnprintf (errstr
, 1024, fmt
, ap
);
191 ap_log_error (file
, line
, level
| APLOG_NOERRNO
, status
, s
, "(%d) %s", getpid(), errstr
);
193 ap_log_error (file
, line
, level
| APLOG_NOERRNO
, s
, "(%d) %s", getpid(), errstr
);
198 waklog_config
*retrieve_config(request_rec
*r
) {
203 if ( r
&& r
->main
) {
211 if ( my
&& ( cfg
= (waklog_config
*) ap_get_module_config(my
->per_dir_config
, &waklog_module
) ) ) {
214 getModConfig (cfg
, r
->server
);
221 /* set_auth -- sets the tokens of the current process to this user.
222 if "self" is set, it divines the user from the current requests' environment.
223 otherwise, it's gettng it from principal/keytab */
226 set_auth ( server_rec
*s
, request_rec
*r
, int self
, char *principal
, char *keytab
, int storeonly
) {
230 krb5_error_code kerror
= 0;
231 krb5_principal kprinc
= NULL
;
232 krb5_get_init_creds_opt kopts
;
235 struct ktc_principal server
= { "afs", "", "" };
236 struct ktc_principal client
;
237 struct ktc_token token
;
238 krb5_creds
*v5credsp
= NULL
;
239 krb5_keytab krb5kt
= NULL
;
240 char buf
[MAXNAMELEN
];
244 time_t oldest_time
= 0;
249 int cell_in_principal
;
251 int use_client_credentials
= 0;
253 char k5user
[MAXNAMELEN
];
257 k5path
= !r
? NULL
: MK_TABLE_GET( r
->subprocess_env
, "KRB5CCNAME" );
259 memset((char *) &increds
, 0, sizeof(increds
));
260 /* init some stuff if it ain't already */
262 if ( ! child
.kcontext
) {
263 kerror
= krb5_init_context(&child
.kcontext
);
266 if (!k5path
|| !*k5path
) {
267 k5path
= "MEMORY:tmpcache";
269 if ( ( ! child
.ccache
) && ( kerror
= krb5_cc_resolve(child
.kcontext
, k5path
, &child
.ccache
) ) ) {
270 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't initialize credentials cache %s err=%d",
274 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: set_auth: %d, %s, %s, %d, KRB5CC=%s user=%s",
275 self
, principal
? principal
: "NULL",
276 keytab
? keytab
: "NULL",
278 k5path
? k5path
: "NULL",
280 (r
&& r
->user
) ? r
->user
: "NULL"
286 /* pull the server config record that we care about... */
289 cfg
= retrieve_config(r
);
291 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
292 "mod_waklog: set_auth using no config" );
293 getModConfig (cfg
, s
);
297 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: cfg is %d", cfg
);
302 /* pull out our principal name and stuff from the environment -- webauth better have sent
303 through. This here is also where you'd suck stuff out of KRB5CCNAME if we were
304 using something like Cosign */
306 if ( ! ( r
&& r
->connection
&& r
->user
)) {
307 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: self authentication selected, but no data available");
308 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: r->user=%s", (r
->user
==NULL
? "null" : r
->user
==NULL
));
312 strncpy(k5user
, r
->user
, sizeof(k5user
));
314 /* the other thing we need is someone's password */
315 if ( ! ( k5secret
= (char *) MK_TABLE_GET( r
->notes
, "ATTR_PASSWORD" ) ) ) {
316 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cant do self auth without a secret");
320 /* we'll pick this up later after we've checked the cache and current state */
323 if (r
&& r
->user
&& !principal
) {
324 strncpy(k5user
, r
->user
, sizeof(k5user
));
329 strncpy( k5user
, principal
, sizeof(k5user
));
332 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: set_auth: k5user=%s", k5user
? k5user
: "NULL");
335 /* see if we should just go ahead and ignore this call, since we already should be set to these
341 pthread_rwlock_rdlock( sharedlock
);
343 rw_rdlock( sharedlock
);
346 for ( i
= 0; i
< SHARED_TABLE_SIZE
; ++i
) {
348 /* if it's a token for the principal we're looking for, and it hasn't expired yet */
350 if ( ( !strcmp( k5user
,
351 sharedspace
->sharedtokens
[i
].clientprincipal
) ) &&
352 ( sharedspace
->sharedtokens
[i
].token
.endTime
> mytime
) ) {
354 if ( ! memcmp(&child
.token
, &sharedspace
->sharedtokens
[i
].token
, sizeof(child
.token
) ) ) {
360 /* copy the token out of the cache and into the child object */
362 strcpy(child
.clientprincipal
, sharedspace
->sharedtokens
[i
].clientprincipal
);
363 memcpy(&child
.token
, &sharedspace
->sharedtokens
[i
].token
, sizeof(child
.token
));
364 memcpy(&child
.server
, &sharedspace
->sharedtokens
[i
].server
, sizeof(child
.server
));
365 memcpy(&child
.client
, &sharedspace
->sharedtokens
[i
].client
, sizeof(child
.client
));
367 /* set our last used time thing */
368 sharedspace
->sharedtokens
[i
].lastused
= mytime
;
378 /* release the lock on the token cache */
380 pthread_rwlock_unlock( sharedlock
);
382 rw_unlock( sharedlock
);
386 /* release the lock on the token cache */
387 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
,
388 "mod_waklog: set_auth using shared token %d for %s", i
, k5user
);
392 /* if this is something that was in the cache, and it's the same as the token we already have stored,
393 and we weren't calling this just to renew it... */
395 if ( usecached
&& indentical
) {
396 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: token is identical for %s", k5user
);
402 /* if 'usecached' isn't set, we've got to get our tokens from somewhere... */
403 if (( ! usecached
) && ( k5user
)) {
405 /* clear out the creds structure */
406 memset((void *) &v5creds
, 0, sizeof(v5creds
));
408 /* create a principal out of our k5user string */
410 if ( kerror
= krb5_parse_name (child
.kcontext
, k5user
, &kprinc
) ) {
411 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_parse_name %s", (char *) error_message(kerror
) );
415 /* create the credentials options */
417 krb5_get_init_creds_opt_init ( &kopts
);
418 krb5_get_init_creds_opt_set_tkt_life ( &kopts
, TKT_LIFE
);
419 krb5_get_init_creds_opt_set_renew_life ( &kopts
, 0 );
420 krb5_get_init_creds_opt_set_forwardable ( &kopts
, 0 );
421 krb5_get_init_creds_opt_set_proxiable ( &kopts
, 0 );
425 /* if we've been passed a keytab, we're going to be getting our credentials from it */
427 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: using keytab %s", keytab
);
429 if ( kerror
= krb5_kt_resolve(child
.kcontext
, keytab
, &krb5kt
) ) {
430 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
,
431 "mod_waklog: krb5_kt_resolve %s", error_message(kerror
) );
435 if ((kerror
= krb5_get_init_creds_keytab (child
.kcontext
, &v5creds
,
436 kprinc
, krb5kt
, 0, NULL
, &kopts
) ) ) {
437 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_get_init_creds_keytab %s",
438 error_message(kerror
) );
444 /* if 'self' is set, we're going to use the credentials provided in the credential information */
445 /* if you're using CoSign, you'd actually just set the ccache to the KRB5CCNAME credentials */
446 /* and skip ahead... Our WebSSO is lame, but has a way for us to snarf the password out of */
447 /* the encrypted token for proxy-authentication stuff. We only hand out keys that allow this */
448 /* functionality to VERY special people. */
450 if ((kerror
= krb5_get_init_creds_password ( child
.kcontext
, &v5creds
,
451 kprinc
, k5secret
, NULL
, NULL
, 0, NULL
, &kopts
) ) ) {
452 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_get_init_creds_password %s",
453 error_message(kerror
) );
454 /* nuke the password so it doesn't end up in core files */
455 memset(k5secret
, 0, sizeof(k5secret
));
459 memset(k5secret
, 0, sizeof(k5secret
));
462 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: no keytab, no self; assuming mod_auth_kerb or similar");
463 use_client_credentials
= 1;
466 /* initialize the credentials cache and store the stuff we just got */
467 if (!use_client_credentials
) {
468 if ( kerror
= krb5_cc_initialize (child
.kcontext
, child
.ccache
, kprinc
)) {
469 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: init credentials cache %s",
470 error_message(kerror
));
474 if ( kerror
= krb5_cc_store_cred(child
.kcontext
, child
.ccache
, &v5creds
) ) {
475 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot store credentials %s",
476 error_message(kerror
));
481 krb5_free_cred_contents(child
.kcontext
, &v5creds
);
484 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: store cred %s", error_message(kerror
));
488 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: kinit ok for %s", k5user
);
490 /* now, to the 'aklog' portion of our program. */
492 /** we make two attempts here, one for afs@REALM and one for afs/cell@REALM */
493 for(attempt
= 0; attempt
<= 1; attempt
++) {
494 strncpy( buf
, "afs", sizeof(buf
) - 1 );
495 cell_in_principal
= (cfg
->cell_in_principal
+ attempt
) % 2;
497 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: cell_in_principal=%d", cell_in_principal
);
498 if (cell_in_principal
) {
499 strncat(buf
, "/", sizeof(buf
) - strlen(buf
) - 1);
500 strncat(buf
, cfg
->afs_cell
, sizeof(buf
) - strlen(buf
) - 1);
502 if (cfg
->afs_cell_realm
!= WAKLOG_UNSET
) {
503 strncat(buf
, "@", sizeof(buf
) - strlen(buf
) - 1);
504 strncat(buf
, cfg
->afs_cell_realm
, sizeof(buf
) - strlen(buf
) - 1);
507 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: using AFS principal: %s", buf
);
509 if ((kerror
= krb5_parse_name (child
.kcontext
, buf
, &increds
.server
))) {
510 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_parse name %s", error_message(kerror
));
514 if (use_client_credentials
) {
515 if (( kerror
= krb5_cc_resolve( child
.kcontext
, k5path
, &child
.ccache
)) != 0 ) {
516 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_cc_resolve %s", error_message(kerror
));
521 if ((kerror
= krb5_cc_get_principal(child
.kcontext
, child
.ccache
, &increds
.client
))) {
522 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_cc_get_princ %s", error_message(kerror
));
526 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: retrieved data from ccache for %s", k5user
);
528 increds
.times
.endtime
= 0;
530 increds
.keyblock
.enctype
= ENCTYPE_DES_CBC_CRC
;
532 if (kerror
= krb5_get_credentials (child
.kcontext
, 0, child
.ccache
, &increds
, &v5credsp
)) {
533 /* only complain once we've tried both afs@REALM and afs/cell@REALM */
535 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: krb5_get_credentials: %s",
536 error_message(kerror
));
542 cfg
->cell_in_principal
= cell_in_principal
;
546 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: get_credentials passed for %s", k5user
);
548 if ( v5credsp
->ticket
.length
>= MAXKTCTICKETLEN
) {
549 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: ticket size (%d) too big to fake",
550 v5credsp
->ticket
.length
);
554 memset(&token
, 0, sizeof(struct ktc_token
));
556 token
.startTime
= v5credsp
->times
.starttime
? v5credsp
->times
.starttime
: v5credsp
->times
.authtime
;
557 token
.endTime
= v5credsp
->times
.endtime
;
559 memmove( &token
.sessionKey
, v5credsp
->keyblock
.contents
, v5credsp
->keyblock
.length
);
560 token
.kvno
= RXKAD_TKT_TYPE_KERBEROS_V5
;
561 token
.ticketLen
= v5credsp
->ticket
.length
;
562 memmove( token
.ticket
, v5credsp
->ticket
.data
, token
.ticketLen
);
566 memmove( buf
, v5credsp
->client
->data
[0].data
, min(v5credsp
->client
->data
[0].length
,
568 buf
[v5credsp
->client
->data
[0].length
] = '\0';
569 if ( v5credsp
->client
->length
> 1 ) {
570 strncat(buf
, ".", sizeof(buf
) - strlen(buf
) - 1);
571 buflen
= strlen(buf
);
572 memmove(buf
+ buflen
, v5credsp
->client
->data
[1].data
,
573 min(v5credsp
->client
->data
[1].length
,
574 MAXKTCNAMELEN
- strlen(buf
) - 1));
575 buf
[buflen
+ v5credsp
->client
->data
[1].length
] = '\0';
578 /* assemble the client */
579 strncpy(client
.name
, buf
, sizeof(client
.name
) - 1 );
580 strncpy(client
.instance
, "", sizeof(client
.instance
) - 1 );
581 memmove(buf
, v5credsp
->client
->realm
.data
, min(v5credsp
->client
->realm
.length
,
583 buf
[v5credsp
->client
->realm
.length
] = '\0';
584 strncpy(client
.cell
, buf
, sizeof(client
.cell
));
586 /* assemble the server's cell */
587 strncpy(server
.cell
, cfg
->afs_cell
, sizeof(server
.cell
) - 1);
589 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: preparing to init PTS connection for %s", server
.cell
);
591 /* fill out the AFS ID in the client name */
592 /* we've done a pr_Initialize in the child_init -- once, per process. If you try to do it more
593 * strange things seem to happen. */
596 afs_int32 viceId
= 0;
598 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: making PTS call to look up %s", client
.name
);
600 if ( ( rc
= pr_SNameToId( client
.name
, &viceId
) ) == 0 ) {
601 snprintf( client
.name
, sizeof(client
.name
), "AFS ID %d", viceId
);
603 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: PTS call returned error %d ", rc
);
606 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: PTS call returned %s ", client
.name
);
610 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: server: name %s, instance %s, cell %s",
611 server
.name
, server
.instance
, server
.cell
);
613 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: client: name %s, instance %s, cell %s",
614 client
.name
, client
.instance
, client
.cell
);
616 /* copy the resulting stuff into the child structure */
618 strncpy(child
.clientprincipal
, k5user
, sizeof(child
.clientprincipal
));
619 memcpy(&child
.token
, &token
, sizeof(child
.token
));
620 memcpy(&child
.server
, &server
, sizeof(child
.server
));
621 memcpy(&child
.client
, &client
, sizeof(child
.client
));
623 /* stuff the resulting token-related stuff into our shared token cache */
624 /* note, that anything that was set from a keytab is "persistant", and is immune
625 * from LRU-aging. This is because nothing but the process that's running as root
626 * can update these, and it's running every hour or so and renewing these tokens.
627 * and we don't want them aged out.
630 mytime
= oldest_time
= time(0);
632 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: waiting for shared space for %s ", k5user
);
635 pthread_rwlock_wrlock(sharedlock
);
637 rw_wrlock(sharedlock
);
640 for( i
= ( SHARED_TABLE_SIZE
- 1 ); i
>= 0; i
-- ) {
641 if ( ( sharedspace
->sharedtokens
[i
].lastused
<= oldest_time
) &&
642 ( sharedspace
->sharedtokens
[i
].persist
== 0 ) ) {
644 oldest_time
= sharedspace
->sharedtokens
[i
].lastused
;
646 if ( ! strcmp ( sharedspace
->sharedtokens
[i
].clientprincipal
,
647 child
.clientprincipal
) ) {
648 memcpy(&sharedspace
->sharedtokens
[i
].token
, &child
.token
, sizeof(child
.token
) );
649 memcpy(&sharedspace
->sharedtokens
[i
].client
, &child
.client
, sizeof(child
.client
) );
650 memcpy(&sharedspace
->sharedtokens
[i
].server
, &child
.server
, sizeof(child
.server
) );
651 sharedspace
->sharedtokens
[i
].lastused
= mytime
;
652 sharedspace
->sharedtokens
[i
].persist
= keytab
? 1 : 0;
658 if ( stored
== -1 ) {
659 memcpy(&sharedspace
->sharedtokens
[oldest
].token
, &child
.token
, sizeof(child
.token
) );
660 memcpy(&sharedspace
->sharedtokens
[oldest
].client
, &child
.client
, sizeof(child
.client
) );
661 memcpy(&sharedspace
->sharedtokens
[oldest
].server
, &child
.server
, sizeof(child
.server
) );
662 strcpy(sharedspace
->sharedtokens
[oldest
].clientprincipal
, child
.clientprincipal
);
663 sharedspace
->sharedtokens
[oldest
].lastused
= mytime
;
664 sharedspace
->sharedtokens
[oldest
].persist
= keytab
? 1 : 0;
669 pthread_rwlock_unlock(sharedlock
);
671 rw_unlock(sharedlock
);
674 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: token stored in slot %d for %s", stored
,
675 child
.clientprincipal
);
677 } else if ( ! usecached
) {
678 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: set_auth divergent case");
687 /* don't ask. Something about AIX. We're leaving it here.*/
688 /* write(2, "", 0); */
690 /* we try twice, because sometimes the first one fails. Dunno why, but it always works the second time */
692 if ((rc
= ktc_SetToken(&child
.server
, &child
.token
, &child
.client
, 0))) {
693 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: settoken returned %s for %s -- trying again",
694 error_message(rc
), k5user
);
695 if ((rc
= ktc_SetToken(&child
.server
, &child
.token
, &child
.client
, 0))) {
696 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: settoken2 returned %s for %s",
697 error_message(rc
), k5user
);
704 krb5_free_cred_contents(child
.kcontext
, v5credsp
);
705 if ( increds
.client
)
706 krb5_free_principal (child
.kcontext
, increds
.client
);
707 if ( increds
.server
)
708 krb5_free_principal (child
.kcontext
, increds
.server
);
710 (void) krb5_kt_close(child
.kcontext
, krb5kt
);
712 krb5_free_principal (child
.kcontext
, kprinc
);
715 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: set_auth ending with %d", rc
);
716 } else if ( kerror
) {
717 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror
, error_message(kerror
));
719 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: set_auth ending ok");
722 return kerror
? (int) kerror
: (int) rc
;
729 waklog_create_server_config (MK_POOL
* p
, server_rec
* s
)
733 cfg
= (waklog_config
*) ap_pcalloc (p
, sizeof (waklog_config
));
735 memset(cfg
, 0, sizeof(waklog_config
));
736 cfg
->path
= "(server)";
737 cfg
->protect
= WAKLOG_UNSET
;
738 cfg
->usertokens
= WAKLOG_UNSET
;
739 cfg
->disable_token_cache
= WAKLOG_UNSET
;
740 cfg
->keytab
= WAKLOG_UNSET
;
741 cfg
->principal
= WAKLOG_UNSET
;
742 cfg
->default_principal
= WAKLOG_UNSET
;
743 cfg
->default_keytab
= WAKLOG_UNSET
;
744 cfg
->afs_cell
= WAKLOG_UNSET
;
745 cfg
->afs_cell_realm
= WAKLOG_UNSET
;
749 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
750 "mod_waklog: server config created.");
755 /* initialize with host-config information */
758 waklog_create_dir_config (MK_POOL
* p
, char *dir
)
762 cfg
= (waklog_config
*) ap_pcalloc (p
, sizeof (waklog_config
));
763 memset(cfg
, 0, sizeof(waklog_config
));
765 cfg
->path
= ap_pstrdup(p
, dir
);
766 cfg
->protect
= WAKLOG_UNSET
;
767 cfg
->usertokens
= WAKLOG_UNSET
;
768 cfg
->disable_token_cache
= WAKLOG_UNSET
;
769 cfg
->keytab
= WAKLOG_UNSET
;
770 cfg
->principal
= WAKLOG_UNSET
;
771 cfg
->default_principal
= WAKLOG_UNSET
;
772 cfg
->default_keytab
= WAKLOG_UNSET
;
773 cfg
->afs_cell
= WAKLOG_UNSET
;
774 cfg
->afs_cell_realm
= WAKLOG_UNSET
;
781 static void *waklog_merge_dir_config(MK_POOL
*p
, void *parent_conf
, void *newloc_conf
) {
783 waklog_config
*merged
= ( waklog_config
* ) ap_pcalloc(p
, sizeof(waklog_config
) );
784 waklog_config
*parent
= ( waklog_config
* ) parent_conf
;
785 waklog_config
*child
= ( waklog_config
* ) newloc_conf
;
787 merged
->protect
= child
->protect
!= WAKLOG_UNSET
? child
->protect
: parent
->protect
;
789 merged
->path
= child
->path
!= WAKLOG_UNSET
? child
->path
: parent
->path
;
791 merged
->usertokens
= child
->usertokens
!= WAKLOG_UNSET
? child
->usertokens
: parent
->usertokens
;
793 merged
->disable_token_cache
= child
->disable_token_cache
!= WAKLOG_UNSET
? child
->disable_token_cache
: parent
->disable_token_cache
;
795 merged
->principal
= child
->principal
!= WAKLOG_UNSET
? child
->principal
: parent
->principal
;
797 merged
->keytab
= child
->keytab
!= WAKLOG_UNSET
? child
->keytab
: parent
->keytab
;
799 merged
->default_keytab
= child
->default_keytab
!= WAKLOG_UNSET
? child
->default_keytab
: parent
->default_keytab
;
801 merged
->default_principal
= child
->default_principal
!= WAKLOG_UNSET
? child
->default_principal
: parent
->default_principal
;
803 merged
->afs_cell
= child
->afs_cell
!= WAKLOG_UNSET
? child
->afs_cell
: parent
->afs_cell
;
805 merged
->afs_cell_realm
= child
->afs_cell_realm
!= WAKLOG_UNSET
? child
->afs_cell_realm
: parent
->afs_cell_realm
;
807 return (void *) merged
;
811 static void *waklog_merge_server_config(MK_POOL
*p
, void *parent_conf
, void *newloc_conf
) {
813 waklog_config
*merged
= ( waklog_config
* ) ap_pcalloc(p
, sizeof(waklog_config
) );
814 waklog_config
*pconf
= ( waklog_config
* ) parent_conf
;
815 waklog_config
*nconf
= ( waklog_config
* ) newloc_conf
;
817 merged
->protect
= nconf
->protect
== WAKLOG_UNSET
? pconf
->protect
: nconf
->protect
;
819 merged
->usertokens
= nconf
->usertokens
== WAKLOG_UNSET
? pconf
->usertokens
: nconf
->usertokens
;
821 merged
->disable_token_cache
= nconf
->disable_token_cache
== WAKLOG_UNSET
? pconf
->disable_token_cache
: nconf
->disable_token_cache
;
823 merged
->keytab
= nconf
->keytab
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->keytab
) :
824 ( nconf
->keytab
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->keytab
) );
826 merged
->principal
= nconf
->principal
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->principal
) :
827 ( nconf
->principal
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->principal
) );
829 merged
->afs_cell
= nconf
->afs_cell
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->afs_cell
) :
830 ( nconf
->afs_cell
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->afs_cell
) );
832 merged
->afs_cell_realm
= nconf
->afs_cell_realm
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->afs_cell_realm
) :
833 ( nconf
->afs_cell_realm
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->afs_cell_realm
) );
835 merged
->default_keytab
= nconf
->default_keytab
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->default_keytab
) :
836 ( nconf
->default_keytab
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->default_keytab
) );
838 merged
->default_principal
= nconf
->default_principal
== WAKLOG_UNSET
? ap_pstrdup(p
, pconf
->default_principal
) :
839 ( nconf
->default_principal
== WAKLOG_UNSET
? WAKLOG_UNSET
: ap_pstrdup(p
, pconf
->default_principal
) );
842 return (void *) merged
;
847 set_waklog_enabled (cmd_parms
* params
, void *mconfig
, int flag
)
849 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
850 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
854 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
855 "mod_waklog: waklog_enabled set on %s", cfg
->path
? cfg
->path
: "NULL");
860 /* this adds a principal/keytab pair to get their tokens renewed by the
861 child process every few centons. */
863 void add_to_renewtable(MK_POOL
*p
, char *keytab
, char *principal
) {
867 if ( renewcount
>= SHARED_TABLE_SIZE
) {
868 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, NULL
, "mod_waklog: big problem. Increase the SHARED_TABLE_SIZE or \
869 decrease your tokens.");
873 /* check to see if it's already there */
875 for ( i
= 0; i
< renewcount
; i
++ ) {
876 if ( ! strcmp(renewtable
[i
].principal
, principal
) ) {
881 renewtable
[renewcount
].keytab
= ap_pstrdup(p
, keytab
);
882 renewtable
[renewcount
].principal
= ap_pstrdup(p
, principal
);
883 renewtable
[renewcount
].lastrenewed
= 0;
889 set_waklog_location_principal (cmd_parms
*params
, void *mconfig
, char *principal
, char *keytab
)
891 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
892 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
894 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
895 "mod_waklog: configuring principal: %s, keytab: %s", principal
, keytab
);
897 cfg
->principal
= ap_pstrdup(params
->pool
, principal
);
898 cfg
->keytab
= ap_pstrdup (params
->pool
, keytab
);
900 add_to_renewtable(params
->pool
, keytab
, principal
);
908 set_waklog_afs_cell (cmd_parms
* params
, void *mconfig
, char *file
)
910 waklog_config
*waklog_mconfig
= ( waklog_config
* ) mconfig
;
911 waklog_config
*waklog_srvconfig
=
912 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
914 log_error (APLOG_MARK
, APLOG_INFO
, 0, params
->server
,
915 "mod_waklog: will use afs_cell: %s", file
);
917 waklog_srvconfig
->cell_in_principal
= 0;
918 waklog_srvconfig
->afs_cell
= ap_pstrdup (params
->pool
, file
);
919 waklog_srvconfig
->configured
= 1;
921 if (waklog_mconfig
!= NULL
) {
922 waklog_mconfig
->cell_in_principal
= waklog_srvconfig
->cell_in_principal
;
923 waklog_mconfig
->afs_cell
= ap_pstrdup (params
->pool
, file
);
924 waklog_mconfig
->configured
= 1;
930 set_waklog_afs_cell_realm (cmd_parms
* params
, void *mconfig
, char *file
)
932 waklog_config
*waklog_mconfig
= ( waklog_config
* ) mconfig
;
933 waklog_config
*waklog_srvconfig
=
934 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
936 log_error (APLOG_MARK
, APLOG_INFO
, 0, params
->server
,
937 "mod_waklog: will use afs_cell_realm: %s", file
);
939 waklog_srvconfig
->afs_cell_realm
= ap_pstrdup (params
->pool
, file
);
941 if (waklog_mconfig
!= NULL
) {
942 waklog_mconfig
->afs_cell_realm
= ap_pstrdup (params
->pool
, file
);
948 set_waklog_default_principal (cmd_parms
* params
, void *mconfig
, char *principal
, char *keytab
)
950 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
951 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
953 waklog_config
*srvcfg
= ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
955 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
956 "mod_waklog: set default princ/keytab: %s, %s for %s", principal
, keytab
, cfg
->path
? cfg
->path
: "NULL");
958 cfg
->default_principal
= ap_pstrdup (params
->pool
, principal
);
959 cfg
->default_keytab
= ap_pstrdup(params
->pool
, keytab
);
961 /* this also gets set at the server level */
962 if ( mconfig
&& ( ! cfg
->path
) ) {
963 srvcfg
->default_principal
= ap_pstrdup (params
->pool
, principal
);
964 srvcfg
->default_keytab
= ap_pstrdup(params
->pool
, keytab
);
966 log_error(APLOG_MARK
, APLOG_ERR
, 0, params
->server
, "only able to set default principal on a global level!");
967 return "Unable to set DefaultPrincipal outside of top level config!";
970 add_to_renewtable( params
->pool
, keytab
, principal
);
978 set_waklog_use_usertokens (cmd_parms
* params
, void *mconfig
, int flag
)
980 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
981 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
983 cfg
->usertokens
= flag
;
987 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
988 "mod_waklog: waklog_use_user_tokens set");
994 set_waklog_disable_token_cache (cmd_parms
* params
, void *mconfig
, int flag
)
996 waklog_config
*cfg
= mconfig
? ( waklog_config
* ) mconfig
:
997 ( waklog_config
* ) ap_get_module_config(params
->server
->module_config
, &waklog_module
);
999 cfg
->disable_token_cache
= flag
;
1001 cfg
->configured
= 1;
1003 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, params
->server
,
1004 "mod_waklog: waklog_disable_token_cache set");
1010 static void waklog_child_exit( server_rec
*s
, MK_POOL
*p
) {
1012 apr_status_t
waklog_child_exit( void *sr
) {
1014 server_rec
*s
= (server_rec
*) sr
;
1017 if ( child
.ccache
) {
1018 krb5_cc_close(child
.kcontext
, child
.ccache
);
1021 if ( child
.kcontext
) {
1022 krb5_free_context(child
.kcontext
);
1025 /* forget our tokens */
1027 ktc_ForgetAllTokens ();
1029 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1030 "mod_waklog: waklog_child_exit complete");
1040 waklog_child_init (MK_POOL
* p
, server_rec
* s
)
1042 waklog_child_init (server_rec
* s
, MK_POOL
* p
)
1046 krb5_error_code code
;
1051 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: child_init called for pid %d", getpid());
1053 if ( !sharedspace
) {
1054 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: child_init called without shared space? %d", getpid());
1058 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: child_init called for pid %d", getpid());
1060 memset (&child
, 0, sizeof(child
));
1062 if ( code
= krb5_init_context(&child
.kcontext
) ) {
1063 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't init kerberos context %d", code
);
1066 if ( code
= krb5_cc_resolve(child
.kcontext
, "MEMORY:tmpcache", &child
.ccache
) ) {
1067 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't initialize in-memory credentials cache %d", code
);
1070 if ( pag_for_children
) {
1074 getModConfig (cfg
, s
);
1076 if ( cfg
->default_principal
!= WAKLOG_UNSET
) {
1077 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: child_init setting default user %s, %s", cfg
->default_principal
, cfg
->default_keytab
);
1078 set_auth( s
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1081 cell
= strdup(cfg
->afs_cell
);
1082 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR
, cell
);
1085 apr_pool_cleanup_register(p
, s
, waklog_child_exit
, apr_pool_cleanup_null
);
1088 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1089 "mod_waklog: child_init returned");
1094 command_rec waklog_cmds
[] = {
1096 command ("WaklogAFSCell", set_waklog_afs_cell
, 0, TAKE1
,
1097 "Use the supplied AFS cell (required)"),
1099 command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm
, 0, TAKE1
,
1100 "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
1102 command ("WaklogEnabled", set_waklog_enabled
, 0, FLAG
,
1103 "enable waklog on a server, location, or directory basis"),
1105 command ("WaklogDefaultPrincipal", set_waklog_default_principal
, 0, TAKE2
,
1106 "Set the default principal that the server runs as"),
1108 command ("WaklogLocationPrincipal", set_waklog_location_principal
, 0, TAKE2
,
1109 "Set the principal on a <Location>-specific basis"),
1111 command ("WaklogDisableTokenCache", set_waklog_disable_token_cache
, 0, FLAG
,
1112 "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
1114 command ("WaklogUseUserTokens", set_waklog_use_usertokens
, 0, FLAG
,
1115 "Use the requesting user tokens (from webauth)"),
1121 /* not currently using this */
1124 token_cleanup (void *data
)
1126 request_rec
*r
= (request_rec
*) data
;
1128 if (child
.token
.ticketLen
)
1130 memset (&child
.token
, 0, sizeof (struct ktc_token
));
1132 ktc_ForgetAllTokens ();
1134 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1135 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1142 waklog_child_routine (void *data
, child_info
* pinfo
)
1145 server_rec
*s
= (server_rec
*) data
;
1146 krb5_error_code code
;
1148 time_t sleep_time
= ( TKT_LIFE
/ 2 ) ;
1153 getModConfig( cfg
, s
);
1155 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: waklog_child_routine started, running as %d", getuid());
1157 memset (&child
, 0, sizeof(child
));
1159 if ( code
= krb5_init_context(&child
.kcontext
) ) {
1160 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't init kerberos context %d", code
);
1163 if ( code
= krb5_cc_resolve(child
.kcontext
, "MEMORY:tmpcache", &child
.ccache
) ) {
1164 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: can't initialize in-memory credentials cache %d", code
);
1167 /* need to do this so we can make PTS calls */
1168 cell
= strdup(cfg
->afs_cell
); /* stupid */
1169 pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR
, cell
);
1173 for ( i
= 0; i
< renewcount
; ++i
) {
1174 renewtable
[i
].lastrenewed
= time(0);
1175 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: (pid %d) renewing %s / %s", getpid(), renewtable
[i
].principal
,
1176 renewtable
[i
].keytab
);
1178 set_auth( s
, NULL
, 0, renewtable
[i
].principal
, renewtable
[i
].keytab
, 1 );
1180 /* if this is our default token, we want to "stash" it in our current PAG so the parent maintains readability of
1181 things that it needs to read */
1183 if ( cfg
&& cfg
->default_principal
&& ( ! strcmp(cfg
->default_principal
, renewtable
[i
].principal
) ) ) {
1184 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: renewing/setting default tokens" );
1185 set_auth( s
, NULL
, 0, renewtable
[i
].principal
, renewtable
[i
].keytab
, 0 );
1190 sharedspace
->renewcount
++;
1199 left
-= ( time(0) - when
);
1210 waklog_init_handler (apr_pool_t
* p
, apr_pool_t
* plog
,
1211 apr_pool_t
* ptemp
, server_rec
* s
)
1214 extern char *version
;
1219 int use_existing
= 1;
1221 char cache_file
[MAXNAMELEN
];
1223 pthread_rwlockattr_t rwlock_attr
;
1227 getModConfig (cfg
, s
);
1229 /* initialize_module() will be called twice, and if it's a DSO
1230 * then all static data from the first call will be lost. Only
1231 * set up our static data on the second call.
1232 * see http://issues.apache.org/bugzilla/show_bug.cgi?id=37519 */
1233 apr_pool_userdata_get (&data
, userdata_key
, s
->process
->pool
);
1236 if (cfg
->afs_cell
==NULL
) {
1237 log_error (APLOG_MARK
, APLOG_ERR
, 0, s
,
1238 "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
1239 /** clobber apache */
1245 apr_pool_userdata_set ((const void *) 1, userdata_key
,
1246 apr_pool_cleanup_null
, s
->process
->pool
);
1250 log_error (APLOG_MARK
, APLOG_INFO
, 0, s
,
1251 "mod_waklog: version %s initialized for cell %s", version
, cfg
->afs_cell
);
1253 if ( sharedspace
) {
1254 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: shared memory already allocated." );
1257 snprintf( cache_file
, MAXNAMELEN
, "/tmp/waklog_cache.%d", getpid() );
1259 if ( ( fd
= open( cache_file
, O_RDWR
, 0600 ) ) == -1 ) {
1261 if ( errno
== ENOENT
) {
1263 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: creating shared token cache file %s", cache_file
);
1265 if ( ( fd
= open( cache_file
, O_RDWR
|O_CREAT
|O_TRUNC
, 0600 ) ) == -1 ) {
1266 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file
, errno
);
1270 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file
, errno
);
1274 if ( use_existing
== 0 ) {
1275 struct sharedspace_s bob
;
1276 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: sizing our cache file %d to %d", fd
, sizeof(struct sharedspace_s
) );
1277 memset( &bob
, 0, sizeof(struct sharedspace_s
));
1278 write(fd
, &bob
, sizeof(struct sharedspace_s
));
1279 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s
) );
1282 /* mmap the region */
1284 if ( ( sharedspace
= (struct sharedspace_s
*) mmap ( NULL
, sizeof(struct sharedspace_s
), PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0 ) ) != MAP_FAILED
) {
1285 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: shared mmap region ok %d", sharedspace
);
1288 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: mmap failed %d", errno
);
1294 #define locktype pthread_rwlock_t
1296 #define locktype rwlock_t
1299 if ( sharedlock
= ( locktype
* ) mmap ( NULL
, sizeof(locktype
), PROT_READ
|PROT_WRITE
, MAP_SHARED
|MAP_ANON
, -1, 0 ) ) {
1300 #ifndef use_pthreads
1301 rwlock_init(sharedlock
, USYNC_PROCESS
, NULL
);
1303 pthread_rwlockattr_init(&rwlock_attr
);
1304 pthread_rwlockattr_setpshared(&rwlock_attr
, PTHREAD_PROCESS_SHARED
);
1305 pthread_rwlock_init(sharedlock
, &rwlock_attr
);
1308 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: rwlock mmap failed %d", errno
);
1313 /* set our default tokens */
1315 oldrenewcount
= sharedspace
->renewcount
;
1317 pag_for_children
= 0;
1319 proc
= (apr_proc_t
*) ap_pcalloc (s
->process
->pool
, sizeof (apr_proc_t
));
1321 rv
= apr_proc_fork (proc
, s
->process
->pool
);
1323 if (rv
== APR_INCHILD
)
1325 waklog_child_routine (s
, NULL
);
1329 apr_pool_note_subprocess (s
->process
->pool
, proc
, APR_KILL_ALWAYS
);
1331 /* parent and child */
1332 cfg
->forked
= proc
->pid
;
1333 pag_for_children
= 1;
1335 if ( use_existing
== 0 ) {
1336 /* wait here until our child process has gone and done it's renewing thing. */
1337 while( sharedspace
->renewcount
== oldrenewcount
) {
1338 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: waiting for tokens..." );
1343 if ( cfg
->default_principal
) {
1344 set_auth( s
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1351 waklog_init (server_rec
* s
, MK_POOL
* p
)
1353 extern char *version
;
1358 int use_existing
= 1;
1360 char cache_file
[MAXNAMELEN
];
1362 pthread_rwlockattr_t rwlock_attr
;
1365 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1366 "mod_waklog: version %s initialized.", version
);
1368 if ( sharedspace
) {
1369 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: shared memory already allocated." );
1372 snprintf( cache_file
, MAXNAMELEN
, "/tmp/waklog_cache.%d", getpid() );
1374 if ( ( fd
= open( cache_file
, O_RDWR
, 0600 ) ) == -1 ) {
1376 if ( errno
== ENOENT
) {
1378 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: creating shared token cache file %s", cache_file
);
1380 if ( ( fd
= open( cache_file
, O_RDWR
|O_CREAT
|O_TRUNC
, 0600 ) ) == -1 ) {
1381 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot create shared token cache file %s (%d)", cache_file
, errno
);
1385 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: cannot open existing shared token cache file %s (%d)", cache_file
, errno
);
1390 if ( use_existing
== 0 ) {
1391 struct sharedspace_s bob
;
1392 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: sizing our cache file %d to %d", fd
, sizeof(struct sharedspace_s
) );
1393 memset( &bob
, 0, sizeof(struct sharedspace_s
));
1394 write(fd
, &bob
, sizeof(struct sharedspace_s
));
1395 log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s
) );
1398 /* mmap the region */
1400 if ( ( sharedspace
= (struct sharedspace_s
*) mmap ( NULL
, sizeof(struct sharedspace_s
), PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, 0 ) ) != -1 ) {
1401 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: shared mmap region ok %d", sharedspace
);
1404 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: mmap failed %d", errno
);
1410 #define locktype pthread_rwlock_t
1412 #define locktype rwlock_t
1415 /* mmap our shared space for our lock */
1416 if ( sharedlock
= ( locktype
* ) mmap ( NULL
, sizeof(locktype
), PROT_READ
|PROT_WRITE
, MAP_SHARED
|MAP_ANON
, -1, 0 ) ) {
1417 #ifndef use_pthreads
1418 rwlock_init(sharedlock
, USYNC_PROCESS
, NULL
);
1420 pthread_rwlockattr_init(&rwlock_attr
);
1421 pthread_rwlockattr_setpshared(&rwlock_attr
, PTHREAD_PROCESS_SHARED
);
1422 pthread_rwlock_init(sharedlock
, &rwlock_attr
);
1425 log_error( APLOG_MARK
, APLOG_DEBUG
, 0, s
, "mod_waklog: rwlock mmap failed %d", errno
);
1430 /* set our default tokens */
1432 getModConfig (cfg
, s
);
1434 oldrenewcount
= sharedspace
->renewcount
;
1436 pag_for_children
= 0;
1438 pid
= ap_bspawn_child (p
, waklog_child_routine
, s
, kill_always
,
1441 pag_for_children
= 1;
1443 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, s
,
1444 "mod_waklog: ap_bspawn_child: %d.", pid
);
1446 if ( use_existing
== 0 ) {
1447 /* wait here until our child process has gone and done it's renewing thing. */
1448 while( sharedspace
->renewcount
== oldrenewcount
) {
1449 log_error( APLOG_MARK
, APLOG_ERR
, 0, s
, "mod_waklog: waiting for tokens..." );
1454 if ( cfg
->default_principal
) {
1455 set_auth( s
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1462 waklog_phase0 (request_rec
* r
)
1466 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1467 "mod_waklog: phase0 called");
1469 cfg
= retrieve_config(r
);
1471 if ( cfg
->protect
&& cfg
->principal
) {
1472 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase0 using user %s", cfg
->principal
);
1473 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1474 } else if ( cfg
->default_principal
) {
1475 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase0 using default user %s", cfg
->default_principal
);
1476 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1478 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase0 not doing nothin.");
1485 waklog_phase1 (request_rec
* r
)
1489 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1490 "mod_waklog: phase1 called");
1492 cfg
= retrieve_config(r
);
1494 if ( cfg
->protect
&& cfg
->principal
) {
1495 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase1 using user %s", cfg
->principal
);
1496 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1497 } else if ( cfg
->default_principal
) {
1498 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase1 using default user %s", cfg
->default_principal
);
1499 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1501 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase1 not doing nothin.");
1508 waklog_phase3 (request_rec
* r
)
1512 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1513 "mod_waklog: phase 3 called");
1515 cfg
= retrieve_config(r
);
1517 if ( cfg
->protect
&& cfg
->principal
) {
1518 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase3 using user %s", cfg
->principal
);
1519 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1520 } else if ( cfg
->default_principal
) {
1521 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase3 using default user %s", cfg
->default_principal
);
1522 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1524 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase3 not doing nothin.");
1531 waklog_phase6 (request_rec
* r
)
1535 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1536 "mod_waklog: phase6 called");
1538 cfg
= retrieve_config(r
);
1540 if ( cfg
->protect
&& cfg
->principal
) {
1541 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase6 using user %s", cfg
->principal
);
1542 set_auth(r
->server
, r
, 0, cfg
->principal
, cfg
->keytab
, 0);
1543 } else if ( cfg
->default_principal
) {
1544 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase6 using default user %s", cfg
->default_principal
);
1545 set_auth(r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1547 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase6 not doing nothin.");
1554 waklog_phase7 (request_rec
* r
)
1559 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1560 "mod_waklog: phase7 called");
1562 cfg
= retrieve_config (r
);
1564 if ( cfg
->protect
&& cfg
->usertokens
) {
1565 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase7 using usertokens");
1566 rc
= set_auth( r
->server
, r
, 1, NULL
, NULL
, 0);
1567 } else if ( cfg
->protect
&& cfg
->principal
) {
1568 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase7 using user %s", cfg
->principal
);
1569 rc
= 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: phase7 using default user %s", cfg
->default_principal
);
1572 rc
= set_auth( r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1574 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase7 using no default principal");
1575 set_auth(r
->server
, r
, 0, NULL
, NULL
, 0);
1586 waklog_phase9 (request_rec
* r
)
1590 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1591 "mod_waklog: phase9 called");
1593 getModConfig (cfg
, r
->server
);
1595 if ( cfg
->default_principal
) {
1596 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
, "mod_waklog: phase9 using default user %s", cfg
->default_principal
);
1597 set_auth( r
->server
, r
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1610 waklog_new_connection (conn_rec
* c
1619 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, c
->base_server
,
1620 "mod_waklog: new_connection called: pid: %d", getpid ());
1622 getModConfig(cfg
, c
->base_server
);
1624 if ( cfg
->default_principal
) {
1625 log_error(APLOG_MARK
, APLOG_DEBUG
, 0, c
->base_server
, "mod_waklog: new conn setting default user %s",
1626 cfg
->default_principal
);
1627 set_auth( c
->base_server
, NULL
, 0, cfg
->default_principal
, cfg
->default_keytab
, 0);
1640 ** Here's a quick explaination for phase0 and phase2:
1641 ** Apache does a stat() on the path between phase0 and
1642 ** phase2, and must by ACLed rl to succeed. So, at
1643 ** phase0 we acquire credentials for umweb:servers from
1644 ** a keytab, and at phase2 we must ensure we remove them.
1646 ** Failure to "unlog" would be a security risk.
1649 waklog_phase2 (request_rec
* r
)
1652 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1653 "mod_waklog: phase2 called");
1655 if (child
.token
.ticketLen
)
1657 memset (&child
.token
, 0, sizeof (struct ktc_token
));
1659 ktc_ForgetAllTokens ();
1661 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1662 "mod_waklog: ktc_ForgetAllTokens succeeded: pid: %d",
1666 log_error (APLOG_MARK
, APLOG_DEBUG
, 0, r
->server
,
1667 "mod_waklog: phase2 returning");
1673 module MODULE_VAR_EXPORT waklog_module
= {
1674 STANDARD_MODULE_STUFF
,
1675 waklog_init
, /* module initializer */
1676 waklog_create_dir_config
, /* create per-dir config structures */
1677 waklog_merge_dir_config
, /* merge per-dir config structures */
1678 waklog_create_server_config
, /* create per-server config structures */
1679 waklog_merge_dir_config
, /* merge per-server config structures */
1680 waklog_cmds
, /* table of config file commands */
1681 NULL
, /* [#8] MIME-typed-dispatched handlers */
1682 waklog_phase1
, /* [#1] URI to filename translation */
1683 NULL
, /* [#4] validate user id from request */
1684 NULL
, /* [#5] check if the user is ok _here_ */
1685 waklog_phase3
, /* [#3] check access by host address */
1686 waklog_phase6
, /* [#6] determine MIME type */
1687 waklog_phase7
, /* [#7] pre-run fixups */
1688 waklog_phase9
, /* [#9] log a transaction */
1689 NULL
, /* [#2] header parser */
1690 waklog_child_init
, /* child_init */
1691 waklog_child_exit
, /* child_exit */
1692 waklog_phase0
/* [#0] post read-request */
1694 , NULL
, /* EAPI: add_module */
1695 NULL
, /* EAPI: remove_module */
1696 NULL
, /* EAPI: rewrite_command */
1697 waklog_new_connection
/* EAPI: new_connection */
1702 waklog_register_hooks (apr_pool_t
* p
)
1704 ap_hook_translate_name (waklog_phase1
, NULL
, NULL
, APR_HOOK_FIRST
);
1705 ap_hook_header_parser (waklog_phase2
, NULL
, NULL
, APR_HOOK_FIRST
);
1706 ap_hook_access_checker (waklog_phase3
, NULL
, NULL
, APR_HOOK_FIRST
);
1707 ap_hook_type_checker (waklog_phase6
, NULL
, NULL
, APR_HOOK_FIRST
);
1708 ap_hook_fixups (waklog_phase7
, NULL
, NULL
, APR_HOOK_FIRST
);
1709 ap_hook_log_transaction (waklog_phase9
, NULL
, NULL
, APR_HOOK_FIRST
);
1710 ap_hook_child_init (waklog_child_init
, NULL
, NULL
, APR_HOOK_FIRST
);
1711 ap_hook_post_read_request (waklog_phase0
, NULL
, NULL
, APR_HOOK_FIRST
);
1712 ap_hook_pre_connection (waklog_new_connection
, NULL
, NULL
, APR_HOOK_FIRST
);
1713 ap_hook_post_config (waklog_init_handler
, NULL
, NULL
, APR_HOOK_MIDDLE
);
1717 module AP_MODULE_DECLARE_DATA waklog_module
= {
1718 STANDARD20_MODULE_STUFF
,
1719 waklog_create_dir_config
, /* create per-dir conf structures */
1720 waklog_merge_dir_config
, /* merge per-dir conf structures */
1721 waklog_create_server_config
, /* create per-server conf structures */
1722 waklog_merge_dir_config
, /* merge per-server conf structures */
1723 waklog_cmds
, /* table of configuration directives */
1724 waklog_register_hooks
/* register hooks */