]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Avoid draft 9 fallback after PKINIT failure 605/head
authorGreg Hudson <ghudson@mit.edu>
Tue, 7 Feb 2017 18:12:24 +0000 (13:12 -0500)
committerGreg Hudson <ghudson@mit.edu>
Thu, 9 Feb 2017 16:05:00 +0000 (11:05 -0500)
If a KDC offers both RFC 4556 and draft 9 PKINIT, and we experience a
client-side failure trying RFC 4556 PKINIT (e.g. due to the user
entering the wrong PKCS #11 PIN), do not try to use draft 9 PKINIT.

ticket: 8544

src/plugins/preauth/pkinit/pkinit.h
src/plugins/preauth/pkinit/pkinit_clnt.c
src/plugins/preauth/pkinit/pkinit_trace.h
src/tests/t_pkinit.py

index 876db94c32f86ed498747cceffeb5b4c14dee33b..4c488b76bafc227b0df2e10b9d70833d831588b1 100644 (file)
@@ -209,6 +209,7 @@ struct _pkinit_req_context {
     pkinit_identity_opts *idopts;
     int do_identity_matching;
     krb5_preauthtype pa_type;
+    int rfc4556_kdc;
     int rfc6112_kdc;
     int identity_initialized;
     int identity_prompted;
index e73ad53e99dfe99d0acfc653f7da8772aa926d93..f1bc6b21dc479d390929e7e81c13c4aae206f55b 100644 (file)
@@ -1175,15 +1175,22 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
         reqctx->rfc6112_kdc = 1;
         return 0;
     case KRB5_PADATA_PK_AS_REQ:
+        reqctx->rfc4556_kdc = 1;
         pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
         processing_request = 1;
         break;
 
     case KRB5_PADATA_PK_AS_REP:
+        reqctx->rfc4556_kdc = 1;
         pkiDebug("processing KRB5_PADATA_PK_AS_REP\n");
         break;
     case KRB5_PADATA_PK_AS_REP_OLD:
     case KRB5_PADATA_PK_AS_REQ_OLD:
+        /* Don't fall back to draft9 code if the KDC supports RFC 4556. */
+        if (reqctx->rfc4556_kdc) {
+            TRACE_PKINIT_CLIENT_NO_DRAFT9(context);
+            return KRB5KDC_ERR_PREAUTH_FAILED;
+        }
         if (in_padata->length == 0) {
             pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
             in_padata->pa_type = KRB5_PADATA_PK_AS_REQ_OLD;
index b3f5cbb20e185da9e8b34b1a03455f2b47999686..a3cc9cc6712b076a940cb012663f4f99c1032d50 100644 (file)
@@ -47,6 +47,8 @@
 #define TRACE_PKINIT_CLIENT_KDF_OS2K(c, keyblock)                       \
     TRACE(c, "PKINIT client used octetstring2key to compute reply key " \
           "{keyblock}", keyblock)
+#define TRACE_PKINIT_CLIENT_NO_DRAFT9(c)                                \
+    TRACE(c, "PKINIT client ignoring draft 9 offer from RFC 4556 KDC")
 #define TRACE_PKINIT_CLIENT_NO_IDENTITY(c)                              \
     TRACE(c, "PKINIT client has no configured identity; giving up")
 #define TRACE_PKINIT_CLIENT_REP_CHECKSUM_FAIL(c, expected, received)    \
index c8111d5cc3433c53a2d7ba0577acb7b0711dc10e..2dc057f11e6caaedb49dfbf0875872f47d093a10 100755 (executable)
@@ -320,6 +320,14 @@ realm.kinit(realm.user_princ,
 realm.klist(realm.user_princ)
 realm.run([kvno, realm.host_princ])
 
+# Supply the wrong PIN, and verify that we ignore the draft9 padata offer
+# in the KDC method data after RFC 4556 PKINIT fails.
+expected_trace = ('PKINIT client has no configured identity; giving up',
+                  'PKINIT client ignoring draft 9 offer from RFC 4556 KDC')
+realm.kinit(realm.user_princ,
+            flags=['-X', 'X509_user_identity=%s' % p11_identity],
+            password='wrong', expected_code=1, expected_trace=expected_trace)
+
 # PKINIT with PKCS11: identity, with a PIN supplied by the responder.
 # Supply the response in raw form.
 realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p11_token_identity,