From 4a93c4774a597f58546e631a3699b8ad0775dce5 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 18 Dec 2018 16:02:05 +1100 Subject: [PATCH] gss: intern OIDs (#447) Intern OIDs so that gss_release_oid() can be a NOOP. --- lib/gssapi/gen-oid.pl | 8 ++ lib/gssapi/mech/gss_authorize_localname.c | 4 +- lib/gssapi/mech/gss_compare_name.c | 2 +- lib/gssapi/mech/gss_display_name.c | 2 +- lib/gssapi/mech/gss_duplicate_name.c | 2 +- lib/gssapi/mech/gss_duplicate_oid.c | 19 +---- lib/gssapi/mech/gss_import_name.c | 7 +- lib/gssapi/mech/gss_indicate_mechs.c | 2 +- lib/gssapi/mech/gss_inquire_cred.c | 4 +- lib/gssapi/mech/gss_inquire_mechs_for_name.c | 6 +- lib/gssapi/mech/gss_krb5.c | 6 +- lib/gssapi/mech/gss_mech_switch.c | 36 ++++++--- lib/gssapi/mech/gss_mo.c | 8 +- lib/gssapi/mech/gss_names.c | 3 +- lib/gssapi/mech/gss_oid.c | 78 ++++++++++++++++++++ lib/gssapi/mech/gss_release_name.c | 3 +- lib/gssapi/mech/gss_release_oid.c | 12 --- lib/gssapi/mech/gss_set_cred_option.c | 2 +- lib/gssapi/mech/gss_utils.c | 74 ++++++++++++++++++- lib/gssapi/mech/mech_locl.h | 2 + lib/gssapi/mech/mech_switch.h | 2 +- lib/gssapi/mech/mechqueue.h | 15 ++++ lib/gssapi/mech/name.h | 2 +- lib/gssapi/mech/utils.h | 2 +- lib/gssapi/spnego/context_stubs.c | 5 +- lib/gssapi/spnego/cred_stubs.c | 2 +- lib/gssapi/spnego/init_sec_context.c | 2 +- lib/gssapi/spnego/spnego_locl.h | 2 +- 28 files changed, 232 insertions(+), 80 deletions(-) diff --git a/lib/gssapi/gen-oid.pl b/lib/gssapi/gen-oid.pl index a2341ad98..d635f2857 100644 --- a/lib/gssapi/gen-oid.pl +++ b/lib/gssapi/gen-oid.pl @@ -112,6 +112,7 @@ while(<>) { printf "/* $name - $oid */\n"; printf "gss_OID_desc GSSAPI_LIB_VARIABLE $store = { $length, rk_UNCONST(\"$data\") };\n\n"; } + push(@oidstorage, $store); } elsif (/^desc\s+([\w]+)\s+(\w+)\s+(\"[^\"]*\")\s+(\"[^\"]*\")/) { my ($type, $oid, $short, $long) = ($1, $2, $3, $4); my $object = { type=> $type, oid => $oid, short => $short, long => $long }; @@ -138,4 +139,11 @@ foreach my $k (sort keys %types) { if ($header) { printf "#endif /* GSSAPI_GSSAPI_OID */\n"; +} else { + printf "gss_OID _gss_ot_internal[] = {\n"; + foreach my $k (@oidstorage) { + print " &$k,\n"; + } + printf "};\n\n"; + printf "size_t _gss_ot_internal_count = sizeof(_gss_ot_internal) / sizeof(_gss_ot_internal[0]);\n"; } diff --git a/lib/gssapi/mech/gss_authorize_localname.c b/lib/gssapi/mech/gss_authorize_localname.c index c04cfe018..75060a446 100644 --- a/lib/gssapi/mech/gss_authorize_localname.c +++ b/lib/gssapi/mech/gss_authorize_localname.c @@ -56,7 +56,7 @@ mech_authorize_localname(OM_uint32 *minor_status, major_status = m->gm_authorize_localname(minor_status, mn->gmn_name, &user->gn_value, - &user->gn_type); + user->gn_type); if (major_status != GSS_S_UNAUTHORIZED) break; } @@ -75,7 +75,7 @@ attr_authorize_localname(OM_uint32 *minor_status, OM_uint32 major_status = GSS_S_UNAVAILABLE; int more = -1; - if (!gss_oid_equal(&user->gn_type, GSS_C_NT_USER_NAME)) + if (!gss_oid_equal(user->gn_type, GSS_C_NT_USER_NAME)) return GSS_S_BAD_NAMETYPE; while (more != 0 && major_status != GSS_S_COMPLETE) { diff --git a/lib/gssapi/mech/gss_compare_name.c b/lib/gssapi/mech/gss_compare_name.c index 18a8536ab..b2032d89e 100644 --- a/lib/gssapi/mech/gss_compare_name.c +++ b/lib/gssapi/mech/gss_compare_name.c @@ -44,7 +44,7 @@ gss_compare_name(OM_uint32 *minor_status, */ if (name1->gn_value.value && name2->gn_value.value) { *name_equal = 1; - if (!gss_oid_equal(&name1->gn_type, &name2->gn_type)) { + if (!gss_oid_equal(name1->gn_type, name2->gn_type)) { *name_equal = 0; } else if (name1->gn_value.length != name2->gn_value.length || memcmp(name1->gn_value.value, name2->gn_value.value, diff --git a/lib/gssapi/mech/gss_display_name.c b/lib/gssapi/mech/gss_display_name.c index a4af66a90..cf8e9186a 100644 --- a/lib/gssapi/mech/gss_display_name.c +++ b/lib/gssapi/mech/gss_display_name.c @@ -62,7 +62,7 @@ gss_display_name(OM_uint32 *minor_status, memcpy(output_name_buffer->value, name->gn_value.value, output_name_buffer->length); if (output_name_type) - *output_name_type = &name->gn_type; + *output_name_type = name->gn_type; *minor_status = 0; return (GSS_S_COMPLETE); diff --git a/lib/gssapi/mech/gss_duplicate_name.c b/lib/gssapi/mech/gss_duplicate_name.c index d6aaf4923..1f58b4230 100644 --- a/lib/gssapi/mech/gss_duplicate_name.c +++ b/lib/gssapi/mech/gss_duplicate_name.c @@ -48,7 +48,7 @@ gss_duplicate_name(OM_uint32 *minor_status, */ if (name->gn_value.value) { major_status = gss_import_name(minor_status, - &name->gn_value, &name->gn_type, dest_name); + &name->gn_value, name->gn_type, dest_name); if (major_status != GSS_S_COMPLETE) return (major_status); new_name = (struct _gss_name *) *dest_name; diff --git a/lib/gssapi/mech/gss_duplicate_oid.c b/lib/gssapi/mech/gss_duplicate_oid.c index 10a200048..29a9cf862 100644 --- a/lib/gssapi/mech/gss_duplicate_oid.c +++ b/lib/gssapi/mech/gss_duplicate_oid.c @@ -47,22 +47,5 @@ gss_duplicate_oid ( return GSS_S_COMPLETE; } - *dest_oid = malloc(sizeof(**dest_oid)); - if (*dest_oid == GSS_C_NO_OID) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - (*dest_oid)->elements = malloc(src_oid->length); - if ((*dest_oid)->elements == NULL) { - free(*dest_oid); - *dest_oid = GSS_C_NO_OID; - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - memcpy((*dest_oid)->elements, src_oid->elements, src_oid->length); - (*dest_oid)->length = src_oid->length; - - *minor_status = 0; - return GSS_S_COMPLETE; + return _gss_intern_oid(minor_status, src_oid, dest_oid); } diff --git a/lib/gssapi/mech/gss_import_name.c b/lib/gssapi/mech/gss_import_name.c index 4c1d940d9..121b242fe 100644 --- a/lib/gssapi/mech/gss_import_name.c +++ b/lib/gssapi/mech/gss_import_name.c @@ -221,7 +221,7 @@ gss_import_name(OM_uint32 *minor_status, HEIM_SLIST_INIT(&name->gn_mn); - major_status = _gss_copy_oid(minor_status, + major_status = _gss_intern_oid(minor_status, name_type, &name->gn_type); if (major_status) { free(name); @@ -256,8 +256,7 @@ gss_import_name(OM_uint32 *minor_status, major_status = (*m->gm_mech.gm_import_name)(minor_status, &name->gn_value, - (name->gn_type.elements - ? &name->gn_type : GSS_C_NO_OID), + name->gn_type, &mn->gmn_name); if (major_status != GSS_S_COMPLETE) { _gss_mg_error(&m->gm_mech, major_status, *minor_status); @@ -266,7 +265,7 @@ gss_import_name(OM_uint32 *minor_status, } mn->gmn_mech = &m->gm_mech; - mn->gmn_mech_oid = &m->gm_mech_oid; + mn->gmn_mech_oid = m->gm_mech_oid; HEIM_SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); } diff --git a/lib/gssapi/mech/gss_indicate_mechs.c b/lib/gssapi/mech/gss_indicate_mechs.c index 12d7f1ae3..c38a5864c 100644 --- a/lib/gssapi/mech/gss_indicate_mechs.c +++ b/lib/gssapi/mech/gss_indicate_mechs.c @@ -56,7 +56,7 @@ gss_indicate_mechs(OM_uint32 *minor_status, gss_release_oid_set(minor_status, &set); } else { gss_add_oid_set_member( - minor_status, &m->gm_mech_oid, mech_set); + minor_status, m->gm_mech_oid, mech_set); } } diff --git a/lib/gssapi/mech/gss_inquire_cred.c b/lib/gssapi/mech/gss_inquire_cred.c index 992514a9a..1b0204e59 100644 --- a/lib/gssapi/mech/gss_inquire_cred.c +++ b/lib/gssapi/mech/gss_inquire_cred.c @@ -151,7 +151,7 @@ gss_inquire_cred(OM_uint32 *minor_status, continue; } mn->gmn_mech = &m->gm_mech; - mn->gmn_mech_oid = &m->gm_mech_oid; + mn->gmn_mech_oid = m->gm_mech_oid; mn->gmn_name = mc_name; HEIM_SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); } else if (mc_name) { @@ -164,7 +164,7 @@ gss_inquire_cred(OM_uint32 *minor_status, if (mechanisms) gss_add_oid_set_member(minor_status, - &m->gm_mech_oid, mechanisms); + m->gm_mech_oid, mechanisms); found++; } } diff --git a/lib/gssapi/mech/gss_inquire_mechs_for_name.c b/lib/gssapi/mech/gss_inquire_mechs_for_name.c index 8fd2286ea..b445c6530 100644 --- a/lib/gssapi/mech/gss_inquire_mechs_for_name.c +++ b/lib/gssapi/mech/gss_inquire_mechs_for_name.c @@ -54,17 +54,17 @@ gss_inquire_mechs_for_name(OM_uint32 *minor_status, */ HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) { major_status = gss_inquire_names_for_mech(minor_status, - &m->gm_mech_oid, &name_types); + m->gm_mech_oid, &name_types); if (major_status) { gss_release_oid_set(minor_status, mech_types); return (major_status); } gss_test_oid_set_member(minor_status, - &name->gn_type, name_types, &present); + name->gn_type, name_types, &present); gss_release_oid_set(minor_status, &name_types); if (present) { major_status = gss_add_oid_set_member(minor_status, - &m->gm_mech_oid, mech_types); + m->gm_mech_oid, mech_types); if (major_status) { gss_release_oid_set(minor_status, mech_types); return (major_status); diff --git a/lib/gssapi/mech/gss_krb5.c b/lib/gssapi/mech/gss_krb5.c index fe88a384b..8151bb40c 100644 --- a/lib/gssapi/mech/gss_krb5.c +++ b/lib/gssapi/mech/gss_krb5.c @@ -607,7 +607,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, gss_buffer_t ad_data) { gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; - OM_uint32 maj_stat; + OM_uint32 maj_stat, tmp; gss_OID_desc oid_flat; heim_oid baseoid, oid; size_t size; @@ -653,7 +653,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1, oid_flat.length, &oid, &size) != 0) { free(oid.components); - free(oid_flat.elements); + _gss_free_oid(&tmp, &oid_flat); *minor_status = EINVAL; return GSS_S_FAILURE; } @@ -669,7 +669,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, &oid_flat, &data_set); - free(oid_flat.elements); + _gss_free_oid(&tmp, &oid_flat); if (maj_stat) return maj_stat; diff --git a/lib/gssapi/mech/gss_mech_switch.c b/lib/gssapi/mech/gss_mech_switch.c index dab2978b5..16598741d 100644 --- a/lib/gssapi/mech/gss_mech_switch.c +++ b/lib/gssapi/mech/gss_mech_switch.c @@ -43,15 +43,15 @@ static HEIMDAL_MUTEX _gss_mech_mutex = HEIMDAL_MUTEX_INITIALIZER; * (e.g. 1.2.840.113554.1.2.2) to a gss_OID. */ static int -_gss_string_to_oid(const char* s, gss_OID oid) +_gss_string_to_oid(const char* s, gss_OID *oidp) { int number_count, i, j; size_t byte_count; const char *p, *q; char *res; + gss_OID_desc oid; - oid->length = 0; - oid->elements = NULL; + *oidp = GSS_C_NO_OID; /* * First figure out how many numbers in the oid, then @@ -142,11 +142,22 @@ _gss_string_to_oid(const char* s, gss_OID oid) res = malloc(byte_count); if (!res) return (ENOMEM); - oid->length = byte_count; - oid->elements = res; + oid.length = byte_count; + oid.elements = res; } } + { + OM_uint32 minor_status, tmp; + + if (GSS_ERROR(_gss_intern_oid(&minor_status, &oid, oidp))) { + _gss_free_oid(&tmp, &oid); + return (minor_status); + } + + _gss_free_oid(&tmp, &oid); + } + return (0); } #endif @@ -205,7 +216,9 @@ add_builtin(gssapi_mech_interface mech) return ENOMEM; m->gm_so = NULL; m->gm_mech = *mech; - m->gm_mech_oid = mech->gm_mech_oid; /* XXX */ + _gss_intern_oid(&minor_status, &mech->gm_mech_oid, &m->gm_mech_oid); + if (minor_status) + return minor_status; gss_add_oid_set_member(&minor_status, &m->gm_mech.gm_mech_oid, &_gss_mech_oids); @@ -236,7 +249,7 @@ _gss_load_mech(void) char *name, *oid, *lib, *kobj; struct _gss_mech_switch *m; void *so; - gss_OID_desc mech_oid; + gss_OID mech_oid; int found; #endif @@ -291,9 +304,8 @@ _gss_load_mech(void) */ found = 0; HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) { - if (gss_oid_equal(&m->gm_mech.gm_mech_oid, &mech_oid)) { + if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech_oid)) { found = 1; - free(mech_oid.elements); break; } } @@ -321,7 +333,7 @@ _gss_load_mech(void) m->gm_so = so; m->gm_mech_oid = mech_oid; m->gm_mech.gm_name = strdup(name); - m->gm_mech.gm_mech_oid = mech_oid; + 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) @@ -392,7 +404,7 @@ _gss_load_mech(void) mi = dlsym(so, "gss_mo_init"); if (mi != NULL) { - major_status = mi(&minor_status, &mech_oid, + major_status = mi(&minor_status, mech_oid, &m->gm_mech.gm_mo, &m->gm_mech.gm_mo_num); if (GSS_ERROR(major_status)) goto bad; @@ -419,7 +431,7 @@ _gss_load_mech(void) bad: if (m != NULL) { free(m->gm_mech.gm_compat); - free(m->gm_mech.gm_mech_oid.elements); + /* do not free OID, it has been interned */ free((char *)m->gm_mech.gm_name); free(m); } diff --git a/lib/gssapi/mech/gss_mo.c b/lib/gssapi/mech/gss_mo.c index d0cde08ef..c692365f9 100644 --- a/lib/gssapi/mech/gss_mo.c +++ b/lib/gssapi/mech/gss_mo.c @@ -357,12 +357,12 @@ gss_inquire_mech_for_saslname(OM_uint32 *minor_status, struct gss_mech_compat_desc_struct *gmc; /* Native SPI */ - major = mo_value(&m->gm_mech_oid, GSS_C_MA_SASL_MECH_NAME, &name); + 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(&junk, &name); - *mech_type = &m->gm_mech_oid; + *mech_type = m->gm_mech_oid; return GSS_S_COMPLETE; } gss_release_buffer(&junk, &name); @@ -382,9 +382,9 @@ gss_inquire_mech_for_saslname(OM_uint32 *minor_status, 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 && + 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; + *mech_type = m->gm_mech_oid; return GSS_S_COMPLETE; } } diff --git a/lib/gssapi/mech/gss_names.c b/lib/gssapi/mech/gss_names.c index 43e0e2a85..240c47d45 100644 --- a/lib/gssapi/mech/gss_names.c +++ b/lib/gssapi/mech/gss_names.c @@ -61,8 +61,7 @@ _gss_find_mn(OM_uint32 *minor_status, struct _gss_name *name, gss_OID mech, major_status = m->gm_import_name(minor_status, &name->gn_value, - (name->gn_type.elements - ? &name->gn_type : GSS_C_NO_OID), + name->gn_type, &mn->gmn_name); if (major_status != GSS_S_COMPLETE) { _gss_mg_error(m, major_status, *minor_status); diff --git a/lib/gssapi/mech/gss_oid.c b/lib/gssapi/mech/gss_oid.c index fe9686d53..c6583bf22 100644 --- a/lib/gssapi/mech/gss_oid.c +++ b/lib/gssapi/mech/gss_oid.c @@ -264,3 +264,81 @@ struct _gss_oid_name_table _gss_ont_mech[] = { { NULL, NULL, NULL, NULL } }; +gss_OID _gss_ot_internal[] = { + &__gss_krb5_copy_ccache_x_oid_desc, + &__gss_krb5_get_tkt_flags_x_oid_desc, + &__gss_krb5_extract_authz_data_from_sec_context_x_oid_desc, + &__gss_krb5_compat_des3_mic_x_oid_desc, + &__gss_krb5_register_acceptor_identity_x_oid_desc, + &__gss_krb5_export_lucid_context_x_oid_desc, + &__gss_krb5_export_lucid_context_v1_x_oid_desc, + &__gss_krb5_set_dns_canonicalize_x_oid_desc, + &__gss_krb5_get_subkey_x_oid_desc, + &__gss_krb5_get_initiator_subkey_x_oid_desc, + &__gss_krb5_get_acceptor_subkey_x_oid_desc, + &__gss_krb5_send_to_kdc_x_oid_desc, + &__gss_krb5_get_authtime_x_oid_desc, + &__gss_krb5_get_service_keyblock_x_oid_desc, + &__gss_krb5_set_allowable_enctypes_x_oid_desc, + &__gss_krb5_set_default_realm_x_oid_desc, + &__gss_krb5_ccache_name_x_oid_desc, + &__gss_krb5_set_time_offset_x_oid_desc, + &__gss_krb5_get_time_offset_x_oid_desc, + &__gss_krb5_plugin_register_x_oid_desc, + &__gss_ntlm_get_session_key_x_oid_desc, + &__gss_c_nt_ntlm_oid_desc, + &__gss_c_nt_dn_oid_desc, + &__gss_krb5_nt_principal_name_referral_oid_desc, + &__gss_c_ntlm_avguest_oid_desc, + &__gss_c_ntlm_v1_oid_desc, + &__gss_c_ntlm_v2_oid_desc, + &__gss_c_ntlm_session_key_oid_desc, + &__gss_c_ntlm_force_v1_oid_desc, + &__gss_krb5_cred_no_ci_flags_x_oid_desc, + &__gss_krb5_import_cred_x_oid_desc, + &__gss_c_ma_sasl_mech_name_oid_desc, + &__gss_c_ma_mech_name_oid_desc, + &__gss_c_ma_mech_description_oid_desc, + &__gss_c_cred_password_oid_desc, + &__gss_c_cred_certificate_oid_desc, + &__gss_sasl_digest_md5_mechanism_oid_desc, + &__gss_netlogon_mechanism_oid_desc, + &__gss_netlogon_set_session_key_x_oid_desc, + &__gss_netlogon_set_sign_algorithm_x_oid_desc, + &__gss_netlogon_nt_netbios_dns_name_oid_desc, + &__gss_c_inq_win2k_pac_x_oid_desc, + &__gss_c_inq_sspi_session_key_oid_desc, + &__gss_krb5_mechanism_oid_desc, + &__gss_ntlm_mechanism_oid_desc, + &__gss_spnego_mechanism_oid_desc, + &__gss_c_peer_has_updated_spnego_oid_desc, + &__gss_c_ma_mech_concrete_oid_desc, + &__gss_c_ma_mech_pseudo_oid_desc, + &__gss_c_ma_mech_composite_oid_desc, + &__gss_c_ma_mech_nego_oid_desc, + &__gss_c_ma_mech_glue_oid_desc, + &__gss_c_ma_not_mech_oid_desc, + &__gss_c_ma_deprecated_oid_desc, + &__gss_c_ma_not_dflt_mech_oid_desc, + &__gss_c_ma_itok_framed_oid_desc, + &__gss_c_ma_auth_init_oid_desc, + &__gss_c_ma_auth_targ_oid_desc, + &__gss_c_ma_auth_init_init_oid_desc, + &__gss_c_ma_auth_targ_init_oid_desc, + &__gss_c_ma_auth_init_anon_oid_desc, + &__gss_c_ma_auth_targ_anon_oid_desc, + &__gss_c_ma_deleg_cred_oid_desc, + &__gss_c_ma_integ_prot_oid_desc, + &__gss_c_ma_conf_prot_oid_desc, + &__gss_c_ma_mic_oid_desc, + &__gss_c_ma_wrap_oid_desc, + &__gss_c_ma_prot_ready_oid_desc, + &__gss_c_ma_replay_det_oid_desc, + &__gss_c_ma_oos_det_oid_desc, + &__gss_c_ma_cbindings_oid_desc, + &__gss_c_ma_pfs_oid_desc, + &__gss_c_ma_compress_oid_desc, + &__gss_c_ma_ctx_trans_oid_desc, +}; + +size_t _gss_ot_internal_count = sizeof(_gss_ot_internal) / sizeof(_gss_ot_internal[0]); diff --git a/lib/gssapi/mech/gss_release_name.c b/lib/gssapi/mech/gss_release_name.c index fd0b5df36..fba46c0c0 100644 --- a/lib/gssapi/mech/gss_release_name.c +++ b/lib/gssapi/mech/gss_release_name.c @@ -56,8 +56,7 @@ gss_release_name(OM_uint32 *minor_status, name = (struct _gss_name *) *input_name; - if (name->gn_type.elements) - free(name->gn_type.elements); + gss_release_oid(minor_status, &name->gn_type); while (HEIM_SLIST_FIRST(&name->gn_mn)) { struct _gss_mechanism_name *mn; mn = HEIM_SLIST_FIRST(&name->gn_mn); diff --git a/lib/gssapi/mech/gss_release_oid.c b/lib/gssapi/mech/gss_release_oid.c index 610daf229..4f674b01d 100644 --- a/lib/gssapi/mech/gss_release_oid.c +++ b/lib/gssapi/mech/gss_release_oid.c @@ -37,22 +37,10 @@ GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_oid(OM_uint32 *minor_status, gss_OID *oid) { - gss_OID o = *oid; - *oid = GSS_C_NO_OID; if (minor_status != NULL) *minor_status = 0; - if (o == GSS_C_NO_OID) - return GSS_S_COMPLETE; - - if (o->elements != NULL) { - free(o->elements); - o->elements = NULL; - } - o->length = 0; - free(o); - return GSS_S_COMPLETE; } diff --git a/lib/gssapi/mech/gss_set_cred_option.c b/lib/gssapi/mech/gss_set_cred_option.c index d33453d92..661fd071e 100644 --- a/lib/gssapi/mech/gss_set_cred_option.c +++ b/lib/gssapi/mech/gss_set_cred_option.c @@ -70,7 +70,7 @@ gss_set_cred_option (OM_uint32 *minor_status, } mc->gmc_mech = &m->gm_mech; - mc->gmc_mech_oid = &m->gm_mech_oid; + mc->gmc_mech_oid = m->gm_mech_oid; mc->gmc_cred = GSS_C_NO_CREDENTIAL; major_status = m->gm_mech.gm_set_cred_option( diff --git a/lib/gssapi/mech/gss_utils.c b/lib/gssapi/mech/gss_utils.c index 2071621b2..a13133ab1 100644 --- a/lib/gssapi/mech/gss_utils.c +++ b/lib/gssapi/mech/gss_utils.c @@ -28,9 +28,9 @@ #include "mech_locl.h" -OM_uint32 +static OM_uint32 _gss_copy_oid(OM_uint32 *minor_status, - const gss_OID from_oid, gss_OID to_oid) + gss_const_OID from_oid, gss_OID to_oid) { size_t len = from_oid->length; @@ -58,6 +58,76 @@ _gss_free_oid(OM_uint32 *minor_status, gss_OID oid) return (GSS_S_COMPLETE); } +struct _gss_interned_oid { + HEIM_SLIST_ENTRY(_gss_interned_oid) gio_link; + gss_OID_desc gio_oid; +}; + +static HEIM_SLIST_HEAD(_gss_interned_oid_list, _gss_interned_oid) interned_oids = +HEIM_SLIST_HEAD_INITIALIZER(interned_oids); + +extern gss_OID _gss_ot_internal[]; +extern size_t _gss_ot_internal_count; + +static OM_uint32 +intern_oid_static(OM_uint32 *minor_status, + gss_const_OID from_oid, + gss_OID *to_oid) +{ + size_t i; + + /* statically allocated OIDs */ + for (i = 0; i < _gss_ot_internal_count; i++) { + if (gss_oid_equal(_gss_ot_internal[i], from_oid)) { + *minor_status = 0; + *to_oid = _gss_ot_internal[i]; + return GSS_S_COMPLETE; + } + } + + return GSS_S_CONTINUE_NEEDED; +} + +OM_uint32 +_gss_intern_oid(OM_uint32 *minor_status, + gss_const_OID from_oid, + gss_OID *to_oid) +{ + OM_uint32 major_status; + struct _gss_interned_oid *iop; + + major_status = intern_oid_static(minor_status, from_oid, to_oid); + if (major_status != GSS_S_CONTINUE_NEEDED) + return major_status; + + HEIM_SLIST_ATOMIC_FOREACH(iop, &interned_oids, gio_link) { + if (gss_oid_equal(&iop->gio_oid, from_oid)) { + *minor_status = 0; + *to_oid = &iop->gio_oid; + return GSS_S_COMPLETE; + } + } + + iop = malloc(sizeof(*iop)); + if (iop == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + major_status = _gss_copy_oid(minor_status, from_oid, &iop->gio_oid); + if (GSS_ERROR(major_status)) { + free(iop); + return major_status; + } + + HEIM_SLIST_ATOMIC_INSERT_HEAD(&interned_oids, iop, gio_link); + + *minor_status = 0; + *to_oid = &iop->gio_oid; + + return GSS_S_COMPLETE; +} + OM_uint32 _gss_copy_buffer(OM_uint32 *minor_status, const gss_buffer_t from_buf, gss_buffer_t to_buf) diff --git a/lib/gssapi/mech/mech_locl.h b/lib/gssapi/mech/mech_locl.h index 6c23ac525..613a93bb2 100644 --- a/lib/gssapi/mech/mech_locl.h +++ b/lib/gssapi/mech/mech_locl.h @@ -46,6 +46,8 @@ #include #include +#include + #include #include diff --git a/lib/gssapi/mech/mech_switch.h b/lib/gssapi/mech/mech_switch.h index 7ed3d4d4a..5ef883cc2 100644 --- a/lib/gssapi/mech/mech_switch.h +++ b/lib/gssapi/mech/mech_switch.h @@ -31,7 +31,7 @@ struct _gss_mech_switch { HEIM_SLIST_ENTRY(_gss_mech_switch) gm_link; - gss_OID_desc gm_mech_oid; + gss_OID gm_mech_oid; gss_OID_set gm_name_types; void *gm_so; gssapi_mech_interface_desc gm_mech; diff --git a/lib/gssapi/mech/mechqueue.h b/lib/gssapi/mech/mechqueue.h index 95941bab7..7abde30d5 100644 --- a/lib/gssapi/mech/mechqueue.h +++ b/lib/gssapi/mech/mechqueue.h @@ -94,4 +94,19 @@ struct { \ #define HEIM_SLIST_FIRST(head) ((head)->slh_first) #define HEIM_SLIST_NEXT(elm, field) ((elm)->field.sle_next) +/* + * Singly-linked List atomic functions. + */ +#include "heimbase.h" + +#define HEIM_SLIST_ATOMIC_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = \ + heim_base_exchange_pointer(&(head)->slh_first, (elm)); \ +} while (/*CONSTCOND*/0) + +#define HEIM_SLIST_ATOMIC_FOREACH(var, head, field) \ + for (heim_base_exchange_pointer(&(var), (head)->slh_first); \ + (var) != NULL; \ + heim_base_exchange_pointer(&(var), (var)->field.sle_next)) + #endif /* !_MECHQUEUE_H_ */ diff --git a/lib/gssapi/mech/name.h b/lib/gssapi/mech/name.h index 4baeebf36..10334957c 100644 --- a/lib/gssapi/mech/name.h +++ b/lib/gssapi/mech/name.h @@ -36,7 +36,7 @@ struct _gss_mechanism_name { HEIM_SLIST_HEAD(_gss_mechanism_name_list, _gss_mechanism_name); struct _gss_name { - gss_OID_desc gn_type; /* type of name */ + gss_OID gn_type; /* type of name */ gss_buffer_desc gn_value; /* value (as imported) */ struct _gss_mechanism_name_list gn_mn; /* list of MNs */ }; diff --git a/lib/gssapi/mech/utils.h b/lib/gssapi/mech/utils.h index 7b27d38f3..77e308f28 100644 --- a/lib/gssapi/mech/utils.h +++ b/lib/gssapi/mech/utils.h @@ -28,6 +28,6 @@ */ OM_uint32 _gss_free_oid(OM_uint32 *, gss_OID); -OM_uint32 _gss_copy_oid(OM_uint32 *, const gss_OID, gss_OID); +OM_uint32 _gss_intern_oid(OM_uint32 *, gss_const_OID, gss_OID *); OM_uint32 _gss_copy_buffer(OM_uint32 *minor_status, const gss_buffer_t from_buf, gss_buffer_t to_buf); diff --git a/lib/gssapi/spnego/context_stubs.c b/lib/gssapi/spnego/context_stubs.c index 836ce5859..23e1a18db 100644 --- a/lib/gssapi/spnego/context_stubs.c +++ b/lib/gssapi/spnego/context_stubs.c @@ -274,7 +274,7 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name *name_equal = 0; - if (!gss_oid_equal(&n1->type, &n2->type)) + if (!gss_oid_equal(n1->type, n2->type)) return GSS_S_COMPLETE; if (n1->value.length != n2->value.length) return GSS_S_COMPLETE; @@ -322,7 +322,7 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name return GSS_S_FAILURE; } - maj_stat = _gss_copy_oid(minor_status, name_type, &name->type); + maj_stat = _gss_intern_oid(minor_status, name_type, &name->type); if (maj_stat) { free(name); return GSS_S_FAILURE; @@ -369,7 +369,6 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name if (*input_name != GSS_C_NO_NAME) { OM_uint32 junk; spnego_name name = (spnego_name)*input_name; - _gss_free_oid(&junk, &name->type); gss_release_buffer(&junk, &name->value); if (name->mech != GSS_C_NO_NAME) gss_release_name(&junk, &name->mech); diff --git a/lib/gssapi/spnego/cred_stubs.c b/lib/gssapi/spnego/cred_stubs.c index f82c4d1e8..6f7feccf8 100644 --- a/lib/gssapi/spnego/cred_stubs.c +++ b/lib/gssapi/spnego/cred_stubs.c @@ -75,7 +75,7 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_acquire_cred *output_cred_handle = GSS_C_NO_CREDENTIAL; if (dname) { - ret = gss_import_name(minor_status, &dname->value, &dname->type, &name); + ret = gss_import_name(minor_status, &dname->value, dname->type, &name); if (ret) { return ret; } diff --git a/lib/gssapi/spnego/init_sec_context.c b/lib/gssapi/spnego/init_sec_context.c index a12ce3847..006f3ef59 100644 --- a/lib/gssapi/spnego/init_sec_context.c +++ b/lib/gssapi/spnego/init_sec_context.c @@ -223,7 +223,7 @@ spnego_initial ctx->local = 1; - sub = gss_import_name(&minor, &name->value, &name->type, &ctx->target_name); + sub = gss_import_name(&minor, &name->value, name->type, &ctx->target_name); if (GSS_ERROR(sub)) { *minor_status = minor; _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); diff --git a/lib/gssapi/spnego/spnego_locl.h b/lib/gssapi/spnego/spnego_locl.h index bc20a3f39..b237031d8 100644 --- a/lib/gssapi/spnego/spnego_locl.h +++ b/lib/gssapi/spnego/spnego_locl.h @@ -98,7 +98,7 @@ typedef struct { } *gssspnego_ctx; typedef struct { - gss_OID_desc type; + gss_OID type; gss_buffer_desc value; gss_name_t mech; } *spnego_name;