On 05/26/2015 04:22 PM, Jakub Hrozek wrote:
On Tue, May 26, 2015 at 03:39:20PM +0200, Pavel Reichl wrote:
On 05/26/2015 03:09 PM, Jakub Hrozek wrote:
On Tue, May 26, 2015 at 11:13:38AM +0200, Jakub Hrozek wrote:
I'll test the patch now..
Functionality passed:
[jhrozek@client] sssd $ [(review)] su - jhrozek
Password: (I used the IPA admin password here)
[jhrozek@client] ~ $ [] klist
Ticket cache: KEYRING:persistent:1000:krb_ccache_tovv73R
Default principal: ad...@linux.test
Valid starting Expires Service principal
05/26/2015 15:07:31 05/27/2015 15:07:31 krbtgt/linux.t...@linux.test
So fix the nitpicks and I'll ack :-)
Great, thanks.
Please see attached patch. I'm completely sure that I've absolutely sorted
out the nitpicks...unless I've made them even worse. :-)
I think that the coverity warning was false positive, because the map value
would never be read when uninitialized, but to get rid of the warning I
added a check and call the function conditionally. Would you prefer If I
rather initialized the variable?
This is fine.
I found one typo in manpage (sorry..), the rest looks good to me now. I
tested proxy user, IPA user and AD trust user, all worked fine.
Sorry for missing that. Fixed.
I'm happy that testing passed.
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel
From 81473f2441dcdfb3c04864414d9bb30a20a2740d 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
[...]
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>.
The example gives joe and dick but the text talks about joe and vince.
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel
>From 923e68ba56f276db473a38fffe339a0dc9770a4f 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 | 8 +--
src/providers/krb5/krb5_auth.c | 76 ++++++++++++++++++---
src/providers/krb5/krb5_auth.h | 5 +-
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 | 114 +++++++++++++++++++++++++++++++
src/providers/krb5/krb5_utils.h | 5 ++
src/tests/krb5_utils-tests.c | 111 ++++++++++++++++++++++++++++++
17 files changed, 372 insertions(+), 18 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..3d3c58cf6dfbd31c76d7a88e0ec849c10e15fe76 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>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..3afb90150d77ef4ab2c1b5b79abb95d68eb131f6 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 148b08fdf860e92d00be0582eb73a822113f3880..8c851442b31994f819f33722bb67d19bb01e4b77 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;
talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
@@ -191,9 +228,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;
}
@@ -502,7 +558,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;
@@ -535,9 +592,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..a00f1d9d9be38453da11c9e64ab73fe23f67d475 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -55,10 +55,13 @@ 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,
- 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 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..0b73880eca6015fc9dffa4a850b230afc5dfddfc 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 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..650ed48592768c214156d5274e654a447be98e36 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;
--
2.1.0
_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel