#include "mglueP.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#include <time.h>
static OM_uint32
alloc_union_cred(OM_uint32 *minor_status,
gss_mechanism mech,
gss_cred_id_t mech_cred,
gss_union_cred_t *pcred)
{
OM_uint32 status;
OM_uint32 temp_minor_status;
gss_union_cred_t cred = NULL;
*pcred = NULL;
status = GSS_S_FAILURE;
cred = calloc(1, sizeof(*cred));
if (cred == NULL) {
*minor_status = ENOMEM;
goto cleanup;
}
cred->loopback = cred;
cred->count = 1;
cred->cred_array = calloc(cred->count, sizeof(gss_cred_id_t));
if (cred->cred_array == NULL) {
*minor_status = ENOMEM;
goto cleanup;
}
cred->cred_array[0] = mech_cred;
status = generic_gss_copy_oid(minor_status,
&mech->mech_type,
&cred->mechs_array);
if (status != GSS_S_COMPLETE)
goto cleanup;
status = GSS_S_COMPLETE;
*pcred = cred;
cleanup:
if (status != GSS_S_COMPLETE)
gss_release_cred(&temp_minor_status, (gss_cred_id_t *)&cred);
return status;
}
OM_uint32 KRB5_CALLCONV
gss_set_cred_option(OM_uint32 *minor_status,
gss_cred_id_t *cred_handle,
const gss_OID desired_object,
const gss_buffer_t value)
{
gss_union_cred_t union_cred;
gss_mechanism mech;
int i;
OM_uint32 status;
OM_uint32 mech_status;
OM_uint32 mech_minor_status;
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*minor_status = 0;
if (cred_handle == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
status = GSS_S_UNAVAILABLE;
if (*cred_handle == GSS_C_NO_CREDENTIAL) {
gss_cred_id_t mech_cred = GSS_C_NO_CREDENTIAL;
mech = gssint_get_mechanism(NULL);
if (mech == NULL)
return GSS_S_BAD_MECH;
if (mech->gssspi_set_cred_option == NULL)
return GSS_S_UNAVAILABLE;
status = mech->gssspi_set_cred_option(minor_status,
&mech_cred,
desired_object,
value);
if (status != GSS_S_COMPLETE) {
map_error(minor_status, mech);
return status;
}
if (mech_cred != GSS_C_NO_CREDENTIAL) {
status = alloc_union_cred(minor_status,
mech,
mech_cred,
&union_cred);
if (status != GSS_S_COMPLETE)
return status;
*cred_handle = (gss_cred_id_t)union_cred;
}
} else {
union_cred = (gss_union_cred_t)*cred_handle;
for (i = 0; i < union_cred->count; i++) {
mech = gssint_get_mechanism(&union_cred->mechs_array[i]);
if (mech == NULL) {
status = GSS_S_BAD_MECH;
break;
}
if (mech->gssspi_set_cred_option == NULL)
continue;
mech_status = mech->gssspi_set_cred_option(&mech_minor_status,
&union_cred->cred_array[i],
desired_object,
value);
if (mech_status == GSS_S_UNAVAILABLE)
continue;
else {
status = mech_status;
*minor_status = mech_minor_status;
}
if (status != GSS_S_COMPLETE) {
map_error(minor_status, mech);
break;
}
}
}
return status;
}
OM_uint32 KRB5_CALLCONV
gssspi_set_cred_option(OM_uint32 *minor_status,
gss_cred_id_t cred,
const gss_OID desired_object,
const gss_buffer_t value);
OM_uint32 KRB5_CALLCONV
gssspi_set_cred_option(OM_uint32 *minor_status,
gss_cred_id_t cred,
const gss_OID desired_object,
const gss_buffer_t value)
{
return gss_set_cred_option(minor_status, &cred,
desired_object, value);
}