#include "mglueP.h"
static OM_uint32
val_exp_cred_args(OM_uint32 *minor_status, gss_cred_id_t cred_handle,
gss_buffer_t token)
{
if (minor_status != NULL)
*minor_status = 0;
if (token != GSS_C_NO_BUFFER) {
token->length = 0;
token->value = NULL;
}
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
if (cred_handle == GSS_C_NO_CREDENTIAL)
return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED;
if (token == GSS_C_NO_BUFFER)
return GSS_S_CALL_INACCESSIBLE_WRITE;
return GSS_S_COMPLETE;
}
OM_uint32 KRB5_CALLCONV
gss_export_cred(OM_uint32 * minor_status, gss_cred_id_t cred_handle,
gss_buffer_t token)
{
OM_uint32 status, tmpmin;
gss_union_cred_t cred;
gss_OID mech_oid;
gss_OID public_oid;
gss_mechanism mech;
gss_buffer_desc mech_token;
struct k5buf buf;
int i;
status = val_exp_cred_args(minor_status, cred_handle, token);
if (status != GSS_S_COMPLETE)
return status;
k5_buf_init_dynamic(&buf);
cred = (gss_union_cred_t) cred_handle;
for (i = 0; i < cred->count; i++) {
mech_oid = &cred->mechs_array[i];
public_oid = gssint_get_public_oid(mech_oid);
mech = gssint_get_mechanism(mech_oid);
if (public_oid == GSS_C_NO_OID || mech == NULL) {
status = GSS_S_DEFECTIVE_CREDENTIAL;
goto error;
}
if (mech->gss_export_cred == NULL) {
status = GSS_S_UNAVAILABLE;
goto error;
}
status = mech->gss_export_cred(minor_status, cred->cred_array[i],
&mech_token);
if (status != GSS_S_COMPLETE) {
map_error(minor_status, mech);
goto error;
}
k5_buf_add_uint32_be(&buf, public_oid->length);
k5_buf_add_len(&buf, public_oid->elements, public_oid->length);
k5_buf_add_uint32_be(&buf, mech_token.length);
k5_buf_add_len(&buf, mech_token.value, mech_token.length);
gss_release_buffer(&tmpmin, &mech_token);
}
return k5buf_to_gss(minor_status, &buf, token);
error:
k5_buf_free(&buf);
return status;
}