#ifdef sun
#include <synch.h>
+#include <stropts.h>
+#include <sys/ioccom.h>
#elif linux
#define use_pthreads
#include <features.h>
/********************* APACHE1 ******************************************************************************/
#ifndef APACHE2
#include "ap_config.h"
-#if defined(sun)
-#include <sys/ioccom.h>
-#endif /* sun */
#include <http_conf_globals.h>
#define MK_POOL pool
#define MK_TABLE_GET ap_table_get
{ name, func, \
NULL , \
RSRC_CONF | ACCESS_CONF , type, usage }
+module waklog_module;
/********************* APACHE2 ******************************************************************************/
#else
+#include "http_connection.h"
#include <apr_strings.h>
#include <apr_base64.h>
-//#include <ap_compat.h>
#define ap_pcalloc apr_pcalloc
#define ap_pdupstr apr_pdupstr
#define ap_pstrdup apr_pstrdup
-
-module AP_MODULE_DECLARE_DATA waklog_module;
-
#define MK_POOL apr_pool_t
#define MK_TABLE_GET apr_table_get
#define MK_TABLE_SET apr_table_set
-#include "unixd.h"
-extern unixd_config_rec unixd_config;
-#define ap_user_id unixd_config.user_id
-#define ap_group_id unixd_config.group_id
-#define ap_user_name unixd_config.user_name
#define command(name, func, var, type, usage) \
AP_INIT_ ## type (name, (void*) func, \
NULL, \
RSRC_CONF | ACCESS_CONF, usage)
-typedef struct
-{
- int dummy;
-}
-child_info;
-
+module AP_MODULE_DECLARE_DATA waklog_module;
+typedef struct { int dummy; } child_info;
const char *userdata_key = "waklog_init";
+
+/* Apache 2.4 */
+#ifdef APLOG_USE_MODULE
+APLOG_USE_MODULE(waklog);
+#endif
+
#endif /* APACHE2 */
/**************************************************************************************************/
#include <krb5.h>
-#include <stropts.h>
+#include <kopenafs.h>
+
+#include <afs/param.h>
+
#include <afs/venus.h>
#include <afs/auth.h>
#include <afs/dirpath.h>
#define TKT_LIFE ( 12 * 60 * 60 )
#define SLEEP_TIME ( TKT_LIFE - 5*60 )
-#define WAKLOG_ON 1
-#define WAKLOG_OFF 2
-#define WAKLOG_UNSET 0
+#define WAKLOG_UNSET -1
#ifdef WAKLOG_DEBUG
#undef APLOG_DEBUG
#define APLOG_DEBUG APLOG_ERR
#endif
-#ifndef CELL_IN_PRINCIPAL
-int cell_in_principal = 1;
-#else
-int cell_in_principal = 0;
-#endif
-
/* this is used to turn off pag generation for the backround worker child during startup */
int pag_for_children = 1;
int configured;
int protect;
int usertokens;
+ int cell_in_principal;
+ int disable_token_cache;
char *keytab;
char *principal;
char *default_principal;
char *default_keytab;
char *afs_cell;
+ char *afs_cell_realm;
char *path;
MK_POOL *p;
}
int renewcount = 0;
-module waklog_module;
#define getModConfig(P, X) P = (waklog_config *) ap_get_module_config( (X)->module_config, &waklog_module );
-#include <krb5.h>
-
-#if defined(sun)
-#include <sys/ioccom.h>
-#endif /* sun */
-#include <stropts.h>
-#include <afs/venus.h>
-#include <afs/auth.h>
-#include <afs/dirpath.h>
-#include <afs/ptuser.h>
-#include <rx/rxkad.h>
-
-/* If there's an error, retry more aggressively */
-#define ERR_SLEEP_TIME 5*60
-
-
-#define K5PATH "FILE:/tmp/waklog.creds.k5"
+#ifdef APLOG_USE_MODULE
+static void
+log_error (const char *file, int line, int module_index, int level, int status,
+ const server_rec * s, const char *fmt, ...)
+#else
static void
log_error (const char *file, int line, int level, int status,
const server_rec * s, const char *fmt, ...)
+#endif
{
char errstr[4096];
va_list ap;
va_end (ap);
#ifdef APACHE2
+ #ifdef APLOG_USE_MODULE
+ /* Apache 2.4 */
+ ap_log_error (file, line, module_index, level | APLOG_NOERRNO, status, s, "%s", errstr);
+ #else
ap_log_error (file, line, level | APLOG_NOERRNO, status, s, "(%d) %s", getpid(), errstr);
+ #endif
#else
ap_log_error (file, line, level | APLOG_NOERRNO, s, "(%d) %s", getpid(), errstr);
#endif
krb5_get_init_creds_opt kopts;
krb5_creds v5creds;
krb5_creds increds;
+ krb5_ccache clientccache;
struct ktc_principal server = { "afs", "", "" };
struct ktc_principal client;
struct ktc_token token;
int rc = 0;
int buflen = 0;
time_t oldest_time = 0;
- int oldest;
+ int oldest = 0;
int stored = -1;
time_t mytime;
int indentical;
+ int cell_in_principal;
+ int attempt;
+ int use_client_credentials = 0;
- char k5user[MAXNAMELEN];
- char *k5secret;
+ char k5user[MAXNAMELEN] = "";
+ char *k5secret = NULL;
+
+ char *k5path = NULL;
memset((char *) &increds, 0, sizeof(increds));
-
/* init some stuff if it ain't already */
-
+ /* XXX - In what situation will these not be initialized? */
+
if ( ! child.kcontext ) {
- kerror = krb5_init_context(&child.kcontext);
+ if ((kerror = krb5_init_context(&child.kcontext))) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize Kerberos context err=%d",
+ kerror);
+ return(-1);
+ }
}
-
- if ( ( ! child.ccache ) && ( kerror = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", kerror );
+
+ if ( !child.ccache) {
+ if ((kerror = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache))) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize credentials cache %s err=%d",
+ k5path, kerror );
+ return(-1);
+ }
}
-
- log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: %d, %s, %s, %d", self, principal ? principal : "NULL",
- keytab ? keytab : "NULL", storeonly);
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: %d, %s, %s, %d, KRB5CC=%s user=%s",
+ self, principal ? principal : "NULL",
+ keytab ? keytab : "NULL",
+ storeonly,
+ k5path ? k5path : "NULL",
+#ifdef APACHE2
+ (r && r->user) ? r->user : "NULL"
+#else
+ (r && r->connection && r->connection->user) ? r->connection->user : "NULL"
+#endif
+ );
/* pull the server config record that we care about... */
if ( ! cfg ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: cfg is %d", cfg );
}
-
-#ifdef APACHE2
+
+
if ( self ) {
/* pull out our principal name and stuff from the environment -- webauth better have sent
- through. This here is also where you'd suck stuff out of KRB5CCNAME if we were
- using something like Cosign */
-
+ through. */
+
+#ifdef APACHE2
if ( ! ( r && r->connection && r->user )) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: self authentication selected, but no data available");
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: r->user=%s", (r->user==NULL ? "null" : r->user));
return -1;
}
strncpy(k5user, r->user, sizeof(k5user));
-
- /* the other thing we need is someone's password */
- if ( ! ( k5secret = (char *) MK_TABLE_GET( r->notes, "ATTR_PASSWORD" ) ) ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cant do self auth without a secret");
+#else
+ if ( ! (r && r->connection && r->connection->user)) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: self authentication selected, but no username available");
return -1;
- }
+ }
+
+ strncpy(k5user, r->connection->user, sizeof(k5user));
+#endif
+ /* if they've supplied a credentials cache */
+ k5path = (char *) MK_TABLE_GET( r->subprocess_env, "KRB5CCNAME" );
+
+ /* the other thing we need is someone's password */
+ k5secret = (char *) MK_TABLE_GET( r->notes, "ATTR_PASSWORD" );
/* we'll pick this up later after we've checked the cache and current state */
} else
-#endif
if ( principal ) {
- strncpy( k5user, principal, sizeof(k5user));
+ strncpy(k5user, principal, sizeof(k5user));
+ } else
+#ifdef APACHE2
+ if (r && r->user) {
+ strncpy(k5user, r->user, sizeof(k5user));
+ }
+#else
+ if (r && r->connection && r->connection->user) {
+ strncpy(k5user, r->connection->user, sizeof(k5user));
}
+#endif
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth: k5user=%s", k5user);
mytime = time(0);
/* see if we should just go ahead and ignore this call, since we already should be set to these
}
}
-
+
/* if 'usecached' isn't set, we've got to get our tokens from somewhere... */
-
- if (( ! usecached ) && ( k5user )) {
+ if ( ! usecached ) {
/* clear out the creds structure */
memset((void *) &v5creds, 0, sizeof(v5creds));
/* create a principal out of our k5user string */
- if ( kerror = krb5_parse_name (child.kcontext, k5user, &kprinc ) ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse_name %s", (char *) error_message(kerror) );
+ if ( ( kerror = krb5_parse_name (child.kcontext, k5user, &kprinc ) ) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse_name %s", (char *) afs_error_message(kerror) );
goto cleanup;
}
krb5_get_init_creds_opt_set_forwardable ( &kopts, 0 );
krb5_get_init_creds_opt_set_proxiable ( &kopts, 0 );
- if ( keytab ) {
+ if ( keytab || k5secret ) {
- /* if we've been passed a keytab, we're going to be getting our credentials from it */
+ if (keytab) {
+ /* if we've been passed a keytab, we're going to be getting our credentials from it */
- log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using keytab %s", keytab);
+ log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using keytab %s", keytab);
- if ( kerror = krb5_kt_resolve(child.kcontext, keytab, &krb5kt ) ) {
- log_error( APLOG_MARK, APLOG_ERR, 0, s,
- "mod_waklog: krb5_kt_resolve %s", error_message(kerror) );
- goto cleanup;
- }
+ if ( ( kerror = krb5_kt_resolve(child.kcontext, keytab, &krb5kt ) ) ) {
+ log_error( APLOG_MARK, APLOG_ERR, 0, s,
+ "mod_waklog: krb5_kt_resolve %s", afs_error_message(kerror) );
+ goto cleanup;
+ }
- if ((kerror = krb5_get_init_creds_keytab (child.kcontext, &v5creds,
- kprinc, krb5kt, 0, NULL, &kopts ) ) ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_init_creds_keytab %s",
- error_message(kerror) );
- goto cleanup;
- }
+ if ((kerror = krb5_get_init_creds_keytab (child.kcontext, &v5creds,
+ kprinc, krb5kt, 0, NULL, &kopts ) ) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_init_creds_keytab %s",
+ afs_error_message(kerror) );
+ goto cleanup;
+ }
+ } else if (k5secret) {
- } else if ( self ) {
+ /* If the WebSSO is lame enough to provide a secret, then try and use that to get a token */
- /* if 'self' is set, we're going to use the credentials provided in the credential information */
- /* if you're using CoSign, you'd actually just set the ccache to the KRB5CCNAME credentials */
- /* and skip ahead... Our WebSSO is lame, but has a way for us to snarf the password out of */
- /* the encrypted token for proxy-authentication stuff. We only hand out keys that allow this */
- /* functionality to VERY special people. */
+ if ((kerror = krb5_get_init_creds_password ( child.kcontext, &v5creds,
+ kprinc, k5secret, NULL, NULL, 0, NULL, &kopts ) ) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_init_creds_password %s",
+ afs_error_message(kerror) );
+ /* nuke the password so it doesn't end up in core files */
+ memset(k5secret, 0, strlen(k5secret));
+ goto cleanup;
+ }
- if ((kerror = krb5_get_init_creds_password ( child.kcontext, &v5creds,
- kprinc, k5secret, NULL, NULL, 0, NULL, &kopts ) ) ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_init_creds_password %s",
- error_message(kerror) );
- /* nuke the password so it doesn't end up in core files */
- memset(k5secret, 0, sizeof(k5secret));
- goto cleanup;
+ memset(k5secret, 0, strlen(k5secret));
}
-
- memset(k5secret, 0, sizeof(k5secret));
-
- } else {
-
- /* degenerate case -- we don't have enough information to do anything */
-
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: no keytab, no self?");
- kerror = -1;
- goto cleanup;
-
- }
-
+
/* initialize the credentials cache and store the stuff we just got */
+ if ( ( kerror = krb5_cc_initialize (child.kcontext, child.ccache, kprinc) ) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: init credentials cache %s",
+ afs_error_message(kerror));
+ goto cleanup;
+ }
- if ( kerror = krb5_cc_initialize (child.kcontext, child.ccache, kprinc)) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: init credentials cache %s",
- error_message(kerror));
- goto cleanup;
- }
-
- if ( kerror = krb5_cc_store_cred(child.kcontext, child.ccache, &v5creds) ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot store credentials %s",
- error_message(kerror));
- goto cleanup;
- }
+ if ( ( kerror = krb5_cc_store_cred(child.kcontext, child.ccache, &v5creds) ) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: cannot store credentials %s",
+ afs_error_message(kerror));
+ goto cleanup;
+ }
- krb5_free_cred_contents(child.kcontext, &v5creds);
+ krb5_free_cred_contents(child.kcontext, &v5creds);
+
+ if ( kerror ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: store cred %s", afs_error_message(kerror));
+ goto cleanup;
+ }
+
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: kinit ok for %s", k5user );
+
+ } else if (k5path) {
+ /* If we've got a path to a credentials cache, then try and use that. We can't just
+ * replace child.creds, because we want to ensure that only this request gets access to
+ * that cache */
+
+ if ( ( kerror = krb5_cc_resolve(child.kcontext, k5path, &clientccache ) ) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s,
+ "mod_waklog: can't open provided credentials cache %s err=%d",
+ k5path, kerror );
+ goto cleanup;
+ }
+
+ use_client_credentials = 1;
+ }
- if ( kerror ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: store cred %s", error_message(kerror));
- goto cleanup;
- }
-
- log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: kinit ok for %s", k5user );
-
/* now, to the 'aklog' portion of our program. */
- strncpy( buf, "afs", sizeof(buf) - 1 );
-
- if (cell_in_principal) {
- strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
- strncat(buf, cfg->afs_cell, sizeof(buf) - strlen(buf) - 1);
- }
+ /** we make two attempts here, one for afs@REALM and one for afs/cell@REALM */
+ for(attempt = 0; attempt <= 1; attempt++) {
+ strncpy( buf, "afs", sizeof(buf) - 1 );
+ cell_in_principal = (cfg->cell_in_principal + attempt) % 2;
+
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: cell_in_principal=%d", cell_in_principal );
+ if (cell_in_principal) {
+ strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
+ strncat(buf, cfg->afs_cell, sizeof(buf) - strlen(buf) - 1);
+ }
+ if (cfg->afs_cell_realm != NULL) {
+ strncat(buf, "@", sizeof(buf) - strlen(buf) - 1);
+ strncat(buf, cfg->afs_cell_realm, sizeof(buf) - strlen(buf) - 1);
+ }
+
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using AFS principal: %s", buf);
+
+ if ((kerror = krb5_parse_name (child.kcontext, buf, &increds.server))) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse name %s", afs_error_message(kerror));
+ goto cleanup;
+ }
- log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: using AFS principal: %s", buf);
-
- if ((kerror = krb5_parse_name (child.kcontext, buf, &increds.server))) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_parse name %s", error_message(kerror));
- goto cleanup;
- }
-
- if ((kerror = krb5_cc_get_principal(child.kcontext, child.ccache, &increds.client))) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_get_princ %s", error_message(kerror));
- goto cleanup;
- }
-
- log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: retrieved data from ccache for %s", k5user);
-
- increds.times.endtime = 0;
-
- increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-
- if (kerror = krb5_get_credentials (child.kcontext, 0, child.ccache, &increds, &v5credsp )) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
- error_message(kerror));
- goto cleanup;
+ if (!use_client_credentials) {
+ clientccache = child.ccache;
+ }
+
+ if ((kerror = krb5_cc_get_principal(child.kcontext, clientccache, &increds.client))) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_cc_get_princ %s %p", afs_error_message(kerror), clientccache);
+ goto cleanup;
+ }
+
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: retrieved data from ccache for %s", k5user);
+
+ increds.times.endtime = 0;
+
+ if ( ( kerror = krb5_get_credentials (child.kcontext, 0, clientccache, &increds, &v5credsp ) ) ) {
+ /* only complain once we've tried both afs@REALM and afs/cell@REALM */
+ if (attempt>=1) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: krb5_get_credentials: %s",
+ afs_error_message(kerror));
+ goto cleanup;
+ } else {
+ continue;
+ }
+ }
+ cfg->cell_in_principal = cell_in_principal;
+ break;
}
-
+
log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: get_credentials passed for %s", k5user);
if ( v5credsp->ticket.length >= MAXKTCTICKETLEN ) {
token.startTime = v5credsp->times.starttime ? v5credsp->times.starttime : v5credsp->times.authtime;
token.endTime = v5credsp->times.endtime;
- memmove( &token.sessionKey, v5credsp->keyblock.contents, v5credsp->keyblock.length);
+ if (tkt_DeriveDesKey(v5credsp->keyblock.enctype, v5credsp->keyblock.contents,
+ v5credsp->keyblock.length, &token.sessionKey) != 0) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: tkt_DeriveDesKey failure (enctype: %d)",
+ v5credsp->keyblock.enctype);
+ goto cleanup;
+ }
token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
token.ticketLen = v5credsp->ticket.length;
memmove( token.ticket, v5credsp->ticket.data, token.ticketLen);
if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: settoken returned %s for %s -- trying again",
- error_message(rc), k5user);
+ afs_error_message(rc), k5user);
if ((rc = ktc_SetToken(&child.server, &child.token, &child.client, 0))) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: settoken2 returned %s for %s",
- error_message(rc), k5user);
+ afs_error_message(rc), k5user);
goto cleanup;
}
}
cleanup:
+ if (use_client_credentials)
+ krb5_cc_close(child.kcontext, clientccache);
if ( v5credsp )
krb5_free_cred_contents(child.kcontext, v5credsp);
if ( increds.client )
if ( rc ) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with %d", rc );
} else if ( kerror ) {
- log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror, error_message(kerror));
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: set_auth ending with krb5 error %d, %s", kerror, afs_error_message(kerror));
} else {
log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: set_auth ending ok");
}
}
+int get_cfg_usertokens(waklog_config *cfg)
+{
+ if (cfg->usertokens==WAKLOG_UNSET)
+ return 0; /* default */
+ return cfg->usertokens;
+}
+
+int get_cfg_protect(waklog_config *cfg)
+{
+ if (cfg->protect==WAKLOG_UNSET)
+ return 0; /* default */
+ return cfg->protect;
+}
+
+int get_cfg_disable_token_cache(waklog_config *cfg)
+{
+ if (cfg->disable_token_cache==WAKLOG_UNSET)
+ return 0; /* default */
+ return cfg->disable_token_cache;
+}
+
static void *
waklog_create_server_config (MK_POOL * p, server_rec * s)
cfg->path = "(server)";
cfg->protect = WAKLOG_UNSET;
cfg->usertokens = WAKLOG_UNSET;
- cfg->keytab = WAKLOG_UNSET;
- cfg->principal = WAKLOG_UNSET;
- cfg->default_principal = WAKLOG_UNSET;
- cfg->default_keytab = WAKLOG_UNSET;
- cfg->afs_cell = WAKLOG_UNSET;
+ cfg->disable_token_cache = WAKLOG_UNSET;
+ cfg->keytab = NULL;
+ cfg->principal = NULL;
+ cfg->default_principal = NULL;
+ cfg->default_keytab = NULL;
+ cfg->afs_cell = NULL;
+ cfg->afs_cell_realm = NULL;
cfg->forked = 0;
cfg->configured = 0;
cfg->path = ap_pstrdup(p, dir );
cfg->protect = WAKLOG_UNSET;
cfg->usertokens = WAKLOG_UNSET;
- cfg->keytab = WAKLOG_UNSET;
- cfg->principal = WAKLOG_UNSET;
- cfg->default_principal = WAKLOG_UNSET;
- cfg->default_keytab = WAKLOG_UNSET;
- cfg->afs_cell = WAKLOG_UNSET;
+ cfg->disable_token_cache = WAKLOG_UNSET;
+ cfg->keytab = NULL;
+ cfg->principal = NULL;
+ cfg->default_principal = NULL;
+ cfg->default_keytab = NULL;
+ cfg->afs_cell = NULL;
+ cfg->afs_cell_realm = NULL;
cfg->forked = 0;
cfg->configured = 0;
merged->protect = child->protect != WAKLOG_UNSET ? child->protect : parent->protect;
- merged->path = child->path != WAKLOG_UNSET ? child->path : parent->path;
+ merged->path = child->path != NULL ? child->path : parent->path;
merged->usertokens = child->usertokens != WAKLOG_UNSET ? child->usertokens : parent->usertokens;
+
+ merged->disable_token_cache = child->disable_token_cache != WAKLOG_UNSET ? child->disable_token_cache : parent->disable_token_cache;
- merged->principal = child->principal != WAKLOG_UNSET ? child->principal : parent->principal;
+ merged->principal = child->principal != NULL ? child->principal : parent->principal;
- merged->keytab = child->keytab != WAKLOG_UNSET ? child->keytab : parent->keytab;
+ merged->keytab = child->keytab != NULL ? child->keytab : parent->keytab;
- merged->default_keytab = child->default_keytab != WAKLOG_UNSET ? child->default_keytab : parent->default_keytab;
+ merged->default_keytab = child->default_keytab != NULL ? child->default_keytab : parent->default_keytab;
- merged->default_principal = child->default_principal != WAKLOG_UNSET ? child->default_principal : parent->default_principal;
+ merged->default_principal = child->default_principal != NULL ? child->default_principal : parent->default_principal;
- merged->afs_cell = child->afs_cell != WAKLOG_UNSET ? child->afs_cell : parent->afs_cell;
+ merged->afs_cell = child->afs_cell != NULL ? child->afs_cell : parent->afs_cell;
+
+ merged->afs_cell_realm = child->afs_cell_realm != NULL ? child->afs_cell_realm : parent->afs_cell_realm;
return (void *) merged;
merged->usertokens = nconf->usertokens == WAKLOG_UNSET ? pconf->usertokens : nconf->usertokens;
- merged->keytab = nconf->keytab == WAKLOG_UNSET ? ap_pstrdup(p, pconf->keytab) :
- ( nconf->keytab == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->keytab) );
+ merged->disable_token_cache = nconf->disable_token_cache == WAKLOG_UNSET ? pconf->disable_token_cache : nconf->disable_token_cache;
+
+ merged->keytab = nconf->keytab == NULL ? ap_pstrdup(p, pconf->keytab) :
+ ( nconf->keytab == NULL ? NULL : ap_pstrdup(p, nconf->keytab) );
- merged->principal = nconf->principal == WAKLOG_UNSET ? ap_pstrdup(p, pconf->principal) :
- ( nconf->principal == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->principal) );
+ merged->principal = nconf->principal == NULL ? ap_pstrdup(p, pconf->principal) :
+ ( nconf->principal == NULL ? NULL : ap_pstrdup(p, nconf->principal) );
- merged->afs_cell = nconf->afs_cell == WAKLOG_UNSET ? ap_pstrdup(p, pconf->afs_cell) :
- ( nconf->afs_cell == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->afs_cell) );
+ merged->afs_cell = nconf->afs_cell == NULL ? ap_pstrdup(p, pconf->afs_cell) :
+ ( nconf->afs_cell == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell) );
+
+ merged->afs_cell_realm = nconf->afs_cell_realm == NULL ? ap_pstrdup(p, pconf->afs_cell_realm) :
+ ( nconf->afs_cell_realm == NULL ? NULL : ap_pstrdup(p, nconf->afs_cell_realm) );
- merged->default_keytab = nconf->default_keytab == WAKLOG_UNSET ? ap_pstrdup(p, pconf->default_keytab) :
- ( nconf->default_keytab == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->default_keytab) );
+ merged->default_keytab = nconf->default_keytab == NULL ? ap_pstrdup(p, pconf->default_keytab) :
+ ( nconf->default_keytab == NULL ? NULL : ap_pstrdup(p, nconf->default_keytab) );
- merged->default_principal = nconf->default_principal == WAKLOG_UNSET ? ap_pstrdup(p, pconf->default_principal) :
- ( nconf->default_principal == WAKLOG_UNSET ? WAKLOG_UNSET : ap_pstrdup(p, pconf->default_principal) );
+ merged->default_principal = nconf->default_principal == NULL ? ap_pstrdup(p, pconf->default_principal) :
+ ( nconf->default_principal == NULL ? NULL : ap_pstrdup(p, nconf->default_principal) );
return (void *) merged;
}
static const char *
-set_waklog_protect (cmd_parms * params, void *mconfig, int flag)
+set_waklog_enabled (cmd_parms * params, void *mconfig, int flag)
{
waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
cfg->protect = flag;
cfg->configured = 1;
log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
- "mod_waklog: waklog_protect set on %s", cfg->path ? cfg->path : "NULL");
+ "mod_waklog: waklog_enabled set on %s", cfg->path ? cfg->path : "NULL");
return (NULL);
}
}
static const char *
-set_waklog_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
+set_waklog_location_principal (cmd_parms *params, void *mconfig, char *principal, char *keytab)
{
waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
}
static const char *
-set_waklog_use_afs_cell (cmd_parms * params, void *mconfig, char *file)
+set_waklog_afs_cell (cmd_parms * params, void *mconfig, char *file)
{
waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
waklog_config *waklog_srvconfig =
log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
"mod_waklog: will use afs_cell: %s", file);
+ // Prefer afs/cell@REALM over afs@REALM, just like the OpenAFS tools
+ waklog_srvconfig->cell_in_principal = 1;
+
waklog_srvconfig->afs_cell = ap_pstrdup (params->pool, file);
waklog_srvconfig->configured = 1;
if (waklog_mconfig != NULL) {
+ waklog_mconfig->cell_in_principal = waklog_srvconfig->cell_in_principal;
waklog_mconfig->afs_cell = ap_pstrdup (params->pool, file);
waklog_mconfig->configured = 1;
}
return (NULL);
}
+static const char *
+set_waklog_afs_cell_realm (cmd_parms * params, void *mconfig, char *file)
+{
+ waklog_config *waklog_mconfig = ( waklog_config * ) mconfig;
+ waklog_config *waklog_srvconfig =
+ ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
+
+ log_error (APLOG_MARK, APLOG_INFO, 0, params->server,
+ "mod_waklog: will use afs_cell_realm: %s", file);
+
+ waklog_srvconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
+
+ if (waklog_mconfig != NULL) {
+ waklog_mconfig->afs_cell_realm = ap_pstrdup (params->pool, file);
+ }
+ return (NULL);
+}
+
static const char *
set_waklog_default_principal (cmd_parms * params, void *mconfig, char *principal, char *keytab)
{
}
+static const char *
+set_waklog_disable_token_cache (cmd_parms * params, void *mconfig, int flag)
+{
+ waklog_config *cfg = mconfig ? ( waklog_config * ) mconfig :
+ ( waklog_config * ) ap_get_module_config(params->server->module_config, &waklog_module );
+
+ cfg->disable_token_cache = flag;
+
+ cfg->configured = 1;
+
+ log_error (APLOG_MARK, APLOG_DEBUG, 0, params->server,
+ "mod_waklog: waklog_disable_token_cache set");
+ return (NULL);
+}
+
+
#ifndef APACHE2
static void waklog_child_exit( server_rec *s, MK_POOL *p ) {
#else
memset (&child, 0, sizeof(child));
- if ( code = krb5_init_context(&child.kcontext) ) {
+ if ( ( code = krb5_init_context(&child.kcontext) ) ) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
}
- if ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) {
+ if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
}
if ( pag_for_children ) {
- setpag ();
+ k_setpag ();
}
getModConfig (cfg, s);
- if ( cfg->default_principal != WAKLOG_UNSET ) {
+ if ( cfg->default_principal != NULL ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: child_init setting default user %s, %s", cfg->default_principal, cfg->default_keytab);
set_auth( s, NULL, 0, cfg->default_principal, cfg->default_keytab, 0);
}
command_rec waklog_cmds[] = {
- command ("WaklogProtected", set_waklog_protect, 0, FLAG,
- "enable waklog on a location or directory basis"),
-
- command ("WaklogPrincipal", set_waklog_principal, 0, TAKE2,
- "Use the supplied keytab rather than the default"),
+ command ("WaklogAFSCell", set_waklog_afs_cell, 0, TAKE1,
+ "Use the supplied AFS cell (required)"),
- command ("WaklogUseAFSCell", set_waklog_use_afs_cell, 0, TAKE1,
- "Use the supplied AFS cell rather than the default"),
+ command ("WaklogAFSCellRealm", set_waklog_afs_cell_realm, 0, TAKE1,
+ "Assume that the AFS cell belongs to the specified Kerberos realm (optional)"),
- command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
- "Use the requesting user tokens (from webauth)"),
+ command ("WaklogEnabled", set_waklog_enabled, 0, FLAG,
+ "enable waklog on a server, location, or directory basis"),
command ("WaklogDefaultPrincipal", set_waklog_default_principal, 0, TAKE2,
- "Set the default principal that the server runs as"),
-
+ "Set the default principal that the server runs as"),
+
+ command ("WaklogLocationPrincipal", set_waklog_location_principal, 0, TAKE2,
+ "Set the principal on a <Location>-specific basis"),
+
+ command ("WaklogDisableTokenCache", set_waklog_disable_token_cache, 0, FLAG,
+ "Ignore the token cache (location-specific); useful for scripts that need kerberos tickets."),
+
+ command ("WaklogUseUserTokens", set_waklog_use_usertokens, 0, FLAG,
+ "Use the requesting user tokens (from webauth)"),
+
{NULL}
};
return 0;
}
+/* This function doesn't return anything but is passed to ap_bspawn_child on
+ * Apache 1 which expects it to return a pid as an int. For want of better
+ * understanding, err on the side of not changing Apache 1 code while fixing
+ * the compile warning on Apache 2. */
+#ifdef APACHE2
+static void
+#else
static int
+#endif
waklog_child_routine (void *data, child_info * pinfo)
{
int i;
memset (&child, 0, sizeof(child));
- if ( code = krb5_init_context(&child.kcontext) ) {
+ if ( ( code = krb5_init_context(&child.kcontext) ) ) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't init kerberos context %d", code );
}
- if ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) {
+ if ( ( code = krb5_cc_resolve(child.kcontext, "MEMORY:tmpcache", &child.ccache) ) ) {
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: can't initialize in-memory credentials cache %d", code );
}
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: about to pr_Initialize");
+
/* need to do this so we can make PTS calls */
cell = strdup(cfg->afs_cell); /* stupid */
pr_Initialize( 0, AFSDIR_CLIENT_ETC_DIR, cell );
-
+
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: still here");
+
while(1) {
for ( i = 0; i < renewcount; ++i ) {
if (cfg->afs_cell==NULL) {
log_error (APLOG_MARK, APLOG_ERR, 0, s,
- "mod_waklog: afs_cell==NULL; please provide the WaklogUseAFSCell directive");
+ "mod_waklog: afs_cell==NULL; please provide the WaklogAFSCell directive");
/** clobber apache */
exit(-1);
}
struct sharedspace_s bob;
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: sizing our cache file %d to %d", fd, sizeof(struct sharedspace_s) );
memset( &bob, 0, sizeof(struct sharedspace_s));
- write(fd, &bob, sizeof(struct sharedspace_s));
+ if ( write(fd, &bob, sizeof(struct sharedspace_s)) != sizeof(struct sharedspace_s) ) {
+ log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: failed to write to our cache file %s (%d)", cache_file, errno );
+ exit(errno);
+ }
log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: done sizing our cache file to %d", sizeof(struct sharedspace_s) );
}
/* mmap the region */
if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != MAP_FAILED ) {
+ int err = 0;
log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
- close(fd);
+ err = unlink(cache_file);
+ if (err) {
+ log_error( APLOG_MARK, APLOG_ERR, 0, s, "mod_waklog: unable to delete %s due to %d", cache_file, errno);
+ } else {
+ log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared cache unlinked (will be deleted when Apache quits)");
+ }
} else {
log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: mmap failed %d", errno );
exit(errno);
#define locktype rwlock_t
#endif
- if ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) {
+ if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) != NULL ) {
#ifndef use_pthreads
rwlock_init(sharedlock, USYNC_PROCESS, NULL );
#else
extern char *version;
int pid;
waklog_config *cfg;
- char *cell;
int fd = -1;
int use_existing = 1;
int oldrenewcount;
/* mmap the region */
- if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != -1 ) {
+ if ( ( sharedspace = (struct sharedspace_s *) mmap ( NULL, sizeof(struct sharedspace_s), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ) ) != (void *) -1 ) {
log_error( APLOG_MARK, APLOG_DEBUG, 0, s, "mod_waklog: shared mmap region ok %d", sharedspace );
close(fd);
} else {
#endif
/* mmap our shared space for our lock */
- if ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) {
+ if ( ( sharedlock = ( locktype * ) mmap ( NULL, sizeof(locktype), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0 ) ) ) {
#ifndef use_pthreads
rwlock_init(sharedlock, USYNC_PROCESS, NULL );
#else
cfg = retrieve_config(r);
- if ( cfg->protect && cfg->principal ) {
+ if ( get_cfg_protect(cfg) && cfg->principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using user %s", cfg->principal);
set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
} else if ( cfg->default_principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 using default user %s", cfg->default_principal);
set_auth(r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
} else {
+
+ if (child.token.ticketLen) {
+ memset( &child.token, 0, sizeof (struct ktc_token) );
+ ktc_ForgetAllTokens();
+ }
+
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase0 not doing nothin.");
}
cfg = retrieve_config(r);
- if ( cfg->protect && cfg->principal ) {
+ if ( get_cfg_protect(cfg) && cfg->principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase1 using user %s", cfg->principal);
set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
} else if ( cfg->default_principal ) {
cfg = retrieve_config(r);
- if ( cfg->protect && cfg->principal ) {
+ if ( get_cfg_protect(cfg) && cfg->principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase3 using user %s", cfg->principal);
set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
} else if ( cfg->default_principal ) {
cfg = retrieve_config(r);
- if ( cfg->protect && cfg->principal ) {
+ if ( get_cfg_protect(cfg) && cfg->principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase6 using user %s", cfg->principal);
set_auth(r->server, r, 0, cfg->principal, cfg->keytab, 0);
} else if ( cfg->default_principal ) {
cfg = retrieve_config (r);
- if ( cfg->protect && cfg->usertokens ) {
+ if ( get_cfg_protect(cfg) && get_cfg_usertokens(cfg) ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using usertokens");
rc = set_auth( r->server, r, 1, NULL, NULL, 0);
- } else if ( cfg->protect && cfg->principal ) {
+ } else if ( get_cfg_protect(cfg) && cfg->principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using user %s", cfg->principal);
rc = set_auth( r->server, r, 0, cfg->principal, cfg->keytab, 0);
} else if ( cfg->default_principal ) {
log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: phase7 using default user %s", cfg->default_principal);
rc = set_auth( r->server, r, 0, cfg->default_principal, cfg->default_keytab, 0);
+ } else {
+ log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mod_waklog: no tokens");
+ if (child.token.ticketLen) {
+ memset(&child.token, 0, sizeof(struct ktc_token));
+ ktc_ForgetAllTokens();
+ }
}
if ( rc ) {
waklog_phase6, /* [#6] determine MIME type */
waklog_phase7, /* [#7] pre-run fixups */
waklog_phase9, /* [#9] log a transaction */
- NULL, /* [#2] header parser */
+ waklog_phase2, /* [#2] header parser */
waklog_child_init, /* child_init */
waklog_child_exit, /* child_exit */
waklog_phase0 /* [#0] post read-request */