]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Load certs when checking pkinit_identities values 1157/head
authorKen Hornstein <kenh@cmf.nrl.navy.mil>
Thu, 28 Jan 2021 02:21:19 +0000 (21:21 -0500)
committerGreg Hudson <ghudson@mit.edu>
Thu, 11 Feb 2021 17:50:44 +0000 (12:50 -0500)
Move the crypto_load_certs() probe from pkinit_identity_initialize()
to process_option_identity().  This will attempt to load a certificate
for each pkinit_identities value, and if the certificate load fails to
move to the next line.

For PKCS11, return an error if pkinit_open_session() fails, but do not
fail in pkinit_open_session() just because identity prompts are
deferred.

[ghudson@mit.edu: added test case; moved cert probe to
process_option_identity(); rewrote commit message]

ticket: 8984 (new)

doc/admin/conf_files/krb5_conf.rst
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
src/plugins/preauth/pkinit/pkinit_identity.c
src/tests/t_pkinit.py

index 08e0fc8630dc5337497f326fd5f8f0bdafbc3dee..d5d6e06ebb797f01d9b21185fc032b5bcfb2b32c 100644 (file)
@@ -1123,10 +1123,9 @@ PKINIT krb5.conf options
 **pkinit_identities**
     Specifies the location(s) to be used to find the user's X.509
     identity information.  If this option is specified multiple times,
-    the first valid value is used; this can be used to specify an
-    environment variable (with **ENV:**\ *envvar*) followed by a
-    default value.  Note that these values are not used if the user
-    specifies **X509_user_identity** on the command line.
+    each value is attempted in order until certificates are found.
+    Note that these values are not used if the user specifies
+    **X509_user_identity** on the command line.
 
 **pkinit_kdc_hostname**
     The presence of this option indicates that the client is willing
index d7d1593f431397b9915692bc4d2fa276f8103b68..e5940a5135c6aab77105cc1f43f33f18669a9e36 100644 (file)
@@ -3748,7 +3748,7 @@ pkinit_open_session(krb5_context context,
             pkinit_set_deferred_id(&cctx->deferred_ids,
                                    p11name, tinfo.flags, NULL);
             free(p11name);
-            return KRB5KRB_ERR_GENERIC;
+            return 0;
         }
         /* Look up a responder-supplied password for the token. */
         password = pkinit_find_deferred_id(cctx->deferred_ids, p11name);
@@ -4552,11 +4552,9 @@ pkinit_get_certs_pkcs11(krb5_context context,
     id_cryptoctx->slotid = idopts->slotid;
     id_cryptoctx->pkcs11_method = 1;
 
-    if (pkinit_open_session(context, id_cryptoctx)) {
-        pkiDebug("can't open pkcs11 session\n");
-        if (!id_cryptoctx->defer_id_prompt)
-            return KRB5KDC_ERR_PREAUTH_FAILED;
-    }
+    r = pkinit_open_session(context, id_cryptoctx);
+    if (r != 0)
+        return r;
     if (id_cryptoctx->defer_id_prompt) {
         /*
          * We need to reset all of the PKCS#11 state, so that the next time we
index b89c5d015c303395199a4f24209a44e3ac5c2ae9..4046b15f4d99b7e5ee5814b42d7ca530607560b5 100644 (file)
@@ -378,7 +378,7 @@ process_option_identity(krb5_context context,
                         pkinit_req_crypto_context req_cryptoctx,
                         pkinit_identity_opts *idopts,
                         pkinit_identity_crypto_context id_cryptoctx,
-                        const char *value)
+                        krb5_principal princ, const char *value)
 {
     const char *residual;
     int idtype;
@@ -424,7 +424,7 @@ process_option_identity(krb5_context context,
     switch (idtype) {
     case IDTYPE_ENVVAR:
         return process_option_identity(context, plg_cryptoctx, req_cryptoctx,
-                                       idopts, id_cryptoctx,
+                                       idopts, id_cryptoctx, princ,
                                        secure_getenv(residual));
         break;
     case IDTYPE_FILE:
@@ -450,7 +450,16 @@ process_option_identity(krb5_context context,
         retval = EINVAL;
         break;
     }
-    return retval;
+    if (retval)
+        return retval;
+
+    retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx, idopts,
+                               id_cryptoctx, princ, TRUE);
+    if (retval)
+        return retval;
+
+    crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx);
+    return 0;
 }
 
 static krb5_error_code
@@ -525,12 +534,13 @@ pkinit_identity_initialize(krb5_context context,
         if (idopts->identity != NULL) {
             retval = process_option_identity(context, plg_cryptoctx,
                                              req_cryptoctx, idopts,
-                                             id_cryptoctx, idopts->identity);
+                                             id_cryptoctx, princ,
+                                             idopts->identity);
         } else if (idopts->identity_alt != NULL) {
             for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++) {
                 retval = process_option_identity(context, plg_cryptoctx,
                                                  req_cryptoctx, idopts,
-                                                 id_cryptoctx,
+                                                 id_cryptoctx, princ,
                                                  idopts->identity_alt[i]);
             }
         } else {
@@ -540,16 +550,6 @@ pkinit_identity_initialize(krb5_context context,
             pkiDebug("%s: no user identity options specified\n", __FUNCTION__);
             goto errout;
         }
-        if (retval)
-            goto errout;
-
-        retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
-                                   idopts, id_cryptoctx, princ, TRUE);
-        if (retval)
-            goto errout;
-
-        crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
-                              id_cryptoctx);
     } else {
         /* We're the anonymous principal. */
         retval = 0;
index f224383c81b757b5a2bdd4e5f43b0451fe415f2a..aee4da2b14a712564c86c5da73d37abd0c01d1b3 100755 (executable)
@@ -183,6 +183,13 @@ realm.kinit(realm.user_princ,
 realm.klist(realm.user_princ)
 realm.run([kvno, realm.host_princ])
 
+# Try using multiple configured pkinit_identities, to make sure we
+# fall back to the second one when the first one cannot be read.
+id_conf = {'realms': {'$realm': {'pkinit_identities': [file_identity + 'X',
+                                                       file_identity]}}}
+id_env = realm.special_env('idconf', False, krb5_conf=id_conf)
+realm.kinit(realm.user_princ, expected_trace=msgs, env=id_env)
+
 # Try again using RSA instead of DH.
 mark('FILE identity, no password, RSA')
 realm.kinit(realm.user_princ,