From fc9f9b322a8883dbc28faec3801693aaf52315fd Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 6 Sep 2021 13:22:53 +1000 Subject: [PATCH] gss: implement gss_krb5_ccache_name() Correctly implement gss_krb5_ccache_name() in terms of gss_set_sec_context_option(GSS_KRB5_CCACHE_NAME_X). The previous implementation was a NOOP. Note: global ccache name should really be thread-specific rather than global. Closes #803. --- lib/gssapi/krb5/ccache_name.c | 27 ++++++++++---------- lib/gssapi/krb5/gsskrb5_locl.h | 5 ++++ lib/gssapi/krb5/set_sec_context_option.c | 26 +++++++------------ lib/gssapi/mech/gss_krb5.c | 32 ++++++++++++++++++------ 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/lib/gssapi/krb5/ccache_name.c b/lib/gssapi/krb5/ccache_name.c index 1577fb20d..0a2d5960f 100644 --- a/lib/gssapi/krb5/ccache_name.c +++ b/lib/gssapi/krb5/ccache_name.c @@ -33,7 +33,7 @@ #include "gsskrb5_locl.h" -char *last_out_name; +static heim_base_atomic(char *) last_out_name; /* XXX should be thread-specific */ OM_uint32 _gsskrb5_krb5_ccache_name(OM_uint32 *minor_status, @@ -48,24 +48,25 @@ _gsskrb5_krb5_ccache_name(OM_uint32 *minor_status, GSSAPI_KRB5_INIT(&context); if (out_name) { - const char *n; + const char *def_name; - if (last_out_name) { - free(last_out_name); - last_out_name = NULL; + *out_name = NULL; + + def_name = krb5_cc_default_name(context); + if (def_name) { + char *s = strdup(def_name); + if (s) { + s = heim_base_exchange_pointer(&last_out_name, s); + free(s); + + *out_name = last_out_name; + } } - n = krb5_cc_default_name(context); - if (n == NULL) { + if (*out_name == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } - last_out_name = strdup(n); - if (last_out_name == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - *out_name = last_out_name; } kret = krb5_cc_set_default_name(context, name); diff --git a/lib/gssapi/krb5/gsskrb5_locl.h b/lib/gssapi/krb5/gsskrb5_locl.h index b2e7c178b..fbbb168c6 100644 --- a/lib/gssapi/krb5/gsskrb5_locl.h +++ b/lib/gssapi/krb5/gsskrb5_locl.h @@ -145,4 +145,9 @@ extern HEIMDAL_MUTEX gssapi_keytab_mutex; #define SC_ORDER 0x0080 #define SC_AUTHENTICATOR 0x0100 +struct gsskrb5_ccache_name_args { + const char *name; + const char *out_name; +}; + #endif diff --git a/lib/gssapi/krb5/set_sec_context_option.c b/lib/gssapi/krb5/set_sec_context_option.c index 56a30cd07..3a6f86bb2 100644 --- a/lib/gssapi/krb5/set_sec_context_option.c +++ b/lib/gssapi/krb5/set_sec_context_option.c @@ -294,23 +294,6 @@ _gsskrb5_set_sec_context_option *minor_status = EINVAL; return GSS_S_FAILURE; - } else if (gss_oid_equal(desired_object, GSS_KRB5_CCACHE_NAME_X)) { - char *str; - - maj_stat = get_string(minor_status, value, &str); - if (maj_stat != GSS_S_COMPLETE) - return maj_stat; - if (str == NULL) { - *minor_status = 0; - return GSS_S_CALL_INACCESSIBLE_READ; - } - - *minor_status = krb5_cc_set_default_name(context, str); - free(str); - if (*minor_status) - return GSS_S_FAILURE; - - return GSS_S_COMPLETE; } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_TIME_OFFSET_X)) { OM_uint32 offset; time_t t; @@ -352,6 +335,15 @@ _gsskrb5_set_sec_context_option *minor_status = 0; return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_CCACHE_NAME_X)) { + struct gsskrb5_ccache_name_args *args = value->value; + + if (value->length != sizeof(*args)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + return _gsskrb5_krb5_ccache_name(minor_status, args->name, &args->out_name); } else if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_RFC4121_CONTEXT_X)) { return make_rfc4121_context(minor_status, context, context_handle, value); } diff --git a/lib/gssapi/mech/gss_krb5.c b/lib/gssapi/mech/gss_krb5.c index ee376229c..0f6d14209 100644 --- a/lib/gssapi/mech/gss_krb5.c +++ b/lib/gssapi/mech/gss_krb5.c @@ -487,26 +487,42 @@ gss_krb5_ccache_name(OM_uint32 *minor_status, { struct _gss_mech_switch *m; gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; - OM_uint32 junk; + OM_uint32 major_status; + struct gsskrb5_ccache_name_args args; _gss_load_mech(); + *minor_status = 0; + if (out_name) *out_name = NULL; - buffer.value = rk_UNCONST(name); - if (name) { - buffer.length = strlen(name); - } + args.name = name; + args.out_name = NULL; + + buffer.value = &args; + buffer.length = sizeof(args); + + major_status = GSS_S_UNAVAILABLE; HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { + OM_uint32 mech_major, mech_minor; + if (m->gm_mech.gm_set_sec_context_option == NULL) continue; - m->gm_mech.gm_set_sec_context_option(&junk, NULL, - GSS_KRB5_CCACHE_NAME_X, &buffer); + + mech_major = m->gm_mech.gm_set_sec_context_option(&mech_minor, + NULL, GSS_KRB5_CCACHE_NAME_X, &buffer); + if (mech_major != GSS_S_UNAVAILABLE) { + major_status = mech_major; + *minor_status = mech_minor; + break; + } } - return (GSS_S_COMPLETE); + *out_name = args.out_name; + + return major_status; }