diff options
Diffstat (limited to 'src/lib/gssapi/mechglue/g_mechattr.c')
| -rw-r--r-- | src/lib/gssapi/mechglue/g_mechattr.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/lib/gssapi/mechglue/g_mechattr.c b/src/lib/gssapi/mechglue/g_mechattr.c new file mode 100644 index 000000000000..e49651eb6ade --- /dev/null +++ b/src/lib/gssapi/mechglue/g_mechattr.c @@ -0,0 +1,222 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/mechglue/g_mechattr.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#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; +} + +/* + * Return TRUE iff all the elements of desired and none of the elements + * of except exist in available. + */ +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; +} + +/* + * Return TRUE iff all the elements of critical exist in known. + */ +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) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor = 0; + + if (mechs == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *mechs = GSS_C_NO_OID_SET; + + 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) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *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; + + 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 the mech does not implement RFC 5587, return success with an empty + * mech_attrs and known_mech_attrs. */ + if (mech->gss_inquire_attrs_for_mech == NULL) + return GSS_S_COMPLETE; + + 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 (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) { + status = generic_gss_copy_oid_set(minor, + gss_ma_known_attrs, + 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); +} |
