#endif
} kerb_auth_config;
+typedef struct krb5_conn_data {
+ char *authline;
+ char *user;
+ char *mech;
+ int last_return;
+} krb5_conn_data;
+
static void
set_kerb_auth_headers(request_rec *r, const kerb_auth_config *conf,
int use_krb4, int use_krb5pwd, char *negotiate_ret_value);
} else
keytab = ap_req_keytab;
+#ifdef HAVE_KRB5_CC_NEW_UNIQUE
+ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &local_ccache);
+#else
ret = krb5_cc_resolve(context, "MEMORY:", &local_ccache);
+#endif
+
if (ret) {
log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"krb5_cc_resolve() failed when verifying KDC");
krb5_keytab keytab, int krb_verify_kdc, krb5_ccache *ccache)
{
krb5_creds creds;
+ krb5_get_init_creds_opt options;
krb5_error_code ret;
krb5_ccache ret_ccache = NULL;
char *name = NULL;
free(name);
}
+ krb5_get_init_creds_opt_init(&options);
ret = krb5_get_init_creds_password(context, &creds, principal,
(char *)password, NULL,
- NULL, 0, NULL, NULL);
+ NULL, 0, NULL, &options);
if (ret) {
log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"krb5_get_init_creds_password() failed: %s",
goto end;
}
+#ifdef HAVE_KRB5_CC_NEW_UNIQUE
+ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ret_ccache);
+#else
ret = krb5_cc_resolve(context, "MEMORY:", &ret_ccache);
+#endif
+
if (ret) {
log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"generating new memory ccache failed: %s",
int all_principals_unkown;
char *p = NULL;
- //temporary fix for KrbServiceName Any
+ //temporary fix for KrbServiceName Any, use default SERVICE_NAME
if (conf->krb_service_name && strcmp(conf->krb_service_name,"Any") == 0)
- snprintf(conf->krb_service_name, 5,"%s","HTTP");
+ snprintf(conf->krb_service_name, 5,"%s",SERVICE_NAME);
code = krb5_init_context(&kcontext);
if (code) {
#endif /* KRB5 */
-static int
-already_succeeded(request_rec *r)
+static krb5_conn_data *
+already_succeeded(request_rec *r, char *auth_line)
{
- if (ap_is_initial_req(r) || MK_AUTH_TYPE == NULL)
- return 0;
- if (strcmp(MK_AUTH_TYPE, MECH_NEGOTIATE) ||
- (strcmp(MK_AUTH_TYPE, "Basic") && strchr(MK_USER, '@')))
- return 1;
- return 0;
+ krb5_conn_data *conn_data;
+ const char keyname[1024];
+
+ snprintf(keyname, sizeof(keyname) - 1,
+ "mod_auth_kerb::connection::%s::%ld", r->connection->remote_ip,
+ r->connection->id);
+
+ if (apr_pool_userdata_get(&conn_data, keyname, r->connection->pool) != 0)
+ return NULL;
+
+ if(conn_data) {
+ if(strcmp(conn_data->authline, auth_line) == 0) {
+ log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "matched previous auth request");
+ return conn_data;
+ }
+ }
+ return NULL;
}
static void
kerb_auth_config *conf =
(kerb_auth_config *) ap_get_module_config(r->per_dir_config,
&auth_kerb_module);
+ krb5_conn_data *prevauth = NULL;
const char *auth_type = NULL;
const char *auth_line = NULL;
const char *type = NULL;
int ret;
static int last_return = HTTP_UNAUTHORIZED;
char *negotiate_ret_value = NULL;
+ char keyname[1024];
/* get the type specified in .htaccess */
type = ap_auth_type(r);
(strcasecmp(auth_type, "Basic") == 0))
return DECLINED;
- if (already_succeeded(r))
- return last_return;
-
- ret = HTTP_UNAUTHORIZED;
+ if ( (prevauth = already_succeeded(r, auth_line)) == NULL) {
+ ret = HTTP_UNAUTHORIZED;
#ifdef KRB5
if (use_krb5 && conf->krb_method_gssapi &&
strcasecmp(auth_type, "Basic") == 0) {
ret = authenticate_user_krb5pwd(r, conf, auth_line);
}
- if (ret == OK && conf->krb5_do_auth_to_local)
- ret = do_krb5_an_to_ln(r);
#endif
#ifdef KRB4
if (ret == HTTP_UNAUTHORIZED)
set_kerb_auth_headers(r, conf, use_krb4, use_krb5, negotiate_ret_value);
+ } else {
+ ret = prevauth->last_return;
+ MK_USER = prevauth->user;
+ MK_AUTH_TYPE = prevauth->mech;
+ }
+
+ /*
+ * save who was auth'd, if it's not already stashed.
+ */
+ if(!prevauth) {
+ prevauth = (krb5_conn_data *) apr_pcalloc(r->connection->pool, sizeof(krb5_conn_data));
+ prevauth->user = apr_pstrdup(r->connection->pool, MK_USER);
+ prevauth->authline = apr_pstrdup(r->connection->pool, auth_line);
+ prevauth->mech = apr_pstrdup(r->connection->pool, auth_type);
+ prevauth->last_return = ret;
+ snprintf(keyname, sizeof(keyname) - 1,
+ "mod_auth_kerb::connection::%s::%ld",
+ r->connection->remote_ip, r->connection->id);
+ apr_pool_userdata_set(prevauth, keyname, NULL, r->connection->pool);
+ }
+
+ if (ret == OK && conf->krb5_do_auth_to_local)
+ ret = do_krb5_an_to_ln(r);
+
/* XXX log_debug: if ret==OK, log(user XY authenticated) */
last_return = ret;