[30746] in CVS-changelog-for-Kerberos-V5

home help back first fref pref prev next nref lref last post

krb5 commit: Allow certauth modules to set hw-authent flag

daemon@ATHENA.MIT.EDU (Greg Hudson)
Thu Feb 27 15:23:43 2020

Date: Thu, 27 Feb 2020 15:23:24 -0500
From: Greg Hudson <ghudson@mit.edu>
Message-ID: <202002272023.01RKNO9f024677@drugstore.mit.edu>
To: <cvs-krb5@mit.edu>
MIME-Version: 1.0
Reply-To: krbdev@mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu

https://github.com/krb5/krb5/commit/50fb43b4a2d97ce2cd53e1ced30e8e8224fede70
commit 50fb43b4a2d97ce2cd53e1ced30e8e8224fede70
Author: Greg Hudson <ghudson@mit.edu>
Date:   Mon Feb 24 15:58:59 2020 -0500

    Allow certauth modules to set hw-authent flag
    
    In PKINIT, if a certauth module returns KRB5_CERTAUTH_HWAUTH from its
    authorize method, set the hw-authent flag in the ticket.
    
    ticket: 8879 (new)

 doc/plugindev/certauth.rst              |    7 +++++--
 src/include/krb5/certauth_plugin.h      |    9 ++++++---
 src/lib/krb5/error_tables/k5e1_err.et   |    1 +
 src/plugins/certauth/test/Makefile.in   |    4 ++--
 src/plugins/certauth/test/main.c        |   11 +++++++++--
 src/plugins/preauth/pkinit/pkinit_srv.c |   24 ++++++++++++++++--------
 src/tests/t_certauth.py                 |   13 +++++++++++++
 7 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/doc/plugindev/certauth.rst b/doc/plugindev/certauth.rst
index 8a7f7c5..3b715f7 100644
--- a/doc/plugindev/certauth.rst
+++ b/doc/plugindev/certauth.rst
@@ -15,8 +15,11 @@ principal.  **authorize** receives the DER-encoded certificate, the
 requested client principal, and a pointer to the client's
 krb5_db_entry (for modules that link against libkdb5).  It returns the
 authorization status and optionally outputs a list of authentication
-indicator strings to be added to the ticket.  A module must use its
-own internal or library-provided ASN.1 certificate decoder.
+indicator strings to be added to the ticket.  Beginning in release
+1.19, the authorize method can request that the hardware
+authentication bit be set in the ticket by returning
+**KRB5_CERTAUTH_HWAUTH**.  A module must use its own internal or
+library-provided ASN.1 certificate decoder.
 
 A module can optionally create and destroy module data with the
 **init** and **fini** methods.  Module data objects last for the
diff --git a/src/include/krb5/certauth_plugin.h b/src/include/krb5/certauth_plugin.h
index 3074790..3466cf3 100644
--- a/src/include/krb5/certauth_plugin.h
+++ b/src/include/krb5/certauth_plugin.h
@@ -85,14 +85,17 @@ typedef void
 (*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata);
 
 /*
- * Mandatory:
- * Return 0 if the DER-encoded cert is authorized for PKINIT authentication by
- * princ; otherwise return one of the following error codes:
+ * Mandatory: return 0 or KRB5_CERTAUTH_HWAUTH if the DER-encoded cert is
+ * authorized for PKINIT authentication by princ; otherwise return one of the
+ * following error codes:
  * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value
  * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU
  * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error
  * - KRB5_PLUGIN_NO_HANDLE - the module has no opinion about cert
  *
+ * Returning KRB5_CERTAUTH_HWAUTH will cause the hw-authent flag to be set in
+ * the issued ticket (new in release 1.19).
+ *
  * - opts is used by built-in modules to receive internal data, and must be
  *   ignored by other modules.
  * - db_entry receives the client principal database entry, and can be ignored
diff --git a/src/lib/krb5/error_tables/k5e1_err.et b/src/lib/krb5/error_tables/k5e1_err.et
index ade5cae..abd9f3b 100644
--- a/src/lib/krb5/error_tables/k5e1_err.et
+++ b/src/lib/krb5/error_tables/k5e1_err.et
@@ -42,4 +42,5 @@ error_code KRB5_KCM_MALFORMED_REPLY, "Malformed reply from KCM daemon"
 error_code KRB5_KCM_RPC_ERROR, "Mach RPC error communicating with KCM daemon"
 error_code KRB5_KCM_REPLY_TOO_BIG, "KCM daemon reply too big"
 error_code KRB5_KCM_NO_SERVER, "No KCM server found"
+error_code KRB5_CERTAUTH_HWAUTH, "Authorize and set hw-authent ticket flag"
 end
diff --git a/src/plugins/certauth/test/Makefile.in b/src/plugins/certauth/test/Makefile.in
index d352408..e94c138 100644
--- a/src/plugins/certauth/test/Makefile.in
+++ b/src/plugins/certauth/test/Makefile.in
@@ -5,8 +5,8 @@ LIBBASE=certauth_test
 LIBMAJOR=0
 LIBMINOR=0
 RELDIR=../plugins/certauth/test
-SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS)
-SHLIB_EXPLIBS=$(KRB5_BASE_LIBS)
+SHLIB_EXPDEPS=$(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+SHLIB_EXPLIBS=$(KDB5_LIBS) $(KRB5_BASE_LIBS)
 
 STLIBOBJS=main.o
 
diff --git a/src/plugins/certauth/test/main.c b/src/plugins/certauth/test/main.c
index 7764123..d4633b8 100644
--- a/src/plugins/certauth/test/main.c
+++ b/src/plugins/certauth/test/main.c
@@ -31,6 +31,7 @@
  */
 
 #include <k5-int.h>
+#include <kdb.h>
 #include "krb5/certauth_plugin.h"
 
 struct krb5_certauth_moddata_st {
@@ -131,7 +132,8 @@ has_cn(krb5_context context, const uint8_t *cert, size_t cert_len,
 
 /*
  * Test module 2 returns OK if princ matches the CN part of the subject name,
- * and returns indicators of the module name and princ.
+ * and returns indicators of the module name and princ.  If the "hwauth" string
+ * attribute is set on db_entry, it returns KRB5_CERTAUTH_HWAUTH.
  */
 static krb5_error_code
 test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
@@ -141,7 +143,7 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
                 char ***authinds_out)
 {
     krb5_error_code ret;
-    char *name = NULL, **ais = NULL;
+    char *name = NULL, *strval = NULL, **ais = NULL;
 
     *authinds_out = NULL;
 
@@ -167,6 +169,11 @@ test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
 
     ais = NULL;
 
+    ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",
+                              &strval);
+    ret = (strval != NULL) ? KRB5_CERTAUTH_HWAUTH : 0;
+    krb5_dbe_free_string(context, strval);
+
 cleanup:
     krb5_free_unparsed_name(context, name);
     return ret;
diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c
index feca118..3ae56c0 100644
--- a/src/plugins/preauth/pkinit/pkinit_srv.c
+++ b/src/plugins/preauth/pkinit/pkinit_srv.c
@@ -320,12 +320,12 @@ static krb5_error_code
 authorize_cert(krb5_context context, certauth_handle *certauth_modules,
                pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx,
                krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
-               krb5_principal client)
+               krb5_principal client, krb5_boolean *hwauth_out)
 {
     krb5_error_code ret;
     certauth_handle h;
     struct certauth_req_opts opts;
-    krb5_boolean accepted = FALSE;
+    krb5_boolean accepted = FALSE, hwauth = FALSE;
     uint8_t *cert;
     size_t i, cert_len;
     void *db_ent = NULL;
@@ -347,9 +347,10 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
 
     /*
      * Check the certificate against each certauth module.  For the certificate
-     * to be authorized at least one module must return 0, and no module can an
-     * error code other than KRB5_PLUGIN_NO_HANDLE (pass).  Add indicators from
-     * modules that return 0 or pass.
+     * to be authorized at least one module must return 0 or
+     * KRB5_CERTAUTH_HWAUTH, and no module can return an error code other than
+     * KRB5_PLUGIN_NO_HANDLE (pass).  Add indicators from modules that return 0
+     * or pass.
      */
     ret = KRB5_PLUGIN_NO_HANDLE;
     for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) {
@@ -359,6 +360,8 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
                               &opts, db_ent, &ais);
         if (ret == 0)
             accepted = TRUE;
+        else if (ret == KRB5_CERTAUTH_HWAUTH)
+            accepted = hwauth = TRUE;
         else if (ret != KRB5_PLUGIN_NO_HANDLE)
             goto cleanup;
 
@@ -374,6 +377,7 @@ authorize_cert(krb5_context context, certauth_handle *certauth_modules,
         }
     }
 
+    *hwauth_out = hwauth;
     ret = accepted ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
 
 cleanup:
@@ -430,7 +434,7 @@ pkinit_server_verify_padata(krb5_context context,
     int is_signed = 1;
     krb5_pa_data **e_data = NULL;
     krb5_kdcpreauth_modreq modreq = NULL;
-    krb5_boolean valid_freshness_token = FALSE;
+    krb5_boolean valid_freshness_token = FALSE, hwauth = FALSE;
     char **sp;
 
     pkiDebug("pkinit_verify_padata: entered!\n");
@@ -494,7 +498,7 @@ pkinit_server_verify_padata(krb5_context context,
     }
     if (is_signed) {
         retval = authorize_cert(context, moddata->certauth_modules, plgctx,
-                                reqctx, cb, rock, request->client);
+                                reqctx, cb, rock, request->client, &hwauth);
         if (retval)
             goto cleanup;
 
@@ -613,6 +617,8 @@ pkinit_server_verify_padata(krb5_context context,
 
     /* remember to set the PREAUTH flag in the reply */
     enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
+    if (hwauth)
+        enc_tkt_reply->flags |= TKT_FLG_HW_AUTH;
     modreq = (krb5_kdcpreauth_modreq)reqctx;
     reqctx = NULL;
 
@@ -1044,7 +1050,9 @@ pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype)
 {
     if (patype == KRB5_PADATA_PKINIT_KX)
         return PA_INFO;
-    return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA;
+    /* PKINIT does not normally set the hw-authent ticket flag, but a
+     * certauth module can cause it to do so. */
+    return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA | PA_HARDWARE;
 }
 
 static krb5_preauthtype supported_server_pa_types[] = {
diff --git a/src/tests/t_certauth.py b/src/tests/t_certauth.py
index 9c70945..0fe0fdb 100644
--- a/src/tests/t_certauth.py
+++ b/src/tests/t_certauth.py
@@ -43,4 +43,17 @@ out = realm.kinit("user2@KRBTEST.COM",
                   expected_code=1,
                   expected_msg='kinit: Certificate mismatch')
 
+# Test the KRB5_CERTAUTH_HWAUTH return code.
+mark('hw-authent flag tests')
+# First test +requires_hwauth without causing the hw-authent ticket
+# flag to be set.  This currently results in a preauth loop.
+realm.run([kadminl, 'modprinc', '+requires_hwauth', realm.user_princ])
+realm.kinit(realm.user_princ,
+            flags=['-X', 'X509_user_identity=%s' % file_identity],
+            expected_code=1, expected_msg='Looping detected')
+# Cause the test2 module to return KRB5_CERTAUTH_HWAUTH and try again.
+realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'x'])
+realm.kinit(realm.user_princ,
+            flags=['-X', 'X509_user_identity=%s' % file_identity])
+
 success("certauth tests")
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5

home help back first fref pref prev next nref lref last post