diff --git a/Makefile.am b/Makefile.am
index 97394efb16c..75d7431b907 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3807,7 +3807,8 @@ test_passkey_LDFLAGS = \
-Wl,-wrap,fido_assert_sig_len \
-Wl,-wrap,fido_assert_set_count \
-Wl,-wrap,fido_assert_set_authdata \
- -Wl,-wrap,fido_assert_set_sig
+ -Wl,-wrap,fido_assert_set_sig \
+ -Wl,-wrap,fido_dev_get_retry_count
test_passkey_LDADD = \
$(CMOCKA_LIBS) \
$(SSSD_LIBS) \
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index 9fa19312749..ed9330379f9 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -703,6 +703,9 @@ do
sss-certmap*)
echo \%lang\(${lang}\) \%{_mandir}/${man}\* >> libsss_certmap.lang
;;
+ sssd-passkey*)
+ echo \%lang\(${lang}\) \%{_mandir}/${man}\* >> sssd_passkey.lang
+ ;;
*)
echo \%lang\(${lang}\) \%{_mandir}/${man}\* >> sssd.lang
;;
@@ -1034,6 +1037,7 @@ install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/sssd.conf
%{_udevrulesdir}/90-sssd-token-access.rules
%endif
%config(noreplace) %{_sysconfdir}/krb5.conf.d/sssd_enable_passkey
+%{_mandir}/man5/sssd-passkey.5*
%endif
%if %{use_sssd_user}
diff --git a/src/man/Makefile.am b/src/man/Makefile.am
index 4e1cbd311ed..3880c669f1f 100644
--- a/src/man/Makefile.am
+++ b/src/man/Makefile.am
@@ -120,6 +120,10 @@ if BUILD_ID_PROVIDER_IDP
man_MANS += sssd-idp.5
endif
+if BUILD_PASSKEY
+man_MANS += sssd-passkey.5
+endif
+
$(builddir)/src/man/sssd_user_name.include:
@mkdir -p $(builddir)/src/man
@echo -n $(SSSD_USER) > $(builddir)/src/man/sssd_user_name.include
diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg
index 41af1c22159..94dc729f3c4 100644
--- a/src/man/po/po4a.cfg
+++ b/src/man/po/po4a.cfg
@@ -29,6 +29,7 @@
[type:docbook] sssd-systemtap.5.xml $lang:$(builddir)/$lang/sssd-systemtap.5.xml
[type:docbook] sssd-ldap-attributes.5.xml $lang:$(builddir)/$lang/sssd-ldap-attributes.5.xml
[type:docbook] sssd_krb5_localauth_plugin.8.xml $lang:$(builddir)/$lang/sssd_krb5_localauth_plugin.8.xml
+[type:docbook] sssd-passkey.5.xml $lang:$(builddir)/$lang/sssd-passkey.5.xml
[type:docbook] include/autofs_attributes.xml $lang:$(builddir)/$lang/include/autofs_attributes.xml opt:"-k 0"
[type:docbook] include/service_discovery.xml $lang:$(builddir)/$lang/include/service_discovery.xml opt:"-k 0"
[type:docbook] include/upstream.xml $lang:$(builddir)/$lang/include/upstream.xml opt:"-k 0"
diff --git a/src/man/sssd-passkey.5.xml b/src/man/sssd-passkey.5.xml
new file mode 100644
index 00000000000..bcaff71f703
--- /dev/null
+++ b/src/man/sssd-passkey.5.xml
@@ -0,0 +1,128 @@
+
+
+
+SSSD Manual pages
+
+
+
+
+ sssd-passkey
+ 5
+ File Formats and Conventions
+
+
+
+ sssd-passkey
+ SSSD passkey options
+
+
+
+ DESCRIPTION
+
+ This manual page describes the specifics for configuration of
+ passkey for
+
+ sssd
+ 8
+ .
+ Refer to the FILE FORMAT
section of the
+
+ sssd.conf
+ 5
+ manual page for detailed syntax information.
+
+
+
+ CONFIGURATION OPTIONS
+
+
+
+ user_verification (boolean)
+
+
+ Enable or disable the requirement for user
+ verification (i.e. PIN, fingerprint) on the passkey
+ device during authentication.
+
+
+ Three different actors come into play when deciding
+ whether to request user verification: LDAP server,
+ sssd.conf
+ 5
+ option and the passkey device itself.
+
+
+ If the IPA provider is used and online, Kerberos
+ based passkey authentication is available, the
+ server-side settings are applied for all passkey
+ usages. For other cases the settings in
+ sssd.conf are used. This
+ includes passkey authentication with any other
+ provider; and the IPA provider in case online
+ authentication is not available and local passkey
+ is allowed by the option
+ local_auth_policy = enable:passkey.
+
+
+ The interaction of the
+ user_verification option and
+ the passkey device option is explained in the
+ following table:
+
+
+
+
+
+
+
+
+ user_verificationDevice
+ Result
+
+
+
+ True
+ User verification is configured
+ User verification is requested
+
+
+ True
+ User verification is not configured
+
+ User verification is requested; however, the
+ authentication is expected to fail if the device is
+ not replaced with a device where user verification
+ is configured during the authentication process.
+
+
+
+ False
+ User verification is configured
+
+ sssd automatically detects it during device query
+ and user verification is requested
+
+
+
+ False
+ User verification is not configured
+ User verification is not requested
+
+
+
+ If 'enter' is pressed at the PIN prompt for user
+ verification without typing any characters, then
+ SSSD falls back from passkey to password
+ authentication.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 1a2d761af39..6afc965bf42 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -682,15 +682,16 @@
Enable or disable the user
verification (i.e. PIN, fingerprint)
- during authentication. If enabled, the
- PIN will always be requested.
+ during authentication.
- The default is that the key settings
- decide what to do. In the IPA or
- kerberos pre-authentication case,
- this value will be overwritten by the
- server.
+ See
+
+ sssd-passkey
+ 5
+ to
+ understand the behaviour of this option
+ in the different scenarios.
diff --git a/src/passkey_child/passkey_child.c b/src/passkey_child/passkey_child.c
index 320996608ec..1fe0076faa3 100644
--- a/src/passkey_child/passkey_child.c
+++ b/src/passkey_child/passkey_child.c
@@ -64,13 +64,13 @@ int main(int argc, const char *argv[])
fido_init(init_flags);
if (data.action == ACTION_REGISTER) {
- ret = register_key(&data);
+ ret = register_key(&data, TIMEOUT);
if (ret != EOK) {
ERROR("Error registering key.\n");
goto done;
}
} else if (data.action == ACTION_AUTHENTICATE) {
- ret = authenticate(&data);
+ ret = authenticate(&data, TIMEOUT);
if (ret == EOK) {
PRINT("Authentication success.\n");
goto done;
@@ -79,7 +79,7 @@ int main(int argc, const char *argv[])
goto done;
}
} else if (data.action == ACTION_GET_ASSERT) {
- ret = get_assert_data(&data);
+ ret = get_assert_data(&data, TIMEOUT);
if (ret != EOK) {
ERROR("Error getting assertion data.\n");
goto done;
@@ -93,12 +93,20 @@ int main(int argc, const char *argv[])
ERROR("Verification error.\n");
goto done;
}
+ } else if (data.action == ACTION_PREFLIGHT) {
+ ret = preflight(&data, 1);
+ /* Errors are ignored, as in most cases they are due to the device not
+ * being connected to the system. If an error occurs, the default
+ * values are returned, and that is sufficient for the time being.
+ */
}
done:
talloc_free(main_ctx);
- if (ret != EOK) {
+ if (ret == FIDO_ERR_PIN_AUTH_BLOCKED) {
+ return PIN_AUTH_BLOCKED_EXIT_CODE;
+ } else if (ret != EOK) {
return EXIT_FAILURE;
} else {
return EXIT_SUCCESS;
diff --git a/src/passkey_child/passkey_child.h b/src/passkey_child/passkey_child.h
index 185e7e63af7..05fdae92508 100644
--- a/src/passkey_child/passkey_child.h
+++ b/src/passkey_child/passkey_child.h
@@ -34,13 +34,15 @@
#define USER_ID_SIZE 32
#define TIMEOUT 15
#define FREQUENCY 1
+#define MAX_PIN_RETRIES 8
enum action_opt {
ACTION_NONE,
ACTION_REGISTER,
ACTION_AUTHENTICATE,
ACTION_GET_ASSERT,
- ACTION_VERIFY_ASSERT
+ ACTION_VERIFY_ASSERT,
+ ACTION_PREFLIGHT
};
enum credential_type {
@@ -103,12 +105,13 @@ check_arguments(const struct passkey_data *data);
* @brief Register a key for a user
*
* @param[in] data passkey data
+ * @param[in] timeout Timeout to stop looking for a device
*
* @return 0 if the key was registered properly,
* another value on error.
*/
errno_t
-register_key(struct passkey_data *data);
+register_key(struct passkey_data *data, int timeout);
/**
* @brief Translate COSE type from string to int
@@ -139,13 +142,14 @@ prepare_credentials(struct passkey_data *data, fido_dev_t *dev,
/**
* @brief List connected passkey devices
*
+ * @param[in] timeout Timeout to stop looking for a device
* @param[out] dev_list passkey device list
* @param[out] dev_number Number of passkey devices
*
* @return 0 if the list was retrieved properly, another value on error.
*/
errno_t
-list_devices(fido_dev_info_t *dev_list, size_t *dev_number);
+list_devices(int timeout, fido_dev_info_t *dev_list, size_t *dev_number);
/**
* @brief Select passkey device
@@ -322,18 +326,20 @@ public_key_to_base64(TALLOC_CTX *mem_ctx, const struct passkey_data *data,
* key, request the assert and verify it.
*
* @param[in] data passkey data
+ * @param[in] timeout Timeout to stop looking for a device
*
* @return 0 if the user was authenticated properly,
* error code otherwise.
*/
errno_t
-authenticate(struct passkey_data *data);
+authenticate(struct passkey_data *data, int timeout);
/*
* @brief Select authenticator for verification
*
*
* @param[in] data passkey data
+ * @param[in] timeout Timeout to stop looking for a device
* @param[out] _dev Device information
* @param[out] _assert Assert
* @param[out] _index Index for key handle list
@@ -342,7 +348,7 @@ authenticate(struct passkey_data *data);
* error code otherwise.
*/
errno_t
-select_authenticator(struct passkey_data *data, fido_dev_t **_dev,
+select_authenticator(struct passkey_data *data, int timeout, fido_dev_t **_dev,
fido_assert_t **_assert, int *_index);
/**
@@ -533,12 +539,13 @@ print_assert_data(const char *key_handle, const char *crypto_challenge,
* and print this all information.
*
* @param[in] data passkey data
+ * @param[in] timeout Timeout to stop looking for a device
*
* @return 0 if the assertion was obtained properly,
* error code otherwise.
*/
errno_t
-get_assert_data(struct passkey_data *data);
+get_assert_data(struct passkey_data *data, int timeout);
/**
* @brief Verify assertion data
@@ -554,4 +561,47 @@ get_assert_data(struct passkey_data *data);
errno_t
verify_assert_data(struct passkey_data *data);
+/**
+ * @brief Obtain PIN retries in the device
+ *
+ * @param[in] dev Device information
+ * @param[in] data passkey data
+ * @param[in] _pin_retries Number of PIN retries
+ *
+ * @return 0 if the PIN retries were obtained properly,
+ * error code otherwise.
+ */
+errno_t
+get_device_pin_retries(fido_dev_t *dev, struct passkey_data *data,
+ int *_pin_retries);
+
+/**
+ * @brief Print preflight information
+ *
+ * Print user-verification and pin retries
+ *
+ * @param[in] data passkey data
+ * @param[in] _pin_retries Number of PIN retries
+ *
+ * @return EOK
+ *
+ */
+errno_t
+print_preflight(const struct passkey_data *data, int pin_retries);
+
+/**
+ * @brief Obtain authentication data prior to processing
+ *
+ * Prepare the assertion request data, select the device to use, get the device
+ * options and compare them with the organization policy, get the PIN retries
+ * and print the preflight data.
+ *
+ * @param[in] data passkey data
+ * @param[in] timeout Timeout in seconds to stop looking for a device
+ *
+ * @return EOK
+ */
+errno_t
+preflight(struct passkey_data *data, int timeout);
+
#endif /* __PASSKEY_CHILD_H__ */
diff --git a/src/passkey_child/passkey_child_assert.c b/src/passkey_child/passkey_child_assert.c
index 5139dc82ef0..7920e6fd7fb 100644
--- a/src/passkey_child/passkey_child_assert.c
+++ b/src/passkey_child/passkey_child_assert.c
@@ -51,7 +51,8 @@ set_assert_client_data_hash(const struct passkey_data *data,
return ENOMEM;
}
- if (data->action == ACTION_AUTHENTICATE) {
+ if (data->action == ACTION_AUTHENTICATE
+ || data->action == ACTION_PREFLIGHT) {
ret = sss_generate_csprng_buffer(cdh, sizeof(cdh));
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
diff --git a/src/passkey_child/passkey_child_common.c b/src/passkey_child/passkey_child_common.c
index 6fadd024333..ff80dcb6bdc 100644
--- a/src/passkey_child/passkey_child_common.c
+++ b/src/passkey_child/passkey_child_common.c
@@ -177,6 +177,8 @@ parse_arguments(TALLOC_CTX *mem_ctx, int argc, const char *argv[],
_("Obtain assertion data"), NULL },
{"verify-assert", 0, POPT_ARG_NONE, NULL, 'v',
_("Verify assertion data"), NULL },
+ {"preflight", 0, POPT_ARG_NONE, NULL, 'p',
+ _("Obtain authentication data prior to processing"), NULL },
{"username", 0, POPT_ARG_STRING, &data->shortname, 0,
_("Shortname"), NULL },
{"domain", 0, POPT_ARG_STRING, &data->domain, 0,
@@ -259,6 +261,16 @@ parse_arguments(TALLOC_CTX *mem_ctx, int argc, const char *argv[],
}
data->action = ACTION_VERIFY_ASSERT;
break;
+ case 'p':
+ if (data->action != ACTION_NONE) {
+ fprintf(stderr, "\nActions are mutually exclusive and should" \
+ " be used only once.\n\n");
+ poptPrintUsage(pc, stderr, 0);
+ ret = EINVAL;
+ goto done;
+ }
+ data->action = ACTION_PREFLIGHT;
+ break;
case 'q':
data->quiet = true;
break;
@@ -419,12 +431,20 @@ check_arguments(const struct passkey_data *data)
goto done;
}
+ if (data->action == ACTION_PREFLIGHT
+ && (data->domain == NULL || data->key_handle_list == NULL)) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Too few arguments for preflight action.\n");
+ ret = ERR_INPUT_PARSE;
+ goto done;
+ }
+
done:
return ret;
}
errno_t
-register_key(struct passkey_data *data)
+register_key(struct passkey_data *data, int timeout)
{
TALLOC_CTX *tmp_ctx = NULL;
fido_cred_t *cred = NULL;
@@ -460,7 +480,7 @@ register_key(struct passkey_data *data)
goto done;
}
- ret = list_devices(dev_list, &dev_number);
+ ret = list_devices(timeout, dev_list, &dev_number);
if (ret != EOK) {
goto done;
}
@@ -571,7 +591,7 @@ public_key_to_base64(TALLOC_CTX *mem_ctx, const struct passkey_data *data,
}
errno_t
-select_authenticator(struct passkey_data *data, fido_dev_t **_dev,
+select_authenticator(struct passkey_data *data, int timeout, fido_dev_t **_dev,
fido_assert_t **_assert, int *_index)
{
fido_dev_info_t *dev_list = NULL;
@@ -589,7 +609,7 @@ select_authenticator(struct passkey_data *data, fido_dev_t **_dev,
}
DEBUG(SSSDBG_TRACE_FUNC, "Checking for devices.\n");
- ret = list_devices(dev_list, &dev_list_len);
+ ret = list_devices(timeout, dev_list, &dev_list_len);
if (ret != EOK) {
goto done;
}
@@ -706,7 +726,7 @@ public_key_to_libfido2(const char *pem_public_key, struct pk_data_t *_pk_data)
}
errno_t
-authenticate(struct passkey_data *data)
+authenticate(struct passkey_data *data, int timeout)
{
TALLOC_CTX *tmp_ctx = NULL;
fido_assert_t *assert = NULL;
@@ -721,7 +741,7 @@ authenticate(struct passkey_data *data)
return ENOMEM;
}
- ret = select_authenticator(data, &dev, &assert, &index);
+ ret = select_authenticator(data, timeout, &dev, &assert, &index);
if (ret != EOK) {
goto done;
}
@@ -779,7 +799,7 @@ authenticate(struct passkey_data *data)
}
errno_t
-get_assert_data(struct passkey_data *data)
+get_assert_data(struct passkey_data *data, int timeout)
{
TALLOC_CTX *tmp_ctx = NULL;
fido_dev_t *dev = NULL;
@@ -795,7 +815,7 @@ get_assert_data(struct passkey_data *data)
return ENOMEM;
}
- ret = select_authenticator(data, &dev, &assert, &index);
+ ret = select_authenticator(data, timeout, &dev, &assert, &index);
if (ret != EOK) {
goto done;
}
@@ -887,3 +907,47 @@ verify_assert_data(struct passkey_data *data)
return ret;
}
+
+errno_t
+preflight(struct passkey_data *data, int timeout)
+{
+ fido_assert_t *assert = NULL;
+ fido_dev_t *dev = NULL;
+ int index = 0;
+ int pin_retries = 0;
+ errno_t ret;
+
+ ret = select_authenticator(data, timeout, &dev, &assert, &index);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Comparing the device and policy options.\n");
+ ret = get_device_options(dev, data);
+ if (ret != FIDO_OK) {
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Checking the number of remaining PIN retries.\n");
+ ret = get_device_pin_retries(dev, data, &pin_retries);
+ if (ret != FIDO_OK) {
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ data->user_verification = FIDO_OPT_TRUE;
+ pin_retries = MAX_PIN_RETRIES;
+ }
+ print_preflight(data, pin_retries);
+
+ if (dev != NULL) {
+ fido_dev_close(dev);
+ }
+ fido_dev_free(&dev);
+ fido_assert_free(&assert);
+
+ return EOK;
+}
diff --git a/src/passkey_child/passkey_child_credentials.c b/src/passkey_child/passkey_child_credentials.c
index e27afb411bb..dc88fb8ccbf 100644
--- a/src/passkey_child/passkey_child_credentials.c
+++ b/src/passkey_child/passkey_child_credentials.c
@@ -23,6 +23,7 @@
*/
#include
+#include
#include
#include
@@ -679,3 +680,40 @@ evp_pkey_to_eddsa_pubkey(const EVP_PKEY *evp_pkey, struct pk_data_t *_pk_data)
done:
return ret;
}
+
+errno_t
+print_preflight(const struct passkey_data *data, int pin_retries)
+{
+ json_t *jroot = NULL;
+ char* string = NULL;
+ bool user_verification;
+
+ if (data->user_verification == FIDO_OPT_TRUE) {
+ user_verification = true;
+ } else {
+ user_verification = false;
+ }
+
+ jroot = json_pack("{s:b, s:i}",
+ "pin_required", user_verification,
+ "attempts", pin_retries);
+
+ if (jroot == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to create jroot object.\n");
+ goto done;
+ }
+
+ string = json_dumps(jroot, 0);
+ if (string == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "json_dumps() failed.\n");
+ goto done;
+ }
+
+ puts(string);
+ free(string);
+
+done:
+ json_decref(jroot);
+
+ return EOK;
+}
diff --git a/src/passkey_child/passkey_child_devices.c b/src/passkey_child/passkey_child_devices.c
index 2011b12f661..7ea0409f04f 100644
--- a/src/passkey_child/passkey_child_devices.c
+++ b/src/passkey_child/passkey_child_devices.c
@@ -28,11 +28,11 @@
#include "passkey_child.h"
errno_t
-list_devices(fido_dev_info_t *dev_list, size_t *dev_number)
+list_devices(int timeout, fido_dev_info_t *dev_list, size_t *dev_number)
{
- errno_t ret;
+ errno_t ret = EOK;
- for (int i = 0; i < TIMEOUT; i += FREQUENCY) {
+ for (int i = 0; i < timeout; i += FREQUENCY) {
ret = fido_dev_info_manifest(dev_list, DEVLIST_SIZE, dev_number);
if (ret != FIDO_OK) {
DEBUG(SSSDBG_OP_FAILURE,
@@ -45,7 +45,7 @@ list_devices(fido_dev_info_t *dev_list, size_t *dev_number)
break;
}
- if (i < (TIMEOUT - 1)) {
+ if (i < (timeout - 1)) {
DEBUG(SSSDBG_TRACE_FUNC, "No device available, retrying.\n");
sleep(FREQUENCY);
}
@@ -244,3 +244,25 @@ get_device_options(fido_dev_t *dev, struct passkey_data *_data)
return ret;
}
+
+errno_t
+get_device_pin_retries(fido_dev_t *dev, struct passkey_data *data,
+ int *_pin_retries)
+{
+ int ret = EOK;
+
+ if (data->user_verification == FIDO_OPT_TRUE) {
+ ret = fido_dev_get_retry_count(dev, _pin_retries);
+ if (ret != FIDO_OK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "fido_dev_get_retry_count failed [%d]: %s.\n",
+ ret, fido_strerr(ret));
+ goto done;
+ }
+ } else {
+ *_pin_retries = MAX_PIN_RETRIES;
+ }
+
+done:
+ return ret;
+}
diff --git a/src/tests/cmocka/test_passkey_child.c b/src/tests/cmocka/test_passkey_child.c
index 5003152c453..5f79d4bbe21 100644
--- a/src/tests/cmocka/test_passkey_child.c
+++ b/src/tests/cmocka/test_passkey_child.c
@@ -524,6 +524,17 @@ __wrap_fido_assert_set_sig(fido_assert_t *assert, size_t idx,
return ret;
}
+int
+__wrap_fido_dev_get_retry_count(fido_dev_t *dev, int *pin_retries)
+{
+ int ret;
+
+ ret = mock();
+ (*pin_retries) = mock();
+
+ return ret;
+}
+
/***********************
* TEST
**********************/
@@ -658,7 +669,7 @@ void test_list_devices_one_device(void **state)
will_return(__wrap_fido_dev_info_manifest, FIDO_OK);
will_return(__wrap_fido_dev_info_manifest, 1);
- ret = list_devices(ts->dev_list, &ts->dev_number);
+ ret = list_devices(TIMEOUT, ts->dev_list, &ts->dev_number);
assert_int_equal(ret, FIDO_OK);
assert_int_equal(ts->dev_number, 1);
@@ -677,7 +688,7 @@ void test_list_devices_no_device(void **state)
}
}
- ret = list_devices(ts->dev_list, &ts->dev_number);
+ ret = list_devices(TIMEOUT, ts->dev_list, &ts->dev_number);
assert_int_equal(ret, FIDO_OK);
assert_int_equal(ts->dev_number, 0);
@@ -696,7 +707,7 @@ void test_list_devices_error(void **state)
}
}
- ret = list_devices(ts->dev_list, &ts->dev_number);
+ ret = list_devices(TIMEOUT, ts->dev_list, &ts->dev_number);
assert_int_equal(ret, FIDO_ERR_INVALID_ARGUMENT);
}
@@ -907,7 +918,7 @@ void test_register_key_integration(void **state)
will_return(__wrap_fido_cred_pubkey_ptr, TEST_ES256_HEX_PUBLIC_KEY);
will_return(__wrap_fido_cred_pubkey_len, 64);
- ret = register_key(&data);
+ ret = register_key(&data, TIMEOUT);
assert_int_equal(ret, EOK);
}
@@ -941,7 +952,7 @@ void test_select_authenticator(void **state)
will_return(__wrap_fido_dev_is_fido2, true);
will_return(__wrap_fido_dev_get_assert, FIDO_OK);
- ret = select_authenticator(&data, &dev, &assert, &index);
+ ret = select_authenticator(&data, TIMEOUT, &dev, &assert, &index);
assert_int_equal(ret, FIDO_OK);
@@ -1244,7 +1255,7 @@ void test_authenticate_integration(void **state)
will_return(__wrap_fido_assert_set_uv, FIDO_OK);
will_return(__wrap_fido_assert_verify, FIDO_OK);
- ret = authenticate(&data);
+ ret = authenticate(&data, TIMEOUT);
assert_int_equal(ret, EOK);
talloc_free(tmp_ctx);
@@ -1297,7 +1308,7 @@ void test_get_assert_data_integration(void **state)
will_return(__wrap_fido_assert_sig_ptr, TEST_HEX_SIGNATURE);
will_return(__wrap_fido_assert_sig_len, TEST_SIGNATURE_LEN);
- ret = get_assert_data(&data);
+ ret = get_assert_data(&data, TIMEOUT);
assert_int_equal(ret, EOK);
talloc_free(tmp_ctx);
@@ -1339,6 +1350,38 @@ void test_verify_assert_data_integration(void **state)
talloc_free(tmp_ctx);
}
+void test_get_device_pin_retries_success(void **state)
+{
+ struct passkey_data data;
+ fido_dev_t *dev = NULL;
+ int pin_retries = 0;
+ errno_t ret;
+
+ data.user_verification = FIDO_OPT_TRUE;
+ will_return(__wrap_fido_dev_get_retry_count, FIDO_OK);
+ will_return(__wrap_fido_dev_get_retry_count, 8);
+
+ ret = get_device_pin_retries(dev, &data, &pin_retries);
+ assert_int_equal(ret, FIDO_OK);
+ assert_int_equal(pin_retries, 8);
+}
+
+void test_get_device_pin_retries_failure(void **state)
+{
+ struct passkey_data data;
+ fido_dev_t *dev = NULL;
+ int pin_retries = 0;
+ errno_t ret;
+
+ data.user_verification = FIDO_OPT_TRUE;
+ will_return(__wrap_fido_dev_get_retry_count, FIDO_ERR_INVALID_ARGUMENT);
+ will_return(__wrap_fido_dev_get_retry_count, 8);
+
+ ret = get_device_pin_retries(dev, &data, &pin_retries);
+ assert_int_equal(ret, FIDO_ERR_INVALID_ARGUMENT);
+ assert_int_equal(pin_retries, 8);
+}
+
static void test_parse_supp_valgrind_args(void)
{
/*
@@ -1349,6 +1392,54 @@ static void test_parse_supp_valgrind_args(void)
DEBUG_CLI_INIT(debug_level);
}
+void test_preflight_integration(void **state)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct passkey_data data;
+ size_t dev_number = 3;
+ char *key_handle;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ assert_non_null(tmp_ctx);
+ data.action = ACTION_PREFLIGHT;
+ data.shortname = "user";
+ data.domain = "test.com";
+ key_handle = talloc_strdup(tmp_ctx, TEST_KEY_HANDLE);
+ data.key_handle_list = &key_handle;
+ data.key_handle_size = 1;
+ data.type = COSE_ES256;
+ data.user_verification = FIDO_OPT_TRUE;
+ data.user_id = NULL;
+ data.quiet = false;
+ will_return(__wrap_fido_dev_info_manifest, FIDO_OK);
+ will_return(__wrap_fido_dev_info_manifest, dev_number);
+ will_return(__wrap_fido_assert_set_rp, FIDO_OK);
+ will_return(__wrap_fido_assert_allow_cred, FIDO_OK);
+ will_return(__wrap_fido_assert_set_uv, FIDO_OK);
+ will_return(__wrap_fido_assert_set_clientdata_hash, FIDO_OK);
+ for (size_t i = 0; i < (dev_number - 1); i++) {
+ will_return(__wrap_fido_dev_info_path, TEST_PATH);
+ will_return(__wrap_fido_dev_open, FIDO_OK);
+ will_return(__wrap_fido_dev_is_fido2, true);
+ if (i == 0) {
+ will_return(__wrap_fido_dev_get_assert, FIDO_ERR_INVALID_SIG);
+ } else {
+ will_return(__wrap_fido_dev_get_assert, FIDO_OK);
+ }
+ }
+ will_return(__wrap_fido_dev_has_uv, false);
+ will_return(__wrap_fido_dev_has_pin, true);
+ will_return(__wrap_fido_dev_supports_uv, false);
+ will_return(__wrap_fido_dev_get_retry_count, FIDO_OK);
+ will_return(__wrap_fido_dev_get_retry_count, 8);
+
+ ret = preflight(&data, 1);
+ assert_int_equal(ret, EOK);
+
+ talloc_free(tmp_ctx);
+}
+
int main(int argc, const char *argv[])
{
poptContext pc;
@@ -1396,6 +1487,9 @@ int main(int argc, const char *argv[])
cmocka_unit_test(test_authenticate_integration),
cmocka_unit_test(test_get_assert_data_integration),
cmocka_unit_test(test_verify_assert_data_integration),
+ cmocka_unit_test(test_get_device_pin_retries_success),
+ cmocka_unit_test(test_get_device_pin_retries_failure),
+ cmocka_unit_test(test_preflight_integration),
};
/* Set debug level to invalid value so we can decide if -d 0 was used. */
diff --git a/src/util/util.h b/src/util/util.h
index 9906863e921..76bec23a344 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -122,6 +122,7 @@ extern int socket_activated;
enum sssd_exit_status {
CHILD_TIMEOUT_EXIT_CODE = 7,
CA_DB_NOT_FOUND_EXIT_CODE = 50,
+ PIN_AUTH_BLOCKED_EXIT_CODE = 52, /* to match FIDO_ERR_PIN_AUTH_BLOCKED in fido2 error codes */
SSS_WATCHDOG_EXIT_CODE = 70 /* to match EX_SOFTWARE in sysexits.h */
};