From: Simo Sorce Date: Thu, 26 Jan 2017 10:45:17 +0000 (-0500) Subject: Add OID to inquire GSS cred impersonator name X-Git-Tag: krb5-1.16-beta1~143 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F601%2Fhead;p=thirdparty%2Fkrb5.git Add OID to inquire GSS cred impersonator name In the krb5 GSS mechanism, add support in gss_inquire_cred_by_oid() for inquiring the impersonator name of a credential object, using OID 1.2.840.113554.1.2.2.5.14. [ghudson@mit.edu: edited code slightly; added documentation; expanded commit message] ticket: 8548 (new) --- diff --git a/doc/appdev/gssapi.rst b/doc/appdev/gssapi.rst index 0258f793b9..c39bbddb97 100644 --- a/doc/appdev/gssapi.rst +++ b/doc/appdev/gssapi.rst @@ -312,6 +312,25 @@ issue a ticket from the client to the target service. The GSSAPI library will then use this ticket to authenticate to the target service. +If an application needs to find out whether a credential it holds is a +proxy credential and the name of the intermediate service, it can +query the credential with the **GSS_KRB5_GET_CRED_IMPERSONATOR** OID +(new in release 1.16, declared in ````) using +the gss_inquire_cred_by_oid extension (declared in +````):: + + OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + gss_OID desired_object, + gss_buffer_set_t *data_set); + +If the call succeeds and *cred_handle* is a proxy credential, +*data_set* will be set to a single-element buffer set containing the +unparsed principal name of the intermediate service. If *cred_handle* +is not a proxy credential, *data_set* will be set to an empty buffer +set. If the library does not support the query, +gss_inquire_cred_by_oid will return **GSS_S_UNAVAILABLE**. + AEAD message wrapping --------------------- diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index d7bdef7e28..cd65966b9c 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -1425,4 +1425,10 @@ iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle, * the format changes. */ #define CRED_EXPORT_MAGIC "K5C1" +OM_uint32 +gss_krb5int_get_cred_impersonator(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + #endif /* _GSSAPIP_KRB5_H_ */ diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index 99092ccab1..e12b662278 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -126,6 +126,8 @@ #define NO_CI_FLAGS_X_OID_LENGTH 6 #define NO_CI_FLAGS_X_OID "\x2a\x85\x70\x2b\x0d\x1d" +#define GET_CRED_IMPERSONATOR_OID_LENGTH 11 +#define GET_CRED_IMPERSONATOR_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e" const gss_OID_desc krb5_gss_oid_array[] = { /* this is the official, rfc-specified OID */ @@ -148,6 +150,8 @@ const gss_OID_desc krb5_gss_oid_array[] = { /* gss_nt_krb5_principal. Object identifier for a krb5_principal. Do not use. */ {10, "\052\206\110\206\367\022\001\002\002\002"}, {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID}, + /* this is an inquire cred OID */ + {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID}, { 0, 0 } }; @@ -164,6 +168,7 @@ const gss_OID gss_nt_krb5_principal = &kg_oids[6]; const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &kg_oids[5]; const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &kg_oids[7]; +const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &kg_oids[8]; static const gss_OID_set_desc oidsets[] = { {1, &kg_oids[0]}, /* RFC OID */ @@ -400,13 +405,16 @@ krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, /* * gss_inquire_cred_by_oid() methods */ -#if 0 + static struct { gss_OID_desc oid; OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *); } krb5_gss_inquire_cred_by_oid_ops[] = { + { + {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID}, + gss_krb5int_get_cred_impersonator + } }; -#endif static OM_uint32 KRB5_CALLCONV krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, @@ -415,9 +423,7 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, gss_buffer_set_t *data_set) { OM_uint32 major_status = GSS_S_FAILURE; -#if 0 size_t i; -#endif if (minor_status == NULL) return GSS_S_CALL_INACCESSIBLE_WRITE; @@ -440,7 +446,6 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, if (GSS_ERROR(major_status)) return major_status; -#if 0 for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/ sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) { if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) { @@ -450,7 +455,6 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, data_set); } } -#endif *minor_status = EINVAL; diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h index 37fa3da27d..e145eec3b4 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.h +++ b/src/lib/gssapi/krb5/gssapi_krb5.h @@ -96,6 +96,15 @@ GSS_DLLIMP extern const gss_OID_desc krb5_gss_oid_array[]; */ GSS_DLLIMP extern const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X; +/* + * This OID can be used with gss_inquire_cred_by_oid(0 to retrieve the + * impersonator name (if any). + * + * iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5-gssapi-ext(5) get-cred-impersonator(14) + */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR; + #define gss_krb5_nt_general_name gss_nt_krb5_name #define gss_krb5_nt_principal gss_nt_krb5_principal #define gss_krb5_nt_service_name gss_nt_service_name diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c index 4e35a05631..d375f86323 100644 --- a/src/lib/gssapi/krb5/inq_cred.c +++ b/src/lib/gssapi/krb5/inq_cred.c @@ -245,3 +245,44 @@ krb5_gss_inquire_cred_by_mech(minor_status, cred_handle, } return(mstat); } + +OM_uint32 +gss_krb5int_get_cred_impersonator(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t)cred_handle; + gss_buffer_desc rep = GSS_C_EMPTY_BUFFER; + krb5_context context = NULL; + char *impersonator = NULL; + krb5_error_code ret; + OM_uint32 major; + + *data_set = GSS_C_NO_BUFFER_SET; + + /* Return an empty buffer set if no impersonator is present */ + if (cred->impersonator == NULL) + return generic_gss_create_empty_buffer_set(minor_status, data_set); + + ret = krb5_gss_init_context(&context); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_unparse_name(context, cred->impersonator, &impersonator); + if (ret) { + krb5_free_context(context); + *minor_status = ret; + return GSS_S_FAILURE; + } + + rep.value = impersonator; + rep.length = strlen(impersonator); + major = generic_gss_add_buffer_set_member(minor_status, &rep, data_set); + + krb5_free_unparsed_name(context, impersonator); + krb5_free_context(context); + return major; +} diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports index 9facb3f426..16d38e94b9 100644 --- a/src/lib/gssapi/libgssapi_krb5.exports +++ b/src/lib/gssapi/libgssapi_krb5.exports @@ -10,6 +10,7 @@ GSS_C_NT_STRING_UID_NAME GSS_C_NT_USER_NAME GSS_KRB5_NT_PRINCIPAL_NAME GSS_KRB5_CRED_NO_CI_FLAGS_X +GSS_KRB5_GET_CRED_IMPERSONATOR GSS_C_MA_MECH_CONCRETE GSS_C_MA_MECH_PSEUDO GSS_C_MA_MECH_COMPOSITE diff --git a/src/tests/gssapi/t_s4u.c b/src/tests/gssapi/t_s4u.c index 5bc1e4470b..0400f8f61f 100644 --- a/src/tests/gssapi/t_s4u.c +++ b/src/tests/gssapi/t_s4u.c @@ -242,6 +242,7 @@ main(int argc, char *argv[]) gss_cred_id_t delegated_cred_handle = GSS_C_NO_CREDENTIAL; gss_name_t user = GSS_C_NO_NAME, target = GSS_C_NO_NAME; gss_OID_set mechs; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; if (argc < 2 || argc > 5) { fprintf(stderr, "Usage: %s [--spnego] [user] " @@ -305,6 +306,25 @@ main(int argc, char *argv[]) fprintf(stderr, "\n"); } + if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { + /* Inquire impersonator status. */ + major = gss_inquire_cred_by_oid(&minor, user_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count == 0) + errout("gss_inquire_cred_by_oid(user) returned NO impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + + major = gss_inquire_cred_by_oid(&minor, impersonator_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count != 0) + errout("gss_inquire_cred_by_oid(svc) returned an impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + } + (void)gss_release_name(&minor, &user); (void)gss_release_name(&minor, &target); (void)gss_release_cred(&minor, &delegated_cred_handle);