70e9980ac6
- Resolves: rhbz#1060325 - Does sssd-ad use the most suitable attribute for group name - Resolves: upstream #2335 - Investigate using the krb5 responder for driving the PAM conversation with OTPs - Enable cmocka tests for secondary architectures
766 lines
27 KiB
Diff
766 lines
27 KiB
Diff
From 3e3445a31a97d0e680ec436e4d627b46fcebc04e Mon Sep 17 00:00:00 2001
|
|
From: Sumit Bose <sbose@redhat.com>
|
|
Date: Wed, 7 Jan 2015 18:11:16 +0100
|
|
Subject: [PATCH 102/114] utils: add sss_authtok_[gs]et_2fa
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
|
|
(cherry picked from commit bc052ea17d858c19f9cb9c9e2bc602e754f68831)
|
|
---
|
|
Makefile.am | 5 ++
|
|
src/sss_client/pam_sss.c | 1 +
|
|
src/sss_client/sss_cli.h | 3 +
|
|
src/tests/cmocka/test_authtok.c | 189 +++++++++++++++++++++++++++++++++++++++-
|
|
src/util/authtok-utils.c | 74 ++++++++++++++++
|
|
src/util/authtok-utils.h | 70 +++++++++++++++
|
|
src/util/authtok.c | 181 ++++++++++++++++++++++++++++++++++++++
|
|
src/util/authtok.h | 44 ++++++++++
|
|
8 files changed, 564 insertions(+), 3 deletions(-)
|
|
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 fc369f6bdae5d414fad1cc6abd3a514ce931ecec..3bc37a3984a5fa0471a1f3247bda9b869fc823e5 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 \
|
|
@@ -752,6 +753,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 \
|
|
@@ -1852,6 +1854,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) \
|
|
@@ -2703,6 +2706,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 \
|
|
@@ -2734,6 +2738,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 28a36d5af95297b394a74f39d6614f48831bb901..4007d125e34932dfb5ac6bc840f4d25306e3008f 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 <libintl.h>
|
|
#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..5aa47c7b6b8c955666a9c73d5f9627d6378d13e0 100644
|
|
--- a/src/tests/cmocka/test_authtok.c
|
|
+++ b/src/tests/cmocka/test_authtok.c
|
|
@@ -57,7 +57,7 @@ static int teardown(void **state)
|
|
|
|
assert_non_null(ts);
|
|
|
|
- assert_true(check_leaks_pop(ts) == true);
|
|
+ assert_true(check_leaks_pop(ts));
|
|
talloc_free(ts);
|
|
assert_true(leak_check_teardown());
|
|
return 0;
|
|
@@ -118,8 +118,8 @@ static void test_sss_authtok_password(void **state)
|
|
assert_int_equal(len - 1, ret_len);
|
|
|
|
ret = sss_authtok_set_password(ts->authtoken, data, len);
|
|
-
|
|
assert_int_equal(ret, EOK);
|
|
+
|
|
ret = sss_authtok_get_password(ts->authtoken, &pwd, &ret_len);
|
|
assert_int_equal(ret, EOK);
|
|
assert_string_equal(data, pwd);
|
|
@@ -311,6 +311,183 @@ static void test_sss_authtok_copy(void **state)
|
|
talloc_free(data);
|
|
}
|
|
|
|
+void test_sss_authtok_2fa(void **state)
|
|
+{
|
|
+ int ret;
|
|
+ const char *fa1;
|
|
+ size_t fa1_size;
|
|
+ const char *fa2;
|
|
+ size_t fa2_size;
|
|
+ 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);
|
|
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
+ assert_memory_equal(sss_authtok_get_data(ts->authtoken),
|
|
+ "\2\0\0\0\3\0\0\0a\0bc\0",
|
|
+ 2 * sizeof(uint32_t) + 5);
|
|
+#else
|
|
+ assert_memory_equal(sss_authtok_get_data(ts->authtoken),
|
|
+ "\0\0\0\2\0\0\0\3a\0bc\0",
|
|
+ 2 * sizeof(uint32_t) + 5);
|
|
+#endif
|
|
+
|
|
+ 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);
|
|
+ assert_int_equal(ret, EOK);
|
|
+
|
|
+ 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,
|
|
+ (const uint8_t *) "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(NULL, 0, "defg", 0, NULL, 0, &needed_size);
|
|
+ assert_int_equal(ret, EINVAL);
|
|
+
|
|
+ ret = sss_auth_pack_2fa_blob("abc", 0, NULL, 0, NULL, 0, &needed_size);
|
|
+ assert_int_equal(ret, EINVAL);
|
|
+
|
|
+ ret = sss_auth_pack_2fa_blob("", 0, "defg", 0, NULL, 0, &needed_size);
|
|
+ assert_int_equal(ret, EINVAL);
|
|
+
|
|
+ ret = sss_auth_pack_2fa_blob("abc", 0, "", 0, NULL, 0, &needed_size);
|
|
+ assert_int_equal(ret, EINVAL);
|
|
+
|
|
+ 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);
|
|
+
|
|
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
+ assert_memory_equal(buf, "\4\0\0\0\5\0\0\0abc\0defg\0", needed_size);
|
|
+#else
|
|
+ assert_memory_equal(buf, "\0\0\0\4\0\0\0\5abc\0defg\0", needed_size);
|
|
+#endif
|
|
+
|
|
+ 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;
|
|
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
+ 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'};
|
|
+#else
|
|
+ uint8_t b0[] = {0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 'a', 'b', 'c', 0x00, 'd', 'e', 'f', 'g', 0x00};
|
|
+ uint8_t b1[] = {0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 0x00};
|
|
+ uint8_t b2[] = {0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 'a', 'b', 'c', 0x00, 'd', 'e', 'f', 'g'};
|
|
+ uint8_t b3[] = {0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 'a', 'b', 'c', 'd', 'e', 'f', 'g'};
|
|
+#endif
|
|
+
|
|
+
|
|
+ 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 +510,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..65fba9022db11786c0c7e4dcab6fec89c9e0cb19
|
|
--- /dev/null
|
|
+++ b/src/util/authtok-utils.c
|
|
@@ -0,0 +1,74 @@
|
|
+/*
|
|
+ SSSD - auth utils helpers
|
|
+
|
|
+ Copyright (C) Sumit Bose <sbose@redhat.com> 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 <http://www.gnu.org/licenses/>.
|
|
+*/
|
|
+
|
|
+/* 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 <errno.h>
|
|
+
|
|
+#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 == '\0' || fa1_len > UINT32_MAX
|
|
+ || fa2 == NULL || *fa2 == '\0' || 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 == NULL || 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..07aef3c18395d6e967289f6e345f27e9ee868da2
|
|
--- /dev/null
|
|
+++ b/src/util/authtok-utils.h
|
|
@@ -0,0 +1,70 @@
|
|
+/*
|
|
+ SSSD - auth utils helpers
|
|
+
|
|
+ Copyright (C) Sumit Bose <simo@redhat.com> 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 <http://www.gnu.org/licenses/>.
|
|
+*/
|
|
+
|
|
+#ifndef __AUTHTOK_UTILS_H__
|
|
+#define __AUTHTOK_UTILS_H__
|
|
+
|
|
+#include <talloc.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);
|
|
+
|
|
+/**
|
|
+ * @brief Extract 2FA data from memory buffer
|
|
+ *
|
|
+ * @param[in] mem_ctx Talloc memory context to allocate the 2FA data on
|
|
+ * @param[in] blob Memory buffer containing the 2FA data
|
|
+ * @param[in] blob_len Size of the memory buffer
|
|
+ * @param[out] _fa1 First authentication factor, null terminated
|
|
+ * @param[out] _fa1_len Length of the first authentication factor
|
|
+ * @param[out] _fa2 Second authentication factor, null terminated
|
|
+ * @param[out] _fa2_len Length of the second authentication factor
|
|
+ *
|
|
+ * @return EOK on success
|
|
+ * EINVAL if input data is not consistent
|
|
+ * EINVAL if no memory can be allocated
|
|
+ */
|
|
+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);
|
|
+#endif /* __AUTHTOK_UTILS_H__ */
|
|
diff --git a/src/util/authtok.c b/src/util/authtok.c
|
|
index b7bc17ed0cdc5cfee7f455b0d7047803e628274a..45761df80175fded8a6c6e5dac8a90180b11d225 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,175 @@ 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..cb366270832852281a222018f8e27feb1500ff01 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, may not be modified or freed
|
|
+ * @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, may not be modified or freed
|
|
+ * @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.4.0
|
|
|