/* * Free a SPNEGO context handle. The caller must have acquired * the lock before this is called. */ OM_uint32 GSSAPI_CALLCONV _gss_spnego_internal_delete_sec_context (OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t output_token ) { gssspnego_ctx ctx; OM_uint32 ret, minor; *minor_status = 0; if (context_handle == NULL) { return GSS_S_NO_CONTEXT; } if (output_token != GSS_C_NO_BUFFER) { output_token->length = 0; output_token->value = NULL; } ctx = (gssspnego_ctx)*context_handle; *context_handle = GSS_C_NO_CONTEXT; if (ctx == NULL) { return GSS_S_NO_CONTEXT; } if (ctx->initiator_mech_types.val != NULL) free_MechTypeList(&ctx->initiator_mech_types); gss_release_oid(&minor, &ctx->preferred_mech_type); ctx->negotiated_mech_type = GSS_C_NO_OID; gss_release_name(&minor, &ctx->target_name); gss_release_name(&minor, &ctx->mech_src_name); if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { ret = gss_delete_sec_context(minor_status, &ctx->negotiated_ctx_id, output_token); ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; } else { ret = GSS_S_COMPLETE; } HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); free(ctx); return ret; }
static int decode_MechTypeList(const unsigned char *p, size_t len, MechTypeList * data, size_t * size) { size_t ret = 0, reallen; size_t l; int e; memset(data, 0, sizeof(*data)); reallen = 0; e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l); FORW; if (len < reallen) return ASN1_OVERRUN; len = reallen; { size_t origlen = len; size_t oldret = ret; ret = 0; (data)->len = 0; (data)->val = NULL; while (ret < origlen) { void *old = (data)->val; (data)->len++; (data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len); if ((data)->val == NULL) { (data)->val = old; (data)->len--; return ENOMEM; } e = decode_MechType(p, len, &(data)->val[(data)->len - 1], &l); FORW; len = origlen - ret; } ret += oldret; } if (size) *size = ret; return 0; fail: free_MechTypeList(data); return e; }
static void free_NegTokenInit(NegTokenInit * data) { free_MechTypeList(&(data)->mechTypes); if ((data)->reqFlags) { free_ContextFlags((data)->reqFlags); free((data)->reqFlags); (data)->reqFlags = NULL; } if ((data)->mechToken) { free_octet_string((data)->mechToken); free((data)->mechToken); (data)->mechToken = NULL; } if ((data)->mechListMIC) { free_octet_string((data)->mechListMIC); free((data)->mechListMIC); (data)->mechListMIC = NULL; } }
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; }