summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Reichl <preichl@redhat.com>2015-04-30 06:43:05 -0400
committerJakub Hrozek <jhrozek@redhat.com>2015-05-28 11:24:21 +0200
commitc494e100f9b2422e2890507f63019afcaff9b7c6 (patch)
tree94fdfcc88f25273b85f3aaf934522920b298ad4d
parentd788ec2d8205639dcb560800852d7fe89bcc33f7 (diff)
downloadsssd-c494e100f9b2422e2890507f63019afcaff9b7c6.tar.gz
sssd-c494e100f9b2422e2890507f63019afcaff9b7c6.tar.xz
sssd-c494e100f9b2422e2890507f63019afcaff9b7c6.zip
krb5: new option krb5_map_user
New option `krb5_map_user` providing mapping of ID provider names to Kerberos principals. Resolves: https://fedorahosted.org/sssd/ticket/2509 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/config/SSSDConfig/__init__.py.in1
-rwxr-xr-xsrc/config/SSSDConfigTest.py9
-rw-r--r--src/config/etc/sssd.api.d/sssd-ad.conf1
-rw-r--r--src/config/etc/sssd.api.d/sssd-ipa.conf1
-rw-r--r--src/config/etc/sssd.api.d/sssd-krb5.conf1
-rw-r--r--src/man/sssd-krb5.5.xml36
-rw-r--r--src/providers/ad/ad_opts.h1
-rw-r--r--src/providers/ipa/ipa_opts.h1
-rw-r--r--src/providers/krb5/krb5_access.c8
-rw-r--r--src/providers/krb5/krb5_auth.c76
-rw-r--r--src/providers/krb5/krb5_auth.h5
-rw-r--r--src/providers/krb5/krb5_common.h8
-rw-r--r--src/providers/krb5/krb5_init_shared.c11
-rw-r--r--src/providers/krb5/krb5_opts.h1
-rw-r--r--src/providers/krb5/krb5_utils.c114
-rw-r--r--src/providers/krb5/krb5_utils.h5
-rw-r--r--src/tests/krb5_utils-tests.c111
17 files changed, 372 insertions, 18 deletions
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index dbbffebf3..1d4b9c2cc 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -216,6 +216,7 @@ option_strings = {
'krb5_fast_principal' : _("Selects the principal to use for FAST"),
'krb5_canonicalize' : _("Enables principal canonicalization"),
'krb5_use_enterprise_principal' : _("Enables enterprise principals"),
+ 'krb5_map_user' : _('A mapping from user names to kerberos principal names'),
# [provider/krb5/chpass]
'krb5_kpasswd' : _('Server where the change password service is running if not on the KDC'),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 3a5312ea9..87ee2b5f7 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -621,7 +621,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'krb5_fast_principal',
'krb5_canonicalize',
'krb5_use_enterprise_principal',
- 'krb5_use_kdcinfo'])
+ 'krb5_use_kdcinfo',
+ 'krb5_map_user'])
options = domain.list_options()
@@ -781,7 +782,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'krb5_fast_principal',
'krb5_canonicalize',
'krb5_use_enterprise_principal',
- 'krb5_use_kdcinfo']
+ 'krb5_use_kdcinfo',
+ 'krb5_map_user']
self.assertTrue(type(options) == dict,
"Options should be a dictionary")
@@ -981,7 +983,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'krb5_fast_principal',
'krb5_canonicalize',
'krb5_use_enterprise_principal',
- 'krb5_use_kdcinfo'])
+ 'krb5_use_kdcinfo',
+ 'krb5_map_user'])
options = domain.list_options()
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index 5a5ea0c36..c46f3a7cb 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -139,6 +139,7 @@ krb5_renew_interval = str, None, false
krb5_use_fast = str, None, false
krb5_fast_principal = str, None, false
krb5_use_enterprise_principal = bool, None, false
+krb5_map_user = str, None, false
[provider/ad/access]
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 2a3b7ef15..d9ab673f2 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -155,6 +155,7 @@ krb5_renew_interval = str, None, false
krb5_use_fast = str, None, false
krb5_fast_principal = str, None, false
krb5_use_enterprise_principal = bool, None, false
+krb5_map_user = str, None, false
[provider/ipa/access]
ipa_hbac_refresh = int, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-krb5.conf b/src/config/etc/sssd.api.d/sssd-krb5.conf
index e65ed01b6..b7423b74f 100644
--- a/src/config/etc/sssd.api.d/sssd-krb5.conf
+++ b/src/config/etc/sssd.api.d/sssd-krb5.conf
@@ -21,6 +21,7 @@ krb5_use_fast = str, None, false
krb5_fast_principal = str, None, false
krb5_canonicalize = bool, None, false
krb5_use_enterprise_principal = bool, None, false
+krb5_map_user = str, None, false
[provider/krb5/access]
diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index 9f61f8f70..da62b2507 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -516,6 +516,42 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>krb5_map_user (string)</term>
+ <listitem>
+ <para>
+ The list of mappings is given as a comma-separated
+ list of pairs <quote>username:primary</quote>
+ where <quote>username</quote> is a UNIX user name
+ and <quote>primary</quote> is a user part of
+ a kerberos principal. This mapping is used when
+ user is authenticating using
+ <quote>auth_provider = krb5</quote>.
+ </para>
+
+ <para>
+ example:
+<programlisting>
+krb5_realm = REALM
+krb5_map_user = joe:juser,dick:richard
+</programlisting>
+ </para>
+ <para>
+ <quote>joe</quote> and <quote>dick</quote> are
+ UNIX user names and <quote>juser</quote> and
+ <quote>richard</quote> are primaries of kerberos
+ principals. For user <quote>joe</quote> resp.
+ <quote>dick</quote> SSSD will try to kinit as
+ <quote>juser@REALM</quote> resp.
+ <quote>richard@REALM</quote>.
+ </para>
+
+ <para>
+ Default: not set
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect1>
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index f4c1c523b..4c287021c 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -168,6 +168,7 @@ struct dp_option ad_def_krb5_opts[] = {
{ "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
{ "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 66af64858..5ce47c31e 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -311,6 +311,7 @@ struct dp_option ipa_def_krb5_opts[] = {
{ "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
{ "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/krb5/krb5_access.c b/src/providers/krb5/krb5_access.c
index 7fda2a379..3afb90150 100644
--- a/src/providers/krb5/krb5_access.c
+++ b/src/providers/krb5/krb5_access.c
@@ -64,7 +64,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx,
state->krb5_ctx = krb5_ctx;
state->access_allowed = false;
- ret = krb5_setup(state, pd, krb5_ctx, &state->kr);
+ ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive,
+ &state->kr);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n");
goto done;
@@ -105,9 +106,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx,
goto done;
break;
case 1:
- ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx,
- be_ctx->domain, pd->user, pd->domain,
- &state->kr->upn);
+ ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, be_ctx->domain,
+ state->kr->user, pd->domain, &state->kr->upn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "find_or_guess_upn failed.\n");
goto done;
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 25caf7b78..9f136041e 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -36,6 +36,7 @@
#include "util/find_uid.h"
#include "util/auth_utils.h"
#include "db/sysdb.h"
+#include "util/sss_utf8.h"
#include "util/child_common.h"
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
@@ -175,15 +176,51 @@ static int krb5_cleanup(void *ptr)
return EOK;
}
+static errno_t
+get_krb_primary(struct map_id_name_to_krb_primary *name_to_primary,
+ char *id_prov_name, bool cs, const char **_krb_primary)
+{
+ errno_t ret;
+ int i = 0;
+
+ while(name_to_primary != NULL &&
+ name_to_primary[i].id_name != NULL &&
+ name_to_primary[i].krb_primary != NULL) {
+
+ if (sss_string_equal(cs, name_to_primary[i].id_name, id_prov_name)) {
+ *_krb_primary = name_to_primary[i].krb_primary;
+ ret = EOK;
+ goto done;
+ }
+ i++;
+ }
+
+ /* Handle also the case of name_to_primary being NULL */
+ ret = ENOENT;
+
+done:
+ return ret;
+}
+
errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
- struct krb5_ctx *krb5_ctx, struct krb5child_req **krb5_req)
+ struct krb5_ctx *krb5_ctx, bool cs,
+ struct krb5child_req **_krb5_req)
{
- struct krb5child_req *kr = NULL;
+ struct krb5child_req *kr;
+ const char *mapped_name;
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
- kr = talloc_zero(mem_ctx, struct krb5child_req);
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ kr = talloc_zero(tmp_ctx, struct krb5child_req);
if (kr == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
kr->is_offline = false;
kr->run_as_user = true;
@@ -192,9 +229,28 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
kr->pd = pd;
kr->krb5_ctx = krb5_ctx;
- *krb5_req = kr;
+ ret = get_krb_primary(krb5_ctx->name_to_primary,
+ pd->user, cs, &mapped_name);
+ if (ret == EOK) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Setting mapped name to: %s\n", mapped_name);
+ kr->user = mapped_name;
+ } else if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_ALL, "No mapping for: %s\n", pd->user);
+ kr->user = pd->user;
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "get_krb_primary failed - %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ }
- return EOK;
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ *_krb5_req = talloc_steal(mem_ctx, kr);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
}
@@ -476,7 +532,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
attrs[6] = SYSDB_AUTH_TYPE;
attrs[7] = NULL;
- ret = krb5_setup(state, pd, krb5_ctx, &state->kr);
+ ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive,
+ &state->kr);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n");
goto done;
@@ -509,9 +566,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
break;
case 1:
- ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx,
- be_ctx->domain, pd->user, pd->domain,
- &kr->upn);
+ ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, be_ctx->domain,
+ kr->user, pd->domain, &kr->upn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "find_or_guess_upn failed.\n");
goto done;
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index 00cb658c4..e9f8f4580 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -56,10 +56,13 @@ struct krb5child_req {
bool run_as_user;
bool upn_from_different_realm;
bool send_pac;
+
+ const char *user;
};
errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
- struct krb5_ctx *krb5_ctx, struct krb5child_req **krb5_req);
+ struct krb5_ctx *krb5_ctx, bool case_sensitive,
+ struct krb5child_req **krb5_req);
void krb5_pam_handler(struct be_req *be_req);
void krb5_pam_handler_auth_done(struct tevent_req *req);
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 81e64688a..8f6fb229a 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -67,6 +67,7 @@ enum krb5_opts {
KRB5_CANONICALIZE,
KRB5_USE_ENTERPRISE_PRINCIPAL,
KRB5_USE_KDCINFO,
+ KRB5_MAP_USER,
KRB5_OPTS
};
@@ -89,6 +90,11 @@ enum krb5_config_type {
K5C_IPA_SERVER
};
+struct map_id_name_to_krb_primary {
+ const char *id_name;
+ const char* krb_primary;
+};
+
struct krb5_ctx {
/* opts taken from kinit */
/* in seconds */
@@ -128,6 +134,8 @@ struct krb5_ctx {
hash_table_t *wait_queue_hash;
enum krb5_config_type config_type;
+
+ struct map_id_name_to_krb_primary *name_to_primary;
};
struct remove_info_files_ctx {
diff --git a/src/providers/krb5/krb5_init_shared.c b/src/providers/krb5/krb5_init_shared.c
index 3b4bf096e..767291c0b 100644
--- a/src/providers/krb5/krb5_init_shared.c
+++ b/src/providers/krb5/krb5_init_shared.c
@@ -24,6 +24,7 @@
#include "providers/krb5/krb5_common.h"
#include "providers/krb5/krb5_auth.h"
+#include "providers/krb5/krb5_utils.h"
#include "providers/krb5/krb5_init_shared.h"
errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
@@ -90,6 +91,16 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
goto done;
}
+ ret = parse_krb5_map_user(krb5_auth_ctx,
+ dp_opt_get_cstring(krb5_auth_ctx->opts,
+ KRB5_MAP_USER),
+ &krb5_auth_ctx->name_to_primary);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "parse_krb5_map_user failed: %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ }
+
ret = EOK;
done:
diff --git a/src/providers/krb5/krb5_opts.h b/src/providers/krb5/krb5_opts.h
index db62cc3b2..50d701b8b 100644
--- a/src/providers/krb5/krb5_opts.h
+++ b/src/providers/krb5/krb5_opts.h
@@ -45,6 +45,7 @@ struct dp_option default_krb5_opts[] = {
{ "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
{ "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+ { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
DP_OPTION_TERMINATOR
};
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index de2d94503..0b73880ec 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -465,3 +465,117 @@ errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
return EOK;
}
+
+static errno_t split_tuple(TALLOC_CTX *mem_ctx, const char *tuple,
+ const char **_first, const char **_second)
+{
+ errno_t ret;
+ char **list;
+ int n;
+
+ ret = split_on_separator(mem_ctx, tuple, ':', true, true, &list, &n);
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "split_on_separator failed - %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ } else if (n != 2) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "split_on_separator failed - Expected format is: "
+ "'username:primary' but got: '%s'.\n", tuple);
+ ret = EINVAL;
+ goto done;
+ }
+
+ *_first = list[0];
+ *_second = list[1];
+
+done:
+ return ret;
+}
+
+static errno_t
+fill_name_to_primary_map(TALLOC_CTX *mem_ctx, char **map,
+ struct map_id_name_to_krb_primary *name_to_primary,
+ size_t size)
+{
+ int i;
+ errno_t ret;
+
+ for (i = 0; i < size; i++) {
+ ret = split_tuple(mem_ctx, map[i],
+ &name_to_primary[i].id_name,
+ &name_to_primary[i].krb_primary);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "split_tuple failed - %s:[%d]\n", sss_strerror(ret), ret);
+ goto done;
+ }
+ }
+
+ ret = EOK;
+
+done:
+ return ret;
+}
+
+errno_t
+parse_krb5_map_user(TALLOC_CTX *mem_ctx, const char *krb5_map_user,
+ struct map_id_name_to_krb_primary **_name_to_primary)
+{
+ int size;
+ char **map;
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ struct map_id_name_to_krb_primary *name_to_primary;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (krb5_map_user == NULL || strlen(krb5_map_user) == 0) {
+ DEBUG(SSSDBG_FUNC_DATA, "Warning: krb5_map_user is empty!\n");
+ size = 0;
+ } else {
+ ret = split_on_separator(tmp_ctx, krb5_map_user, ',', true, true,
+ &map, &size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to parse krb5_map_user!\n");
+ goto done;
+ }
+ }
+
+ name_to_primary = talloc_zero_array(tmp_ctx,
+ struct map_id_name_to_krb_primary,
+ size + 1);
+ if (name_to_primary == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ /* sentinel */
+ name_to_primary[size].id_name = NULL;
+ name_to_primary[size].krb_primary = NULL;
+
+ if (size > 0) {
+ ret = fill_name_to_primary_map(name_to_primary, map, name_to_primary,
+ size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "fill_name_to_primary_map failed: %s:[%d]\n",
+ sss_strerror(ret), ret);
+ goto done;
+ }
+ }
+
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ *_name_to_primary = talloc_steal(mem_ctx, name_to_primary);
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
index 0155905b5..75b93c30e 100644
--- a/src/providers/krb5/krb5_utils.h
+++ b/src/providers/krb5/krb5_utils.h
@@ -49,4 +49,9 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
char *domain_name,
struct sss_domain_info **dom);
+
+errno_t
+parse_krb5_map_user(TALLOC_CTX *mem_ctx, const char *krb5_map_user,
+ struct map_id_name_to_krb_primary **_name_to_primary);
+
#endif /* __KRB5_UTILS_H__ */
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
index 409c0f01d..650ed4859 100644
--- a/src/tests/krb5_utils-tests.c
+++ b/src/tests/krb5_utils-tests.c
@@ -29,6 +29,7 @@
#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 "tests_krb5_utils"
@@ -574,6 +575,115 @@ START_TEST(test_compare_principal_realm)
}
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) {
+ fail_unless(i < len);
+ ret = sss_utf8_case_eq((const uint8_t*)a[i].id_name,
+ (const uint8_t*)str[i*2]);
+ fail_unless(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]);
+ fail_unless(ret == EOK, "%s does not match %s",
+ a[i].krb_primary, str[i*2+1]);
+ i++;
+ }
+ fail_unless(len == i, "%u != %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, &name_to_primary);
+ fail_unless(ret == EOK);
+ fail_unless(name_to_primary[0].id_name == NULL &&
+ name_to_primary[0].krb_primary == NULL);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, "", &name_to_primary);
+ fail_unless(ret == EOK);
+ fail_unless(name_to_primary[0].id_name == NULL &&
+ name_to_primary[0].krb_primary == NULL);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, ",", &name_to_primary);
+ fail_unless(ret == EOK);
+ fail_unless(name_to_primary[0].id_name == NULL &&
+ name_to_primary[0].krb_primary == NULL);
+ talloc_free(name_to_primary);
+
+ ret = parse_krb5_map_user(mem_ctx, ",,", &name_to_primary);
+ fail_unless(ret == EOK);
+ fail_unless(name_to_primary[0].id_name == NULL &&
+ name_to_primary[0].krb_primary == NULL);
+ talloc_free(name_to_primary);
+
+ check_leaks_pop(mem_ctx);
+ }
+ /* 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", "preichl", "joe", "juser", "jdoe", "ßlack"};
+ ret = parse_krb5_map_user(mem_ctx, p, &name_to_primary);
+ fail_unless(ret == EOK);
+ 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, &name_to_primary);
+ fail_unless(ret == EOK);
+ compare_map_id_name_to_krb_primary(name_to_primary, expected,
+ sizeof(expected)/sizeof(const char*)/2);
+ talloc_free(name_to_primary);
+ check_leaks_pop(mem_ctx);
+ }
+ /* invalid input */
+ {
+ check_leaks_push(mem_ctx);
+
+ ret = parse_krb5_map_user(mem_ctx, ":", &name_to_primary);
+ fail_unless(ret == EINVAL);
+
+ ret = parse_krb5_map_user(mem_ctx, "joe:", &name_to_primary);
+ fail_unless(ret == EINVAL);
+
+ ret = parse_krb5_map_user(mem_ctx, ":joe", &name_to_primary);
+ fail_unless(ret == EINVAL);
+
+ ret = parse_krb5_map_user(mem_ctx, "joe:,", &name_to_primary);
+ fail_unless(ret == EINVAL);
+
+ ret = parse_krb5_map_user(mem_ctx, ",joe", &name_to_primary);
+ fail_unless(ret == EINVAL);
+
+ ret = parse_krb5_map_user(mem_ctx, "joe:j:user", &name_to_primary);
+ fail_unless(ret == EINVAL);
+
+ check_leaks_pop(mem_ctx);
+ }
+
+ talloc_free(mem_ctx);
+}
+END_TEST
+
Suite *krb5_utils_suite (void)
{
Suite *s = suite_create ("krb5_utils");
@@ -612,6 +722,7 @@ Suite *krb5_utils_suite (void)
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);
suite_add_tcase(s, tc_krb5_helpers);
return s;