krb5 commit: Add OID to inquire GSS cred impersonator name

Greg Hudson ghudson at mit.edu
Tue Feb 21 12:59:15 EST 2017


https://github.com/krb5/krb5/commit/750cd27317d8e8af506c3b9e412a3ccbeef299b0
commit 750cd27317d8e8af506c3b9e412a3ccbeef299b0
Author: Simo Sorce <simo at redhat.com>
Date:   Thu Jan 26 05:45:17 2017 -0500

    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 at mit.edu: edited code slightly; added documentation; expanded
    commit message]
    
    ticket: 8548 (new)

 doc/appdev/gssapi.rst                 |   19 +++++++++++++++
 src/lib/gssapi/krb5/gssapiP_krb5.h    |    6 +++++
 src/lib/gssapi/krb5/gssapi_krb5.c     |   16 ++++++++-----
 src/lib/gssapi/krb5/gssapi_krb5.h     |    9 +++++++
 src/lib/gssapi/krb5/inq_cred.c        |   41 +++++++++++++++++++++++++++++++++
 src/lib/gssapi/libgssapi_krb5.exports |    1 +
 src/tests/gssapi/t_s4u.c              |   20 ++++++++++++++++
 7 files changed, 106 insertions(+), 6 deletions(-)

diff --git a/doc/appdev/gssapi.rst b/doc/appdev/gssapi.rst
index 0258f79..c39bbdd 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 ``<gssapi/gssapi_krb5.h>``) using
+the gss_inquire_cred_by_oid extension (declared in
+``<gssapi/gssapi_ext.h>``)::
+
+    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 d7bdef7..cd65966 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 99092cc..e12b662 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 37fa3da..e145eec 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 4e35a05..d375f86 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 9facb3f..16d38e9 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 5bc1e44..0400f8f 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);


More information about the cvs-krb5 mailing list