From f9a027877ecdd697a052f6135963fb3726692310 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Fri, 26 Jun 2015 17:55:23 +0200 Subject: authok: add support for Smart Card related authtokens Reviewed-by: Jakub Hrozek --- src/sss_client/sss_cli.h | 7 ++++ src/tests/cmocka/test_authtok.c | 75 +++++++++++++++++++++++++++++++++++++++++ src/util/authtok.c | 64 +++++++++++++++++++++++++++++++++++ src/util/authtok.h | 41 ++++++++++++++++++++++ 4 files changed, 187 insertions(+) diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h index 0dfb525ba..3c4e938ae 100644 --- a/src/sss_client/sss_cli.h +++ b/src/sss_client/sss_cli.h @@ -308,6 +308,13 @@ enum sss_authtok_type { SSS_AUTHTOK_TYPE_2FA = 0x0003, /**< Authentication token has two * factors, they may or may no contain * a trailing \\0 */ + SSS_AUTHTOK_TYPE_SC_PIN = 0x0004, /**< Authentication token is a Smart + * Card pin, it may or may no contain + * a trailing \\0 */ + SSS_AUTHTOK_TYPE_SC_KEYPAD = 0x0005, /**< Authentication token indicates + * Smart Card authentication is used + * and that the pin will be entered + * at the card reader. */ }; /** diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c index 5aa47c7b6..30dcc9c84 100644 --- a/src/tests/cmocka/test_authtok.c +++ b/src/tests/cmocka/test_authtok.c @@ -488,6 +488,77 @@ void test_sss_authtok_2fa_blobs_missing_null(void **state) MISSING_NULL_CHECK; } +void test_sss_authtok_sc_keypad(void **state) +{ + struct test_state *ts; + + ts = talloc_get_type_abort(*state, struct test_state); + + sss_authtok_set_sc_keypad(NULL); + + sss_authtok_set_sc_keypad(ts->authtoken); + assert_int_equal(sss_authtok_get_type(ts->authtoken), + SSS_AUTHTOK_TYPE_SC_KEYPAD); + assert_int_equal(sss_authtok_get_size(ts->authtoken), 0); + assert_null(sss_authtok_get_data(ts->authtoken)); +} + +void test_sss_authtok_sc_pin(void **state) +{ + struct test_state *ts; + int ret; + size_t size; + const char *pin; + size_t len; + + ts = talloc_get_type_abort(*state, struct test_state); + + ret = sss_authtok_set_sc_pin(NULL, NULL, 0); + assert_int_equal(ret, EFAULT); + + ret = sss_authtok_set_sc_pin(ts->authtoken, NULL, 0); + assert_int_equal(ret, EINVAL); + + ret = sss_authtok_set_sc_pin(ts->authtoken, "12345678", 0); + assert_int_equal(ret, EOK); + assert_int_equal(sss_authtok_get_type(ts->authtoken), + SSS_AUTHTOK_TYPE_SC_PIN); + size = sss_authtok_get_size(ts->authtoken); + assert_int_equal(size, 9); + assert_memory_equal(sss_authtok_get_data(ts->authtoken), "12345678\0", + size); + + ret = sss_authtok_set_sc_pin(ts->authtoken, "12345678", 5); + assert_int_equal(ret, EOK); + assert_int_equal(sss_authtok_get_type(ts->authtoken), + SSS_AUTHTOK_TYPE_SC_PIN); + size = sss_authtok_get_size(ts->authtoken); + assert_int_equal(size, 6); + assert_memory_equal(sss_authtok_get_data(ts->authtoken), "12345\0", + size); + + ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len); + assert_int_equal(ret, EOK); + assert_int_equal(len, 5); + assert_string_equal(pin, "12345"); + + sss_authtok_set_empty(ts->authtoken); + + ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len); + assert_int_equal(ret, ENOENT); + + ret = sss_authtok_set_password(ts->authtoken, "12345", 0); + assert_int_equal(ret, EOK); + + ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len); + assert_int_equal(ret, EACCES); + + sss_authtok_set_empty(ts->authtoken); + + ret = sss_authtok_get_sc_pin(NULL, &pin, &len); + assert_int_equal(ret, EFAULT); +} + int main(int argc, const char *argv[]) { poptContext pc; @@ -517,6 +588,10 @@ int main(int argc, const char *argv[]) setup, teardown), cmocka_unit_test_setup_teardown(test_sss_authtok_2fa_blobs_missing_null, setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_authtok_sc_keypad, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_authtok_sc_pin, + setup, teardown), }; /* Set debug level to invalid value so we can deside if -d 0 was used. */ diff --git a/src/util/authtok.c b/src/util/authtok.c index 45761df80..6062cd875 100644 --- a/src/util/authtok.c +++ b/src/util/authtok.c @@ -39,6 +39,8 @@ size_t sss_authtok_get_size(struct sss_auth_token *tok) case SSS_AUTHTOK_TYPE_PASSWORD: case SSS_AUTHTOK_TYPE_CCFILE: case SSS_AUTHTOK_TYPE_2FA: + case SSS_AUTHTOK_TYPE_SC_PIN: + case SSS_AUTHTOK_TYPE_SC_KEYPAD: return tok->length; case SSS_AUTHTOK_TYPE_EMPTY: return 0; @@ -72,6 +74,8 @@ errno_t sss_authtok_get_password(struct sss_auth_token *tok, return EOK; case SSS_AUTHTOK_TYPE_CCFILE: case SSS_AUTHTOK_TYPE_2FA: + case SSS_AUTHTOK_TYPE_SC_PIN: + case SSS_AUTHTOK_TYPE_SC_KEYPAD: return EACCES; } @@ -95,6 +99,8 @@ errno_t sss_authtok_get_ccfile(struct sss_auth_token *tok, return EOK; case SSS_AUTHTOK_TYPE_PASSWORD: case SSS_AUTHTOK_TYPE_2FA: + case SSS_AUTHTOK_TYPE_SC_PIN: + case SSS_AUTHTOK_TYPE_SC_KEYPAD: return EACCES; } @@ -144,9 +150,11 @@ void sss_authtok_set_empty(struct sss_auth_token *tok) return; case SSS_AUTHTOK_TYPE_PASSWORD: case SSS_AUTHTOK_TYPE_2FA: + case SSS_AUTHTOK_TYPE_SC_PIN: safezero(tok->data, tok->length); break; case SSS_AUTHTOK_TYPE_CCFILE: + case SSS_AUTHTOK_TYPE_SC_KEYPAD: break; } @@ -187,6 +195,11 @@ errno_t sss_authtok_set(struct sss_auth_token *tok, return sss_authtok_set_ccfile(tok, (const char *)data, len); case SSS_AUTHTOK_TYPE_2FA: return sss_authtok_set_2fa_from_blob(tok, data, len); + case SSS_AUTHTOK_TYPE_SC_PIN: + return sss_authtok_set_sc_pin(tok, (const char*)data, len); + case SSS_AUTHTOK_TYPE_SC_KEYPAD: + sss_authtok_set_sc_keypad(tok); + return EOK; case SSS_AUTHTOK_TYPE_EMPTY: sss_authtok_set_empty(tok); return EOK; @@ -411,3 +424,54 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok, return EOK; } + +errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin, + size_t len) +{ + if (tok == NULL) { + return EFAULT; + } + if (pin == NULL) { + return EINVAL; + } + + sss_authtok_set_empty(tok); + + return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_SC_PIN, + "sc_pin", pin, len); +} + +errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin, + size_t *len) +{ + if (!tok) { + return EFAULT; + } + switch (tok->type) { + case SSS_AUTHTOK_TYPE_EMPTY: + return ENOENT; + case SSS_AUTHTOK_TYPE_SC_PIN: + *pin = (const char *)tok->data; + if (len) { + *len = tok->length - 1; + } + return EOK; + case SSS_AUTHTOK_TYPE_PASSWORD: + case SSS_AUTHTOK_TYPE_CCFILE: + case SSS_AUTHTOK_TYPE_2FA: + case SSS_AUTHTOK_TYPE_SC_KEYPAD: + return EACCES; + } + + return EINVAL; +} + +void sss_authtok_set_sc_keypad(struct sss_auth_token *tok) +{ + if (!tok) { + return; + } + sss_authtok_set_empty(tok); + + tok->type = SSS_AUTHTOK_TYPE_SC_KEYPAD; +} diff --git a/src/util/authtok.h b/src/util/authtok.h index cb3662708..f1a01a423 100644 --- a/src/util/authtok.h +++ b/src/util/authtok.h @@ -223,4 +223,45 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok, errno_t sss_authtok_get_2fa(struct sss_auth_token *tok, const char **fa1, size_t *fa1_len, const char **fa2, size_t *fa2_len); + +/** + * @brief Set a Smart Card pin into a an auth token, replacing any previous data + * + * @param tok A pointer to a sss_auth_token structure to change, also + * used as a memory context to allocate the internal data. + * @param pin A string + * @param len The length of the string or, if 0 is passed, + * then strlen(password) will be used internally. + * + * @return EOK on success + * ENOMEM on error + */ +errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin, + size_t len); + +/** + * @brief Returns a Smart Card pin as const string if the auth token is of + * type SSS_AUTHTOK_TYPE_SC_PIN, otherwise it returns an error + * + * @param tok A pointer to an sss_auth_token + * @param pin A pointer to a const char *, that will point to a null + * terminated string + * @param len The length of the pin string + * + * @return EOK on success + * ENOENT if the token is empty + * EACCESS if the token is not a Smart Card pin token + */ +errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin, + size_t *len); + +/** + * @brief Sets an auth token to type SSS_AUTHTOK_TYPE_SC_KEYPAD, replacing any + * previous data + * + * @param tok A pointer to a sss_auth_token structure to change, also + * used as a memory context to allocate the internal data. + */ +void sss_authtok_set_sc_keypad(struct sss_auth_token *tok); + #endif /* __AUTHTOK_H__ */ -- cgit