# define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
# define krb5_get_err_text(context,code) error_message(code)
#endif
+#include "spnegokrb5.h"
#endif /* KRB5 */
#ifdef KRB4
char *krb_auth_realms;
int krb_save_credentials;
int krb_verify_kdc;
+ char *krb_service_name;
#ifdef KRB5
char *krb_5_keytab;
int krb_method_gssapi;
command("KrbVerifyKDC", ap_set_flag_slot, krb_verify_kdc,
FLAG, "Verify tickets against keytab to prevent KDC spoofing attacks."),
+ command("KrbServiceName", ap_set_file_slot, krb_service_name,
+ TAKE1, "Service name to be used by Apache for authentication."),
+
#ifdef KRB5
command("Krb5Keytab", ap_set_file_slot, krb_5_keytab,
TAKE1, "Location of Kerberos V5 keytab file."),
rec = (kerb_auth_config *) ap_pcalloc(p, sizeof(kerb_auth_config));
((kerb_auth_config *)rec)->krb_verify_kdc = 1;
+ ((kerb_auth_config *)rec)->krb_service_name = "khttp";
#ifdef KRB5
((kerb_auth_config *)rec)->krb_method_k5pass = 1;
((kerb_auth_config *)rec)->krb_method_gssapi = 1;
ret = verify_krb4_user(r, (char *)sent_name,
(sent_instance) ? sent_instance : "",
- (char *)realm, (char *)sent_pw, "khttp",
+ (char *)realm, (char *)sent_pw,
+ conf->krb_service_name,
conf->krb_4_srvtab, conf->krb_verify_kdc);
if (ret == 0)
break;
if (code)
continue;
- code = verify_krb5_user(r, kcontext, client, ccache, sent_pw, "khttp",
+ code = verify_krb5_user(r, kcontext, client, ccache, sent_pw,
+ conf->krb_service_name,
keytab, conf->krb_verify_kdc);
if (code == 0)
break;
gss_name_t server_name = GSS_C_NO_NAME;
char buf[1024];
- snprintf(buf, sizeof(buf), "%s/%s", "khttp", ap_get_server_name(r));
+ snprintf(buf, sizeof(buf), "%s/%s", conf->krb_service_name, ap_get_server_name(r));
input_token.value = buf;
input_token.length = strlen(buf) + 1;
}
static int
+cmp_gss_type(gss_buffer_t token, gss_OID oid)
+{
+ unsigned char *p;
+ size_t len;
+
+ if (token->length == 0)
+ return GSS_S_DEFECTIVE_TOKEN;
+
+ p = token->value;
+ if (*p++ != 0x60)
+ return GSS_S_DEFECTIVE_TOKEN;
+ len = *p++;
+ if (len & 0x80) {
+ if ((len & 0x7f) > 4)
+ return GSS_S_DEFECTIVE_TOKEN;
+ p += len & 0x7f;
+ }
+ if (*p++ != 0x06)
+ return GSS_S_DEFECTIVE_TOKEN;
+
+ if (((OM_uint32) *p++) != oid->length)
+ return GSS_S_DEFECTIVE_TOKEN;
+
+ return memcmp(p, oid->elements, oid->length);
+}
+
+static int
authenticate_user_gss(request_rec *r,
kerb_auth_config *conf,
const char *auth_line)
int ret;
gss_name_t client_name = GSS_C_NO_NAME;
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
+ OM_uint32 (*accept_sec_token)();
+ gss_OID_desc spnego_oid;
+
+ spnego_oid.length = 6;
+ spnego_oid.elements = (void *)"\x2b\x06\x01\x05\x05\x02";
if (gss_connection == NULL) {
gss_connection = ap_pcalloc(r->connection->pool, sizeof(*gss_connection));
}
input_token.length = ap_base64decode(input_token.value, auth_param);
-#if 0
- major_status = gss_accept_sec_context(
-#else
- major_status = gss_accept_sec_context_spnego(
-#endif
- &minor_status,
- &gss_connection->context,
- gss_connection->server_creds,
- &input_token,
- GSS_C_NO_CHANNEL_BINDINGS,
- &client_name,
- NULL,
- &output_token,
- NULL,
- NULL,
- &delegated_cred);
+ accept_sec_token = (cmp_gss_type(&input_token, &spnego_oid) == 0) ?
+ gss_accept_sec_context_spnego : gss_accept_sec_context;
+
+ major_status = accept_sec_token(&minor_status,
+ &gss_connection->context,
+ gss_connection->server_creds,
+ &input_token,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &client_name,
+ NULL,
+ &output_token,
+ NULL,
+ NULL,
+ &delegated_cred);
if (output_token.length) {
char *token = NULL;
size_t len;