On 05/14/2015 05:10 PM, Jakub Hrozek wrote:
On Thu, May 14, 2015 at 01:55:01PM +0200, Pavel Reichl wrote:
Please see updated patch.
Thanks, this looks much better. I only have some nitpicks now:
From 4f0bd09258e52ae633bc91603e30edf9ce02b279 Mon Sep 17 00:00:00 2001
From: Pavel Reichl <prei...@redhat.com>
Date: Thu, 30 Apr 2015 06:43:05 -0400
Subject: [PATCH] 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
[...]
+ </para>
+ <para>
+ `joe` and `vince` are UNIX user names and `juser`
+ and `rraines` are primaries of kerberos principals.
+ For user `joe` resp. `dick` SSSD will try to kinit
+ as `juser@REALM` resp. `richard@REALM`
Could we use something else than backticks in the XML. Remember we used
XML because it's possible to render other formats than troff, we already
render HTML. Would <quote> be a better choice?
done
+ </para>
+
+ <para>
+ Default: not set
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect1>
[...]
+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;
+ talloc(mem_ctx, int);
huh?
Sorry, but I need more changed lines to stats :-).
fixed
+
+ 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.\n");
+ 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,
+ int size)
Can we use size_t for size?
sure, but it takes input from split_on_separator() which is int, should
I fix split_on_separator() to use size_t instead if int?
+{
+ 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;
+ ret = EOK;
+ goto done;
+ }
I won't block the patch over this but I still don't understand why you
prefer to use the NULL pointer for "an empty mapping" instead of always
allocating the sentinel. I'd argue that using the sentinel would
ultimately make the code easier because you wouldn't have to check for
NULL mapping pointer, but just loop over the mapping array..one less
special case..
done
+
+ 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;
+
+ 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) {
+ if (size == 0) {
+ *_name_to_primary = NULL;
+ } else {
+ *_name_to_primary = talloc_steal(mem_ctx, name_to_primary);
+ }
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel
>From 2b027b7f702bfdc8453e0a4c7096e6943d7141ca Mon Sep 17 00:00:00 2001
From: Pavel Reichl <prei...@redhat.com>
Date: Thu, 30 Apr 2015 06:43:05 -0400
Subject: [PATCH] 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
---
src/config/SSSDConfig/__init__.py.in | 1 +
src/config/SSSDConfigTest.py | 9 ++-
src/config/etc/sssd.api.d/sssd-ad.conf | 1 +
src/config/etc/sssd.api.d/sssd-ipa.conf | 1 +
src/config/etc/sssd.api.d/sssd-krb5.conf | 1 +
src/man/sssd-krb5.5.xml | 36 ++++++++++
src/providers/ad/ad_opts.h | 1 +
src/providers/ipa/ipa_opts.h | 1 +
src/providers/krb5/krb5_access.c | 5 +-
src/providers/krb5/krb5_auth.c | 55 +++++++++++++--
src/providers/krb5/krb5_auth.h | 2 +
src/providers/krb5/krb5_common.h | 8 +++
src/providers/krb5/krb5_init_shared.c | 11 +++
src/providers/krb5/krb5_opts.h | 1 +
src/providers/krb5/krb5_utils.c | 110 ++++++++++++++++++++++++++++++
src/providers/krb5/krb5_utils.h | 5 ++
src/tests/krb5_utils-tests.c | 112 +++++++++++++++++++++++++++++++
17 files changed, 349 insertions(+), 11 deletions(-)
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 31c9c648045f1e2b031c6f9b2196b44e9c4c4313..f58c52faf7dd3f9199bd0af4286546d4fe804a88 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -215,6 +215,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 db16bc433cf4c47c6a15760d85b322a6655aa0c1..476e30806ceda64b14d25f5545a63785efaacf15 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -622,7 +622,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()
@@ -782,7 +783,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")
@@ -983,7 +985,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 5a5ea0c36b07d7497c1caa4208c7270d6de6dcc9..c46f3a7cb50db519d113e15f425c7f746d34ad81 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 230bdd7df3e7512eab9096c136624cdd7923ed96..6bae609fa9ff57e70c195b858eeea4eca680f62f 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 e65ed01b688078aff090ff53b91779595fd6f465..b7423b74f7b6845d235cc523a8e249d6a74d69ab 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 8d5bbeed6ce6ec6bcb2db09895ca045905338639..eee6dfbdf9f8ae75b6b20d8f3d3cf21d7e38971f 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>vince</quote> are
+ UNIX user names and <quote>juser</quote> and
+ <quote>rraines</quote> are primaries of kerberos
+ principals. For user <quote>joe</quote> resp.
+ <quote>dick</quote> SSSD will try to kinit as
+ <quote>dick@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 15b140434fec815aeee989e24cc1b7930f040add..6e859447f927ef683d53bf08d25d658764581348 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 8a0764265521e86ca86249e4b62f0f967bc44189..34e9e167eb46f290d017b5af817571122b359b4f 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -310,6 +310,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 7fda2a37922a537f7fe53d629c4e0cb4df1bd4da..6e9ebd4e0c76e96c38078c5b41d2ed55d584c710 100644
--- a/src/providers/krb5/krb5_access.c
+++ b/src/providers/krb5/krb5_access.c
@@ -105,9 +105,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 148b08fdf860e92d00be0582eb73a822113f3880..a488867bf3c92741f99d711db3abd7eb1c4361dd 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,44 @@ 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, 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) {
+ ret = sss_utf8_case_eq((const uint8_t*)name_to_primary[i].id_name,
+ (const uint8_t*)id_prov_name);
+ if (ret == EOK) {
+ *_krb_primary = name_to_primary[i].krb_primary;
+ 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 krb5child_req *kr = NULL;
+ const char *mapped_name;
+ errno_t ret;
kr = talloc_zero(mem_ctx, struct krb5child_req);
if (kr == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
kr->is_offline = false;
talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
@@ -191,9 +221,25 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
kr->pd = pd;
kr->krb5_ctx = krb5_ctx;
+ ret = get_krb_primary(krb5_ctx->name_to_primary,
+ pd->user, &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;
+ }
+
*krb5_req = kr;
+ ret = EOK;
- return EOK;
+done:
+ return ret;
}
@@ -535,9 +581,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 c9325291627c40e509dc804714b662942fb1d07a..509e08375688b10d4a0c99311d454ec4a028a571 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -55,6 +55,8 @@ struct krb5child_req {
bool valid_tgt;
bool upn_from_different_realm;
bool send_pac;
+
+ const char *user;
};
errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 81e64688a6d93a4b3ecf41d75d1bf6166b4619ce..8f6fb229ac2ecf83ceec67d3b0817ddd57b93543 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 3b4bf096ef49d0f2d369fda20462b7fd56d61127..767291c0b953ea3f227f64a7e21f191262424cf5 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 db62cc3b23d8a5eadd3df97a102fb84128b740da..50d701b8ba431719dbf67799230ec345cdee30a9 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 de2d94503744b80b0a3365efb227cd05434579ff..976c26819a7356eab89034b269a0f79cda13a743 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -465,3 +465,113 @@ 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.\n");
+ 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;
+
+ 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 0155905b5bc7469d09aecbd51cae0e8cc61b3952..75b93c30ef5be5d16f2ce73f44abef674c6e98ff 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 409c0f01d2cce9c24a648306007b9fa7f5bc8372..59a1b1ff8969076161a0f1abf6176c241267d3b6 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,116 @@ 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 +723,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;
--
2.1.0
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel