#include "mglueP.h"
static int
testMechAttr(gss_const_OID attr,
gss_const_OID_set against)
{
int present = 0;
OM_uint32 minor;
if (GSS_ERROR(generic_gss_test_oid_set_member(&minor, attr,
(gss_OID_set)against,
&present)))
return 0;
return present;
}
static int
testMechAttrsOffered(gss_const_OID_set desired,
gss_const_OID_set except,
gss_const_OID_set available)
{
size_t i;
if (desired != GSS_C_NO_OID_SET) {
for (i = 0; i < desired->count; i++) {
if (!testMechAttr(&desired->elements[i], available))
return 0;
}
}
if (except != GSS_C_NO_OID_SET) {
for (i = 0; i < except->count; i++) {
if (testMechAttr(&except->elements[i], available))
return 0;
}
}
return 1;
}
static int
testMechAttrsKnown(gss_const_OID_set critical,
gss_const_OID_set known)
{
size_t i;
if (critical != GSS_C_NO_OID_SET) {
for (i = 0; i < critical->count; i++) {
if (!testMechAttr(&critical->elements[i], known))
return 0;
}
}
return 1;
}
OM_uint32 KRB5_CALLCONV
gss_indicate_mechs_by_attrs(
OM_uint32 *minor,
gss_const_OID_set desired_mech_attrs,
gss_const_OID_set except_mech_attrs,
gss_const_OID_set critical_mech_attrs,
gss_OID_set *mechs)
{
OM_uint32 status, tmpMinor;
gss_OID_set allMechs = GSS_C_NO_OID_SET;
size_t i;
if (minor != NULL)
*minor = 0;
if (mechs != NULL)
*mechs = GSS_C_NO_OID_SET;
if (minor == NULL || mechs == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
status = gss_indicate_mechs(minor, &allMechs);
if (GSS_ERROR(status))
goto cleanup;
status = generic_gss_create_empty_oid_set(minor, mechs);
if (GSS_ERROR(status))
goto cleanup;
for (i = 0; i < allMechs->count; i++) {
gss_OID_set supportedAttrs = GSS_C_NO_OID_SET;
gss_OID_set knownAttrs = GSS_C_NO_OID_SET;
status = gss_inquire_attrs_for_mech(minor, &allMechs->elements[i],
&supportedAttrs, &knownAttrs);
if (GSS_ERROR(status))
continue;
if (testMechAttrsOffered(desired_mech_attrs,
except_mech_attrs, supportedAttrs) &&
testMechAttrsKnown(critical_mech_attrs, knownAttrs)) {
status = gss_add_oid_set_member(minor, &allMechs->elements[i],
mechs);
if (GSS_ERROR(status)) {
gss_release_oid_set(&tmpMinor, &supportedAttrs);
gss_release_oid_set(&tmpMinor, &knownAttrs);
goto cleanup;
}
}
gss_release_oid_set(&tmpMinor, &supportedAttrs);
gss_release_oid_set(&tmpMinor, &knownAttrs);
}
*minor = 0;
status = GSS_S_COMPLETE;
cleanup:
gss_release_oid_set(&tmpMinor, &allMechs);
return status;
}
OM_uint32 KRB5_CALLCONV
gss_inquire_attrs_for_mech(
OM_uint32 *minor,
gss_const_OID mech_oid,
gss_OID_set *mech_attrs,
gss_OID_set *known_mech_attrs)
{
OM_uint32 status, tmpMinor;
gss_OID selected_mech, public_mech;
gss_mechanism mech;
if (minor != NULL)
*minor = 0;
if (mech_attrs != NULL)
*mech_attrs = GSS_C_NO_OID_SET;
if (known_mech_attrs != NULL)
*known_mech_attrs = GSS_C_NO_OID_SET;
if (minor == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
status = gssint_select_mech_type(minor, mech_oid, &selected_mech);
if (status != GSS_S_COMPLETE)
return status;
mech = gssint_get_mechanism(selected_mech);
if (mech == NULL)
return GSS_S_BAD_MECH;
if (mech->gss_inquire_attrs_for_mech != NULL) {
public_mech = gssint_get_public_oid(selected_mech);
status = mech->gss_inquire_attrs_for_mech(minor, public_mech,
mech_attrs,
known_mech_attrs);
if (GSS_ERROR(status)) {
map_error(minor, mech);
return status;
}
}
if (mech_attrs != NULL && *mech_attrs == GSS_C_NO_OID_SET) {
status = generic_gss_create_empty_oid_set(minor, mech_attrs);
if (status != GSS_S_COMPLETE) {
if (known_mech_attrs != NULL)
gss_release_oid_set(&tmpMinor, known_mech_attrs);
return status;
}
}
if (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) {
if (mech->gss_inquire_attrs_for_mech != NULL) {
status = generic_gss_copy_oid_set(minor,
gss_ma_known_attrs,
known_mech_attrs);
} else {
status = generic_gss_create_empty_oid_set(minor, known_mech_attrs);
}
if (GSS_ERROR(status)) {
gss_release_oid_set(&tmpMinor, mech_attrs);
if (mech_attrs != NULL)
*mech_attrs = GSS_C_NO_OID_SET;
}
}
return GSS_S_COMPLETE;
}
OM_uint32 KRB5_CALLCONV
gss_display_mech_attr(
OM_uint32 *minor,
gss_const_OID mech_attr,
gss_buffer_t name,
gss_buffer_t short_desc,
gss_buffer_t long_desc)
{
return generic_gss_display_mech_attr(minor, mech_attr,
name, short_desc, long_desc);
}