krb5 commit: Add GSS_KRB5_NT_X509_CERT name type

Greg Hudson ghudson at mit.edu
Wed Jul 1 13:17:16 EDT 2020


https://github.com/krb5/krb5/commit/f2e28f13156785851819fc74cae52100e0521690
commit f2e28f13156785851819fc74cae52100e0521690
Author: Isaac Boukris <iboukris at gmail.com>
Date:   Mon Aug 12 11:13:07 2019 +0000

    Add GSS_KRB5_NT_X509_CERT name type
    
    If this name type is used for the desired_name parameter of
    gss_acquire_cred_impersonate_name(), identify the S4U2Self user by
    certificate.  Co-authored with Purand Chand <pchand at vmware.com>.
    
    [ghudson at mit.edu: added documentation; updated to use a boolean at the
    GSS layer rather than a new krb5 name type; rewrote commit message]
    
    ticket: 8923 (new)

 doc/appdev/gssapi.rst                 |    6 ++++++
 src/lib/gssapi/krb5/gssapiP_krb5.h    |    1 +
 src/lib/gssapi/krb5/gssapi_krb5.c     |    3 +++
 src/lib/gssapi/krb5/gssapi_krb5.h     |    5 +++++
 src/lib/gssapi/krb5/import_name.c     |   12 +++++++++++-
 src/lib/gssapi/krb5/s4u_gss_glue.c    |    9 ++++++---
 src/lib/gssapi/libgssapi_krb5.exports |    1 +
 src/lib/gssapi32.def                  |    2 ++
 src/tests/gssapi/common.c             |    4 +++-
 src/tests/gssapi/t_imp_name.c         |    2 ++
 src/tests/gssapi/t_s4u.py             |   10 ++++++++++
 11 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/doc/appdev/gssapi.rst b/doc/appdev/gssapi.rst
index 66561fd..452ead2 100644
--- a/doc/appdev/gssapi.rst
+++ b/doc/appdev/gssapi.rst
@@ -61,6 +61,12 @@ name types are supported by the krb5 mechanism:
   is defined in the ``<gssapi/gssapi_krb5.h>`` header.  (New in
   release 1.17.)
 
+* **GSS_KRB5_NT_X509_CERT**: The value should be an X.509 certificate
+  encoded according to :rfc:`5280`.  This name form can be used for
+  the desired_name parameter of gss_acquire_cred_impersonate_name(),
+  to identify the S4U2Self user by certificate.  (New in release
+  1.19.)
+
 
 Initiator credentials
 ---------------------
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 2e2c775..53d077a 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -163,6 +163,7 @@ typedef struct _krb5_gss_name_rec {
     krb5_principal princ;       /* immutable */
     char *service;              /* immutable */
     char *host;                 /* immutable */
+    int is_cert;                /* immutable */
     k5_mutex_t lock;            /* protects ad_context only for now */
     krb5_authdata_context ad_context;
 } krb5_gss_name_rec, *krb5_gss_name_t;
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index 128ffff..a96d7ce 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -152,6 +152,8 @@ const gss_OID_desc krb5_gss_oid_array[] = {
     {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID},
     /* GSS_KRB5_NT_ENTERPRISE_NAME */
     {10, "\052\206\110\206\367\022\001\002\002\006"},
+    /* GSS_KRB5_NT_X509_CERT */
+    {10, "\052\206\110\206\367\022\001\002\002\007"},
     { 0, 0 }
 };
 
@@ -170,6 +172,7 @@ 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];
 const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME       = &kg_oids[9];
+const gss_OID GSS_KRB5_NT_X509_CERT             = &kg_oids[10];
 
 static const gss_OID_set_desc oidsets[] = {
     {1, &kg_oids[0]}, /* RFC OID */
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h
index e266b59..8141f41 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.h
+++ b/src/lib/gssapi/krb5/gssapi_krb5.h
@@ -78,6 +78,11 @@ GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME;
 /* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
  * krb5(2) krb5-enterprise-name(6)}. */
 
+/* Kerberos X.509 DER-encoded certificate */
+GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_X509_CERT;
+/* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * krb5(2) krb5-x509-cert(7)}. */
+
 GSS_DLLIMP extern const gss_OID gss_mech_krb5;
 GSS_DLLIMP extern const gss_OID gss_mech_krb5_old;
 GSS_DLLIMP extern const gss_OID gss_mech_krb5_wrong;
diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c
index 21023dd..f64635a 100644
--- a/src/lib/gssapi/krb5/import_name.c
+++ b/src/lib/gssapi/krb5/import_name.c
@@ -136,7 +136,7 @@ krb5_gss_import_name(minor_status, input_name_buffer,
 #ifndef NO_PASSWORD
     struct passwd *pw;
 #endif
-    int is_composite = 0;
+    int is_composite = 0, is_cert = 0;
     krb5_authdata_context ad_context = NULL;
     OM_uint32 status = GSS_S_FAILURE;
     krb5_gss_name_t name;
@@ -188,6 +188,14 @@ krb5_gss_import_name(minor_status, input_name_buffer,
                                    &princ);
         if (code)
             goto cleanup;
+    } else if ((input_name_type != NULL) &&
+               g_OID_equal(input_name_type, GSS_KRB5_NT_X509_CERT)) {
+        code = krb5_build_principal_ext(context, &princ, 0, NULL,
+                                        input_name_buffer->length,
+                                        input_name_buffer->value, 0);
+        if (code)
+            goto cleanup;
+        is_cert = 1;
     } else {
 #ifndef NO_PASSWORD
         uid_t uid;
@@ -315,6 +323,8 @@ krb5_gss_import_name(minor_status, input_name_buffer,
                         KG_INIT_NAME_NO_COPY, &name);
     if (code)
         goto cleanup;
+    name->is_cert = is_cert;
+
     princ = NULL;
     ad_context = NULL;
     service = host = NULL;
diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c
index 126ca97..7dcfe4e 100644
--- a/src/lib/gssapi/krb5/s4u_gss_glue.c
+++ b/src/lib/gssapi/krb5/s4u_gss_glue.c
@@ -48,11 +48,15 @@ kg_impersonate_name(OM_uint32 *minor_status,
     OM_uint32 major_status;
     krb5_error_code code;
     krb5_creds in_creds, *out_creds = NULL;
+    krb5_data *subject_cert = NULL;
 
     *output_cred = NULL;
     memset(&in_creds, 0, sizeof(in_creds));
 
-    in_creds.client = user->princ;
+    if (user->is_cert)
+        subject_cert = user->princ->data;
+    else
+        in_creds.client = user->princ;
     in_creds.server = impersonator_cred->name->princ;
 
     if (impersonator_cred->req_enctypes != NULL)
@@ -77,8 +81,7 @@ kg_impersonate_name(OM_uint32 *minor_status,
     code = krb5_get_credentials_for_user(context,
                                          KRB5_GC_CANONICALIZE | KRB5_GC_NO_STORE,
                                          impersonator_cred->ccache,
-                                         &in_creds,
-                                         NULL, &out_creds);
+                                         &in_creds, subject_cert, &out_creds);
     if (code != 0) {
         krb5_free_authdata(context, in_creds.authdata);
         *minor_status = code;
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
index 166acfa..fd4fced 100644
--- a/src/lib/gssapi/libgssapi_krb5.exports
+++ b/src/lib/gssapi/libgssapi_krb5.exports
@@ -12,6 +12,7 @@ GSS_C_NT_STRING_UID_NAME
 GSS_C_NT_USER_NAME
 GSS_KRB5_NT_PRINCIPAL_NAME
 GSS_KRB5_NT_ENTERPRISE_NAME
+GSS_KRB5_NT_X509_CERT
 GSS_KRB5_CRED_NO_CI_FLAGS_X
 GSS_KRB5_GET_CRED_IMPERSONATOR
 GSS_C_MA_MECH_CONCRETE
diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
index e6b1479..a5a1e4a 100644
--- a/src/lib/gssapi32.def
+++ b/src/lib/gssapi32.def
@@ -187,3 +187,5 @@ EXPORTS
 	GSS_C_SEC_CONTEXT_SASL_SSF			@149	DATA
 ; Added in 1.17
 	GSS_KRB5_NT_ENTERPRISE_NAME			@150 	DATA
+; Added in 1.19
+	GSS_KRB5_NT_X509_CERT				@151	DATA
diff --git a/src/tests/gssapi/common.c b/src/tests/gssapi/common.c
index 7ba72f7..b49c13d 100644
--- a/src/tests/gssapi/common.c
+++ b/src/tests/gssapi/common.c
@@ -99,10 +99,12 @@ import_name(const char *str)
         nametype = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME;
     else if (*str == 'e')
         nametype = (gss_OID)GSS_KRB5_NT_ENTERPRISE_NAME;
+    else if (*str == 'c')
+        nametype = (gss_OID)GSS_KRB5_NT_X509_CERT;
     else if (*str == 'h')
         nametype = GSS_C_NT_HOSTBASED_SERVICE;
     if (nametype == NULL || str[1] != ':')
-        errout("names must begin with u: or p: or e: or h:");
+        errout("names must begin with u: or p: or e: or c: or h:");
     buf.value = (char *)str + 2;
     buf.length = strlen(str) - 2;
     major = gss_import_name(&minor, &buf, nametype, &name);
diff --git a/src/tests/gssapi/t_imp_name.c b/src/tests/gssapi/t_imp_name.c
index 3d73dc8..e7dbcc4 100644
--- a/src/tests/gssapi/t_imp_name.c
+++ b/src/tests/gssapi/t_imp_name.c
@@ -41,6 +41,8 @@ oid_str(char type)
         return "{ 1 2 840 113554 1 2 2 1 }";
     case 'e': /* GSS_KRB5_NT_ENTERPRISE_NAME */
         return "{ 1 2 840 113554 1 2 2 6 }";
+    case 'c': /* GSS_KRB5_NT_X509_CERT */
+        return "{ 1 2 840 113554 1 2 2 7 }";
     case 'h': /* GSS_C_NT_HOSTBASED_SERVICE */
         return "{ 1 2 840 113554 1 2 1 4 }";
     }
diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py
index 8077d8c..67eba44 100755
--- a/src/tests/gssapi/t_s4u.py
+++ b/src/tests/gssapi/t_s4u.py
@@ -277,6 +277,16 @@ msgs = ('Getting initial credentials for enterprise\\@abc at SREALM',
 r1.run([kvno, '-U', 'enterprise at abc', '-F', cert_path, r1.user_princ],
        expected_trace=msgs)
 
+shutil.copyfile(savefile, r1.ccache)
+
+mark('S4U2Self using X509 certificate (GSSAPI)')
+
+r1.run(['./t_s4u', 'c:other', '-', r1.keytab])
+r1.run(['./t_s4u', 'c:user at UREALM', '-', r1.keytab])
+
+r1.run(['./t_s4u', '--spnego', 'c:other', '-', r1.keytab])
+r1.run(['./t_s4u', '--spnego', 'c:user at UREALM', '-', r1.keytab])
+
 r1.stop()
 r2.stop()
 


More information about the cvs-krb5 mailing list