summaryrefslogtreecommitdiffstats
path: root/src/tests/krb5_utils-tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/krb5_utils-tests.c')
-rw-r--r--src/tests/krb5_utils-tests.c854
1 files changed, 854 insertions, 0 deletions
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
new file mode 100644
index 0000000..7674292
--- /dev/null
+++ b/src/tests/krb5_utils-tests.c
@@ -0,0 +1,854 @@
+/*
+ SSSD
+
+ Kerberos 5 Backend Module -- Utilities tests
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2009 Red Hat
+
+ 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/>.
+*/
+
+#include <stdlib.h>
+#include <popt.h>
+#include <check.h>
+
+#include "providers/krb5/krb5_utils.h"
+#include "providers/krb5/krb5_ccache.h"
+#include "providers/krb5/krb5_auth.h"
+#include "util/sss_utf8.h"
+#include "tests/common.h"
+
+#define TESTS_PATH "tp_" BASE_FILE_STEM
+
+#define BASE "/abc/def"
+#define FILENAME "ghi"
+
+#define USERNAME "testuser"
+#define USERNAME_CASE "TestUser"
+#define DOMAIN_NAME "testdomain"
+#define UID "12345"
+#define PRINCIPAL_NAME "testuser@EXAMPLE.COM"
+#define REALM "REALM.ORG"
+#define HOME_DIRECTORY "/home/testuser"
+#define CCACHE_DIR "/var/tmp"
+#define PID "4321"
+
+extern struct dp_option default_krb5_opts[];
+
+TALLOC_CTX *tmp_ctx = NULL;
+struct krb5child_req *kr;
+
+#define RMDIR(__dir__) do { \
+ ret = rmdir(__dir__); \
+ ck_assert_msg(ret == EOK, "rmdir [%s] failed, [%d][%s].", __dir__, \
+ errno, strerror(errno)); \
+} while(0)
+
+void setup_create_dir(void)
+{
+ ck_assert_msg(tmp_ctx == NULL, "Talloc context already initialized.");
+ tmp_ctx = talloc_new(NULL);
+ ck_assert_msg(tmp_ctx != NULL, "Cannot create talloc context.");
+}
+
+void teardown_create_dir(void)
+{
+ int ret;
+ ck_assert_msg(tmp_ctx != NULL, "Talloc context already freed.");
+ ret = talloc_free(tmp_ctx);
+ tmp_ctx = NULL;
+ ck_assert_msg(ret == 0, "Cannot free talloc context.");
+}
+
+static void check_dir(const char *dirname, uid_t uid, gid_t gid, mode_t mode)
+{
+ struct stat stat_buf;
+ int ret;
+
+ ret = stat(dirname, &stat_buf);
+ ck_assert_msg(ret == EOK, "stat failed [%d][%s].", errno, strerror(errno));
+
+ ck_assert_msg(S_ISDIR(stat_buf.st_mode), "[%s] is not a directory.", dirname);
+ ck_assert_msg(stat_buf.st_uid == uid, "uid does not match, "
+ "expected [%d], got [%d].",
+ uid, stat_buf.st_uid);
+ ck_assert_msg(stat_buf.st_gid == gid, "gid does not match, "
+ "expected [%d], got [%d].",
+ gid, stat_buf.st_gid);
+ ck_assert_msg((stat_buf.st_mode & ~S_IFMT) == mode,
+ "mode of [%s] does not match, "
+ "expected [%o], got [%o].", dirname,
+ mode, (stat_buf.st_mode & ~S_IFMT));
+}
+
+START_TEST(test_private_ccache_dir_in_user_dir)
+{
+ int ret;
+ char *cwd;
+ char *user_dir;
+ char *dn1;
+ char *dn2;
+ char *dn3;
+ char *filename;
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+
+ if (uid == 0) {
+ uid = 12345;
+ gid = 12345;
+ }
+
+ cwd = getcwd(NULL, 0);
+ ck_assert_msg(cwd != NULL, "getcwd failed.");
+
+ user_dir = talloc_asprintf(tmp_ctx, "%s/%s/user", cwd, TESTS_PATH);
+ free(cwd);
+ ck_assert_msg(user_dir != NULL, "talloc_asprintf failed.");
+ ret = mkdir(user_dir, 0700);
+ ck_assert_msg(ret == EOK, "mkdir failed.");
+ ret = chown(user_dir, uid, gid);
+ ck_assert_msg(ret == EOK, "chown failed.");
+
+ dn1 = talloc_asprintf(tmp_ctx, "%s/a", user_dir);
+ ck_assert_msg(dn1 != NULL, "talloc_asprintf failed.");
+ dn2 = talloc_asprintf(tmp_ctx, "%s/b", dn1);
+ ck_assert_msg(dn2 != NULL, "talloc_asprintf failed.");
+ dn3 = talloc_asprintf(tmp_ctx, "%s/c", dn2);
+ ck_assert_msg(dn3 != NULL, "talloc_asprintf failed.");
+ filename = talloc_asprintf(tmp_ctx, "%s/ccfile", dn3);
+ ck_assert_msg(filename != NULL, "talloc_asprintf failed.");
+
+ ret = chmod(user_dir, 0600);
+ ck_assert_msg(ret == EOK, "chmod failed.");
+ ret = sss_krb5_precreate_ccache(filename, uid, gid);
+ ck_assert_msg(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
+ "while x-bit is missing.");
+
+ ret = chmod(user_dir, 0700);
+ ck_assert_msg(ret == EOK, "chmod failed.");
+ ret = sss_krb5_precreate_ccache(filename, uid, gid);
+ ck_assert_msg(ret == EOK, "sss_krb5_precreate_ccache failed.");
+
+ check_dir(dn3, uid, gid, 0700);
+ RMDIR(dn3);
+ check_dir(dn2, uid, gid, 0700);
+ RMDIR(dn2);
+ check_dir(dn1, uid, gid, 0700);
+ RMDIR(dn1);
+ RMDIR(user_dir);
+}
+END_TEST
+
+START_TEST(test_private_ccache_dir_in_wrong_user_dir)
+{
+ int ret;
+ char *cwd;
+ char *dirname;
+ char *subdirname;
+ char *filename;
+
+ ck_assert_msg(getuid() == 0, "This test must be run as root.");
+
+ cwd = getcwd(NULL, 0);
+ ck_assert_msg(cwd != NULL, "getcwd failed.");
+
+ dirname = talloc_asprintf(tmp_ctx, "%s/%s/priv_ccdir", cwd, TESTS_PATH);
+ free(cwd);
+ ck_assert_msg(dirname != NULL, "talloc_asprintf failed.");
+ ret = mkdir(dirname, 0700);
+ ck_assert_msg(ret == EOK, "mkdir failed.\n");
+ ret = chown(dirname, 12346, 12346);
+ ck_assert_msg(ret == EOK, "chown failed.\n");
+ subdirname = talloc_asprintf(tmp_ctx, "%s/subdir", dirname);
+ ck_assert_msg(subdirname != NULL, "talloc_asprintf failed.");
+ filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
+ ck_assert_msg(filename != NULL, "talloc_asprintf failed.");
+
+ ret = sss_krb5_precreate_ccache(filename, 12345, 12345);
+ ck_assert_msg(ret == EINVAL, "Creating private ccache dir in wrong user "
+ "dir does not failed with EINVAL.");
+
+ RMDIR(dirname);
+}
+END_TEST
+
+START_TEST(test_illegal_patterns)
+{
+ char *cwd;
+ char *dirname;
+ char *filename;
+ sss_regexp_t *illegal_re;
+ int err;
+ char *result = NULL;
+
+
+ err = sss_regexp_new(NULL, ILLEGAL_PATH_PATTERN, 0, &illegal_re);
+
+ ck_assert_msg(err == 0, "Invalid Regular Expression pattern error %d.\n", err);
+ ck_assert_msg(illegal_re != NULL, "No error but illegal_re is NULL.\n");
+
+ cwd = getcwd(NULL, 0);
+ ck_assert_msg(cwd != NULL, "getcwd failed.");
+
+ dirname = talloc_asprintf(tmp_ctx, "%s/%s/priv_ccdir", cwd, TESTS_PATH);
+ free(cwd);
+ ck_assert_msg(dirname != NULL, "talloc_asprintf failed.");
+
+ result = expand_ccname_template(tmp_ctx, kr, "abc/./ccfile", illegal_re, true, true);
+ ck_assert_msg(result == NULL, "expand_ccname_template allowed relative path\n");
+
+ filename = talloc_asprintf(tmp_ctx, "%s/abc/./ccfile", dirname);
+ ck_assert_msg(filename != NULL, "talloc_asprintf failed.");
+ result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
+ ck_assert_msg(result == NULL, "expand_ccname_template allowed "
+ "illegal pattern '/./'\n");
+
+ filename = talloc_asprintf(tmp_ctx, "%s/abc/../ccfile", dirname);
+ ck_assert_msg(filename != NULL, "talloc_asprintf failed.");
+ result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
+ ck_assert_msg(result == NULL, "expand_ccname_template allowed "
+ "illegal pattern '/../' in filename [%s].",
+ filename);
+
+ filename = talloc_asprintf(tmp_ctx, "%s/abc//ccfile", dirname);
+ ck_assert_msg(filename != NULL, "talloc_asprintf failed.");
+ result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
+ ck_assert_msg(result == NULL, "expand_ccname_template allowed "
+ "illegal pattern '//' in filename [%s].",
+ filename);
+
+ talloc_free(illegal_re);
+}
+END_TEST
+
+START_TEST(test_cc_dir_create)
+{
+ char *residual;
+ char *dirname;
+ char *cwd;
+ uid_t uid = getuid();
+ gid_t gid = getgid();
+ errno_t ret;
+
+ cwd = getcwd(NULL, 0);
+ ck_assert_msg(cwd != NULL, "getcwd failed.");
+
+ dirname = talloc_asprintf(tmp_ctx, "%s/%s/user_dir",
+ cwd, TESTS_PATH);
+ ck_assert_msg(dirname != NULL, "talloc_asprintf failed.");
+ residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir");
+ ck_assert_msg(residual != NULL, "talloc_asprintf failed.");
+
+ ret = sss_krb5_precreate_ccache(residual, uid, gid);
+ ck_assert_msg(ret == EOK, "sss_krb5_precreate_ccache failed\n");
+ ret = rmdir(dirname);
+ if (ret < 0) ret = errno;
+ ck_assert_msg(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
+ talloc_free(residual);
+
+ dirname = talloc_asprintf(tmp_ctx, "%s/%s/user_dir2",
+ cwd, TESTS_PATH);
+ ck_assert_msg(dirname != NULL, "talloc_asprintf failed.");
+ residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir/");
+ ck_assert_msg(residual != NULL, "talloc_asprintf failed.");
+
+ ret = sss_krb5_precreate_ccache(residual, uid, gid);
+ ck_assert_msg(ret == EOK, "sss_krb5_precreate_ccache failed\n");
+ ret = rmdir(dirname);
+ if (ret < 0) ret = errno;
+ ck_assert_msg(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
+ talloc_free(residual);
+ free(cwd);
+}
+END_TEST
+
+
+void setup_talloc_context(void)
+{
+ int ret;
+ int i;
+
+ struct pam_data *pd;
+ struct krb5_ctx *krb5_ctx;
+ ck_assert_msg(tmp_ctx == NULL, "Talloc context already initialized.");
+ tmp_ctx = talloc_new(NULL);
+ ck_assert_msg(tmp_ctx != NULL, "Cannot create talloc context.");
+
+ kr = talloc_zero(tmp_ctx, struct krb5child_req);
+ ck_assert_msg(kr != NULL, "Cannot create krb5child_req structure.");
+
+ pd = create_pam_data(tmp_ctx);
+ ck_assert_msg(pd != NULL, "Cannot create pam_data structure.");
+
+ krb5_ctx = talloc_zero(tmp_ctx, struct krb5_ctx);
+ ck_assert_msg(pd != NULL, "Cannot create krb5_ctx structure.");
+
+ pd->user = sss_create_internal_fqname(pd, USERNAME, DOMAIN_NAME);
+ ck_assert_msg(pd->user != NULL, "Failed to allocate memory");
+ kr->uid = atoi(UID);
+ kr->upn = discard_const(PRINCIPAL_NAME);
+ pd->cli_pid = atoi(PID);
+
+ krb5_ctx->opts = talloc_zero_array(tmp_ctx, struct dp_option, KRB5_OPTS);
+ ck_assert_msg(krb5_ctx->opts != NULL, "Cannot created options.");
+ for (i = 0; i < KRB5_OPTS; i++) {
+ krb5_ctx->opts[i].opt_name = default_krb5_opts[i].opt_name;
+ krb5_ctx->opts[i].type = default_krb5_opts[i].type;
+ krb5_ctx->opts[i].def_val = default_krb5_opts[i].def_val;
+ }
+ ret = dp_opt_set_string(krb5_ctx->opts, KRB5_REALM, REALM);
+ ck_assert_msg(ret == EOK, "Failed to set Realm");
+ ret = dp_opt_set_string(krb5_ctx->opts, KRB5_CCACHEDIR, CCACHE_DIR);
+ ck_assert_msg(ret == EOK, "Failed to set Ccache dir");
+
+ kr->homedir = HOME_DIRECTORY;
+
+ kr->pd = pd;
+ kr->krb5_ctx = krb5_ctx;
+
+}
+
+void free_talloc_context(void)
+{
+ int ret;
+ ck_assert_msg(tmp_ctx != NULL, "Talloc context already freed.");
+ ret = talloc_free(tmp_ctx);
+ tmp_ctx = NULL;
+ ck_assert_msg(ret == 0, "Cannot free talloc context.");
+}
+
+static void do_test(const char *file_template, const char *dir_template,
+ const char *expected)
+{
+ char *result;
+ int ret;
+
+ ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, dir_template);
+ ck_assert_msg(ret == EOK, "Failed to set Ccache dir");
+
+ result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
+
+ ck_assert_msg(result != NULL, "Cannot expand template [%s].", file_template);
+ ck_assert_msg(strcmp(result, expected) == 0,
+ "Expansion failed, result [%s], expected [%s].",
+ result, expected);
+}
+
+START_TEST(test_multiple_substitutions)
+{
+ do_test(BASE"_%u_%U_%u", CCACHE_DIR, BASE"_"USERNAME"_"UID"_"USERNAME);
+ do_test("%d/"FILENAME, BASE"_%u_%U_%u",
+ BASE"_"USERNAME"_"UID"_"USERNAME"/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_username)
+{
+ do_test(BASE"_%u", CCACHE_DIR, BASE"_"USERNAME);
+ do_test("%d/"FILENAME, BASE"_%u", BASE"_"USERNAME"/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_case_sensitive)
+{
+ char *result;
+ int ret;
+ const char *file_template = BASE"_%u";
+ const char *expected_cs = BASE"_TestUser";
+ const char *expected_ci = BASE"_testuser";
+
+ kr->pd->user = sss_create_internal_fqname(kr, USERNAME_CASE, DOMAIN_NAME);
+ ck_assert_msg(kr->pd->user != NULL, "Failed to allocate memory");
+ ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, CCACHE_DIR);
+ ck_assert_msg(ret == EOK, "Failed to set Ccache dir");
+
+ result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
+
+ ck_assert_msg(result != NULL, "Cannot expand template [%s].", file_template);
+ ck_assert_msg(strcmp(result, expected_cs) == 0,
+ "Expansion failed, result [%s], expected [%s].",
+ result, expected_cs);
+
+ result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, false);
+
+ ck_assert_msg(result != NULL, "Cannot expand template [%s].", file_template);
+ ck_assert_msg(strcmp(result, expected_ci) == 0,
+ "Expansion failed, result [%s], expected [%s].",
+ result, expected_ci);
+}
+END_TEST
+
+START_TEST(test_uid)
+{
+ do_test(BASE"_%U", CCACHE_DIR, BASE"_"UID);
+ do_test("%d/"FILENAME, BASE"_%U", BASE"_"UID"/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_upn)
+{
+ do_test(BASE"_%p", CCACHE_DIR, BASE"_"PRINCIPAL_NAME);
+ do_test("%d/"FILENAME, BASE"_%p", BASE"_"PRINCIPAL_NAME"/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_realm)
+{
+ do_test(BASE"_%r", CCACHE_DIR, BASE"_"REALM);
+ do_test("%d/"FILENAME, BASE"_%r", BASE"_"REALM"/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_home)
+{
+ do_test(BASE"_%h", CCACHE_DIR, BASE"_"HOME_DIRECTORY);
+ do_test("%d/"FILENAME, BASE"_%h", BASE"_"HOME_DIRECTORY"/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_ccache_dir)
+{
+ char *result;
+ int ret;
+
+ do_test(BASE"_%d", CCACHE_DIR, BASE"_"CCACHE_DIR);
+
+ ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%d");
+ ck_assert_msg(ret == EOK, "Failed to set Ccache dir");
+
+ result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, NULL, true, true);
+
+ ck_assert_msg(result == NULL, "Using %%d in ccache dir should fail.");
+}
+END_TEST
+
+START_TEST(test_pid)
+{
+ char *result;
+ int ret;
+
+ do_test(BASE"_%P", CCACHE_DIR, BASE"_"PID);
+
+ ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%P");
+ ck_assert_msg(ret == EOK, "Failed to set Ccache dir");
+
+ result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, NULL, true, true);
+
+ ck_assert_msg(result == NULL, "Using %%P in ccache dir should fail.");
+}
+END_TEST
+
+START_TEST(test_percent)
+{
+ do_test(BASE"_%%", CCACHE_DIR, BASE"_%");
+ do_test("%d/"FILENAME, BASE"_%%", BASE"_%/"FILENAME);
+}
+END_TEST
+
+START_TEST(test_unknown_template)
+{
+ const char *test_template = BASE"_%X";
+ char *result;
+ int ret;
+
+ result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
+
+ ck_assert_msg(result == NULL, "Unknown template [%s] should fail.",
+ test_template);
+
+ ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%X");
+ ck_assert_msg(ret == EOK, "Failed to set Ccache dir");
+ test_template = "%d/"FILENAME;
+ result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
+
+ ck_assert_msg(result == NULL, "Unknown template [%s] should fail.",
+ test_template);
+}
+END_TEST
+
+START_TEST(test_NULL)
+{
+ char *test_template = NULL;
+ char *result;
+
+ result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
+
+ ck_assert_msg(result == NULL,
+ "Expected NULL as a result for an empty input for "
+ "NULL template");
+}
+END_TEST
+
+START_TEST(test_no_substitution)
+{
+ const char *test_template = BASE;
+ char *result;
+
+ result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
+
+ ck_assert_msg(result != NULL, "Cannot expand template [%s].", test_template);
+ ck_assert_msg(strcmp(result, test_template) == 0,
+ "Expansion failed, result [%s], expected [%s].",
+ result, test_template);
+}
+END_TEST
+
+START_TEST(test_krb5_style_expansion)
+{
+ char *result;
+ const char *file_template;
+ const char *expected;
+
+ file_template = BASE"/%{uid}/%{USERID}/%{euid}/%{username}";
+ expected = BASE"/"UID"/"UID"/"UID"/"USERNAME;
+ result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
+
+ ck_assert_msg(result != NULL, "Cannot expand template [%s].", file_template);
+ ck_assert_msg(strcmp(result, expected) == 0,
+ "Expansion failed, result [%s], expected [%s].",
+ result, expected);
+
+ file_template = BASE"/%{unknown}";
+ expected = BASE"/%{unknown}";
+ result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
+
+ ck_assert_msg(result != NULL, "Cannot expand template [%s].", file_template);
+ ck_assert_msg(strcmp(result, expected) == 0,
+ "Expansion failed, result [%s], expected [%s].",
+ result, expected);
+}
+END_TEST
+
+START_TEST(test_compare_principal_realm)
+{
+ int ret;
+ bool different_realm;
+
+ ret = compare_principal_realm(NULL, "a", &different_realm);
+ ck_assert_msg(ret == EINVAL, "NULL upn does not cause EINVAL.");
+
+ ret = compare_principal_realm("a", NULL, &different_realm);
+ ck_assert_msg(ret == EINVAL, "NULL realm does not cause EINVAL.");
+
+ ret = compare_principal_realm("a", "b", NULL);
+ ck_assert_msg(ret == EINVAL, "NULL different_realmbool " \
+ "does not cause EINVAL.");
+
+ ret = compare_principal_realm("", "a", &different_realm);
+ ck_assert_msg(ret == EINVAL, "Empty upn does not cause EINVAL.");
+
+ ret = compare_principal_realm("a", "", &different_realm);
+ ck_assert_msg(ret == EINVAL, "Empty realm does not cause EINVAL.");
+
+ ret = compare_principal_realm("ABC", "ABC", &different_realm);
+ ck_assert_msg(ret == EINVAL, "Short UPN does not cause EINVAL.");
+
+ ret = compare_principal_realm("userABC", "ABC", &different_realm);
+ ck_assert_msg(ret == EINVAL, "Missing '@' does not cause EINVAL.");
+
+ ret = compare_principal_realm("user@ABC", "ABC", &different_realm);
+ ck_assert_msg(ret == EOK, "Failure with same realm");
+ ck_assert_msg(different_realm == false, "Same realm but " \
+ "different_realm is not false.");
+
+ ret = compare_principal_realm("user@ABC", "DEF", &different_realm);
+ ck_assert_msg(ret == EOK, "Failure with different realm");
+ ck_assert_msg(different_realm == true, "Different realm but " \
+ "different_realm is not true.");
+
+ ret = compare_principal_realm("user@ABC", "REALMNAMELONGERTHANUPN",
+ &different_realm);
+ ck_assert_msg(ret == EOK, "Failure with long realm name.");
+ ck_assert_msg(different_realm == true, "Realm name longer than UPN but "
+ "different_realm is not true.");
+}
+END_TEST
+
+static void
+compare_map_id_name_to_krb_primary(struct map_id_name_to_krb_primary *a,
+ const char **str,
+ size_t len)
+{
+ int i = 0;
+ errno_t ret;
+
+ while (a[i].id_name != NULL && a[i].krb_primary != NULL) {
+ ck_assert_msg(i < len,
+ "Index: %d mus =t be lowwer than: %zd", i, len);
+ ret = sss_utf8_case_eq((const uint8_t*)a[i].id_name,
+ (const uint8_t*)str[i*2]);
+ ck_assert_msg(ret == EOK,
+ "%s does not match %s", a[i].id_name, str[i*2]);
+
+ ret = sss_utf8_case_eq((const uint8_t*)a[i].krb_primary,
+ (const uint8_t*)str[i*2+1]);
+ ck_assert_msg(ret == EOK, "%s does not match %s",
+ a[i].krb_primary, str[i*2+1]);
+ i++;
+ }
+ ck_assert_msg(len == i, "%zu != %u", len, i);
+}
+
+START_TEST(test_parse_krb5_map_user)
+{
+ errno_t ret;
+ TALLOC_CTX *mem_ctx;
+ struct map_id_name_to_krb_primary *name_to_primary;
+
+ mem_ctx = talloc_new(NULL);
+
+ /* empty input */
+ {
+ check_leaks_push(mem_ctx);
+ ret = parse_krb5_map_user(mem_ctx, NULL, DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EOK,
+ "parse_krb5_map_user failed with error: %d", ret);
+ ck_assert_msg(name_to_primary[0].id_name == NULL,
+ "id_name must be NULL. Got: %s",
+ name_to_primary[0].id_name);
+ ck_assert_msg(name_to_primary[0].krb_primary == NULL,
+ "krb_primary must be NULL. Got: %s",
+ name_to_primary[0].krb_primary);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, "", DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EOK,
+ "parse_krb5_map_user failed with error: %d", ret);
+ ck_assert_msg(name_to_primary[0].id_name == NULL,
+ "id_name must be NULL. Got: %s",
+ name_to_primary[0].id_name);
+ ck_assert_msg(name_to_primary[0].krb_primary == NULL,
+ "krb_primary must be NULL. Got: %s",
+ name_to_primary[0].krb_primary);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, ",", DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EOK,
+ "parse_krb5_map_user failed with error: %d", ret);
+ ck_assert_msg(name_to_primary[0].id_name == NULL,
+ "id_name must be NULL. Got: %s",
+ name_to_primary[0].id_name);
+ ck_assert_msg(name_to_primary[0].krb_primary == NULL,
+ "krb_primary must be NULL. Got: %s",
+ name_to_primary[0].krb_primary);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, ",,", DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EOK,
+ "parse_krb5_map_user failed with error: %d", ret);
+ ck_assert_msg(name_to_primary[0].id_name == NULL,
+ "id_name must be NULL. Got: %s",
+ name_to_primary[0].id_name);
+ ck_assert_msg(name_to_primary[0].krb_primary == NULL,
+ "krb_primary must be NULL. Got: %s",
+ name_to_primary[0].krb_primary);
+
+ talloc_free(name_to_primary);
+
+ ck_assert_msg(check_leaks_pop(mem_ctx),
+ "check_leaks_pop failed");
+ }
+ /* valid input */
+ {
+ check_leaks_push(mem_ctx);
+ const char *p = "pája:preichl,joe:juser,jdoe:ßlack";
+ const char *p2 = " pája : preichl , joe:\njuser,jdoe\t: ßlack ";
+ const char *expected[] = { "pája@testdomain", "preichl@" DOMAIN_NAME,
+ "joe@testdomain", "juser@testdomain",
+ "jdoe@testdomain", "ßlack@testdomain" };
+ ret = parse_krb5_map_user(mem_ctx, p, DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EOK,
+ "parse_krb5_map_user failed with error: %d", ret);
+ compare_map_id_name_to_krb_primary(name_to_primary, expected,
+ sizeof(expected)/sizeof(const char*)/2);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, p2, DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EOK,
+ "parse_krb5_map_user failed with error: %d", ret);
+ compare_map_id_name_to_krb_primary(name_to_primary, expected,
+ sizeof(expected)/sizeof(const char*)/2);
+ talloc_free(name_to_primary);
+ ck_assert_msg(check_leaks_pop(mem_ctx),
+ "check_leaks_pop failed");
+ }
+ /* invalid input */
+ {
+ check_leaks_push(mem_ctx);
+
+ ret = parse_krb5_map_user(mem_ctx, ":", DOMAIN_NAME, &name_to_primary);
+ ck_assert_msg(ret == EINVAL,
+ "parse_krb5_map_user must fail with EINVAL got: %d", ret);
+
+ ret = parse_krb5_map_user(mem_ctx, "joe:", DOMAIN_NAME,
+ &name_to_primary);
+ ck_assert_msg(ret == EINVAL,
+ "parse_krb5_map_user must fail with EINVAL got: %d", ret);
+
+ ret = parse_krb5_map_user(mem_ctx, ":joe", DOMAIN_NAME,
+ &name_to_primary);
+ ck_assert_msg(ret == EINVAL,
+ "parse_krb5_map_user must fail with EINVAL got: %d", ret);
+
+ ret = parse_krb5_map_user(mem_ctx, "joe:,", DOMAIN_NAME,
+ &name_to_primary);
+ ck_assert_msg(ret == EINVAL,
+ "parse_krb5_map_user must fail with EINVAL got: %d", ret);
+
+ ret = parse_krb5_map_user(mem_ctx, ",joe", DOMAIN_NAME,
+ &name_to_primary);
+ ck_assert_msg(ret == EINVAL,
+ "parse_krb5_map_user must fail with EINVAL got: %d", ret);
+
+ ret = parse_krb5_map_user(mem_ctx, "joe:j:user", DOMAIN_NAME,
+ &name_to_primary);
+ ck_assert_msg(ret == EINVAL,
+ "parse_krb5_map_user must fail with EINVAL got: %d", ret);
+
+ ck_assert_msg(check_leaks_pop(mem_ctx),
+ "check_leaks_pop failed");
+ }
+
+ talloc_free(mem_ctx);
+}
+END_TEST
+
+START_TEST(test_sss_krb5_realm_has_proxy)
+{
+ ck_assert_msg(sss_krb5_realm_has_proxy(NULL) == false,
+ "sss_krb5_realm_has_proxy did not return false");
+
+ setenv("KRB5_CONFIG", "/dev/null", 1);
+ ck_assert_msg(sss_krb5_realm_has_proxy("REALM") == false,
+ "sss_krb5_realm_has_proxy did not return false");
+
+ setenv("KRB5_CONFIG", ABS_SRC_DIR"/src/tests/krb5_proxy_check_test_data.conf", 1);
+ ck_assert_msg(sss_krb5_realm_has_proxy("REALM") == false,
+ "sss_krb5_realm_has_proxy did not return false");
+ ck_assert_msg(sss_krb5_realm_has_proxy("REALM_PROXY") == true,
+ "sss_krb5_realm_has_proxy did not return true");
+}
+END_TEST
+
+Suite *krb5_utils_suite (void)
+{
+ Suite *s = suite_create ("krb5_utils");
+
+ TCase *tc_ccname_template = tcase_create ("ccname_template");
+ tcase_add_checked_fixture (tc_ccname_template, setup_talloc_context,
+ free_talloc_context);
+ tcase_add_test (tc_ccname_template, test_no_substitution);
+ tcase_add_test (tc_ccname_template, test_NULL);
+ tcase_add_test (tc_ccname_template, test_unknown_template);
+ tcase_add_test (tc_ccname_template, test_username);
+ tcase_add_test (tc_ccname_template, test_case_sensitive);
+ tcase_add_test (tc_ccname_template, test_uid);
+ tcase_add_test (tc_ccname_template, test_upn);
+ tcase_add_test (tc_ccname_template, test_realm);
+ tcase_add_test (tc_ccname_template, test_home);
+ tcase_add_test (tc_ccname_template, test_ccache_dir);
+ tcase_add_test (tc_ccname_template, test_pid);
+ tcase_add_test (tc_ccname_template, test_percent);
+ tcase_add_test (tc_ccname_template, test_multiple_substitutions);
+ tcase_add_test (tc_ccname_template, test_krb5_style_expansion);
+ suite_add_tcase (s, tc_ccname_template);
+
+ TCase *tc_create_dir = tcase_create("create_dir");
+ tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
+ teardown_create_dir);
+ tcase_add_test (tc_create_dir, test_illegal_patterns);
+ tcase_add_test (tc_create_dir, test_cc_dir_create);
+ if (getuid() == 0) {
+ tcase_add_test (tc_create_dir, test_private_ccache_dir_in_user_dir);
+ tcase_add_test (tc_create_dir, test_private_ccache_dir_in_wrong_user_dir);
+ } else {
+ printf("Run as root to enable more tests.\n");
+ }
+ suite_add_tcase (s, tc_create_dir);
+
+ TCase *tc_krb5_helpers = tcase_create("Helper functions");
+ tcase_add_test(tc_krb5_helpers, test_compare_principal_realm);
+ tcase_add_test(tc_krb5_helpers, test_parse_krb5_map_user);
+ tcase_add_test(tc_krb5_helpers, test_sss_krb5_realm_has_proxy);
+ suite_add_tcase(s, tc_krb5_helpers);
+
+ return s;
+}
+
+int main(int argc, const char *argv[])
+{
+ int ret;
+ int opt;
+ poptContext pc;
+ int number_failed;
+
+ tests_set_cwd();
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ SSSD_MAIN_OPTS
+ POPT_TABLEEND
+ };
+
+ /* Set debug level to invalid value so we can decide if -d 0 was used. */
+ debug_level = SSSDBG_INVALID;
+
+ pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch(opt) {
+ default:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+ }
+ poptFreeContext(pc);
+
+ DEBUG_CLI_INIT(debug_level);
+
+ ret = mkdir(TESTS_PATH, 0775);
+ if (ret != EOK) {
+ fprintf(stderr, "Could not create empty directory [%s]. ", TESTS_PATH);
+ if (errno == EEXIST) {
+ fprintf(stderr, "Please remove [%s].\n", TESTS_PATH);
+ } else {
+ fprintf(stderr, "[%d][%s].\n", errno, strerror(errno));
+ }
+
+ return 1;
+ }
+
+ Suite *s = krb5_utils_suite ();
+ SRunner *sr = srunner_create (s);
+ /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
+ srunner_run_all(sr, CK_ENV);
+ number_failed = srunner_ntests_failed (sr);
+ srunner_free (sr);
+ if (number_failed == 0) {
+ ret = rmdir(TESTS_PATH);
+ if (ret != EOK) {
+ fprintf(stderr, "Cannot remove [%s]: [%d][%s].\n", TESTS_PATH,
+ errno, strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+ }
+
+ return EXIT_FAILURE;
+}