X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=mech_eap%2Faccept_sec_context.c;h=b594af0abd9d857a26dd2ce29e08e19ec0b86d5b;hb=3f993b33bfbccc6ac801d665a3d77a6f911ff74a;hp=e4f1ef5c1ddc84a2cf165d752bc2c68324628f02;hpb=d762e264f45bc069587d4c47952a797c0de35c01;p=mech_eap.git diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c index e4f1ef5..b594af0 100644 --- a/mech_eap/accept_sec_context.c +++ b/mech_eap/accept_sec_context.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, JANET(UK) + * Copyright (c) 2011, 2013, 2015, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,7 @@ static OM_uint32 eapGssSmAcceptGssReauth(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target, + gss_const_name_t target, gss_OID mech, OM_uint32 reqFlags, OM_uint32 timeReq, @@ -135,7 +135,7 @@ static OM_uint32 eapGssSmAcceptAcceptorName(OM_uint32 *minor, gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -164,7 +164,7 @@ static OM_uint32 eapGssSmAcceptVendorInfo(OM_uint32 *minor, gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx GSSEAP_UNUSED, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -190,7 +190,7 @@ static OM_uint32 eapGssSmAcceptIdentity(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -345,7 +345,7 @@ setAcceptorIdentity(OM_uint32 *minor, krbPrinc = ctx->acceptorName->krbPrincipal; GSSEAP_ASSERT(krbPrinc != NULL); - GSSEAP_ASSERT(KRB_PRINC_LENGTH(krbPrinc) >= 2); + GSSEAP_ASSERT(KRB_PRINC_LENGTH(krbPrinc) >= 1); /* Acceptor-Service-Name */ krbPrincComponentToGssBuffer(krbPrinc, 0, &nameBuf); @@ -358,41 +358,30 @@ setAcceptorIdentity(OM_uint32 *minor, return major; /* Acceptor-Host-Name */ - krbPrincComponentToGssBuffer(krbPrinc, 1, &nameBuf); - - major = gssEapRadiusAddAvp(minor, req, - PW_GSS_ACCEPTOR_HOST_NAME, - 0, - &nameBuf); - if (GSS_ERROR(major)) - return major; - + if (KRB_PRINC_LENGTH(krbPrinc) >= 2) { + krbPrincComponentToGssBuffer(krbPrinc, 1, &nameBuf); + + major = gssEapRadiusAddAvp(minor, req, + PW_GSS_ACCEPTOR_HOST_NAME, + 0, + &nameBuf); + if (GSS_ERROR(major)) + return major; + } if (KRB_PRINC_LENGTH(krbPrinc) > 2) { /* Acceptor-Service-Specific */ - krb5_principal_data ssiPrinc = *krbPrinc; - char *ssi; - - KRB_PRINC_LENGTH(&ssiPrinc) -= 2; - KRB_PRINC_NAME(&ssiPrinc) += 2; - - *minor = krb5_unparse_name_flags(krbContext, &ssiPrinc, - KRB5_PRINCIPAL_UNPARSE_NO_REALM, &ssi); + *minor = krbPrincUnparseServiceSpecifics(krbContext, + krbPrinc, &nameBuf); if (*minor != 0) return GSS_S_FAILURE; - nameBuf.value = ssi; - nameBuf.length = strlen(ssi); - major = gssEapRadiusAddAvp(minor, req, PW_GSS_ACCEPTOR_SERVICE_SPECIFICS, 0, &nameBuf); - - if (GSS_ERROR(major)) { - krb5_free_unparsed_name(krbContext, ssi); + krbFreeUnparsedName(krbContext, &nameBuf); + if (GSS_ERROR(major)) return major; - } - krb5_free_unparsed_name(krbContext, ssi); } krbPrincRealmToGssBuffer(krbPrinc, &nameBuf); @@ -450,6 +439,55 @@ createRadiusHandle(OM_uint32 *minor, return GSS_S_COMPLETE; } +/** + * Choose the correct error for an access reject packet. + */ +static OM_uint32 +eapGssAcceptHandleReject(OM_uint32 *minor, + struct rs_packet *response) +{ + rs_avp **vps; + rs_const_avp *vp = NULL; + OM_uint32 major; + const char *reply_message = NULL; + size_t reply_length = 0; + + rs_packet_avps(response, &vps); + major = gssEapRadiusGetRawAvp(minor, *vps, + PW_REPLY_MESSAGE, 0, &vp); + if (!GSS_ERROR(major)) { + reply_message = rs_avp_string_value(vp); + reply_length = rs_avp_length(vp); + } + + major = gssEapRadiusGetRawAvp(minor, *vps, + PW_ERROR_CAUSE, 0, &vp); + if (!GSS_ERROR(major)) { + switch (rs_avp_integer_value(vp)) { + /* Values from http://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-18 */ + case 502: /* request not routable (proxy) */ + *minor = GSSEAP_RADIUS_UNROUTABLE; + break; + case 501: /* administratively prohibited */ + *minor = GSSEAP_RADIUS_ADMIN_PROHIBIT; + break; + + default: + *minor = GSSEAP_RADIUS_AUTH_FAILURE; + break; + } + } else + *minor = GSSEAP_RADIUS_AUTH_FAILURE; + + if (reply_message != NULL) + gssEapSaveStatusInfo(*minor, "%s: %.*s", error_message(*minor), + reply_length, reply_message); + else + gssEapSaveStatusInfo(*minor, "%s", error_message(*minor)); + + return GSS_S_DEFECTIVE_CREDENTIAL; +} + /* * Process a EAP response from the initiator. */ @@ -457,7 +495,7 @@ static OM_uint32 eapGssSmAcceptAuthenticate(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -538,8 +576,7 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, case PW_ACCESS_ACCEPT: break; case PW_ACCESS_REJECT: - *minor = GSSEAP_RADIUS_AUTH_FAILURE; - major = GSS_S_DEFECTIVE_CREDENTIAL; + major = eapGssAcceptHandleReject( minor, resp); goto cleanup; break; default: @@ -603,7 +640,7 @@ static OM_uint32 eapGssSmAcceptGssFlags(OM_uint32 *minor, gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -637,7 +674,7 @@ static OM_uint32 eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -651,6 +688,9 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, krb5_data data; krb5_checksum cksum; krb5_boolean valid = FALSE; +#ifdef HAVE_HEIMDAL_VERSION + krb5_crypto krbCrypto; +#endif if (chanBindings == GSS_C_NO_CHANNEL_BINDINGS || chanBindings->application_data.length == 0) @@ -664,9 +704,29 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor, KRB_CHECKSUM_INIT(&cksum, ctx->checksumType, inputToken); +#ifdef HAVE_HEIMDAL_VERSION + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, 0, &krbCrypto); + if (code != 0) { + *minor = code; + return GSS_S_FAILURE; + } + + code = krb5_verify_checksum(krbContext, krbCrypto, + KEY_USAGE_GSSEAP_CHBIND_MIC, + data.data, data.length, &cksum); + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + code = 0; + valid = FALSE; + } else if (code == 0) { + valid = TRUE; + } + + krb5_crypto_destroy(krbContext, krbCrypto); +#else code = krb5_c_verify_checksum(krbContext, &ctx->rfc3961Key, KEY_USAGE_GSSEAP_CHBIND_MIC, &data, &cksum, &valid); +#endif /* HAVE_HEIMDAL_VERSION */ if (code != 0) { *minor = code; return GSS_S_FAILURE; @@ -687,7 +747,7 @@ static OM_uint32 eapGssSmAcceptInitiatorMIC(OM_uint32 *minor, gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -727,7 +787,7 @@ static OM_uint32 eapGssSmAcceptReauthCreds(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -756,7 +816,7 @@ static OM_uint32 eapGssSmAcceptAcceptorMIC(OM_uint32 *minor, gss_cred_id_t cred GSSEAP_UNUSED, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech GSSEAP_UNUSED, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -985,7 +1045,7 @@ static OM_uint32 eapGssSmAcceptGssReauth(OM_uint32 *minor, gss_cred_id_t cred, gss_ctx_id_t ctx, - gss_name_t target GSSEAP_UNUSED, + gss_const_name_t target GSSEAP_UNUSED, gss_OID mech, OM_uint32 reqFlags GSSEAP_UNUSED, OM_uint32 timeReq GSSEAP_UNUSED, @@ -1043,7 +1103,11 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor, OM_uint32 GSSAPI_CALLCONV gss_accept_sec_context(OM_uint32 *minor, gss_ctx_id_t *context_handle, +#ifdef HAVE_HEIMDAL_VERSION + gss_const_cred_id_t cred, +#else gss_cred_id_t cred, +#endif gss_buffer_t input_token, gss_channel_bindings_t input_chan_bindings, gss_name_t *src_name, @@ -1081,7 +1145,7 @@ gss_accept_sec_context(OM_uint32 *minor, major = gssEapAcceptSecContext(minor, ctx, - cred, + (gss_cred_id_t)cred, input_token, input_chan_bindings, src_name, @@ -1096,5 +1160,7 @@ gss_accept_sec_context(OM_uint32 *minor, if (GSS_ERROR(major)) gssEapReleaseContext(&tmpMinor, context_handle); + gssEapTraceStatus("gss_accept_sec_context", major, *minor); + return major; }