From: Greg Hudson Date: Tue, 7 Feb 2017 18:12:24 +0000 (-0500) Subject: Avoid draft 9 fallback after PKINIT failure X-Git-Tag: krb5-1.16-beta1~148 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0963fa5f0d01d81d3c4088088b94c455f033e921;p=thirdparty%2Fkrb5.git Avoid draft 9 fallback after PKINIT failure 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 --- diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h index 876db94c32..4c488b76ba 100644 --- a/src/plugins/preauth/pkinit/pkinit.h +++ b/src/plugins/preauth/pkinit/pkinit.h @@ -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; diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c index e73ad53e99..f1bc6b21dc 100644 --- a/src/plugins/preauth/pkinit/pkinit_clnt.c +++ b/src/plugins/preauth/pkinit/pkinit_clnt.c @@ -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; diff --git a/src/plugins/preauth/pkinit/pkinit_trace.h b/src/plugins/preauth/pkinit/pkinit_trace.h index b3f5cbb20e..a3cc9cc671 100644 --- a/src/plugins/preauth/pkinit/pkinit_trace.h +++ b/src/plugins/preauth/pkinit/pkinit_trace.h @@ -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) \ diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py index c8111d5cc3..2dc057f11e 100755 --- a/src/tests/t_pkinit.py +++ b/src/tests/t_pkinit.py @@ -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,