now with patches ...
On Tue, Jul 26, 2016 at 04:55:37PM +0200, Sumit Bose wrote:
> On Tue, Jul 26, 2016 at 11:12:34AM +0200, Jakub Hrozek wrote:
> > On Fri, Jul 22, 2016 at 09:44:33PM +0200, Sumit Bose wrote:
> > > Hi,
> > >
> > > this patch set should fix https://fedorahosted.org/sssd/ticket/2958
> > > "Support multiple principals for IPA users" so the IPA users can log in
> > > with their Kerberos alias as well.
> >
> > First, thank you very much for splitting the patchset into small
> > self-contained changes. The review was much easier this way.
> >
> > >
> > > The overall code-path was already added for the UPN feature but had to
> > > be extended at various places. The main difference is that the realm
> > > part of the AD UPNs with an alternative domain suffix do not related to
> > > a known domain name. The realm part from the Kerberos aliases can come
> > > from any domain. The same is true for email addresses which are supported
> > > by this patch set as well.
> >
> > I wonder if we will immediatelly get a request to provide a list of
> > e-mail domain suffixes by the users that could be used to map the e-mail
> > address to a domain. Do you think it would make sense (maybe in a future
> > patch) to let the admin configure the suffixes for direct integration in
> > sssd.conf and maybe on the server for IPA-AD trusts?
>
> It might help in some cases, but I think in general it will not help
> much. Email domain suffixes as e.g. AD's alternative domain suffixes are
> typically used for a whole organization/forest so I would expect that
> the cases where you have multiple domains and a single email domain
> suffix relates only to a specific domain and is not equal to the domain
> name is rare.
>
> What might help more (and would help lookup by id as well) is to reorder
> the lookups in the responders to check the cache for all domains first
> before iterating over the backends. I think we already have a ticket for
> this.
>
> >
> > >
> > > I know that Jakub had some concerns adding email addresses now and the
> > > another attribute in the next version and so on. I would like to make
> > > this scheme more generic so that the attributes which should be used for
> > > login names can be configured. Unfortunately I didn't had the time do
> > > already do it in this patch-set.
> >
> > np, I think the patches are well structured and make the extension
> > possible.
> >
> > >
> > > Adding a larger number of sources for the login name increases the
> > > chance for collisions. But since each of the name types, Kerberos
> > > principals and email addresses, are expected to be unique in their
> > > domain, I hope the chances are still low enough.
> >
> > Yes.
> >
> > >
> > > bye,
> > > Sumit
> >
> > > From b2012e5b0cc8af65f18a6e48774b80246c68c04a Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Fri, 22 Jul 2016 17:35:43 +0200
> > > Subject: [PATCH 01/14] IPA: fix lookup by UPN for subdomains
> > >
> > > Currently the user name used in the extdom exop request is
> > > unconditionally set to the short name. While this is correct for the
> > > general name based lookups it breaks UPN/email based lookups where the
> > > name part after the @-sign might not match to domain name. I guess this
> > > was introduce during the sysdb refactoring.
> >
> > Yes, it was. Sorry about that. I tested UPN lookups on an IPA-AD trust
> > client and they work fine with this patch.
> >
> > ACK
> >
> > > From 762cd84cc5851666607c871d53f4e309b8760f6c Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Fri, 22 Jul 2016 12:19:26 +0200
> > > Subject: [PATCH 02/14] LDAP: allow multiple user principals
> > >
> > > In general a user can have multiple principals and recent IPA version
> > > added support to defined multiple principals. With this patch SSSD does
> > > not only store the first but all principals read by LDAP from a server.
> > >
> > > Resolves https://fedorahosted.org/sssd/ticket/2958
> >
> > ACK
> >
> >
> > > From 5c1a50ef35d816438880e4e9951d0355b283980f Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Sat, 18 Jun 2016 18:24:50 +0200
> > > Subject: [PATCH 03/14] LDAP: new attribute option ldap_user_email
> >
> > ACK
> >
> > > From 3f09cfc6598d34ff42be1c85f448b5c0635410e0 Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Mon, 20 Jun 2016 12:57:43 +0200
> > > Subject: [PATCH 04/14] sysdb: include email in UPN searches
> >
> > ACK just one question..
> >
> > >
> > > Email addresses and Kerberos user principals names (UPNs) do not only
> > > look similar they also can be used to identify a user uniquely.
> > >
> > > In future this approach should be replace by a more generic one where
> > > the attributes which can uniquely identifies a user can be configured to
> > > support even a wider range of login names.
> >
> > ..I think we want to track this with a ticket (even if it was deferred
> > now). If you agree I can file one.
>
> yes, please.
>
> >
> > > From 6ac7dacf122da2933ce6fe9b2ceff356c1b65721 Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Mon, 20 Jun 2016 12:58:16 +0200
> > > Subject: [PATCH 05/14] LDAP: include email in UPN searches
> >
> > ACK
> >
> > > From b3c9c37baa49ade82f8cf873a2e0d2e0e7e16fad Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Mon, 20 Jun 2016 13:37:56 +0200
> > > Subject: [PATCH 06/14] NSS: add user email to fill_orig()
> > >
> > > The IPA server must send the email address of a user to the clients to
> > > allow login by email.
> >
> > ACK
> >
> > > From 88118645466c50c52a81e5ff38d66ecb2dfda2a7 Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Mon, 20 Jun 2016 16:11:11 +0200
> > > Subject: [PATCH 07/14] utils: add is_email_from_domain()
> >
> > ACK
> >
> > > From 72fb323490acc4155227b56be6470965830b7ade Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Mon, 20 Jun 2016 16:30:03 +0200
> > > Subject: [PATCH 08/14] LDAP/IPA: add local email address to aliases
> > >
> > > Adding email-addresses from the local domain to the alias names is
> > > strictly not needed by might help to speed up lookups in the NSS
> > > responder.
> >
> > ACK, this makes sense, the aliases are indexed.
> >
> > > From 0f2863a0fb1620bf86ffb828e0c51ead4f807b2a Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Tue, 21 Jun 2016 11:06:19 +0200
> > > Subject: [PATCH 09/14] NSS: continue with UPN/email search if name was not
> > > found
> > >
> > > Currently we only search for UPNs if the domain part of the name was not
> > > know, with Kerberos aliases and email addresses we have to do this even
> > > if the domain name is a know domain.
> >
> > ACK
> >
> > > From 84813abfb71dc23ad054c42af0e3d2eba1e74e7e Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Wed, 22 Jun 2016 18:21:11 +0200
> > > Subject: [PATCH 10/14] PAM: continue with UPN/email search if name was not
> > > found
> > >
> > > Currently we only search for UPNs if the domain part of the name was not
> > > know, with Kerberos aliases and email addresses we have to do this even
> > > if the domain name is a know domain.
> >
> > ACK
> >
> > > From bccc06776316459ec10c8103465664df2433f260 Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Fri, 22 Jul 2016 17:34:20 +0200
> > > Subject: [PATCH 12/14] PAM: Fix domain for UPN based lookups
> > >
> > > Since sysdb_search_user_by_upn() searches the whole cache we have to set
> > > the domain so that it matches the result.
> >
> > ACK, we already have a matching commit in NSS
> >
> > > From c132fa210341b30ec4586c0bb951ffb1dc6feb94 Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Fri, 22 Jul 2016 12:20:33 +0200
> > > Subject: [PATCH 13/14] SDAP: add special handling for IPA Kerberos
> > > enterprise
> > > principal strings
> > >
> > > Unfortunately principal aliases with an alternative realm are stored in
> > > IPA as the string representation of an enterprise principal, i.e.
> > > name\@[email protected]. To allow searches with the plain alias
> > > '[email protected]' the returned value is converted before it is saved to
> > > the cache.
> >
> > ACK
> >
> > > From 3b4deb7deb64136094aa5e70705b467a836dd05b Mon Sep 17 00:00:00 2001
> > > From: Sumit Bose <[email protected]>
> > > Date: Fri, 22 Jul 2016 20:10:42 +0200
> > > Subject: [PATCH 14/14] SDAP: add enterprise principal strings for user
> > > searches
> > >
> > > Unfortunately principal aliases with an alternative realm are stored in
> > > IPA as the string representation of an enterprise principal, i.e.
> > > name\@[email protected]. To be able to lookup the alternative
> > > principal in LDAP properly the UPN search filter is extended to search
> > > for this type of name as well.
> >
> > There is a warning:
> > CC src/tests/cmocka/nestedgroups_tests-common_mock_sdap.o
> > /home/remote/jhrozek/devel/sssd/src/providers/ldap/sdap_utils.c: In
> > function ‘get_enterprise_principal_string_filter’:
> > /home/remote/jhrozek/devel/sssd/src/providers/ldap/sdap_utils.c:254:37:
> > warning: field precision specifier ‘.*’ expects argument of type ‘int’, but
> > argument 4 has type ‘long int’ [-Wformat=]
> > return talloc_asprintf(mem_ctx, "(%s=%.*s\\\\@%s@%s)", attr_name,
> > ^
> >
> > But the intent of the code looks good to me.
>
> I fixed this with a cast, I hope this is sufficient to silence the
> warning.
>
> New version which fixes the Coverity warning as well is attached.
>
> bye,
> Sumit
>
> > _______________________________________________
> > sssd-devel mailing list
> > [email protected]
> > https://lists.fedorahosted.org/admin/lists/[email protected]
From 68ba178cd17950e9a681e87386ed31a370bcf52f Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 22 Jul 2016 17:35:43 +0200
Subject: [PATCH 01/14] IPA: fix lookup by UPN for subdomains
Currently the user name used in the extdom exop request is
unconditionally set to the short name. While this is correct for the
general name based lookups it breaks UPN/email based lookups where the
name part after the @-sign might not match to domain name. I guess this
was introduce during the sysdb refactoring.
---
src/providers/ipa/ipa_subdomains_id.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/providers/ipa/ipa_subdomains_id.c
b/src/providers/ipa/ipa_subdomains_id.c
index
0a89ef5a68802fb7d5f9faeb9ef1d9f9cf8d14f2..4a237ca4e2878e0972f7bd884f81cda0317a6fb9
100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -344,6 +344,7 @@ struct ipa_get_subdom_acct {
int entry_type;
const char *filter;
int filter_type;
+ const char *extra_value;
bool use_pac;
struct ldb_message *user_msg;
@@ -393,6 +394,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX
*memctx,
state->entry_type = (ar->entry_type & BE_REQ_TYPE_MASK);
state->filter = ar->filter_value;
state->filter_type = ar->filter_type;
+ state->extra_value = ar->extra_value;
switch (state->entry_type) {
case BE_REQ_USER:
@@ -499,10 +501,16 @@ static void ipa_get_subdom_acct_connected(struct
tevent_req *subreq)
switch (state->filter_type) {
case BE_FILTER_NAME:
req_input->type = REQ_INP_NAME;
- /* The extdom plugin expects the shortname and domain separately */
- ret = sss_parse_internal_fqname(req_input, state->filter,
- &shortname, NULL);
- req_input->inp.name = talloc_steal(req_input, shortname);
+ /* The extdom plugin expects the shortname and domain separately,
+ * but for UPN/email lookup we need to send the raw name */
+ if (state->extra_value != NULL
+ && strcmp(state->extra_value, EXTRA_NAME_IS_UPN) == 0) {
+ req_input->inp.name = talloc_strdup(req_input, state->filter);
+ } else {
+ ret = sss_parse_internal_fqname(req_input, state->filter,
+ &shortname, NULL);
+ req_input->inp.name = talloc_steal(req_input, shortname);
+ }
if (req_input->inp.name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
tevent_req_error(req, ENOMEM);
--
2.1.0
From 24cf1b9ccebe0da2ee06246db8a6cd9142550bfe Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 22 Jul 2016 12:19:26 +0200
Subject: [PATCH 02/14] LDAP: allow multiple user principals
In general a user can have multiple principals and recent IPA version
added support to defined multiple principals. With this patch SSSD does
not only store the first but all principals read by LDAP from a server.
Resolves https://fedorahosted.org/sssd/ticket/2958
---
src/providers/ldap/sdap_async_users.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/src/providers/ldap/sdap_async_users.c
b/src/providers/ldap/sdap_async_users.c
index
e44c045b3f8ff6aed33a42cf2919bc01aa41a243..28101a2d8a38f97d09d50a9f7e071a030b4f9719
100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -142,6 +142,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
char *sid_str;
char *dom_sid_str = NULL;
struct sss_domain_info *subdomain;
+ size_t c;
DEBUG(SSSDBG_TRACE_FUNC, "Save user\n");
@@ -440,20 +441,23 @@ int sdap_save_user(TALLOC_CTX *memctx,
DEBUG(SSSDBG_TRACE_FUNC,
"User principal is not available for [%s].\n", user_name);
} else {
- upn = talloc_strdup(user_attrs, (const char*) el->values[0].data);
- if (!upn) {
- ret = ENOMEM;
- goto done;
- }
- if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
- make_realm_upper_case(upn);
- }
- DEBUG(SSSDBG_TRACE_FUNC,
- "Adding user principal [%s] to attributes of [%s].\n",
- upn, user_name);
- ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
- if (ret) {
- goto done;
+ for (c = 0; c < el->num_values; c++) {
+ upn = talloc_strdup(tmpctx, (const char*) el->values[c].data);
+ if (!upn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
+ make_realm_upper_case(upn);
+ }
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Adding user principal [%s] to attributes of [%s].\n",
+ upn, user_name);
+ ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn);
+ if (ret) {
+ goto done;
+ }
}
}
--
2.1.0
From 202d2c96302869f228d7aa14ece81b66f3e13db9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Sat, 18 Jun 2016 18:24:50 +0200
Subject: [PATCH 03/14] LDAP: new attribute option ldap_user_email
---
src/config/SSSDConfig/__init__.py.in | 1 +
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-ldap.conf | 1 +
src/db/sysdb.h | 1 +
src/man/sssd-ldap.5.xml | 13 +++++++++++++
src/providers/ad/ad_opts.c | 1 +
src/providers/ipa/ipa_opts.c | 1 +
src/providers/ldap/ldap_opts.c | 3 +++
src/providers/ldap/sdap.h | 1 +
10 files changed, 24 insertions(+)
diff --git a/src/config/SSSDConfig/__init__.py.in
b/src/config/SSSDConfig/__init__.py.in
index
b5e078d0118a15c10b43fbe050176943ec90e0ee..7856c4c6b2d675b7f7f0f5f2048086044e8fb5ea
100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -325,6 +325,7 @@ option_strings = {
'ldap_user_ssh_public_key' : _('SSH public key attribute'),
'ldap_user_auth_type' : _('attribute listing allowed authentication types
for a user'),
'ldap_user_certificate' : _('attribute containing the X509 certificate of
the user'),
+ 'ldap_user_email' : _('attribute containing the email address of the
user'),
'ldap_user_extra_attrs' : _('A list of extra attributes to download along
with the user entry'),
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf
b/src/config/etc/sssd.api.d/sssd-ad.conf
index
23006d26ca6fe7ca2b912ef091b4c73d5d23bee1..87a74f4af0770874c71baaea02d2313721db78bf
100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -98,6 +98,7 @@ ldap_pwd_attribute = str, None, false
ldap_user_ssh_public_key = str, None, false
ldap_user_auth_type = str, None, false
ldap_user_certificate = str, None, false
+ldap_user_email = str, None, false
ldap_group_search_base = str, None, false
ldap_group_search_scope = str, None, false
ldap_group_search_filter = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf
b/src/config/etc/sssd.api.d/sssd-ipa.conf
index
67a46102b4e8dfff2b44b21ac18c0ad8822d7f3a..88da36ef4a0a067530dfd44b7a231f4f74c800f2
100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -92,6 +92,7 @@ ldap_pwd_attribute = str, None, false
ldap_user_ssh_public_key = str, None, false
ldap_user_auth_type = str, None, false
ldap_user_certificate = str, None, false
+ldap_user_email = str, None, false
ldap_group_search_base = str, None, false
ldap_group_search_scope = str, None, false
ldap_group_search_filter = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf
b/src/config/etc/sssd.api.d/sssd-ldap.conf
index
8b52f268af195bc68d45389cda52a0ad0aba1aa3..c2ad3463d26cd73b8146604c8060224449421fe6
100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -86,6 +86,7 @@ ldap_user_nds_login_allowed_time_map = str, None, false
ldap_user_ssh_public_key = str, None, false
ldap_user_auth_type = str, None, false
ldap_user_certificate = str, None, false
+ldap_user_email = str, None, false
ldap_group_search_base = str, None, false
ldap_group_search_scope = str, None, false
ldap_group_search_filter = str, None, false
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index
0cc550a4c389b4a1a2b78aff760f4b5cbf94e17f..c85901d15a7ced8033971fdbcfc2dbc04eda3870
100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -139,6 +139,7 @@
#define SYSDB_AUTH_TYPE "authType"
#define SYSDB_USER_CERT "userCertificate"
+#define SYSDB_USER_EMAIL "mail"
#define SYSDB_SUBDOMAIN_REALM "realmName"
#define SYSDB_SUBDOMAIN_FLAT "flatName"
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index
ce2051d9d3c7df51e26e54abf49e8a20bf5ba3d3..6009dd8dfa787874c085c293b2d1f8aac6d95714
100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -828,6 +828,19 @@
</varlistentry>
<varlistentry>
+ <term>ldap_user_email (string)</term>
+ <listitem>
+ <para>
+ Name of the LDAP attribute containing the email
+ address of the user.
+ </para>
+ <para>
+ Default: mail
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>ldap_group_object_class (string)</term>
<listitem>
<para>
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
index
57dfcca6b998083c7cf9ac0bcb142ff7736cc8b9..829f9d9556bc3fa74a95eb76db0e31b19befe8fe
100644
--- a/src/providers/ad/ad_opts.c
+++ b/src/providers/ad/ad_opts.c
@@ -218,6 +218,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = {
{ "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
{ "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
{ "ldap_user_certificate", "userCertificate;binary", SYSDB_USER_CERT, NULL
},
+ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL },
SDAP_ATTR_MAP_TERMINATOR
};
diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
index
a0c318a511693d884f03f0372c592d633ebdcbae..cd3fe9ae4302ff4837a500b9a0c834dadb11f87d
100644
--- a/src/providers/ipa/ipa_opts.c
+++ b/src/providers/ipa/ipa_opts.c
@@ -204,6 +204,7 @@ struct sdap_attr_map ipa_user_map[] = {
{ "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL },
{ "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL },
{ "ldap_user_certificate", "userCertificate;binary", SYSDB_USER_CERT, NULL
},
+ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL },
SDAP_ATTR_MAP_TERMINATOR
};
diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c
index
524579d4fcd478f20678bebf2c3ce18f61ed0cb9..c6efe332f53c04f3cdc80875d5ca339ad90cb7ee
100644
--- a/src/providers/ldap/ldap_opts.c
+++ b/src/providers/ldap/ldap_opts.c
@@ -180,6 +180,7 @@ struct sdap_attr_map rfc2307_user_map[] = {
{ "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
{ "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
{ "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL },
+ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL },
SDAP_ATTR_MAP_TERMINATOR
};
@@ -237,6 +238,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
{ "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
{ "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
{ "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL },
+ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL },
SDAP_ATTR_MAP_TERMINATOR
};
@@ -294,6 +296,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = {
{ "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
{ "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
{ "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL },
+ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL },
SDAP_ATTR_MAP_TERMINATOR
};
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index
81da1144c657cb71ac860bbe82127a18759e0439..e3cb8464ff40538e1e7f1ba853ed71d9a5cc3c98
100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -284,6 +284,7 @@ enum sdap_user_attrs {
SDAP_AT_USER_SSH_PUBLIC_KEY,
SDAP_AT_USER_AUTH_TYPE,
SDAP_AT_USER_CERT,
+ SDAP_AT_USER_EMAIL,
SDAP_OPTS_USER /* attrs counter */
};
--
2.1.0
From 9b743e1ab4e866776455c948d7eebc47a908d10d Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Mon, 20 Jun 2016 12:57:43 +0200
Subject: [PATCH 04/14] sysdb: include email in UPN searches
Email addresses and Kerberos user principals names (UPNs) do not only
look similar they also can be used to identify a user uniquely.
In future this approach should be replace by a more generic one where
the attributes which can uniquely identifies a user can be configured to
support even a wider range of login names.
---
src/db/sysdb.h | 2 +-
src/db/sysdb_ops.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index
c85901d15a7ced8033971fdbcfc2dbc04eda3870..3cae4643bb6481159064112a384fb2b26cb2a628
100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -185,7 +185,7 @@
#define SYSDB_PWNAM_FILTER
"(&("SYSDB_UC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
#define SYSDB_PWUID_FILTER "(&("SYSDB_UC")("SYSDB_UIDNUM"=%lu))"
#define SYSDB_PWSID_FILTER "(&("SYSDB_UC")("SYSDB_SID_STR"=%s))"
-#define SYSDB_PWUPN_FILTER
"(&("SYSDB_UC")(|("SYSDB_UPN"=%s)("SYSDB_CANONICAL_UPN"=%s)))"
+#define SYSDB_PWUPN_FILTER
"(&("SYSDB_UC")(|("SYSDB_UPN"=%s)("SYSDB_CANONICAL_UPN"=%s)("SYSDB_USER_EMAIL"=%s)))"
#define SYSDB_PWENT_FILTER "("SYSDB_UC")"
#define SYSDB_GRNAM_FILTER
"(&("SYSDB_GC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index
19d6be03ede1bcec3bc7a4ed777e326460d80591..ac16015cb636932e71b9f34b22473a84602c92bd
100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -537,7 +537,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
struct ldb_dn *base_dn;
int ret;
const char *def_attrs[] = { SYSDB_NAME, SYSDB_UPN, SYSDB_CANONICAL_UPN,
- NULL };
+ SYSDB_USER_EMAIL, NULL };
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
@@ -553,7 +553,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx,
ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
base_dn, LDB_SCOPE_SUBTREE, attrs ? attrs : def_attrs,
- SYSDB_PWUPN_FILTER, upn, upn);
+ SYSDB_PWUPN_FILTER, upn, upn, upn);
if (ret != EOK) {
ret = sysdb_error_to_errno(ret);
goto done;
--
2.1.0
From 1b73314071c080fbb39376a23998f3dc929b33b1 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Mon, 20 Jun 2016 12:58:16 +0200
Subject: [PATCH 05/14] LDAP: include email in UPN searches
---
src/providers/ldap/ldap_id.c | 18 +++++++++++++----
src/providers/ldap/sdap_async_initgroups.c | 32 ++++++++++++++++++++++++------
2 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index
2fccc7e6c2572c8a35f6bc7b2f09fcf074e8e63c..f27759e45c27f781617f53bc3ca5808a6dcbb601
100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -127,12 +127,22 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
break;
case BE_FILTER_NAME:
if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) {
- attr_name = ctx->opts->user_map[SDAP_AT_USER_PRINC].name;
-
ret = sss_filter_sanitize(state, filter_value, &clean_value);
if (ret != EOK) {
goto done;
}
+ /* TODO: Do we have to check the attribute names more carefully? */
+ user_filter = talloc_asprintf(state, "(|(%s=%s)(%s=%s))",
+
ctx->opts->user_map[SDAP_AT_USER_PRINC].name,
+ clean_value,
+
ctx->opts->user_map[SDAP_AT_USER_EMAIL].name,
+ clean_value);
+ talloc_zfree(clean_value);
+ if (user_filter == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
} else {
attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
@@ -242,8 +252,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
goto done;
}
- if (attr_name == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name.\n");
+ if (attr_name == NULL && user_filter == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name or filter.\n");
ret = EINVAL;
goto done;
}
diff --git a/src/providers/ldap/sdap_async_initgroups.c
b/src/providers/ldap/sdap_async_initgroups.c
index
17593f0a268813662d6c7fbf658b1eb4599ce3c3..0a42b18662a8fe12cf048aadfef257b5d9cb48a3
100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2736,13 +2736,25 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX
*memctx,
break;
case BE_FILTER_NAME:
if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) {
- search_attr = state->opts->user_map[SDAP_AT_USER_PRINC].name;
ret = sss_filter_sanitize(state, state->filter_value, &clean_name);
if (ret != EOK) {
talloc_zfree(req);
return NULL;
}
+
+ state->user_base_filter =
+ talloc_asprintf(state,
+ "(&(|(%s=%s)(%s=%s))(objectclass=%s)",
+
state->opts->user_map[SDAP_AT_USER_PRINC].name,
+ clean_name,
+
state->opts->user_map[SDAP_AT_USER_EMAIL].name,
+ clean_name,
+ state->opts->user_map[SDAP_OC_USER].name);
+ if (state->user_base_filter == NULL) {
+ talloc_zfree(req);
+ return NULL;
+ }
} else {
search_attr = state->opts->user_map[SDAP_AT_USER_NAME].name;
@@ -2766,15 +2778,23 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX
*memctx,
return NULL;
}
- state->user_base_filter =
- talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)",
- search_attr, clean_name,
- state->opts->user_map[SDAP_OC_USER].name);
- if (!state->user_base_filter) {
+ if (search_attr == NULL && state->user_base_filter == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name or filter.\n");
talloc_zfree(req);
return NULL;
}
+ if (state->user_base_filter == NULL) {
+ state->user_base_filter =
+ talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)",
+ search_attr, clean_name,
+ state->opts->user_map[SDAP_OC_USER].name);
+ if (!state->user_base_filter) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ }
+
if (use_id_mapping) {
/* When mapping IDs or looking for SIDs, we don't want to limit
* ourselves to users with a UID value. But there must be a SID to map
--
2.1.0
From 4904beb2de5348fbf740c324b0ec3eaed83df9b9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Mon, 20 Jun 2016 13:37:56 +0200
Subject: [PATCH 06/14] NSS: add user email to fill_orig()
The IPA server must send the email address of a user to the clients to
allow login by email.
---
src/db/sysdb.h | 1 +
src/responder/nss/nsssrv_cmd.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index
3cae4643bb6481159064112a384fb2b26cb2a628..86b58dc303f2969c09d077a7994314ac89d93418
100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -220,6 +220,7 @@
SYSDB_SID_STR, \
SYSDB_UPN, \
SYSDB_USER_CERT, \
+ SYSDB_USER_EMAIL, \
SYSDB_OVERRIDE_DN, \
SYSDB_OVERRIDE_OBJECT_DN, \
SYSDB_DEFAULT_OVERRIDE_NAME, \
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index
1ae17969688fa29734ca14fd2b152decef1fdbca..da007d1e50351eed60d9c99cc60454ae40fc62d9
100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -4416,6 +4416,7 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx
*dctx)
SYSDB_AD_USER_ACCOUNT_CONTROL,
SYSDB_SSH_PUBKEY,
SYSDB_USER_CERT,
+ SYSDB_USER_EMAIL,
SYSDB_ORIG_DN,
SYSDB_ORIG_MEMBEROF,
SYSDB_DEFAULT_ATTRS, NULL};
@@ -4972,6 +4973,7 @@ static errno_t fill_orig(struct sss_packet *packet,
SYSDB_AD_USER_ACCOUNT_CONTROL,
SYSDB_SSH_PUBKEY,
SYSDB_USER_CERT,
+ SYSDB_USER_EMAIL,
SYSDB_ORIG_DN,
SYSDB_ORIG_MEMBEROF,
NULL};
--
2.1.0
From 23cfbcac067fa322c17d82f2392d7485239a1d3a Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Mon, 20 Jun 2016 16:11:11 +0200
Subject: [PATCH 07/14] utils: add is_email_from_domain()
---
src/tests/cmocka/test_utils.c | 21 +++++++++++++++++++++
src/util/domain_info_utils.c | 28 ++++++++++++++++++++++++++++
src/util/util.h | 1 +
3 files changed, 50 insertions(+)
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index
4c72a59437105e683cec2d39c36951aeff63767b..69560dcc782794c43e38d4db38861b749f840d2d
100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -1842,6 +1842,25 @@ static void test_sss_get_domain_mappings_content(void
**state)
* capaths might not be as expected. */
}
+static void test_is_email_from_domain(void **state)
+{
+ struct dom_list_test_ctx *test_ctx = talloc_get_type(*state,
+ struct
dom_list_test_ctx);
+ struct sss_domain_info *d;
+
+ d = find_domain_by_name(test_ctx->dom_list, "name_0.dom", false);
+ assert_non_null(d);
+
+ assert_false(is_email_from_domain(NULL, NULL));
+ assert_false(is_email_from_domain("hello", NULL));
+ assert_false(is_email_from_domain(NULL, d));
+ assert_false(is_email_from_domain("hello", d));
+ assert_false(is_email_from_domain("hello@hello", d));
+
+ assert_true(is_email_from_domain("hello@name_0.dom", d));
+ assert_true(is_email_from_domain("hello@NaMe_0.DoM", d));
+}
+
int main(int argc, const char *argv[])
{
poptContext pc;
@@ -1870,6 +1889,8 @@ int main(int argc, const char *argv[])
setup_dom_list, teardown_dom_list),
cmocka_unit_test_setup_teardown(test_find_domain_by_name_disabled,
setup_dom_list, teardown_dom_list),
+ cmocka_unit_test_setup_teardown(test_is_email_from_domain,
+ setup_dom_list, teardown_dom_list),
cmocka_unit_test_setup_teardown(test_sss_names_init,
confdb_test_setup,
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index
587a6b993d2bd70662df8e0b0d5963fa00c84cf8..d6ede19de282a453687fe15cf2d2eb8c5083da54
100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -824,3 +824,31 @@ void sss_domain_set_state(struct sss_domain_info *dom,
{
dom->state = state;
}
+
+bool is_email_from_domain(const char *email, struct sss_domain_info *dom)
+{
+ const char *p;
+
+ if (email == NULL || dom == NULL) {
+ return false;
+ }
+
+ p = strchr(email, '@');
+ if (p == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Input [%s] does not look like an email address.\n", email);
+ return false;
+ }
+
+ if (strcasecmp(p+1, dom->name) == 0) {
+ DEBUG(SSSDBG_TRACE_ALL, "Email [%s] is from domain [%s].\n", email,
+
dom->name);
+ return true;
+ }
+
+ DEBUG(SSSDBG_TRACE_ALL, "Email [%s] is not from domain [%s].\n", email,
+
dom->name);
+
+ return false;
+}
+
diff --git a/src/util/util.h b/src/util/util.h
index
122be90b967fb7793adaff95f3754d7a199fcf48..4449315f8b1a79ec915bc340b46188c440a27fa3
100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -514,6 +514,7 @@ struct sss_domain_info *find_domain_by_sid(struct
sss_domain_info *domain,
enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom);
void sss_domain_set_state(struct sss_domain_info *dom,
enum sss_domain_state state);
+bool is_email_from_domain(const char *email, struct sss_domain_info *dom);
struct sss_domain_info*
sss_get_domain_by_sid_ldap_fallback(struct sss_domain_info *domain,
--
2.1.0
From 6622b1d974c7bb45c6a8b2f7825b0bd88e9d748d Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Mon, 20 Jun 2016 16:30:03 +0200
Subject: [PATCH 08/14] LDAP/IPA: add local email address to aliases
Adding email-addresses from the local domain to the alias names is
strictly not needed by might help to speed up lookups in the NSS
responder.
---
src/providers/ipa/ipa_s2n_exop.c | 49 ++++++++++++++++++++++++++++++++++++++++
src/providers/ldap/sdap_utils.c | 22 ++++++++++++++++++
2 files changed, 71 insertions(+)
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index
84ef83833cdd0eec1142e45667d574d14e4fd6a5..a8c415b4c86ccd3bd3b180c8df835c75420fbb21
100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -1885,6 +1885,49 @@ done:
return ret;
}
+static errno_t add_emails_to_aliases(struct sysdb_attrs *attrs,
+ struct sss_domain_info *dom)
+{
+ int ret;
+ const char **emails;
+ size_t c;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_get_string_array(attrs, SYSDB_USER_EMAIL, tmp_ctx,
+ &emails);
+ if (ret == EOK) {
+ for (c = 0; emails[c] != NULL; c++) {
+ if (is_email_from_domain(emails[c], dom)) {
+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs, emails[c]);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to add lower-cased version of email [%s] "
+ "into the alias list\n", emails[c]);
+ goto done;
+ }
+ }
+ }
+ } else if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_ALL, "No email addresses available.\n");
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sysdb_attrs_get_string_array failed, skipping ...\n");
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
+
static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
struct req_input *req_input,
struct resp_attrs *attrs,
@@ -2030,6 +2073,12 @@ static errno_t ipa_s2n_save_objects(struct
sss_domain_info *dom,
goto done;
}
+ ret = add_emails_to_aliases(attrs->sysdb_attrs, dom);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "add_emails_to_aliases failed, skipping ...\n");
+ }
+
if (upn == NULL) {
/* We also have to store a fake UPN here, because otherwise the
* krb5 child later won't be able to properly construct one as
diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c
index
696af51d66e279d718e9af142ce5ed871eae7727..a3a9642171ca057be5a59dfae192803b84c501c8
100644
--- a/src/providers/ldap/sdap_utils.c
+++ b/src/providers/ldap/sdap_utils.c
@@ -87,6 +87,7 @@ sdap_save_all_names(const char *name,
int i;
bool lowercase = !dom->case_sensitive;
bool store_as_fqdn;
+ const char **emails;
switch (entry_type) {
case SYSDB_MEMBER_USER:
@@ -143,6 +144,27 @@ sdap_save_all_names(const char *name,
}
+ ret = sysdb_attrs_get_string_array(ldap_attrs, SYSDB_USER_EMAIL, tmp_ctx,
+ &emails);
+ if (ret == EOK) {
+ for (i = 0; emails[i] != NULL; i++) {
+ if (is_email_from_domain(emails[i], dom)) {
+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs, emails[i]);
+ if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to add lower-cased version of email [%s] "
+ "into the alias list\n", emails[i]);
+ goto done;
+ }
+ }
+ }
+ } else if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_ALL, "No email addresses available.\n");
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sysdb_attrs_get_string_array failed, skipping ...\n");
+ }
+
ret = EOK;
done:
talloc_free(tmp_ctx);
--
2.1.0
From 3655a53c50e938951c42a15bf4a147145867f3d9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Tue, 21 Jun 2016 11:06:19 +0200
Subject: [PATCH 09/14] NSS: continue with UPN/email search if name was not
found
Currently we only search for UPNs if the domain part of the name was not
know, with Kerberos aliases and email addresses we have to do this even
if the domain name is a know domain.
---
src/responder/nss/nsssrv_cmd.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index
da007d1e50351eed60d9c99cc60454ae40fc62d9..3054ba4aef52c095546ccfc006c3e9770680dbac
100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -980,6 +980,7 @@ done:
static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min,
const char *err_msg, void *ptr);
+static int nss_cmd_assume_upn(struct nss_dom_ctx *dctx);
/* search for a user.
* Returns:
@@ -1051,6 +1052,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx
*dctx)
/* There are no further domains or this was a
* fully-qualified user request.
*/
+
return ENOENT;
}
@@ -1144,8 +1146,6 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx
*dctx)
if (dom) continue;
}
- DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n");
-
/* User not found in ldb -> delete user from memory cache. */
ret = delete_entry_from_memcache(dctx->domain, name, nctx->rctx,
nctx->pwd_mc_ctx, SSS_MC_PASSWD);
@@ -1163,6 +1163,8 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx
*dctx)
"Deleting user from memcache failed.\n");
}
+ DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n");
+
return ENOENT;
}
@@ -1215,7 +1217,7 @@ static int nss_cmd_assume_upn(struct nss_dom_ctx *dctx)
{
int ret;
- if (dctx->domain == NULL) {
+ if (dctx->cmdctx->name_is_upn == false) {
dctx->domain = dctx->cmdctx->cctx->rctx->domains;
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
dctx->cmdctx->check_next = true;
@@ -1563,6 +1565,7 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd,
struct cli_ctx *cctx)
rawname = (const char *)body;
dctx->mc_name = rawname;
+ dctx->rawname = rawname;
DEBUG(SSSDBG_TRACE_FUNC, "Running command [%d][%s] with input [%s].\n",
cmd, sss_cmd2str(dctx->cmdctx->cmd), rawname);
@@ -1588,7 +1591,6 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd,
struct cli_ctx *cctx)
if (req == NULL) {
ret = ENOMEM;
} else {
- dctx->rawname = rawname;
tevent_req_set_callback(req, nss_cmd_getbynam_done, dctx);
ret = EAGAIN;
}
@@ -1604,7 +1606,6 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd,
struct cli_ctx *cctx)
if (req == NULL) {
ret = ENOMEM;
} else {
- dctx->rawname = rawname;
tevent_req_set_callback(req, nss_cmd_getbynam_done, dctx);
ret = EAGAIN;
}
@@ -1626,7 +1627,6 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd,
struct cli_ctx *cctx)
}
} else {
/* this is a multidomain search */
- dctx->rawname = rawname;
dctx->domain = cctx->rctx->domains;
cmdctx->check_next = true;
if (cctx->rctx->get_domains_last_call.tv_sec == 0) {
--
2.1.0
From 1f26c18754d660ec4a3111aad40874b0e5455451 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Wed, 22 Jun 2016 18:21:11 +0200
Subject: [PATCH 10/14] PAM: continue with UPN/email search if name was not
found
Currently we only search for UPNs if the domain part of the name was not
know, with Kerberos aliases and email addresses we have to do this even
if the domain name is a know domain.
---
src/responder/pam/pamsrv_cmd.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index
3a35c3f08821aa23051989599d45b8b7b0677da4..1c759f009321cbb322fce624b506ed07f93f997b
100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -924,6 +924,39 @@ static void pam_check_user_dp_callback(uint16_t err_maj,
uint32_t err_min,
static int pam_check_user_search(struct pam_auth_req *preq);
static int pam_check_user_done(struct pam_auth_req *preq, int ret);
+static errno_t pam_cmd_assume_upn(struct pam_auth_req *preq)
+{
+ int ret;
+
+ if (!preq->pd->name_is_upn
+ && preq->pd->logon_name != NULL
+ && strchr(preq->pd->logon_name, '@') != NULL) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "No entry found so far, trying UPN/email lookup with [%s].\n",
+ preq->pd->logon_name);
+ /* Assuming Kerberos principal */
+ preq->domain = preq->cctx->rctx->domains;
+ preq->check_provider =
+ NEED_CHECK_PROVIDER(preq->domain->provider);
+ preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name);
+ if (preq->pd->user == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+ return ENOMEM;
+ }
+ preq->pd->name_is_upn = true;
+ preq->pd->domain = NULL;
+
+ ret = pam_check_user_search(preq);
+ if (ret == EOK) {
+ pam_dom_forwarder(preq);
+ }
+ return EOK;
+ }
+
+ return ENOENT;
+}
+
+
/* TODO: we should probably return some sort of cookie that is set in the
* PAM_ENVIRONMENT, so that we can save performing some calls and cache
* data. */
@@ -1220,6 +1253,8 @@ static int pam_forwarder(struct cli_ctx *cctx, int
pam_cmd)
ret = pam_check_user_search(preq);
if (ret == EOK) {
pam_dom_forwarder(preq);
+ } else if (ret == ENOENT) {
+ ret = pam_cmd_assume_upn(preq);
}
done:
@@ -1417,6 +1452,8 @@ static void pam_forwarder_cb(struct tevent_req *req)
ret = pam_check_user_search(preq);
if (ret == EOK) {
pam_dom_forwarder(preq);
+ } else if (ret == ENOENT) {
+ ret = pam_cmd_assume_upn(preq);
}
done:
@@ -1694,6 +1731,8 @@ static void pam_check_user_dp_callback(uint16_t err_maj,
uint32_t err_min,
}
pam_dom_forwarder(preq);
+ } else if (ret == ENOENT) {
+ ret = pam_cmd_assume_upn(preq);
}
ret = pam_check_user_done(preq, ret);
--
2.1.0
From 10c8e32adc72baa0fe1e3f177d880a79a3b3309b Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 22 Jul 2016 16:01:38 +0200
Subject: [PATCH 11/14] NSS: use different neg cache name for UPN searches
If Kerberos principals or email address have the same domain suffix as
the domain itself the first user lookup by name might have already added
the name to the negative cache and the second lookup by UPN/email will
skip the domain because of the neg cache entry. To avoid this a special
name with a '@' prefix is used here.
---
src/responder/nss/nsssrv_cmd.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index
3054ba4aef52c095546ccfc006c3e9770680dbac..a96abc8756e8e0a7561e7e1dcad65138090eb97b
100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -1002,6 +1002,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx
*dctx)
struct ldb_message *msg;
const char *extra_flag = NULL;
const char *sysdb_name;
+ char *neg_cache_name;
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
@@ -1031,9 +1032,15 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx
*dctx)
return ENOMEM;
}
+ if (cmdctx->name_is_upn) {
+ neg_cache_name = talloc_asprintf(name, "@%s", name);
+ } else {
+ neg_cache_name = name;
+ }
+
/* verify this user has not yet been negatively cached,
* or has been permanently filtered */
- ret = sss_ncache_check_user(nctx->rctx->ncache, dom, name);
+ ret = sss_ncache_check_user(nctx->rctx->ncache, dom, neg_cache_name);
/* if neg cached, return we didn't find it */
if (ret == EEXIST) {
@@ -1130,7 +1137,8 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx
*dctx)
if (dctx->res->count == 0 && !dctx->check_provider) {
/* set negative cache only if not result of cache check */
- ret = sss_ncache_set_user(nctx->rctx->ncache, false, dom, name);
+ ret = sss_ncache_set_user(nctx->rctx->ncache, false, dom,
+ neg_cache_name);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set negcache for %s\n",
name);
--
2.1.0
From e5101a94fc63b9a16406c3cd2206b93d410e5c7f Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 22 Jul 2016 17:34:20 +0200
Subject: [PATCH 12/14] PAM: Fix domain for UPN based lookups
Since sysdb_search_user_by_upn() searches the whole cache we have to set
the domain so that it matches the result.
---
src/responder/pam/pamsrv_cmd.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index
1c759f009321cbb322fce624b506ed07f93f997b..66564f5d301a53dcdb5967f43ef4afdb897e9974
100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1474,6 +1474,7 @@ static int pam_check_user_search(struct pam_auth_req
*preq)
static const char *user_attrs[] = SYSDB_PW_ATTRS;
struct ldb_message *msg;
struct ldb_result *res;
+ const char *sysdb_name;
while (dom) {
/* if it is a domainless search, skip domains that require fully
@@ -1533,6 +1534,22 @@ static int pam_check_user_search(struct pam_auth_req
*preq)
if (preq->pd->name_is_upn) {
ret = sysdb_search_user_by_upn(preq, dom, name, user_attrs, &msg);
+
+ /* Since sysdb_search_user_by_upn() searches the whole cache we
+ * have to set the domain so that it matches the result. */
+ sysdb_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ if (sysdb_name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cached entry has no name.\n");
+ return EINVAL;
+ }
+ preq->domain = find_domain_by_object_name(get_domains_head(dom),
+ sysdb_name);
+ if (preq->domain == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Cannot find matching domain for [%s].\n",
+ sysdb_name);
+ return EINVAL;
+ }
} else {
ret = sysdb_getpwnam_with_views(preq, dom, name, &res);
if (res->count > 1) {
--
2.1.0
From 6eb86803d2458bad6c855dc0cbbffe6c88daeff7 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 22 Jul 2016 12:20:33 +0200
Subject: [PATCH 13/14] SDAP: add special handling for IPA Kerberos enterprise
principal strings
Unfortunately principal aliases with an alternative realm are stored in
IPA as the string representation of an enterprise principal, i.e.
name\@[email protected]. To allow searches with the plain alias
'[email protected]' the returned value is converted before it is saved to
the cache.
---
src/providers/ldap/sdap_async_users.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/providers/ldap/sdap_async_users.c
b/src/providers/ldap/sdap_async_users.c
index
28101a2d8a38f97d09d50a9f7e071a030b4f9719..cccd2506b3e1849101a8a06c39fe6cab263777b6
100644
--- a/src/providers/ldap/sdap_async_users.c
+++ b/src/providers/ldap/sdap_async_users.c
@@ -143,6 +143,8 @@ int sdap_save_user(TALLOC_CTX *memctx,
char *dom_sid_str = NULL;
struct sss_domain_info *subdomain;
size_t c;
+ char *p1;
+ char *p2;
DEBUG(SSSDBG_TRACE_FUNC, "Save user\n");
@@ -448,6 +450,21 @@ int sdap_save_user(TALLOC_CTX *memctx,
goto done;
}
+ /* Check for IPA Kerberos enterprise principal strings
+ * 'user\@[email protected]' and use '[email protected]' */
+ if ( (p1 = strchr(upn,'\\')) != NULL
+ && *(p1 + 1) == '@'
+ && (p2 = strchr(p1 + 2, '@')) != NULL) {
+ *p1 = '\0';
+ *p2 = '\0';
+ upn = talloc_asprintf(tmpctx, "%s%s", upn, p1 + 1);
+ if (upn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) {
make_realm_upper_case(upn);
}
--
2.1.0
From 8c4caca41d529191fe6ac31d7afe05a4f6607e20 Mon Sep 17 00:00:00 2001
From: Sumit Bose <[email protected]>
Date: Fri, 22 Jul 2016 20:10:42 +0200
Subject: [PATCH 14/14] SDAP: add enterprise principal strings for user
searches
Unfortunately principal aliases with an alternative realm are stored in
IPA as the string representation of an enterprise principal, i.e.
name\@[email protected]. To be able to lookup the alternative
principal in LDAP properly the UPN search filter is extended to search
for this type of name as well.
---
src/providers/ldap/ldap_common.h | 5 +++++
src/providers/ldap/ldap_id.c | 10 +++++++--
src/providers/ldap/sdap_async_initgroups.c | 9 ++++++--
src/providers/ldap/sdap_utils.c | 28 ++++++++++++++++++++++++
src/tests/cmocka/test_nested_groups.c | 34 ++++++++++++++++++++++++++++++
5 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index
713b1dadf4053339e02db3a34ffac7f778f52a98..ff7ff2854ee55238d0b044b6a95980d08ba3ee84
100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -300,6 +300,11 @@ char *sdap_combine_filters(TALLOC_CTX *mem_ctx,
const char *base_filter,
const char *extra_filter);
+char *get_enterprise_principal_string_filter(TALLOC_CTX *mem_ctx,
+ const char *attr_name,
+ const char *princ,
+ struct dp_option
*sdap_basic_opts);
+
char *sdap_get_access_filter(TALLOC_CTX *mem_ctx,
const char *base_filter);
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index
f27759e45c27f781617f53bc3ca5808a6dcbb601..fe0e219a255640b2934de4338ad796a65f348424
100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -89,6 +89,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
enum idmap_error_code err;
char *sid;
char *user_filter = NULL;
+ char *ep_filter;
req = tevent_req_create(memctx, &state, struct users_get_state);
if (!req) return NULL;
@@ -131,12 +132,17 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
if (ret != EOK) {
goto done;
}
+
+ ep_filter = get_enterprise_principal_string_filter(state,
+
ctx->opts->user_map[SDAP_AT_USER_PRINC].name,
+ clean_value, ctx->opts->basic);
/* TODO: Do we have to check the attribute names more carefully? */
- user_filter = talloc_asprintf(state, "(|(%s=%s)(%s=%s))",
+ user_filter = talloc_asprintf(state, "(|(%s=%s)(%s=%s)%s)",
ctx->opts->user_map[SDAP_AT_USER_PRINC].name,
clean_value,
ctx->opts->user_map[SDAP_AT_USER_EMAIL].name,
- clean_value);
+ clean_value,
+ ep_filter == NULL ? "" : ep_filter);
talloc_zfree(clean_value);
if (user_filter == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
diff --git a/src/providers/ldap/sdap_async_initgroups.c
b/src/providers/ldap/sdap_async_initgroups.c
index
0a42b18662a8fe12cf048aadfef257b5d9cb48a3..7029427724cc37a4508e11ef5448b421e94dc787
100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2682,7 +2682,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX
*memctx,
int ret;
char *clean_name;
bool use_id_mapping;
- const char *search_attr;
+ const char *search_attr = NULL;
+ char *ep_filter;
DEBUG(SSSDBG_TRACE_ALL, "Retrieving info for initgroups call\n");
@@ -2743,13 +2744,17 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX
*memctx,
return NULL;
}
+ ep_filter = get_enterprise_principal_string_filter(state,
+
state->opts->user_map[SDAP_AT_USER_PRINC].name,
+ clean_name, state->opts->basic);
state->user_base_filter =
talloc_asprintf(state,
- "(&(|(%s=%s)(%s=%s))(objectclass=%s)",
+ "(&(|(%s=%s)(%s=%s)%s)(objectclass=%s)",
state->opts->user_map[SDAP_AT_USER_PRINC].name,
clean_name,
state->opts->user_map[SDAP_AT_USER_EMAIL].name,
clean_name,
+ ep_filter == NULL ? "" : ep_filter,
state->opts->user_map[SDAP_OC_USER].name);
if (state->user_base_filter == NULL) {
talloc_zfree(req);
diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c
index
a3a9642171ca057be5a59dfae192803b84c501c8..0ac3ab2e416d887d00480b5123859c611f514274
100644
--- a/src/providers/ldap/sdap_utils.c
+++ b/src/providers/ldap/sdap_utils.c
@@ -227,3 +227,31 @@ char *sdap_combine_filters(TALLOC_CTX *mem_ctx,
{
return sdap_combine_filters_ex(mem_ctx, '&', base_filter, extra_filter);
}
+
+char *get_enterprise_principal_string_filter(TALLOC_CTX *mem_ctx,
+ const char *attr_name,
+ const char *princ,
+ struct dp_option *sdap_basic_opts)
+{
+ const char *realm;
+ char *p;
+
+ if (attr_name == NULL || princ == NULL || sdap_basic_opts == NULL) {
+ return NULL;
+ }
+
+ realm = dp_opt_get_cstring(sdap_basic_opts, SDAP_KRB5_REALM);
+ if (realm == NULL) {
+ return NULL;
+ }
+
+ p = strchr(princ, '@');
+ if (p == NULL) {
+ return NULL;
+ }
+
+ return talloc_asprintf(mem_ctx, "(%s=%.*s\\\\@%s@%s)", attr_name,
+ (int) (p - princ),
+ princ,
+ p + 1, realm);
+}
diff --git a/src/tests/cmocka/test_nested_groups.c
b/src/tests/cmocka/test_nested_groups.c
index
6af7e1f4393992e7f16d72b86e40664487896ea1..c8e80f29fb65f8f8935fea32cd4bf3e16de7d06f
100644
--- a/src/tests/cmocka/test_nested_groups.c
+++ b/src/tests/cmocka/test_nested_groups.c
@@ -31,6 +31,7 @@
#include "providers/ldap/sdap.h"
#include "providers/ldap/sdap_idmap.h"
#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/ldap_opts.h"
#define TESTS_PATH "tp_" BASE_FILE_STEM
#define TEST_CONF_DB "test_ldap_nested_groups_conf.ldb"
@@ -1242,6 +1243,38 @@ static void nested_group_external_member_test(void
**state)
nested_group.gr_name);
}
+static void test_get_enterprise_principal_string_filter(void **state)
+{
+ int ret;
+ char *ep_filter;
+ struct dp_option *no_krb5_realm_opt = default_basic_opts;
+
+ struct dp_option *krb5_realm_opt;
+
+ ret = dp_copy_defaults(NULL, default_basic_opts, SDAP_OPTS_BASIC,
+ &krb5_realm_opt);
+ assert_int_equal(ret, EOK);
+
+ ret = dp_opt_set_string(krb5_realm_opt, SDAP_KRB5_REALM, "TEST.DOM");
+ assert_int_equal(ret, EOK);
+
+ ep_filter = get_enterprise_principal_string_filter(NULL, NULL, NULL, NULL);
+ assert_null(ep_filter);
+
+ ep_filter = get_enterprise_principal_string_filter(NULL, "aBC", "[email protected]",
+ no_krb5_realm_opt);
+ assert_null(ep_filter);
+
+ ep_filter = get_enterprise_principal_string_filter(NULL, "aBC", "p",
+ krb5_realm_opt);
+ assert_null(ep_filter);
+
+ ep_filter = get_enterprise_principal_string_filter(NULL, "aBC", "[email protected]",
+ krb5_realm_opt);
+ assert_non_null(ep_filter);
+ assert_string_equal(ep_filter, "(aBC=p\\\\@[email protected])");
+ talloc_free(ep_filter);
+}
int main(int argc, const char *argv[])
{
@@ -1268,6 +1301,7 @@ int main(int argc, const char *argv[])
cmocka_unit_test_setup_teardown(nested_group_external_member_test,
nested_group_external_member_setup,
nested_group_external_member_teardown),
+ cmocka_unit_test(test_get_enterprise_principal_string_filter),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
--
2.1.0
_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/admin/lists/[email protected]