]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add GSS_KRB5_NT_X509_CERT name type 1081/head
authorIsaac Boukris <iboukris@gmail.com>
Mon, 12 Aug 2019 11:13:07 +0000 (11:13 +0000)
committerGreg Hudson <ghudson@mit.edu>
Wed, 1 Jul 2020 14:58:47 +0000 (10:58 -0400)
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@vmware.com>.

[ghudson@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
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/krb5/gssapi_krb5.h
src/lib/gssapi/krb5/import_name.c
src/lib/gssapi/krb5/s4u_gss_glue.c
src/lib/gssapi/libgssapi_krb5.exports
src/lib/gssapi32.def
src/tests/gssapi/common.c
src/tests/gssapi/t_imp_name.c
src/tests/gssapi/t_s4u.py

index 66561fd0e168960a602cffd0aa17c5ad79e63e6f..452ead2a91078085ba68a066e36b6f4f4c46fbda 100644 (file)
@@ -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
 ---------------------
index 2e2c775d636c035f0d4880d76dae907e1128d9ff..53d077a0f50681729159ecce023bb43009d6ed96 100644 (file)
@@ -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;
index 128ffffa18bf4a701f1236f12eb5d9bcad6500d1..a96d7ceaeb049beb50dd602291c9c496dfd622aa 100644 (file)
@@ -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 */
index e266b59b6f7976833af840b075621966cca73b70..8141f41db9159ef9cf3b7204c3001c9697c56220 100644 (file)
@@ -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;
index 21023dd769b289e1f2bbbf0226479ef4454db058..f64635a20265957eab178e905c41f848b1788ea4 100644 (file)
@@ -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;
index 126ca973cae959c0fe639e8b3beebbee34793845..7dcfe4e1eb6cc4e413e4e62ef25a75709594d1e7 100644 (file)
@@ -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;
index 166acfa34ef1c9d60f892dd50160214a49e55eb7..fd4fced8e9866db63f507fad74d051bb38cf66fc 100644 (file)
@@ -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
index e6b1479bbb9fec628adea1b4340bd79df26e5cf9..a5a1e4a9051d722014c9d105e51546d146e8ee53 100644 (file)
@@ -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
index 7ba72f7b27e5018cd702550963ecc6e214028de9..b49c13d5d40eb3e87f3b5c2ec262255b2a584e37 100644 (file)
@@ -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);
index 3d73dc8fbc8b9df5e37e60c033b3c5f33b9ce836..e7dbcc426e2fe3979b15a26d8544e9a8648ca5f9 100644 (file)
@@ -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 }";
     }
index 8077d8c6bff541bf661d60551420617e29f839ed..67eba44dab108bba864257a1707b577c86036bc1 100755 (executable)
@@ -277,6 +277,16 @@ msgs = ('Getting initial credentials for enterprise\\@abc@SREALM',
 r1.run([kvno, '-U', 'enterprise@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@UREALM', '-', r1.keytab])
+
+r1.run(['./t_s4u', '--spnego', 'c:other', '-', r1.keytab])
+r1.run(['./t_s4u', '--spnego', 'c:user@UREALM', '-', r1.keytab])
+
 r1.stop()
 r2.stop()