int initialized;
};
-/* Test module 1 returns OK with an indicator. */
+/* Test module 1 passes with an indicator. */
static krb5_error_code
test1_authorize(krb5_context context, krb5_certauth_moddata moddata,
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. If the "hwauth" string
- * attribute is set on db_entry, it returns KRB5_CERTAUTH_HWAUTH.
+ * Test module 2 passes if the principal name is "nocert". Otherwise it
+ * returns OK if the CN of the cert matches the principal name, with indicators
+ * of the module name and princ, and errors if the certificate does not match.
*/
static krb5_error_code
test2_authorize(krb5_context context, krb5_certauth_moddata moddata,
char ***authinds_out)
{
krb5_error_code ret;
- char *name = NULL, *strval = NULL, **ais = NULL;
+ char *name = NULL, **ais = NULL;
*authinds_out = NULL;
KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
if (ret)
goto cleanup;
+ if (strcmp(name, "nocert") == 0) {
+ ret = KRB5_PLUGIN_NO_HANDLE;
+ goto cleanup;
+ }
if (!has_cn(context, cert, cert_len, name)) {
ret = KRB5KDC_ERR_CERTIFICATE_MISMATCH;
ais = NULL;
+cleanup:
+ krb5_free_unparsed_name(context, name);
+ return ret;
+}
+
+/*
+ * Test module 3 reads the "hwauth" string attribute on db_entry, and adds an
+ * authentication indicator of "hwauth:<value>" if the attribute is set. It
+ * returns KRB5_CERTAUTH_HWAUTH if the value is "ok", and
+ * KRB5_CERTAUTH_HWAUTH_PASS if the value is "pass". Otherwise it passes.
+ */
+static krb5_error_code
+test3_authorize(krb5_context context, krb5_certauth_moddata moddata,
+ const uint8_t *cert, size_t cert_len,
+ krb5_const_principal princ, const void *opts,
+ const struct _krb5_db_entry_new *db_entry,
+ char ***authinds_out)
+{
+ krb5_error_code ret;
+ char *strval = NULL, **ais = NULL;
+
ret = krb5_dbe_get_string(context, (krb5_db_entry *)db_entry, "hwauth",
&strval);
if (ret)
- goto cleanup;
+ return ret;
+ if (strval != NULL && strcmp(strval, "ok") == 0)
+ ret = KRB5_CERTAUTH_HWAUTH;
+ else if (strval != NULL && strcmp(strval, "pass") == 0)
+ ret = KRB5_CERTAUTH_HWAUTH_PASS;
+ else
+ ret = KRB5_PLUGIN_NO_HANDLE;
- ret = (strval != NULL) ? KRB5_CERTAUTH_HWAUTH : 0;
- krb5_dbe_free_string(context, strval);
+ if (strval != NULL) {
+ ais = calloc(2, sizeof(*ais));
+ assert(ais != NULL);
+ if (asprintf(&ais[0], "hwauth:%s", strval) < 0)
+ abort();
+ assert(ais[0] != NULL);
+ }
-cleanup:
- krb5_free_unparsed_name(context, name);
+ *authinds_out = ais;
+ ais = NULL;
+
+ krb5_dbe_free_string(context, strval);
return ret;
}
vt->free_ind = test_free_ind;
return 0;
}
+
+krb5_error_code
+certauth_test3_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable);
+
+krb5_error_code
+certauth_test3_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable)
+{
+ krb5_certauth_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+ vt = (krb5_certauth_vtable)vtable;
+ vt->name = "test3";
+ vt->authorize = test3_authorize;
+ vt->free_ind = test_free_ind;
+ return 0;
+}
pkinit_krb5_conf = {'realms': {'$realm': {
'pkinit_anchors': 'FILE:%s' % ca_pem}},
'plugins': {'certauth': {'module': ['test1:' + modpath,
- 'test2:' + modpath],
- 'enable_only': ['test1', 'test2']}}}
+ 'test2:' + modpath,
+ 'test3:' + modpath],
+ 'enable_only': ['test1', 'test2',
+ 'test3']}}}
pkinit_kdc_conf = {'realms': {'$realm': {
'default_principal_flags': '+preauth',
'pkinit_eku_checking': 'none',
realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
get_creds=False)
+realm.addprinc('nocert')
-# Let the test module match user to CN=user, with indicators.
-realm.kinit(realm.user_princ,
- flags=['-X', 'X509_user_identity=%s' % file_identity])
+def pkinit(princ, **kw):
+ realm.kinit(princ, flags=['-X', 'X509_user_identity=%s' % file_identity],
+ **kw)
+
+def check_indicators(inds):
+ msg = '+97: [%s]' % inds
+ realm.run(['./adata', realm.host_princ], expected_msg=msg)
+
+# Test that authentication fails if no module accepts.
+pkinit('nocert', expected_code=1, expected_msg='Client name mismatch')
+
+# Let the test2 module match user to CN=user, with indicators.
+pkinit(realm.user_princ)
realm.klist(realm.user_princ)
-realm.run([kvno, realm.host_princ])
-realm.run(['./adata', realm.host_princ],
- expected_msg='+97: [test1, test2, user, indpkinit1, indpkinit2]')
+check_indicators('test1, test2, user, indpkinit1, indpkinit2')
-# Let the test module mismatch with user2 to CN=user.
-realm.addprinc("user2@KRBTEST.COM")
-out = realm.kinit("user2@KRBTEST.COM",
- flags=['-X', 'X509_user_identity=%s' % file_identity],
- expected_code=1,
- expected_msg='kinit: Certificate mismatch')
+# Let the test2 module mismatch with user2 to CN=user.
+realm.addprinc('user2@KRBTEST.COM')
+pkinit('user2', 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])
+pkinit(realm.user_princ, expected_code=1, expected_msg='Looping detected')
+# Cause the test3 module to return KRB5_CERTAUTH_HWAUTH and try again.
+# Authentication should succeed whether or not another module accepts,
+# but not if another module rejects.
+realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'ok'])
+realm.run([kadminl, 'setstr', 'user2', 'hwauth', 'ok'])
+realm.run([kadminl, 'setstr', 'nocert', 'hwauth', 'ok'])
+pkinit(realm.user_princ)
+check_indicators('test1, test2, user, hwauth:ok, indpkinit1, indpkinit2')
+pkinit('user2', expected_code=1, expected_msg='kinit: Certificate mismatch')
+pkinit('nocert')
+check_indicators('test1, hwauth:ok, indpkinit1, indpkinit2')
+
+# Cause the test3 module to return KRB5_CERTAUTH_HWAUTH_PASS and try
+# again. Authentication should succeed only if another module accepts.
+realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'pass'])
+realm.run([kadminl, 'setstr', 'user2', 'hwauth', 'pass'])
+realm.run([kadminl, 'setstr', 'nocert', 'hwauth', 'pass'])
+pkinit(realm.user_princ)
+check_indicators('test1, test2, user, hwauth:pass, indpkinit1, indpkinit2')
+pkinit('user2', expected_code=1, expected_msg='kinit: Certificate mismatch')
+pkinit('nocert', expected_code=1, expected_msg='kinit: Client name mismatch')
success("certauth tests")