static int add_mech_type(gss_OID mech_type, int includeMSCompatOID, MechTypeList *mechtypelist) { MechType mech; int ret; if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM)) return 0; if (includeMSCompatOID && gss_oid_equal(mech_type, &_gss_spnego_krb5_mechanism_oid_desc)) { ret = der_get_oid(_gss_spnego_mskrb_mechanism_oid_desc.elements, _gss_spnego_mskrb_mechanism_oid_desc.length, &mech, NULL); if (ret) return ret; ret = add_MechTypeList(mechtypelist, &mech); free_MechType(&mech); if (ret) return ret; } ret = der_get_oid(mech_type->elements, mech_type->length, &mech, NULL); if (ret) return ret; ret = add_MechTypeList(mechtypelist, &mech); free_MechType(&mech); return ret; }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str) { int ret; size_t size; heim_oid o; char *p; _mg_buffer_zero(oid_str); if (oid == GSS_C_NULL_OID) return GSS_S_FAILURE; ret = der_get_oid (oid->elements, oid->length, &o, &size); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } ret = der_print_heim_oid(&o, ' ', &p); der_free_oid(&o); if (ret) { *minor_status = ret; return GSS_S_FAILURE; } oid_str->value = p; oid_str->length = strlen(p); *minor_status = 0; return GSS_S_COMPLETE; }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_encapsulate_token(gss_const_buffer_t input_token, gss_const_OID oid, gss_buffer_t output_token) { GSSAPIContextToken ct; int ret; size_t size; ret = der_get_oid (oid->elements, oid->length, &ct.thisMech, &size); if (ret) { _mg_buffer_zero(output_token); return GSS_S_FAILURE; } ct.innerContextToken.data = input_token->value; ct.innerContextToken.length = input_token->length; ASN1_MALLOC_ENCODE(GSSAPIContextToken, output_token->value, output_token->length, &ct, &size, ret); der_free_oid(&ct.thisMech); if (ret) { _mg_buffer_zero(output_token); return GSS_S_FAILURE; } if (output_token->length != size) abort(); return GSS_S_COMPLETE; }
static OM_uint32 send_accept (OM_uint32 *minor_status, gss_buffer_t output_token, gss_buffer_t mech_token) { NegTokenTarg targ; OM_uint32 ret; unsigned char *value = NULL; size_t length = 0; memset(&targ, 0, sizeof(targ)); targ.negResult = malloc(sizeof(*targ.negResult)); if (targ.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } *(targ.negResult) = accept_completed; targ.supportedMech = malloc(sizeof(*targ.supportedMech)); if (targ.supportedMech == NULL) { free_NegTokenTarg(&targ); *minor_status = ENOMEM; return GSS_S_FAILURE; } ret = der_get_oid(GSS_KRB5_MECH->elements, GSS_KRB5_MECH->length, targ.supportedMech, NULL); if (ret) { free_NegTokenTarg(&targ); *minor_status = ENOMEM; return GSS_S_FAILURE; } if (mech_token != NULL && mech_token->length != 0) { targ.responseToken = malloc(sizeof(*targ.responseToken)); if (targ.responseToken == NULL) { free_NegTokenTarg(&targ); *minor_status = ENOMEM; return GSS_S_FAILURE; } targ.responseToken->length = mech_token->length; targ.responseToken->data = mech_token->value; mech_token->length = 0; mech_token->value = NULL; } else { targ.responseToken = NULL; } ret = code_NegTokenArg (minor_status, &targ, &value, &length); output_token->value = value; output_token->length = length; free_NegTokenTarg(&targ); if (ret) return ret; return GSS_S_COMPLETE; }
static int oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix) { int ret; heim_oid oid; heim_oid prefix; *suffix = 0; ret = der_get_oid(oid_enc->elements, oid_enc->length, &oid, NULL); if (ret) { return 0; } ret = der_get_oid(prefix_enc->elements, prefix_enc->length, &prefix, NULL); if (ret) { der_free_oid(&oid); return 0; } ret = 0; if (oid.length - 1 == prefix.length) { *suffix = oid.components[oid.length - 1]; oid.length--; ret = (der_heim_oid_cmp(&oid, &prefix) == 0); oid.length++; } der_free_oid(&oid); der_free_oid(&prefix); return ret; }
static int add_mech(MechTypeList *mech_list, gss_OID mech) { MechType *tmp; int ret; tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp)); if (tmp == NULL) return ENOMEM; mech_list->val = tmp; ret = der_get_oid(mech->elements, mech->length, &mech_list->val[mech_list->len], NULL); if (ret) return ret; mech_list->len++; return 0; }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_decapsulate_token(gss_const_buffer_t input_token, gss_const_OID oid, gss_buffer_t output_token) { GSSAPIContextToken ct; heim_oid o; OM_uint32 status; int ret; size_t size; _mg_buffer_zero(output_token); ret = der_get_oid (oid->elements, oid->length, &o, &size); if (ret) return GSS_S_FAILURE; ret = decode_GSSAPIContextToken(input_token->value, input_token->length, &ct, NULL); if (ret) { der_free_oid(&o); return GSS_S_FAILURE; } if (der_heim_oid_cmp(&ct.thisMech, &o) == 0) { status = GSS_S_COMPLETE; output_token->value = ct.innerContextToken.data; output_token->length = ct.innerContextToken.length; der_free_oid(&ct.thisMech); } else { free_GSSAPIContextToken(&ct); status = GSS_S_FAILURE; } der_free_oid(&o); return status; }
OM_uint32 gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, gss_ctx_id_t context_handle, int ad_type, gss_buffer_t ad_data) { gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; OM_uint32 maj_stat; gss_OID_desc oid_flat; heim_oid baseoid, oid; size_t size; if (context_handle == GSS_C_NO_CONTEXT) { *minor_status = EINVAL; return GSS_S_FAILURE; } /* All this to append an integer to an oid... */ if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length, &baseoid, NULL) != 0) { *minor_status = EINVAL; return GSS_S_FAILURE; } oid.length = baseoid.length + 1; oid.components = calloc(oid.length, sizeof(*oid.components)); if (oid.components == NULL) { der_free_oid(&baseoid); *minor_status = ENOMEM; return GSS_S_FAILURE; } memcpy(oid.components, baseoid.components, baseoid.length * sizeof(*baseoid.components)); der_free_oid(&baseoid); oid.components[oid.length - 1] = ad_type; oid_flat.length = der_length_oid(&oid); oid_flat.elements = malloc(oid_flat.length); if (oid_flat.elements == NULL) { free(oid.components); *minor_status = ENOMEM; return GSS_S_FAILURE; } if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1, oid_flat.length, &oid, &size) != 0) { free(oid.components); free(oid_flat.elements); *minor_status = EINVAL; return GSS_S_FAILURE; } if (oid_flat.length != size) abort(); free(oid.components); /* FINALLY, we have the OID */ maj_stat = gss_inquire_sec_context_by_oid (minor_status, context_handle, &oid_flat, &data_set); free(oid_flat.elements); if (maj_stat) return maj_stat; if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { gss_release_buffer_set(minor_status, &data_set); *minor_status = EINVAL; return GSS_S_FAILURE; } ad_data->value = malloc(data_set->elements[0].length); if (ad_data->value == NULL) { gss_release_buffer_set(minor_status, &data_set); *minor_status = ENOMEM; return GSS_S_FAILURE; } ad_data->length = data_set->elements[0].length; memcpy(ad_data->value, data_set->elements[0].value, ad_data->length); gss_release_buffer_set(minor_status, &data_set); *minor_status = 0; return GSS_S_COMPLETE; }
static OM_uint32 send_accept (OM_uint32 *minor_status, gssspnego_ctx context_handle, gss_buffer_t mech_token, int initial_response, gss_buffer_t mech_buf, gss_buffer_t output_token) { NegotiationToken nt; OM_uint32 ret; gss_buffer_desc mech_mic_buf; size_t size; memset(&nt, 0, sizeof(nt)); nt.element = choice_NegotiationToken_negTokenResp; ALLOC(nt.u.negTokenResp.negResult, 1); if (nt.u.negTokenResp.negResult == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } if (context_handle->open) { if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0 && mech_buf != GSS_C_NO_BUFFER) *(nt.u.negTokenResp.negResult) = accept_incomplete; else *(nt.u.negTokenResp.negResult) = accept_completed; } else { if (initial_response && context_handle->require_mic) *(nt.u.negTokenResp.negResult) = request_mic; else *(nt.u.negTokenResp.negResult) = accept_incomplete; } if (initial_response) { ALLOC(nt.u.negTokenResp.supportedMech, 1); if (nt.u.negTokenResp.supportedMech == NULL) { free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } ret = der_get_oid(context_handle->preferred_mech_type->elements, context_handle->preferred_mech_type->length, nt.u.negTokenResp.supportedMech, NULL); if (ret) { free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } } else { nt.u.negTokenResp.supportedMech = NULL; } if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0) { ALLOC(nt.u.negTokenResp.responseToken, 1); if (nt.u.negTokenResp.responseToken == NULL) { free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } nt.u.negTokenResp.responseToken->length = mech_token->length; nt.u.negTokenResp.responseToken->data = mech_token->value; mech_token->length = 0; mech_token->value = NULL; } else { nt.u.negTokenResp.responseToken = NULL; } if (mech_buf != GSS_C_NO_BUFFER) { ret = gss_get_mic(minor_status, context_handle->negotiated_ctx_id, 0, mech_buf, &mech_mic_buf); if (ret == GSS_S_COMPLETE) { ALLOC(nt.u.negTokenResp.mechListMIC, 1); if (nt.u.negTokenResp.mechListMIC == NULL) { gss_release_buffer(minor_status, &mech_mic_buf); free_NegotiationToken(&nt); *minor_status = ENOMEM; return GSS_S_FAILURE; } nt.u.negTokenResp.mechListMIC->length = mech_mic_buf.length; nt.u.negTokenResp.mechListMIC->data = mech_mic_buf.value; } else if (ret == GSS_S_UNAVAILABLE) { nt.u.negTokenResp.mechListMIC = NULL; } else { free_NegotiationToken(&nt); return ret; } } else nt.u.negTokenResp.mechListMIC = NULL; ASN1_MALLOC_ENCODE(NegotiationToken, output_token->value, output_token->length, &nt, &size, ret); if (ret) { free_NegotiationToken(&nt); *minor_status = ret; return GSS_S_FAILURE; } /* * The response should not be encapsulated, because * it is a SubsequentContextToken (note though RFC 1964 * specifies encapsulation for all _Kerberos_ tokens). */ if (*(nt.u.negTokenResp.negResult) == accept_completed) ret = GSS_S_COMPLETE; else ret = GSS_S_CONTINUE_NEEDED; free_NegotiationToken(&nt); return ret; }