From 45cd381f53218abaa8236891ff94a3e8744c8af0 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 9 Jan 2011 22:05:27 +1100 Subject: [PATCH] Cleanup API-as-SPI compatibility layer --- lib/gssapi/gssapi_mech.h | 31 ++------ lib/gssapi/mech/compat.h | 63 +++++++++++++++ lib/gssapi/mech/gss_mech_switch.c | 44 ++++++----- lib/gssapi/mech/gss_mo.c | 126 +++++++++++++++++------------- lib/gssapi/mech/mech_locl.h | 1 + 5 files changed, 166 insertions(+), 99 deletions(-) create mode 100644 lib/gssapi/mech/compat.h diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index 4e2fc9e93..8e873b55d 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -495,33 +495,14 @@ typedef OM_uint32 GSSAPI_CALLCONV _gss_release_any_name_mapping_t ( gss_any_t * /* input */ ); -typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_saslname_for_mech_t ( - OM_uint32 *, /* minor_status */ - const gss_OID, /* desired_mech */ - gss_buffer_t, /* sasl_mech_name */ - gss_buffer_t, /* mech_name */ - gss_buffer_t /* mech_description */ - ); - -typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_mech_for_saslname_t ( - OM_uint32 *, /* minor_status */ - const gss_buffer_t, /* sasl_mech_name */ - gss_OID * /* mech_type */ - ); - -typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_attrs_for_mech_t ( - OM_uint32 *, /* minor_status */ - gss_const_OID, /* mech */ - gss_OID_set *, /* mech_attrs */ - gss_OID_set * /* known_mech_attrs */ - ); +/* mechglue internal */ +struct gss_mech_compat_desc_struct; #define GMI_VERSION 5 /* gm_flags */ #define GM_USE_MG_CRED 1 /* uses mech glue credentials */ - typedef struct gssapi_mech_interface_desc { unsigned gm_version; const char *gm_name; @@ -576,8 +557,7 @@ typedef struct gssapi_mech_interface_desc { _gss_cred_label_set_t *gm_cred_label_set; gss_mo_desc *gm_mo; size_t gm_mo_num; - _gss_acquire_cred_with_password_t *gm_acquire_cred_with_password; - _gss_add_cred_with_password_t *gm_add_cred_with_password; + struct gss_mech_compat_desc_struct *gm_compat; _gss_display_name_ext_t *gm_display_name_ext; _gss_inquire_name_t *gm_inquire_name; _gss_get_name_attribute_t *gm_get_name_attribute; @@ -586,9 +566,8 @@ typedef struct gssapi_mech_interface_desc { _gss_export_name_composite_t *gm_export_name_composite; _gss_map_name_to_any_t *gm_map_name_to_any; _gss_release_any_name_mapping_t *gm_release_any_name_mapping; - _gss_inquire_saslname_for_mech_t *gm_inquire_saslname_for_mech; - _gss_inquire_mech_for_saslname_t *gm_inquire_mech_for_saslname; - _gss_inquire_attrs_for_mech_t *gm_inquire_attrs_for_mech; + _gss_acquire_cred_with_password_t *gm_acquire_cred_with_password; + _gss_add_cred_with_password_t *gm_add_cred_with_password; } gssapi_mech_interface_desc, *gssapi_mech_interface; gssapi_mech_interface diff --git a/lib/gssapi/mech/compat.h b/lib/gssapi/mech/compat.h new file mode 100644 index 000000000..b3ac2f544 --- /dev/null +++ b/lib/gssapi/mech/compat.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2010, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_saslname_for_mech_t ( + OM_uint32 *, /* minor_status */ + const gss_OID, /* desired_mech */ + gss_buffer_t, /* sasl_mech_name */ + gss_buffer_t, /* mech_name */ + gss_buffer_t /* mech_description */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_mech_for_saslname_t ( + OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* sasl_mech_name */ + gss_OID * /* mech_type */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_attrs_for_mech_t ( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech */ + gss_OID_set *, /* mech_attrs */ + gss_OID_set * /* known_mech_attrs */ + ); + +/* + * API-as-SPI compatibility for compatibility with MIT mechanisms; + * native Heimdal mechanisms should not use these. + */ +struct gss_mech_compat_desc_struct { + _gss_inquire_saslname_for_mech_t *gmc_inquire_saslname_for_mech; + _gss_inquire_mech_for_saslname_t *gmc_inquire_mech_for_saslname; + _gss_inquire_attrs_for_mech_t *gmc_inquire_attrs_for_mech; +}; + diff --git a/lib/gssapi/mech/gss_mech_switch.c b/lib/gssapi/mech/gss_mech_switch.c index be61f8d0b..460f06154 100644 --- a/lib/gssapi/mech/gss_mech_switch.c +++ b/lib/gssapi/mech/gss_mech_switch.c @@ -168,6 +168,11 @@ do { \ m->gm_mech.gm_ ## name = dlsym(so, "gssspi_" #name); \ } while (0) +#define COMPATSYM(name) \ +do { \ + m->gm_mech.gm_compat->gmc_ ## name = dlsym(so, "gss_" #name); \ +} while (0) + /* * */ @@ -286,28 +291,26 @@ _gss_load_mech(void) #endif so = dlopen(lib, RTLD_LAZY | RTLD_LOCAL | RTLD_GROUP); - if (!so) { + if (so == NULL) { /* fprintf(stderr, "dlopen: %s\n", dlerror()); */ - free(mech_oid.elements); - continue; + goto bad; } - m = malloc(sizeof(*m)); - if (!m) { - free(mech_oid.elements); - break; - } + m = calloc(1, sizeof(*m)); + if (m == NULL) + goto bad; + m->gm_so = so; m->gm_mech.gm_mech_oid = mech_oid; m->gm_mech.gm_flags = 0; - + m->gm_mech.gm_compat = calloc(1, sizeof(struct gss_mech_compat_desc_struct)); + if (m->gm_mech.gm_compat == NULL) + goto bad; + major_status = gss_add_oid_set_member(&minor_status, &m->gm_mech.gm_mech_oid, &_gss_mech_oids); - if (major_status) { - free(m->gm_mech.gm_mech_oid.elements); - free(m); - continue; - } + if (GSS_ERROR(major_status)) + goto bad; SYM(acquire_cred); SYM(release_cred); @@ -346,8 +349,6 @@ _gss_load_mech(void) OPTSYM(wrap_iov); OPTSYM(unwrap_iov); OPTSYM(wrap_iov_length); - OPTSPISYM(acquire_cred_with_password); - OPTSYM(add_cred_with_password); OPTSYM(display_name_ext); OPTSYM(inquire_name); OPTSYM(get_name_attribute); @@ -356,9 +357,13 @@ _gss_load_mech(void) OPTSYM(export_name_composite); OPTSYM(map_name_to_any); OPTSYM(release_any_name_mapping); - OPTSYM(inquire_saslname_for_mech); - OPTSYM(inquire_mech_for_saslname); - OPTSYM(inquire_attrs_for_mech); + OPTSPISYM(acquire_cred_with_password); + OPTSYM(add_cred_with_password); + + /* API-as-SPI compatibility */ + COMPATSYM(inquire_saslname_for_mech); + COMPATSYM(inquire_mech_for_saslname); + COMPATSYM(inquire_attrs_for_mech); /* pick up the oid sets of names */ @@ -373,6 +378,7 @@ _gss_load_mech(void) continue; bad: + free(m->gm_mech.gm_compat); free(m->gm_mech.gm_mech_oid.elements); free(m); dlclose(so); diff --git a/lib/gssapi/mech/gss_mo.c b/lib/gssapi/mech/gss_mo.c index 71da150e0..f280135b4 100644 --- a/lib/gssapi/mech/gss_mo.c +++ b/lib/gssapi/mech/gss_mo.c @@ -44,7 +44,6 @@ get_option_def(int def, gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) return def; } - int _gss_mo_get_option_1(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) { @@ -63,10 +62,10 @@ _gss_mo_get_ctx_as_string(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t valu if (value) { value->value = strdup((char *)mo->ctx); if (value->value == NULL) - return 1; + return GSS_S_FAILURE; value->length = strlen((char *)mo->ctx); } - return 0; + return GSS_S_COMPLETE; } GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL @@ -82,7 +81,8 @@ gss_mo_set(gss_const_OID mech, gss_const_OID option, for (n = 0; n < m->gm_mo_num; n++) if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].set) return m->gm_mo[n].set(mech, &m->gm_mo[n], enable, value); - return 0; + + return GSS_S_UNAVAILABLE; } GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL @@ -94,13 +94,13 @@ gss_mo_get(gss_const_OID mech, gss_const_OID option, gss_buffer_t value) _mg_buffer_zero(value); if ((m = __gss_get_mechanism(mech)) == NULL) - return 0; + return GSS_S_BAD_MECH; for (n = 0; n < m->gm_mo_num; n++) if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].get) return m->gm_mo[n].get(mech, &m->gm_mo[n], value); - return 0; + return GSS_S_UNAVAILABLE; } static void @@ -179,10 +179,7 @@ mo_value(const gss_const_OID mech, gss_const_OID option, gss_buffer_t name) if (name == NULL) return GSS_S_COMPLETE; - if (gss_mo_get(mech, option, name) != 0 && name->length == 0) - return GSS_S_FAILURE; - - return GSS_S_COMPLETE; + return gss_mo_get(mech, option, name); } /* code derived from draft-ietf-cat-sasl-gssapi-01 */ @@ -210,7 +207,7 @@ make_sasl_name(OM_uint32 *minor, const gss_OID mech, char sasl_name[16]) memcpy(p, "GS2-", 4); p += 4; - *p++ = basis_32[h[0] >> 3]; + *p++ = basis_32[(h[0] >> 3)]; *p++ = basis_32[((h[0] & 7) << 2) | (h[1] >> 6)]; *p++ = basis_32[(h[1] & 0x3f) >> 1]; *p++ = basis_32[((h[1] & 1) << 4) | (h[2] >> 4)]; @@ -218,7 +215,7 @@ make_sasl_name(OM_uint32 *minor, const gss_OID mech, char sasl_name[16]) *p++ = basis_32[(h[3] & 0x7f) >> 2]; *p++ = basis_32[((h[3] & 3) << 3) | (h[4] >> 5)]; *p++ = basis_32[(h[4] & 0x1f)]; - *p++ = basis_32[h[5] >> 3]; + *p++ = basis_32[(h[5] >> 3)]; *p++ = basis_32[((h[5] & 7) << 2) | (h[6] >> 6)]; *p++ = basis_32[(h[6] & 0x3f) >> 1]; @@ -237,6 +234,7 @@ inquire_saslname_for_mech_compat(OM_uint32 *minor, gss_buffer_t mech_name, gss_buffer_t mech_description) { + struct gss_mech_compat_desc_struct *gmc; gssapi_mech_interface m; OM_uint32 major; @@ -244,14 +242,17 @@ inquire_saslname_for_mech_compat(OM_uint32 *minor, if (m == NULL) return GSS_S_BAD_MECH; - if (m->gm_inquire_saslname_for_mech == NULL) - return GSS_S_UNAVAILABLE; + gmc = m->gm_compat; - major = m->gm_inquire_saslname_for_mech(minor, - desired_mech, - sasl_mech_name, - mech_name, - mech_description); + if (gmc != NULL && gmc->gmc_inquire_saslname_for_mech != NULL) { + major = gmc->gmc_inquire_saslname_for_mech(minor, + desired_mech, + sasl_mech_name, + mech_name, + mech_description); + } else { + major = GSS_S_UNAVAILABLE; + } return major; } @@ -289,16 +290,9 @@ gss_inquire_saslname_for_mech(OM_uint32 *minor_status, if (desired_mech == NULL) return GSS_S_BAD_MECH; - major = inquire_saslname_for_mech_compat(minor_status, - desired_mech, - sasl_mech_name, - mech_name, - mech_description); - if (major == GSS_S_COMPLETE) - return major; - major = mo_value(desired_mech, GSS_C_MA_SASL_MECH_NAME, sasl_mech_name); if (major == GSS_S_COMPLETE) { + /* Native SPI */ major = mo_value(desired_mech, GSS_C_MA_MECH_NAME, mech_name); if (GSS_ERROR(major)) return major; @@ -306,9 +300,19 @@ gss_inquire_saslname_for_mech(OM_uint32 *minor_status, major = mo_value(desired_mech, GSS_C_MA_MECH_DESCRIPTION, mech_description); if (GSS_ERROR(major)) return major; + } - return major; - } else { + if (GSS_ERROR(major)) { + /* API-as-SPI compatibility */ + major = inquire_saslname_for_mech_compat(minor_status, + desired_mech, + sasl_mech_name, + mech_name, + mech_description); + } + + if (GSS_ERROR(major)) { + /* Algorithmically dervied SASL mechanism name */ char buf[16]; gss_buffer_desc tmp = { sizeof(buf) - 1, buf }; @@ -341,7 +345,7 @@ gss_inquire_mech_for_saslname(OM_uint32 *minor_status, { struct _gss_mech_switch *m; gss_buffer_desc name; - OM_uint32 major; + OM_uint32 major, junk; char buf[16]; _gss_load_mech(); @@ -349,29 +353,39 @@ gss_inquire_mech_for_saslname(OM_uint32 *minor_status, *mech_type = NULL; HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) { - if (m->gm_mech.gm_inquire_mech_for_saslname) { - major = m->gm_mech.gm_inquire_mech_for_saslname(minor_status, - sasl_mech_name, - mech_type); - if (major == GSS_S_COMPLETE) - return major; - } + struct gss_mech_compat_desc_struct *gmc; + /* Native SPI */ major = mo_value(&m->gm_mech_oid, GSS_C_MA_SASL_MECH_NAME, &name); if (major == GSS_S_COMPLETE && name.length == sasl_mech_name->length && memcmp(name.value, sasl_mech_name->value, name.length) == 0) { - gss_release_buffer(&major, &name); + gss_release_buffer(&junk, &name); *mech_type = &m->gm_mech_oid; return GSS_S_COMPLETE; } - gss_release_buffer(&major, &name); + gss_release_buffer(&junk, &name); - if (sasl_mech_name->length == 16 && - make_sasl_name(minor_status, &m->gm_mech_oid, buf) == GSS_S_COMPLETE && - memcmp(buf, sasl_mech_name->value, 16) == 0) { - *mech_type = &m->gm_mech_oid; - return GSS_S_COMPLETE; + if (GSS_ERROR(major)) { + /* API-as-SPI compatibility */ + gmc = m->gm_mech.gm_compat; + if (gmc && gmc->gmc_inquire_mech_for_saslname) { + major = gmc->gmc_inquire_mech_for_saslname(minor_status, + sasl_mech_name, + mech_type); + if (major == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + } + } + + if (GSS_ERROR(major)) { + /* Algorithmically dervied SASL mechanism name */ + if (sasl_mech_name->length == 16 && + make_sasl_name(minor_status, &m->gm_mech_oid, buf) == GSS_S_COMPLETE && + memcmp(buf, sasl_mech_name->value, 16) == 0) { + *mech_type = &m->gm_mech_oid; + return GSS_S_COMPLETE; + } } } @@ -448,13 +462,14 @@ gss_indicate_mechs_by_attrs(OM_uint32 * minor_status, HEIM_SLIST_FOREACH(ms, &_gss_mechs, gm_link) { gssapi_mech_interface mi = &ms->gm_mech; + struct gss_mech_compat_desc_struct *gmc = mi->gm_compat; OM_uint32 tmp; - if (mi->gm_inquire_attrs_for_mech != NULL) { - major = mi->gm_inquire_attrs_for_mech(minor_status, - &mi->gm_mech_oid, - &mech_attrs, - &known_mech_attrs); + if (gmc && gmc->gmc_inquire_attrs_for_mech) { + major = gmc->gmc_inquire_attrs_for_mech(minor_status, + &mi->gm_mech_oid, + &mech_attrs, + &known_mech_attrs); if (GSS_ERROR(major)) continue; } @@ -507,17 +522,20 @@ gss_inquire_attrs_for_mech(OM_uint32 * minor_status, if (mech_attr && mech) { gssapi_mech_interface m; + struct gss_mech_compat_desc_struct *gmc; if ((m = __gss_get_mechanism(mech)) == NULL) { *minor_status = 0; return GSS_S_BAD_MECH; } - if (m->gm_inquire_attrs_for_mech != NULL) { - major = m->gm_inquire_attrs_for_mech(minor_status, - mech, - mech_attr, - known_mech_attrs); + gmc = m->gm_compat; + + if (gmc && gmc->gmc_inquire_attrs_for_mech) { + major = gmc->gmc_inquire_attrs_for_mech(minor_status, + mech, + mech_attr, + known_mech_attrs); } else { major = gss_create_empty_oid_set(minor_status, mech_attr); if (major == GSS_S_COMPLETE) diff --git a/lib/gssapi/mech/mech_locl.h b/lib/gssapi/mech/mech_locl.h index cb10c23c3..6c23ac525 100644 --- a/lib/gssapi/mech/mech_locl.h +++ b/lib/gssapi/mech/mech_locl.h @@ -62,6 +62,7 @@ #include "mech_switch.h" #include "name.h" #include "utils.h" +#include "compat.h" #define _mg_buffer_zero(buffer) \ do { \