static OM_uint32 select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p, gss_OID *mech_p) { char mechbuf[64]; size_t mech_len; gss_OID_desc oid; gss_OID oidp; gss_OID_set mechs; int i; OM_uint32 ret, junk; ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, sizeof(mechbuf), mechType, &mech_len); if (ret) { return GSS_S_DEFECTIVE_TOKEN; } oid.length = mech_len; oid.elements = mechbuf + sizeof(mechbuf) - mech_len; if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { return GSS_S_BAD_MECH; } *minor_status = 0; /* Translate broken MS Kebreros OID */ if (gss_oid_equal(&oid, &_gss_spnego_mskrb_mechanism_oid_desc)) oidp = &_gss_spnego_krb5_mechanism_oid_desc; else oidp = &oid; ret = gss_indicate_mechs(&junk, &mechs); if (ret) return (ret); for (i = 0; i < mechs->count; i++) if (gss_oid_equal(&mechs->elements[i], oidp)) break; if (i == mechs->count) { gss_release_oid_set(&junk, &mechs); return GSS_S_BAD_MECH; } gss_release_oid_set(&junk, &mechs); ret = gss_duplicate_oid(minor_status, &oid, /* possibly this should be oidp */ mech_p); if (verify_p) { gss_name_t name = GSS_C_NO_NAME; gss_buffer_desc namebuf; char *str = NULL, *host, hostname[MAXHOSTNAMELEN]; host = getenv("GSSAPI_SPNEGO_NAME"); if (host == NULL || issuid()) { if (gethostname(hostname, sizeof(hostname)) != 0) { *minor_status = errno; return GSS_S_FAILURE; } i = asprintf(&str, "host@%s", hostname); if (i < 0 || str == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } host = str; } namebuf.length = strlen(host); namebuf.value = host; ret = gss_import_name(minor_status, &namebuf, GSS_C_NT_HOSTBASED_SERVICE, &name); if (str) free(str); if (ret != GSS_S_COMPLETE) return ret; ret = acceptor_approved(name, *mech_p); gss_release_name(&junk, &name); } return ret; }
OM_uint32 GSSAPI_CALLCONV _gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, gss_name_t target_name, OM_uint32 (*func)(gss_name_t, gss_OID), int includeMSCompatOID, const gss_cred_id_t cred_handle, MechTypeList *mechtypelist, gss_OID *preferred_mech) { gss_OID_set supported_mechs = GSS_C_NO_OID_SET; gss_OID first_mech = GSS_C_NO_OID; OM_uint32 ret; size_t i; mechtypelist->len = 0; mechtypelist->val = NULL; if (cred_handle) { ret = gss_inquire_cred(minor_status, cred_handle, NULL, NULL, NULL, &supported_mechs); } else { ret = gss_indicate_mechs(minor_status, &supported_mechs); } if (ret != GSS_S_COMPLETE) { return ret; } if (supported_mechs->count == 0) { *minor_status = ENOENT; gss_release_oid_set(minor_status, &supported_mechs); return GSS_S_FAILURE; } ret = (*func)(target_name, GSS_KRB5_MECHANISM); if (ret == GSS_S_COMPLETE) { ret = add_mech_type(GSS_KRB5_MECHANISM, includeMSCompatOID, mechtypelist); if (!GSS_ERROR(ret)) first_mech = GSS_KRB5_MECHANISM; } ret = GSS_S_COMPLETE; for (i = 0; i < supported_mechs->count; i++) { OM_uint32 subret; if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM)) continue; if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM)) continue; subret = (*func)(target_name, &supported_mechs->elements[i]); if (subret != GSS_S_COMPLETE) continue; ret = add_mech_type(&supported_mechs->elements[i], includeMSCompatOID, mechtypelist); if (ret != 0) { *minor_status = ret; ret = GSS_S_FAILURE; break; } if (first_mech == GSS_C_NO_OID) first_mech = &supported_mechs->elements[i]; } if (mechtypelist->len == 0) { gss_release_oid_set(minor_status, &supported_mechs); *minor_status = 0; return GSS_S_BAD_MECH; } if (preferred_mech != NULL) { ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech); if (ret != GSS_S_COMPLETE) free_MechTypeList(mechtypelist); } gss_release_oid_set(minor_status, &supported_mechs); return ret; }
OM_uint32 GSSAPI_CALLCONV _gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, gss_name_t target_name, OM_uint32 (*func)(void *, gss_name_t, const gss_cred_id_t, gss_OID), void *userctx, int includeMSCompatOID, const gss_cred_id_t cred_handle, MechTypeList *mechtypelist, gss_OID *preferred_mech) { gss_OID_set supported_mechs = GSS_C_NO_OID_SET; gss_OID first_mech = GSS_C_NO_OID; OM_uint32 ret, junk; int present = 0; size_t i; mechtypelist->len = 0; mechtypelist->val = NULL; if (cred_handle) { ret = gss_inquire_cred(minor_status, cred_handle, NULL, NULL, NULL, &supported_mechs); } else { ret = gss_indicate_mechs(minor_status, &supported_mechs); } if (ret != GSS_S_COMPLETE) { return ret; } if (supported_mechs->count == 0) { *minor_status = ENOENT; gss_release_oid_set(minor_status, &supported_mechs); return GSS_S_FAILURE; } /* * Propose Kerberos mech first if we have Kerberos credentials/supported mechs */ ret = gss_test_oid_set_member(&junk, GSS_KRB5_MECHANISM, supported_mechs, &present); if (ret == GSS_S_COMPLETE && present) { ret = (*func)(userctx, target_name, cred_handle, GSS_KRB5_MECHANISM); if (ret == GSS_S_COMPLETE) { ret = add_mech_type(GSS_KRB5_MECHANISM, includeMSCompatOID, mechtypelist); if (!GSS_ERROR(ret)) { if (includeMSCompatOID) first_mech = &_gss_spnego_mskrb_mechanism_oid_desc; else first_mech = GSS_KRB5_MECHANISM; } #ifdef __APPLE_PRIVATE__ (void)add_mech_type(GSS_APPL_LKDC_SUPPORTED, 0, mechtypelist); #endif } } ret = GSS_S_COMPLETE; /* * Now lets, check all other mechs */ for (i = 0; i < supported_mechs->count; i++) { OM_uint32 subret; if (gss_oid_equal(&supported_mechs->elements[i], GSS_SPNEGO_MECHANISM)) continue; if (gss_oid_equal(&supported_mechs->elements[i], GSS_KRB5_MECHANISM)) continue; if (gss_oid_equal(&supported_mechs->elements[i], GSS_NETLOGON_MECHANISM)) continue; subret = (*func)(userctx, target_name, cred_handle, &supported_mechs->elements[i]); if (subret != GSS_S_COMPLETE) continue; ret = add_mech_type(&supported_mechs->elements[i], includeMSCompatOID, mechtypelist); if (ret != 0) { *minor_status = ret; ret = GSS_S_FAILURE; break; } if (first_mech == GSS_C_NO_OID) first_mech = &supported_mechs->elements[i]; } if (mechtypelist->len == 0) { gss_release_oid_set(minor_status, &supported_mechs); *minor_status = 0; return GSS_S_BAD_MECH; } if (preferred_mech != NULL) { ret = gss_duplicate_oid(minor_status, first_mech, preferred_mech); if (ret != GSS_S_COMPLETE) free_MechTypeList(mechtypelist); } gss_release_oid_set(minor_status, &supported_mechs); return ret; }