From 32819b035a8d60ee81c91d8afc696494e54230c8 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 7 Jan 2015 18:11:16 +0100 Subject: [PATCH 02/14] utils: add sss_authtok_[gs]et_2fa --- Makefile.am | 5 ++ src/sss_client/pam_sss.c | 1 + src/sss_client/sss_cli.h | 3 + src/tests/cmocka/test_authtok.c | 155 +++++++++++++++++++++++++++++++++- src/util/authtok-utils.c | 74 ++++++++++++++++ src/util/authtok-utils.h | 48 +++++++++++ src/util/authtok.c | 182 ++++++++++++++++++++++++++++++++++++++++ src/util/authtok.h | 44 ++++++++++ 8 files changed, 511 insertions(+), 1 deletion(-) create mode 100644 src/util/authtok-utils.c create mode 100644 src/util/authtok-utils.h diff --git a/Makefile.am b/Makefile.am index 5f1fb6ce7ab52480a3038148a71483b8e92518cc..9c90e05619b59326a0079889de1d54ee23f66dee 100644 --- a/Makefile.am +++ b/Makefile.am @@ -519,6 +519,7 @@ dist_noinst_HEADERS = \ src/util/atomic_io.h \ src/util/auth_utils.h \ src/util/authtok.h \ + src/util/authtok-utils.h \ src/util/util_safealign.h \ src/util/util_sss_idmap.h \ src/monitor/monitor.h \ @@ -754,6 +755,7 @@ libsss_util_la_SOURCES = \ src/util/murmurhash3.c \ src/util/atomic_io.c \ src/util/authtok.c \ + src/util/authtok-utils.c \ src/util/sss_selinux.c \ src/util/domain_info_utils.c \ src/util/util_lock.c \ @@ -1849,6 +1851,7 @@ test_negcache_LDADD = \ test_authtok_SOURCES = \ src/tests/cmocka/test_authtok.c \ src/util/authtok.c \ + src/util/authtok-utils.c \ src/util/util.c test_authtok_CFLAGS = \ $(AM_CFLAGS) \ @@ -2773,6 +2776,7 @@ krb5_child_SOURCES = \ src/util/find_uid.c \ src/util/atomic_io.c \ src/util/authtok.c \ + src/util/authtok-utils.c \ src/util/util.c \ src/util/signal.c \ src/util/strtonum.c \ @@ -2804,6 +2808,7 @@ ldap_child_SOURCES = \ src/util/sss_krb5.c \ src/util/atomic_io.c \ src/util/authtok.c \ + src/util/authtok-utils.c \ src/util/util.c \ src/util/signal.c \ src/util/become_user.c \ diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c index 6916575bb6d8288508ce1894d272356ffcc23f04..83769a15337f7ba027f66a8f7e530daa4a287383 100644 --- a/src/sss_client/pam_sss.c +++ b/src/sss_client/pam_sss.c @@ -41,6 +41,7 @@ #include "sss_cli.h" #include "util/atomic_io.h" +#include "util/authtok-utils.h" #include #define _(STRING) dgettext (PACKAGE, STRING) diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h index d508a0671cd1b3ee087e0967f7015628ceabe20f..9a19d7d47d0a9d7dabeac36dc2c866c3420ef501 100644 --- a/src/sss_client/sss_cli.h +++ b/src/sss_client/sss_cli.h @@ -301,6 +301,9 @@ enum sss_authtok_type { * a Kerberos credential cache file, * it may or may no contain * a trailing \\0 */ + SSS_AUTHTOK_TYPE_2FA = 0x0003, /**< Authentication token has two + * factors, they may or may no contain + * a trailing \\0 */ }; /** diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c index 0c7b7197fb2c03d69dc4df2310229ea100ad28d4..871dfef9552ea34388bb650660090e5aca86460a 100644 --- a/src/tests/cmocka/test_authtok.c +++ b/src/tests/cmocka/test_authtok.c @@ -311,6 +311,153 @@ static void test_sss_authtok_copy(void **state) talloc_free(data); } +void test_sss_authtok_2fa(void **state) +{ + int ret; + const char *fa1; + uint32_t fa1_size; + const char *fa2; + uint32_t fa2_size; + struct sss_auth_token *tok; + struct test_state *ts; + + ts = talloc_get_type_abort(*state, struct test_state); + + ret = sss_authtok_set_2fa(NULL, "a", 0, "b", 0); + assert_int_equal(ret, EINVAL); + + /* Test missing first factor */ + ret = sss_authtok_set_2fa(ts->authtoken, NULL, 1, "b", 1); + assert_int_equal(ret, EINVAL); + /* Test missing second factor */ + ret = sss_authtok_set_2fa(ts->authtoken, "a", 1, NULL, 1); + assert_int_equal(ret, EINVAL); + /* Test wrong first factor length */ + ret = sss_authtok_set_2fa(ts->authtoken, "ab", 1, "b", 1); + assert_int_equal(ret, EINVAL); + /* Test wrong second factor length */ + ret = sss_authtok_set_2fa(ts->authtoken, "a", 1, "bc", 1); + assert_int_equal(ret, EINVAL); + + ret = sss_authtok_set_2fa(ts->authtoken, "a", 1, "bc", 2); + assert_int_equal(ret, EOK); + assert_int_equal(sss_authtok_get_size(ts->authtoken), + 2 * sizeof(uint32_t) + 5); + assert_int_equal(sss_authtok_get_type(ts->authtoken), SSS_AUTHTOK_TYPE_2FA); + assert_memory_equal(sss_authtok_get_data(ts->authtoken), + "\2\0\0\0\3\0\0\0a\0bc\0", + 2 * sizeof(uint32_t) + 5); + + ret = sss_authtok_get_2fa(ts->authtoken, &fa1, &fa1_size, &fa2, &fa2_size); + assert_int_equal(ret, EOK); + assert_int_equal(fa1_size, 1); + assert_string_equal(fa1, "a"); + assert_int_equal(fa2_size, 2); + assert_string_equal(fa2, "bc"); + + sss_authtok_set_empty(ts->authtoken); + + /* check return code of empty token */ + ret = sss_authtok_get_2fa(ts->authtoken, &fa1, &fa1_size, &fa2, &fa2_size); + assert_int_equal(ret, ENOENT); + + /* check return code for other token type */ + ret = sss_authtok_set_password(ts->authtoken, "abc", 0); + ret = sss_authtok_get_2fa(ts->authtoken, &fa1, &fa1_size, &fa2, &fa2_size); + assert_int_equal(ret, EACCES); + + sss_authtok_set_empty(ts->authtoken); + + /* check return code for garbage */ + ret = sss_authtok_set(ts->authtoken, SSS_AUTHTOK_TYPE_2FA, + "1111222233334444", 16); + assert_int_equal(ret, EINVAL); + + sss_authtok_set_empty(ts->authtoken); +} + +void test_sss_authtok_2fa_blobs(void **state) +{ + int ret; + struct test_state *ts; + size_t needed_size; + uint8_t *buf; + char *fa1; + size_t fa1_len; + char *fa2; + size_t fa2_len; + + ts = talloc_get_type_abort(*state, struct test_state); + + ret = sss_auth_pack_2fa_blob("abc", 0, "defg", 0, NULL, 0, &needed_size); + assert_int_equal(ret, EAGAIN); + + buf = talloc_size(ts, needed_size); + assert_non_null(buf); + + ret = sss_auth_pack_2fa_blob("abc", 0, "defg", 0, buf, needed_size, + &needed_size); + assert_int_equal(ret, EOK); + + assert_memory_equal(buf, "\4\0\0\0\5\0\0\0abc\0defg\0", needed_size); + + ret = sss_auth_unpack_2fa_blob(ts, buf, needed_size, &fa1, &fa1_len, &fa2, + &fa2_len); + assert_int_equal(ret, EOK); + assert_int_equal(fa1_len, 3); + assert_string_equal(fa1, "abc"); + assert_int_equal(fa2_len, 4); + assert_string_equal(fa2, "defg"); + + talloc_free(buf); + talloc_free(fa1); + talloc_free(fa2); +} + +#define MISSING_NULL_CHECK do { \ + assert_int_equal(ret, EOK); \ + assert_int_equal(fa1_len, 3); \ + assert_string_equal(fa1, "abc"); \ + assert_int_equal(fa2_len, 4); \ + assert_string_equal(fa2, "defg"); \ + \ + talloc_free(fa1); \ + talloc_free(fa2); \ +} while (0) + +void test_sss_authtok_2fa_blobs_missing_null(void **state) +{ + int ret; + struct test_state *ts; + char *fa1; + size_t fa1_len; + char *fa2; + size_t fa2_len; + uint8_t b0[] = {0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 'a', 'b', 'c', 0x00, 'd', 'e', 'f', 'g', 0x00}; + uint8_t b1[] = {0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 0x00}; + uint8_t b2[] = {0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 'a', 'b', 'c', 0x00, 'd', 'e', 'f', 'g'}; + uint8_t b3[] = {0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 'a', 'b', 'c', 'd', 'e', 'f', 'g'}; + + + ts = talloc_get_type_abort(*state, struct test_state); + + ret = sss_auth_unpack_2fa_blob(ts, b0, sizeof(b0), &fa1, &fa1_len, &fa2, + &fa2_len); + MISSING_NULL_CHECK; + + ret = sss_auth_unpack_2fa_blob(ts, b1, sizeof(b1), &fa1, &fa1_len, &fa2, + &fa2_len); + MISSING_NULL_CHECK; + + ret = sss_auth_unpack_2fa_blob(ts, b2, sizeof(b2), &fa1, &fa1_len, &fa2, + &fa2_len); + MISSING_NULL_CHECK; + + ret = sss_auth_unpack_2fa_blob(ts, b3, sizeof(b3), &fa1, &fa1_len, &fa2, + &fa2_len); + MISSING_NULL_CHECK; +} + int main(int argc, const char *argv[]) { poptContext pc; @@ -333,7 +480,13 @@ int main(int argc, const char *argv[]) cmocka_unit_test_setup_teardown(test_sss_authtok_wipe_password, setup, teardown), cmocka_unit_test_setup_teardown(test_sss_authtok_copy, - setup, teardown) + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_authtok_2fa, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_authtok_2fa_blobs, + setup, teardown), + cmocka_unit_test_setup_teardown(test_sss_authtok_2fa_blobs_missing_null, + setup, teardown), }; /* Set debug level to invalid value so we can deside if -d 0 was used. */ diff --git a/src/util/authtok-utils.c b/src/util/authtok-utils.c new file mode 100644 index 0000000000000000000000000000000000000000..3955e6667f0957fa456d8a33d0325299b56f8246 --- /dev/null +++ b/src/util/authtok-utils.c @@ -0,0 +1,74 @@ +/* + SSSD - auth utils helpers + + Copyright (C) Sumit Bose 2015 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* This file is use by SSSD clients and the main daemons. Please do not add + * code which is specific to only one of them. */ + +#include + +#include "sss_client/sss_cli.h" + +errno_t sss_auth_pack_2fa_blob(const char *fa1, size_t fa1_len, + const char *fa2, size_t fa2_len, + uint8_t *buf, size_t buf_len, + size_t *_2fa_blob_len) +{ + size_t c; + uint32_t tmp_uint32_t; + + if (fa1 == NULL || fa1_len > UINT32_MAX || fa2 == NULL + || fa2_len > UINT32_MAX || (buf == NULL && buf_len != 0)) { + return EINVAL; + } + + if (fa1_len == 0) { + fa1_len = strlen(fa1); + } else { + if (fa1[fa1_len] != '\0') { + return EINVAL; + } + } + + if (fa2_len == 0) { + fa2_len = strlen(fa2); + } else { + if (fa2[fa2_len] != '\0') { + return EINVAL; + } + } + + *_2fa_blob_len = fa1_len + fa2_len + 2 + 2 * sizeof(uint32_t); + if (buf_len < *_2fa_blob_len) { + return EAGAIN; + } + + c = 0; + tmp_uint32_t = (uint32_t) fa1_len + 1; + SAFEALIGN_COPY_UINT32(buf, &tmp_uint32_t, &c); + tmp_uint32_t = (uint32_t) fa2_len + 1; + SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c); + + memcpy(buf + c, fa1, fa1_len + 1); + c += fa1_len + 1; + + memcpy(buf + c, fa2, fa2_len + 1); + + return 0; +} + diff --git a/src/util/authtok-utils.h b/src/util/authtok-utils.h new file mode 100644 index 0000000000000000000000000000000000000000..6ef6c20a85dda90e627e5d4d7107aaa8a9da253c --- /dev/null +++ b/src/util/authtok-utils.h @@ -0,0 +1,48 @@ +/* + SSSD - auth utils helpers + + Copyright (C) Sumit Bose 2015 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __AUTHTOK_UTILS_H__ +#define __AUTHTOK_UTILS_H__ + +#include "sss_client/sss_cli.h" + +/** + * @brief Fill memory buffer with 2FA blob + * + * @param[in] fa1 First authentication factor, null terminated + * @param[in] fa1_len Length of the first authentication factor, if 0 + * strlen() will be called internally + * @param[in] fa2 Second authentication factor, null terminated + * @param[in] fa2_len Length of the second authentication factor, if 0 + * strlen() will be called internally + * @param[in] buf memory buffer of size buf_len + * @param[in] buf_len size of memory buffer buf + * + * @param[out] _2fa_blob_len size of the 2FA blob + * + * @return EOK on success + * EINVAL if input data is not consistent + * EAGAIN if provided buffer is too small, _2fa_blob_len + * contains the size needed to store the 2FA blob + */ +errno_t sss_auth_pack_2fa_blob(const char *fa1, size_t fa1_len, + const char *fa2, size_t fa2_len, + uint8_t *buf, size_t buf_len, + size_t *_2fa_blob_len); +#endif /* __AUTHTOK_UTILS_H__ */ diff --git a/src/util/authtok.c b/src/util/authtok.c index b7bc17ed0cdc5cfee7f455b0d7047803e628274a..0276ecc57e90acd09e9dbee080ac12a40ce6ea6a 100644 --- a/src/util/authtok.c +++ b/src/util/authtok.c @@ -38,6 +38,7 @@ size_t sss_authtok_get_size(struct sss_auth_token *tok) switch (tok->type) { case SSS_AUTHTOK_TYPE_PASSWORD: case SSS_AUTHTOK_TYPE_CCFILE: + case SSS_AUTHTOK_TYPE_2FA: return tok->length; case SSS_AUTHTOK_TYPE_EMPTY: return 0; @@ -70,6 +71,7 @@ errno_t sss_authtok_get_password(struct sss_auth_token *tok, } return EOK; case SSS_AUTHTOK_TYPE_CCFILE: + case SSS_AUTHTOK_TYPE_2FA: return EACCES; } @@ -92,6 +94,7 @@ errno_t sss_authtok_get_ccfile(struct sss_auth_token *tok, } return EOK; case SSS_AUTHTOK_TYPE_PASSWORD: + case SSS_AUTHTOK_TYPE_2FA: return EACCES; } @@ -140,6 +143,7 @@ void sss_authtok_set_empty(struct sss_auth_token *tok) case SSS_AUTHTOK_TYPE_EMPTY: return; case SSS_AUTHTOK_TYPE_PASSWORD: + case SSS_AUTHTOK_TYPE_2FA: safezero(tok->data, tok->length); break; case SSS_AUTHTOK_TYPE_CCFILE: @@ -169,6 +173,9 @@ errno_t sss_authtok_set_ccfile(struct sss_auth_token *tok, "ccfile", ccfile, len); } +static errno_t sss_authtok_set_2fa_from_blob(struct sss_auth_token *tok, + const uint8_t *data, size_t len); + errno_t sss_authtok_set(struct sss_auth_token *tok, enum sss_authtok_type type, const uint8_t *data, size_t len) @@ -178,6 +185,8 @@ errno_t sss_authtok_set(struct sss_auth_token *tok, return sss_authtok_set_password(tok, (const char *)data, len); case SSS_AUTHTOK_TYPE_CCFILE: 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_EMPTY: sss_authtok_set_empty(tok); return EOK; @@ -230,3 +239,176 @@ void sss_authtok_wipe_password(struct sss_auth_token *tok) safezero(tok->data, tok->length); } +errno_t sss_auth_unpack_2fa_blob(TALLOC_CTX *mem_ctx, + const uint8_t *blob, size_t blob_len, + char **fa1, size_t *_fa1_len, + char **fa2, size_t *_fa2_len) +{ + size_t c; + uint32_t fa1_len; + uint32_t fa2_len; + + if (blob_len < 2 * sizeof(uint32_t)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n"); + return EINVAL; + } + + c = 0; + SAFEALIGN_COPY_UINT32(&fa1_len, blob, &c); + SAFEALIGN_COPY_UINT32(&fa2_len, blob + c, &c); + + if (blob_len != 2 * sizeof(uint32_t) + fa1_len + fa2_len) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n"); + return EINVAL; + } + + if (fa1_len != 0) { + *fa1 = talloc_strndup(mem_ctx, (const char *) blob + c, fa1_len); + if (*fa1 == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); + return ENOMEM; + } + } else { + *fa1 = NULL; + } + + if (fa2_len != 0) { + *fa2 = talloc_strndup(mem_ctx, (const char *) blob + c + fa1_len, + fa2_len); + if (*fa2 == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); + talloc_free(*fa1); + return ENOMEM; + } + } else { + *fa2 = NULL; + } + + /* Re-calculate length for the case where \0 was missing in the blob */ + *_fa1_len = (*fa1 == NULL) ? 0 : strlen(*fa1); + *_fa2_len = (*fa2 == NULL) ? 0 : strlen(*fa2); + + return EOK; +} + +static errno_t sss_authtok_set_2fa_from_blob(struct sss_auth_token *tok, + const uint8_t *data, size_t len) +{ + TALLOC_CTX *tmp_ctx; + int ret; + char *fa1; + size_t fa1_len; + char *fa2; + size_t fa2_len; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sss_auth_unpack_2fa_blob(tmp_ctx, data, len, &fa1, &fa1_len, + &fa2, &fa2_len); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_auth_unpack_2fa_blob failed.\n"); + goto done; + } + + ret = sss_authtok_set_2fa(tok, fa1, fa1_len, fa2, fa2_len); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_set_2fa failed.\n"); + goto done; + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + + if (ret != EOK) { + sss_authtok_set_empty(tok); + } + + return ret; +} + + +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) +{ + size_t c; + uint32_t tmp_uint32_t; + + if (tok->type != SSS_AUTHTOK_TYPE_2FA) { + return (tok->type == SSS_AUTHTOK_TYPE_EMPTY) ? ENOENT : EACCES; + } + + if (tok->length < 2 * sizeof(uint32_t)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n"); + return EINVAL; + } + + c = 0; + SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data, &c); + *fa1_len = tmp_uint32_t - 1; + SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c); + *fa2_len = tmp_uint32_t - 1; + + if (*fa1_len == 0 || fa2_len == 0 + || tok->length != 2 * sizeof(uint32_t) + *fa1_len + *fa2_len + 2) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n"); + return EINVAL; + } + + if (tok->data[c + *fa1_len] != '\0' + || tok->data[c + *fa1_len + 1 + *fa2_len] != '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing terminating null character.\n"); + return EINVAL; + } + + *fa1 = (const char *) tok->data + c; + *fa2 = (const char *) tok->data + c + *fa1_len + 1; + + return EOK; +} + +errno_t sss_authtok_set_2fa(struct sss_auth_token *tok, + const char *fa1, size_t fa1_len, + const char *fa2, size_t fa2_len) +{ + int ret; + size_t needed_size; + + if (tok == NULL) { + return EINVAL; + } + + sss_authtok_set_empty(tok); + + ret = sss_auth_pack_2fa_blob(fa1, fa1_len, fa2, fa2_len, NULL, 0, + &needed_size); + if (ret != EAGAIN) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sss_auth_pack_2fa_blob unexpectedly returned [%d].\n", ret); + return EINVAL; + } + + tok->data = talloc_size(tok, needed_size); + if (tok->data == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n"); + return ENOMEM; + } + + ret = sss_auth_pack_2fa_blob(fa1, fa1_len, fa2, fa2_len, tok->data, + needed_size, &needed_size); + if (ret != EOK) { + talloc_free(tok->data); + DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_2fa_blob failed.\n"); + return ret; + } + tok->length = needed_size; + tok->type = SSS_AUTHTOK_TYPE_2FA; + + return EOK; +} diff --git a/src/util/authtok.h b/src/util/authtok.h index 1f6def4c3b6a1cbf6c4f34bb76c496ddae6f9d5f..e06ec2c07b68dfcc5dc6582bec6a5644ab3d2648 100644 --- a/src/util/authtok.h +++ b/src/util/authtok.h @@ -21,6 +21,7 @@ #define __AUTHTOK_H__ #include "util/util.h" +#include "util/authtok-utils.h" #include "sss_client/sss_cli.h" /* Use sss_authtok_* accesor functions instead of struct sss_auth_token @@ -179,4 +180,47 @@ void sss_authtok_wipe_password(struct sss_auth_token *tok); */ struct sss_auth_token *sss_authtok_new(TALLOC_CTX *mem_ctx); +/** + * @brief Set authtoken with 2FA 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[in] fa1 First authentication factor, null terminated + * @param[in] fa1_len Length of the first authentication factor, if 0 + * strlen() will be called internally + * @param[in] fa2 Second authentication factor, null terminated + * @param[in] fa2_len Length of the second authentication factor, if 0 + * strlen() will be called internally + * + * @return EOK on success + * ENOMEM if memory allocation failed + * EINVAL if input data is not consistent + */ +errno_t sss_authtok_set_2fa(struct sss_auth_token *tok, + const char *fa1, size_t fa1_len, + const char *fa2, size_t fa2_len); + +/** + * @brief Get 2FA factors from authtoken + * + * @param tok A pointer to a sss_auth_token structure to change, also + * used as a memory context to allocate the internal data. + * @param[out] fa1 A pointer to a const char *, that will point to a + * null terminated string holding the first + * authentication factor + * @param[out] fa1_len Length of the first authentication factor + * @param[out] fa2 A pointer to a const char *, that will point to a + * null terminated string holding the second + * authentication factor + * @param[out] fa2_len Length of the second authentication factor + * + * @return EOK on success + * ENOMEM if memory allocation failed + * EINVAL if input data is not consistent + * ENOENT if the token is empty + * EACCESS if the token is not a 2FA token + */ +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); #endif /* __AUTHTOK_H__ */ -- 2.1.0