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; }
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; }
OM_uint32 GSSAPI_LIB_FUNCTION gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context, int prf_key, const gss_buffer_t prf_in, ssize_t desired_output_len, gss_buffer_t prf_out) { struct _gss_context *ctx = (struct _gss_context *) context; gssapi_mech_interface m; OM_uint32 major_status; _mg_buffer_zero(prf_out); *minor_status = 0; if (ctx == NULL) { *minor_status = 0; return GSS_S_NO_CONTEXT; } m = ctx->gc_mech; if (m->gm_pseudo_random == NULL) return GSS_S_UNAVAILABLE; major_status = (*m->gm_pseudo_random)(minor_status, ctx->gc_ctx, prf_key, prf_in, desired_output_len, prf_out); if (major_status != GSS_S_COMPLETE) _gss_mg_error(m, major_status, *minor_status); return major_status; }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_wrap(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer) { struct _gss_context *ctx = (struct _gss_context *) context_handle; gssapi_mech_interface m; if (conf_state) *conf_state = 0; _mg_buffer_zero(output_message_buffer); if (ctx == NULL) { *minor_status = 0; return GSS_S_NO_CONTEXT; } m = ctx->gc_mech; return (m->gm_wrap(minor_status, ctx->gc_ctx, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer)); }
OM_uint32 GSSAPI_LIB_FUNCTION gss_export_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t interprocess_token) { OM_uint32 major_status; struct _gss_context *ctx = (struct _gss_context *) *context_handle; gssapi_mech_interface m = ctx->gc_mech; gss_buffer_desc buf; _mg_buffer_zero(interprocess_token); major_status = m->gm_export_sec_context(minor_status, &ctx->gc_ctx, &buf); if (major_status == GSS_S_COMPLETE) { unsigned char *p; free(ctx); *context_handle = GSS_C_NO_CONTEXT; interprocess_token->length = buf.length + 2 + m->gm_mech_oid.length; interprocess_token->value = malloc(interprocess_token->length); if (!interprocess_token->value) { /* * We are in trouble here - the context is * already gone. This is allowed as long as we * set the caller's context_handle to * GSS_C_NO_CONTEXT, which we did above. * Return GSS_S_FAILURE. */ _mg_buffer_zero(interprocess_token); *minor_status = ENOMEM; return (GSS_S_FAILURE); } p = interprocess_token->value; p[0] = m->gm_mech_oid.length >> 8; p[1] = m->gm_mech_oid.length; memcpy(p + 2, m->gm_mech_oid.elements, m->gm_mech_oid.length); memcpy(p + 2 + m->gm_mech_oid.length, buf.value, buf.length); gss_release_buffer(minor_status, &buf); } else {
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_get_mic(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t message_token) { struct _gss_context *ctx = (struct _gss_context *) context_handle; gssapi_mech_interface m; _mg_buffer_zero(message_token); if (ctx == NULL) { *minor_status = 0; return GSS_S_NO_CONTEXT; } m = ctx->gc_mech; return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req, message_buffer, message_token)); }
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; }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_export_name(OM_uint32 *minor_status, const gss_name_t input_name, gss_buffer_t exported_name) { struct _gss_name *name = (struct _gss_name *) input_name; struct _gss_mechanism_name *mn; _mg_buffer_zero(exported_name); /* * If this name already has any attached MNs, export the first * one, otherwise export based on the first mechanism in our * list. */ mn = SLIST_FIRST(&name->gn_mn); if (!mn) { *minor_status = 0; return (GSS_S_NAME_NOT_MN); } return mn->gmn_mech->gm_export_name(minor_status, mn->gmn_name, exported_name); }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value, int status_type, const gss_OID mech_type, OM_uint32 *message_content, gss_buffer_t status_string) { OM_uint32 major_status; _mg_buffer_zero(status_string); *message_content = 0; major_status = _gss_mg_get_error(mech_type, status_type, status_value, status_string); if (major_status == GSS_S_COMPLETE) { *message_content = 0; *minor_status = 0; return GSS_S_COMPLETE; } *minor_status = 0; switch (status_type) { case GSS_C_GSS_CODE: { char *buf = NULL; int e; if (GSS_SUPPLEMENTARY_INFO(status_value)) e = asprintf(&buf, "%s", supplementary_error( GSS_SUPPLEMENTARY_INFO(status_value))); else e = asprintf (&buf, "%s %s", calling_error(GSS_CALLING_ERROR(status_value)), routine_error(GSS_ROUTINE_ERROR(status_value))); if (e < 0 || buf == NULL) break; status_string->length = strlen(buf); status_string->value = buf; return GSS_S_COMPLETE; } case GSS_C_MECH_CODE: { OM_uint32 maj_junk, min_junk; gss_buffer_desc oid; char *buf = NULL; int e; maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); if (maj_junk != GSS_S_COMPLETE) { oid.value = rk_UNCONST("unknown"); oid.length = 7; } e = asprintf (&buf, "unknown mech-code %lu for mech %.*s", (unsigned long)status_value, (int)oid.length, (char *)oid.value); if (maj_junk == GSS_S_COMPLETE) gss_release_buffer(&min_junk, &oid); if (e < 0 || buf == NULL) break; status_string->length = strlen(buf); status_string->value = buf; return GSS_S_COMPLETE; } } _mg_buffer_zero(status_string); return (GSS_S_BAD_STATUS); }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, const gss_cred_id_t acceptor_cred_handle, const gss_buffer_t input_token, const gss_channel_bindings_t input_chan_bindings, gss_name_t *src_name, gss_OID *mech_type, gss_buffer_t output_token, OM_uint32 *ret_flags, OM_uint32 *time_rec, gss_cred_id_t *delegated_cred_handle) { OM_uint32 major_status, mech_ret_flags, junk; gssapi_mech_interface m; struct _gss_context *ctx = (struct _gss_context *) *context_handle; struct _gss_cred *cred = (struct _gss_cred *) acceptor_cred_handle; struct _gss_mechanism_cred *mc; gss_cred_id_t acceptor_mc, delegated_mc; gss_name_t src_mn; gss_OID mech_ret_type = NULL; *minor_status = 0; if (src_name) *src_name = GSS_C_NO_NAME; if (mech_type) *mech_type = GSS_C_NO_OID; if (ret_flags) *ret_flags = 0; if (time_rec) *time_rec = 0; if (delegated_cred_handle) *delegated_cred_handle = GSS_C_NO_CREDENTIAL; _mg_buffer_zero(output_token); /* * If this is the first call (*context_handle is NULL), we must * parse the input token to figure out the mechanism to use. */ if (*context_handle == GSS_C_NO_CONTEXT) { gss_OID_desc mech_oid; major_status = choose_mech(input_token, &mech_oid); if (major_status != GSS_S_COMPLETE) return major_status; /* * Now that we have a mechanism, we can find the * implementation. */ ctx = malloc(sizeof(struct _gss_context)); if (!ctx) { *minor_status = ENOMEM; return (GSS_S_DEFECTIVE_TOKEN); } memset(ctx, 0, sizeof(struct _gss_context)); m = ctx->gc_mech = __gss_get_mechanism(&mech_oid); if (!m) { free(ctx); return (GSS_S_BAD_MECH); } *context_handle = (gss_ctx_id_t) ctx; } else { m = ctx->gc_mech; } if (cred) { HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) if (mc->gmc_mech == m) break; if (!mc) { gss_delete_sec_context(&junk, context_handle, NULL); return (GSS_S_BAD_MECH); } acceptor_mc = mc->gmc_cred; } else {