Resolves: rhbz#1276868 - Sudo PAM Login should support multiple password

prompts (e.g. Password + Token)
- Resolves: rhbz#1313041 - ssh with sssd proxy fails with "Connection closed
                           by remote host" if locale not available
This commit is contained in:
Lukas Slebodnik 2016-03-22 09:06:29 +01:00
parent e32d50862e
commit e37379577b
28 changed files with 3250 additions and 34 deletions

View File

@ -0,0 +1,143 @@
From 75dabe3ec5398359f4cccfcd616959cd921cced2 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 18 Feb 2016 13:03:44 +0100
Subject: [PATCH 082/108] IPA: lookup idview name even if there is no master
domain record
Currently the IPA subdomain provider returns with a error if there is no
master domain record found. Since this record contains data which is
only needed to create a trust with AD, like e.g. the IPA domain SID,
this record is only created by ipa-adtrust-install. But the idview name
is read after the master domain record. To make the idview feature work
with a plain FreeIPA setup without running ipa-adtrust-install the
missing master domain record should be handled gracefully and the
following lookup should run as well.
Resolves https://fedorahosted.org/sssd/ticket/2960
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit b25d33b0a775e2337014a334699156ac56b08f9b)
(cherry picked from commit 022e4575980324c2c68a05b3f250bd1a72bc9885)
---
src/providers/ipa/ipa_subdomains.c | 80 +++++++++++++++++++++-----------------
1 file changed, 44 insertions(+), 36 deletions(-)
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index f13847f12a7eae42b13a51e3fe1d09b60878633b..c888279229c891f1d5b8763aa851617a5daedd51 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -1219,6 +1219,9 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req)
size_t reply_count = 0;
struct sysdb_attrs **reply = NULL;
struct ipa_subdomains_req_ctx *ctx;
+ const char *flat = NULL;
+ const char *id = NULL;
+ const char *realm = NULL;
ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
@@ -1230,10 +1233,6 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req)
}
if (reply_count) {
- const char *flat = NULL;
- const char *id = NULL;
- const char *realm;
-
ret = sysdb_attrs_get_string(reply[0], IPA_FLATNAME, &flat);
if (ret != EOK) {
goto done;
@@ -1244,31 +1243,9 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req)
goto done;
}
- realm = dp_opt_get_string(ctx->sd_ctx->id_ctx->ipa_options->basic,
- IPA_KRB5_REALM);
- if (realm == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
- ret = EINVAL;
- goto done;
- }
-
- ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
- realm, flat, id, NULL);
- if (ret != EOK) {
- goto done;
- }
-
/* There is only one master record. Don't bother checking other IPA
* search bases; move to checking subdomains instead
*/
- ret = ipa_subdomains_handler_get_start(ctx,
- ctx->sd_ctx->search_bases,
- IPA_SUBDOMAINS_SLAVE);
- if (ret == EAGAIN) {
- return;
- }
-
- /* Either no search bases or an error. End the request in both cases */
} else {
ret = ipa_subdomains_handler_get_cont(ctx, IPA_SUBDOMAINS_MASTER);
if (ret == EAGAIN) {
@@ -1277,17 +1254,48 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req)
goto done;
}
- /* Right now we know there has been an error
- * and we don't have the master domain record
- */
- DEBUG(SSSDBG_CRIT_FAILURE, "Master domain record not found!\n");
-
- if (!ctx->sd_ctx->configured_explicit) {
- ctx->sd_ctx->disabled_until = time(NULL) +
- IPA_SUBDOMAIN_DISABLED_PERIOD;
+ /* All search paths are searched and no master domain record was
+ * found.
+ *
+ * A default IPA installation will not have a master domain record,
+ * this is only created by ipa-adtrust-install. Nevertheless we should
+ * continue to read other data like the idview on IPA clients. */
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Master domain record not found!\n");
+
+ }
+
+ realm = dp_opt_get_string(ctx->sd_ctx->id_ctx->ipa_options->basic,
+ IPA_KRB5_REALM);
+ if (realm == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
+ realm, flat, id, NULL);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = ipa_subdomains_handler_get_start(ctx,
+ ctx->sd_ctx->search_bases,
+ IPA_SUBDOMAINS_SLAVE);
+ if (ret == EAGAIN) {
+ return;
+ } else if (ret == EOK) {
+ /* If there are no search bases defined for subdomains try to get the
+ * idview before ending the request */
+ if (ctx->sd_ctx->id_ctx->server_mode == NULL) {
+ /* Only get view on clients, on servers it is always 'default' */
+ ret = ipa_get_view_name(ctx);
+ if (ret == EAGAIN) {
+ return;
+ } else if (ret != EOK) {
+ goto done;
+ }
}
-
- ret = EIO;
}
done:
--
2.7.3

View File

@ -0,0 +1,52 @@
From 55fa5564a9835e9697555d1bfeb9336bcce2415f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 22 Feb 2016 16:08:13 +0100
Subject: [PATCH 083/108] IPA: invalidate override data if original view is
missing
If the idview name cannot be read from cache this either means that the
cache was empty or the name wasn't written because of an error. In the
case of an error SSSD would assume that the default view was used. If
the new view is different from the default view the override data must be
invalidated. Since the sysdb call to invalidate the override data would
work with an empty cache as well and do nothing it is safe to call it on
both cases.
Related to https://fedorahosted.org/sssd/ticket/2960
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit b5d48539966aefbea703377ba2ebcb67f9cf88b8)
(cherry picked from commit 1d4d3f15b5cb9b9ffad521ddea0b1e3660587816)
---
src/providers/ipa/ipa_subdomains.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index c888279229c891f1d5b8763aa851617a5daedd51..cb5a23bfb8043e620061e11d5e567d3e39eab6e3 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -898,9 +898,19 @@ static void ipa_get_view_name_done(struct tevent_req *req)
} else {
if (ctx->sd_ctx->id_ctx->view_name == NULL
|| strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0) {
- /* View name changed */
+ /* View name changed. If there was a non-default non-local view
+ * was used the tree in cache containing the override values is
+ * removed. In all cases sysdb_invalidate_overrides() is called to
+ * remove the override attribute from the cached user objects.
+ *
+ * Typically ctx->sd_ctx->id_ctx->view_name == NULL means that the
+ * cache was empty but there was a bug in with caused that the
+ * view name was not written to the cache at all. In this case the
+ * cache must be invalidated if the new view is not the
+ * default-view as well. */
- if (ctx->sd_ctx->id_ctx->view_name != NULL) {
+ if (ctx->sd_ctx->id_ctx->view_name != NULL
+ || !is_default_view(view_name)) {
ret = sysdb_transaction_start(
ctx->sd_ctx->be_ctx->domain->sysdb);
if (ret != EOK) {
--
2.7.3

View File

@ -0,0 +1,62 @@
From 99c197025ad61a9ecd7ae3bcd02e9569415fb90a Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 26 Feb 2016 13:10:50 -0500
Subject: [PATCH 084/108] GPO: Add Cockpit to the Remote Interactive defaults
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Cockpit Project is an administrative console that is gaining in
popularity and is a default component on some operating systems (such
as Fedora Server). Since it is becoming more common, we should ensure
that it is part of the standard mapping.
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
(cherry picked from commit 0e799bc491f636c69657d1678af13d23bf7b7c10)
(cherry picked from commit 71e700368aa88a0adb14047b7fd8c97ff9487c28)
---
src/man/sssd-ad.5.xml | 5 +++++
src/providers/ad/ad_gpo.c | 4 +++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
index 4280eac5f4594b26d158a0ea58622f9fe7beb53e..b042480dff164e3626f61c520e51bb756bcbfd9c 100644
--- a/src/man/sssd-ad.5.xml
+++ b/src/man/sssd-ad.5.xml
@@ -463,6 +463,11 @@ ad_gpo_map_remote_interactive = +my_pam_service, -sshd
sshd
</para>
</listitem>
+ <listitem>
+ <para>
+ cockpit
+ </para>
+ </listitem>
</itemizedlist>
</para>
</listitem>
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index 00f4457ddfa35b8917d7babc6666fdc129fb63ae..69c462f04d60888f11bbf5359d0dda821339bb81 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -191,6 +191,7 @@ int ad_gpo_process_cse_recv(struct tevent_req *req);
#define GPO_SUDO "sudo"
#define GPO_SUDO_I "sudo-i"
#define GPO_SYSTEMD_USER "systemd-user"
+#define GPO_COCKPIT "cockpit"
struct gpo_map_option_entry {
enum gpo_map_type gpo_map_type;
@@ -203,7 +204,8 @@ struct gpo_map_option_entry {
const char *gpo_map_interactive_defaults[] =
{GPO_LOGIN, GPO_SU, GPO_SU_L,
GPO_GDM_FINGERPRINT, GPO_GDM_PASSWORD, GPO_GDM_SMARTCARD, GPO_KDM, NULL};
-const char *gpo_map_remote_interactive_defaults[] = {GPO_SSHD, NULL};
+const char *gpo_map_remote_interactive_defaults[] = {GPO_SSHD, GPO_COCKPIT,
+ NULL};
const char *gpo_map_network_defaults[] = {GPO_FTP, GPO_SAMBA, NULL};
const char *gpo_map_batch_defaults[] = {GPO_CROND, NULL};
const char *gpo_map_service_defaults[] = {NULL};
--
2.7.3

View File

@ -0,0 +1,79 @@
From 665fae391bbb6c5173ec0086247f20d95a0c9026 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 26 Feb 2016 13:21:23 -0500
Subject: [PATCH 085/108] GPO: Add other display managers to interactive logon
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Gone are the days when all systems used GDM or KDM. We need to support
other display managers in the default configuration to avoid issues
when enrolled in AD domains.
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
(cherry picked from commit 293cf52a00c9c67f0ad8f264027f81c020854f66)
(cherry picked from commit 26d4fe97a93b15da60eba98c5c26fde13efd950a)
---
src/man/sssd-ad.5.xml | 20 ++++++++++++++++++++
src/providers/ad/ad_gpo.c | 7 ++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
index b042480dff164e3626f61c520e51bb756bcbfd9c..54a4b56271933bae5d0f86e24b39ddd3fbee7a37 100644
--- a/src/man/sssd-ad.5.xml
+++ b/src/man/sssd-ad.5.xml
@@ -422,6 +422,26 @@ ad_gpo_map_interactive = +my_pam_service, -login
kdm
</para>
</listitem>
+ <listitem>
+ <para>
+ lightdm
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ lxdm
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ sddm
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ xdm
+ </para>
+ </listitem>
</itemizedlist>
</para>
</listitem>
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index 69c462f04d60888f11bbf5359d0dda821339bb81..a6ab1758d104a315ebf5e985f0ef32b58033c21c 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -184,6 +184,10 @@ int ad_gpo_process_cse_recv(struct tevent_req *req);
#define GPO_GDM_PASSWORD "gdm-password"
#define GPO_GDM_SMARTCARD "gdm-smartcard"
#define GPO_KDM "kdm"
+#define GPO_LIGHTDM "lightdm"
+#define GPO_LXDM "lxdm"
+#define GPO_SDDM "sddm"
+#define GPO_XDM "xdm"
#define GPO_SSHD "sshd"
#define GPO_FTP "ftp"
#define GPO_SAMBA "samba"
@@ -203,7 +207,8 @@ struct gpo_map_option_entry {
const char *gpo_map_interactive_defaults[] =
{GPO_LOGIN, GPO_SU, GPO_SU_L,
- GPO_GDM_FINGERPRINT, GPO_GDM_PASSWORD, GPO_GDM_SMARTCARD, GPO_KDM, NULL};
+ GPO_GDM_FINGERPRINT, GPO_GDM_PASSWORD, GPO_GDM_SMARTCARD, GPO_KDM,
+ GPO_LIGHTDM, GPO_LXDM, GPO_SDDM, GPO_XDM, NULL};
const char *gpo_map_remote_interactive_defaults[] = {GPO_SSHD, GPO_COCKPIT,
NULL};
const char *gpo_map_network_defaults[] = {GPO_FTP, GPO_SAMBA, NULL};
--
2.7.3

View File

@ -0,0 +1,70 @@
From a4b24aeab9f44b5fd937b456acc223a18d045bae Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Mon, 29 Feb 2016 10:41:50 +0100
Subject: [PATCH 086/108] CI: Use yum-deprecated instead of dnf
/usr/bin/yum is provided by the dnf-yum package and call /usr/bin/dnf
on new fedora distributions. We should directly use old style yum
which was renamed to /usr/bin/yum-deprecated and is still part of
the yum package.
Reviewed-by: Nikolai Kondrashov <Nikolai.Kondrashov@redhat.com>
(cherry picked from commit 73585f9af928913200999c5b3b983bb9266ee266)
(cherry picked from commit 8f0a510a8c324aa1fa0f318e340b554cd07baf8b)
---
contrib/ci/README.md | 7 ++++++-
contrib/ci/distro.sh | 14 +++++++++++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/contrib/ci/README.md b/contrib/ci/README.md
index 50b73ec354f92e9909a57a82ec72ba1a8516aa1c..6bd2fd92c1bf2c0abe93a8ecb8432b6a7889e492 100644
--- a/contrib/ci/README.md
+++ b/contrib/ci/README.md
@@ -36,11 +36,16 @@ package and on Debian in `lsb-release`.
The rest of the required packages CI will attempt to install itself, using
the distribution's package manager invoked through sudo.
-A sudo rule can be employed to selectively avoid password prompts on Red Hat
+A sudo rule can be employed to selectively avoid password prompts on RHEL
distros:
<USER> ALL=(ALL:ALL) NOPASSWD: /usr/bin/yum --assumeyes install -- *
+on Fedora distros:
+
+ # We need to use yum-deprecated on Fedora because of BZ1215208.
+ <USER> ALL=(ALL:ALL) NOPASSWD: /usr/bin/yum-deprecated --assumeyes install -- *
+
and Debian-based distros:
<USER> ALL=(ALL:ALL) NOPASSWD: /usr/bin/apt-get --yes install -- *
diff --git a/contrib/ci/distro.sh b/contrib/ci/distro.sh
index da797d02f4b110f9e2c074fc2c97f092ae7200af..374e55696d3f2519151b73ff0fc397c04ff48325 100644
--- a/contrib/ci/distro.sh
+++ b/contrib/ci/distro.sh
@@ -50,11 +50,19 @@ function distro_pkg_install()
{
declare prompt=$'Need root permissions to install packages.\n'
prompt+="Enter sudo password for $USER: "
- if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then
+ if [[ "$DISTRO_BRANCH" == -redhat-fedora-2[2-9]* ]]; then
+ # TODO switch fedora to DNF once
+ # https://bugzilla.redhat.com/show_bug.cgi?id=1215208 is fixed
+ [ $# != 0 ] && sudo -p "$prompt" \
+ yum-deprecated --assumeyes install -- "$@" |&
+ # Pass input to output, fail if a missing package is reported
+ awk 'BEGIN {s=0}
+ /^No package .* available.$/ {s=1}
+ {print}
+ END {exit s}'
+ elif [[ "$DISTRO_BRANCH" == -redhat-* ]]; then
[ $# != 0 ] && sudo -p "$prompt" yum --assumeyes install -- "$@" |&
# Pass input to output, fail if a missing package is reported
- # TODO Remove and switch to DNF once
- # https://bugzilla.redhat.com/show_bug.cgi?id=1215208 is fixed
awk 'BEGIN {s=0}
/^No package .* available.$/ {s=1}
{print}
--
2.7.3

View File

@ -0,0 +1,120 @@
From 4cf4c4a60aa226ed4a9e3da253ec9a598e9481a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 23 Feb 2016 11:02:42 +0100
Subject: [PATCH 087/108] remove user certificate if not found on the server
If the user is not found by cert lookup when the user is already
cached, two things may happen:
1) cert was removed from the user object
2) user was removed
Instead of issuing another cert lookup we will just remove cert
attribute from the cache not touching the expiration timestamp so
the user may be updated later when needed.
Resolves:
https://fedorahosted.org/sssd/ticket/2934
Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit 659232f194f83ec7c450ce89c3fd41e4e74409f2)
(cherry picked from commit 90bd6598f0d8ad9fa8d05419c7e14b64e09e8a54)
---
src/db/sysdb.h | 3 ++-
src/db/sysdb_ops.c | 45 ++++++++++++++++++++++++++++++++++++++++++++
src/providers/ldap/ldap_id.c | 10 ++++++++++
3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 95a9086766228a6c36c56d3a68a0bb0e493c0cbe..bb8ca08b12d7eee08d36e5e2f4ac47df686b1d69 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -1155,7 +1155,8 @@ errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx,
const char *cert,
struct ldb_result **res);
-
+errno_t sysdb_remove_cert(struct sss_domain_info *domain,
+ const char *cert);
/* === Functions related to GPOs === */
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index ab0d59ca6db620dfbf7e74a93745df242b6fc3a3..843251b3e87a697a0f9e8cb2bb2d83be0150a474 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -3764,6 +3764,51 @@ errno_t sysdb_search_user_by_cert(TALLOC_CTX *mem_ctx,
return sysdb_search_object_by_cert(mem_ctx, domain, cert, user_attrs, res);
}
+errno_t sysdb_remove_cert(struct sss_domain_info *domain,
+ const char *cert)
+{
+ struct ldb_message_element el = { 0, SYSDB_USER_CERT, 0, NULL };
+ struct sysdb_attrs del_attrs = { 1, &el };
+ const char *attrs[] = {SYSDB_NAME, NULL};
+ struct ldb_result *res = NULL;
+ unsigned int i;
+ errno_t ret;
+
+ ret = sysdb_search_object_by_cert(NULL, domain, cert, attrs, &res);
+ if (ret == ENOENT || res == NULL) {
+ ret = EOK;
+ goto done;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to lookup object by cert "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ /* Certificate may be found on more objects, remove it from all.
+ * If object contains more then one certificate, we still remove the
+ * whole attribute since it will be downloaded again. */
+ for (i = 0; i < res->count; i++) {
+ ret = sysdb_set_entry_attr(domain->sysdb, res->msgs[0]->dn,
+ &del_attrs, SYSDB_MOD_DEL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to remove certificate "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ ret = sysdb_mark_entry_as_expired_ldb_dn(domain, res->msgs[0]->dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to expire object "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ continue;
+ }
+ }
+
+done:
+ talloc_free(res);
+ return ret;
+}
+
errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
struct sss_domain_info *dom,
const char *group_name,
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 905bbd94d36e52e212d118e728f5fe46fa5bc64a..7a986f43775a3d0219c91386d667ba910180b425 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -530,6 +530,16 @@ static void users_get_done(struct tevent_req *subreq)
*/
break;
+ case BE_FILTER_CERT:
+ ret = sysdb_remove_cert(state->domain, state->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to remove user certificate"
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ tevent_req_error(req, ret);
+ return;
+ }
+ break;
+
default:
tevent_req_error(req, EINVAL);
return;
--
2.7.3

View File

@ -0,0 +1,392 @@
From 3968a8ddb1b0e55db8217031f92feb4d2ee25c4d Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 22 Jan 2016 18:14:45 +0100
Subject: [PATCH 088/108] sdap: improve filtering of multiple results in GC
lookups
The Global Catalog of AD contains some information about all users and
groups in an AD forest. Users from different domain in the forest can
have the same name. The most obvious example is the Administrator user
which is present in all domains. Although SSSD uses a domain specific
search base for looking up users in the GC the search might still return
multiple results if there is a user with the same name in one of the
child (or grand-child ...) domains because of the hierarchic nature of
the LDAP tree. Limiting the search depth would not help because users
can be created in deeply nested OUs.
Currently SSSD expects in this case that the user object is store in
CN=Users or below. This works for all default users like Administrator
but in general users can be created anywhere in the directory tree. If a
user is created outside of CN=Users and there is a user with the same
name in a child domain the initgroups command to look up the
group-memberships of the user fails because it is not clear which of the
two results should be used (initgroups for the child domain user works
fine).
This patch adds an additional scheme to select the right result based on
the domain component attribute name 'dc'. This attribute indicates an
additional component in the domain name and hence a child domain. So as
long as the result contains a dc component following out search base it
cannot be the object we are looking for. This scheme includes the old
CN=Users based one but since it is more expensive I kept the old scheme
which so far worked all the time and only use the new one if the old one
fails.
Resolves https://fedorahosted.org/sssd/ticket/2961
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 5ff7a765434ed0b4d37564ade26d7761d06f81c3)
(cherry picked from commit 52ea2caa4d21a980902cd0f2fd77ceba25062a8c)
---
src/db/sysdb.h | 6 ++
src/db/sysdb_subdomains.c | 153 +++++++++++++++++++++++++++++
src/providers/ldap/sdap_async_initgroups.c | 48 ++-------
src/tests/cmocka/test_sysdb_subdomains.c | 73 ++++++++++++++
4 files changed, 238 insertions(+), 42 deletions(-)
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index bb8ca08b12d7eee08d36e5e2f4ac47df686b1d69..4b2feffd058f314d4b0d7270d5a5b242d6555e39 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -1228,4 +1228,10 @@ errno_t sysdb_handle_original_uuid(const char *orig_name,
const char *src_name,
struct sysdb_attrs *dest_attrs,
const char *dest_name);
+
+errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom,
+ const char *domain_component_name,
+ struct sysdb_attrs **usr_attrs,
+ size_t count,
+ struct sysdb_attrs **exp_usr);
#endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index b2bf1a0742171b7beccb44fa915c8adba51fefa3..456e6621b3434a9dbf2e611ad880facbc171c174 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -1049,3 +1049,156 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom,
+ const char *domain_component_name,
+ struct sysdb_attrs **usr_attrs,
+ size_t count,
+ struct sysdb_attrs **exp_usr)
+{
+ char *dom_basedn;
+ size_t dom_basedn_len;
+ char *expected_basedn;
+ size_t expected_basedn_len;
+ size_t dn_len;
+ const char *orig_dn;
+ size_t c = 0;
+ int ret;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_context *ldb_ctx;
+ struct ldb_dn *ldb_dom_basedn;
+ int dom_basedn_comp_num;
+ struct ldb_dn *ldb_dn;
+ int dn_comp_num;
+ const char *component_name;
+ struct sysdb_attrs *result = NULL;
+ const char *result_dn_str = NULL;
+
+ if (dom == NULL || domain_component_name == NULL || usr_attrs == NULL
+ || count == 0) {
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+ return ENOMEM;
+ }
+
+ ret = domain_to_basedn(tmp_ctx, dom->name, &dom_basedn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n");
+ goto done;
+ }
+ expected_basedn = talloc_asprintf(tmp_ctx, "%s%s", "cn=users,", dom_basedn);
+ if (expected_basedn == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ldb_ctx = sysdb_ctx_get_ldb(dom->sysdb);
+ if (ldb_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Missing ldb context.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ ldb_dom_basedn = ldb_dn_new(tmp_ctx, ldb_ctx, dom_basedn);
+ if (ldb_dom_basedn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ dom_basedn_comp_num = ldb_dn_get_comp_num(ldb_dom_basedn);
+ dom_basedn_comp_num++;
+
+ DEBUG(SSSDBG_TRACE_ALL, "Expected BaseDN is [%s].\n", expected_basedn);
+ expected_basedn_len = strlen(expected_basedn);
+ dom_basedn_len = strlen(dom_basedn);
+
+ for (c = 0; c < count; c++) {
+ ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+ goto done;
+ }
+ dn_len = strlen(orig_dn);
+
+ if (dn_len > expected_basedn_len
+ && strcasecmp(orig_dn + (dn_len - expected_basedn_len),
+ expected_basedn) == 0) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Found matching dn [%s].\n", orig_dn);
+ if (result != NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Found 2 matching DN [%s] and [%s], expecting only 1.\n",
+ result_dn_str, orig_dn);
+ ret = EINVAL;
+ goto done;
+ }
+ result = usr_attrs[c];
+ result_dn_str = orig_dn;
+ }
+ }
+
+ if (result == NULL) {
+ for (c = 0; c < count; c++) {
+ ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+ goto done;
+ }
+ dn_len = strlen(orig_dn);
+
+ if (dn_len > dom_basedn_len
+ && strcasecmp(orig_dn + (dn_len - dom_basedn_len),
+ dom_basedn) == 0) {
+ ldb_dn = ldb_dn_new(tmp_ctx, ldb_ctx, orig_dn);
+ if (ldb_dn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ dn_comp_num = ldb_dn_get_comp_num(ldb_dn);
+ if (dn_comp_num > dom_basedn_comp_num) {
+ component_name = ldb_dn_get_component_name(ldb_dn,
+ (dn_comp_num - dom_basedn_comp_num));
+ DEBUG(SSSDBG_TRACE_ALL, "Comparing [%s] and [%s].\n",
+ component_name,
+ domain_component_name);
+ if (component_name != NULL
+ && strcasecmp(component_name,
+ domain_component_name) != 0) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Found matching dn [%s].\n", orig_dn);
+ if (result != NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Found 2 matching DN [%s] and [%s], "
+ "expecting only 1.\n", result_dn_str, orig_dn);
+ ret = EINVAL;
+ goto done;
+ }
+ result = usr_attrs[c];
+ result_dn_str = orig_dn;
+ }
+ }
+ }
+ }
+ }
+
+ if (result == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "No matching DN found.\n");
+ ret = ENOENT;
+ goto done;
+ }
+
+ *exp_usr = result;
+
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 1e5f5ab49896b234bec0c7a2c1429f30d90ae32a..059b18354362a76376da9321118b8fdb12282b9a 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2832,10 +2832,6 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
const char *orig_dn;
const char *cname;
bool in_transaction = false;
- char *expected_basedn;
- size_t expected_basedn_len;
- size_t dn_len;
- size_t c = 0;
DEBUG(SSSDBG_TRACE_ALL, "Receiving info for the user\n");
@@ -2872,54 +2868,22 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
tevent_req_error(req, ret);
return;
}
+ } else if (count == 1) {
+ state->orig_user = usr_attrs[0];
} else if (count != 1) {
DEBUG(SSSDBG_OP_FAILURE,
"Expected one user entry and got %zu\n", count);
- ret = domain_to_basedn(state, state->dom->name, &expected_basedn);
+ ret = sysdb_try_to_find_expected_dn(state->dom, "dc", usr_attrs, count,
+ &state->orig_user);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n");
- tevent_req_error(req, ret);
- return;
- }
- expected_basedn = talloc_asprintf(state, "%s%s",
- "cn=users,", expected_basedn);
- if (expected_basedn == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "talloc_append failed.\n");
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- DEBUG(SSSDBG_TRACE_ALL, "Expected BaseDN is [%s].\n", expected_basedn);
- expected_basedn_len = strlen(expected_basedn);
-
- for (c = 0; c < count; c++) {
- ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
- tevent_req_error(req, ret);
- return;
- }
- dn_len = strlen(orig_dn);
-
- if (dn_len > expected_basedn_len
- && strcasecmp(orig_dn + (dn_len - expected_basedn_len),
- expected_basedn) == 0) {
- DEBUG(SSSDBG_TRACE_ALL,
- "Found matching dn [%s].\n", orig_dn);
- break;
- }
- }
-
- if (c == count) {
- DEBUG(SSSDBG_OP_FAILURE, "No matching DN found.\n");
+ DEBUG(SSSDBG_OP_FAILURE,
+ "try_to_find_expected_dn failed. No matching DN found.\n");
tevent_req_error(req, EINVAL);
return;
}
}
- state->orig_user = usr_attrs[c];
-
ret = sysdb_transaction_start(state->sysdb);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c
index 701bfb726ff7e950d4439b3dc1a3bee437c9e7ed..f55c2918015900351483e3471bf946ea60872dae 100644
--- a/src/tests/cmocka/test_sysdb_subdomains.c
+++ b/src/tests/cmocka/test_sysdb_subdomains.c
@@ -509,6 +509,76 @@ static void test_sysdb_link_ad_multidom(void **state)
}
+static void test_try_to_find_expected_dn(void **state)
+{
+ int ret;
+ struct sysdb_attrs *result;
+ struct sysdb_attrs *usr_attrs[10] = { NULL };
+ struct sss_domain_info *dom;
+ struct subdom_test_ctx *test_ctx =
+ talloc_get_type(*state, struct subdom_test_ctx);
+
+ dom = find_domain_by_name(test_ctx->tctx->dom,
+ "child2.test_sysdb_subdomains_2", true);
+ assert_non_null(dom);
+
+ usr_attrs[0] = sysdb_new_attrs(test_ctx);
+ assert_non_null(usr_attrs[0]);
+
+ ret = sysdb_attrs_add_string(usr_attrs[0], SYSDB_ORIG_DN,
+ "uid=user,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2");
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_try_to_find_expected_dn(NULL, NULL, NULL, 0, NULL);
+ assert_int_equal(ret, EINVAL);
+
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 1, &result);
+ assert_int_equal(ret, ENOENT);
+
+ ret = sysdb_try_to_find_expected_dn(dom, "xy", usr_attrs, 1, &result);
+ assert_int_equal(ret, EOK);
+ assert_ptr_equal(result, usr_attrs[0]);
+
+ usr_attrs[1] = sysdb_new_attrs(test_ctx);
+ assert_non_null(usr_attrs[1]);
+
+ ret = sysdb_attrs_add_string(usr_attrs[1], SYSDB_ORIG_DN,
+ "uid=user1,cn=abc,dc=child2,dc=test_sysdb_subdomains_2");
+ assert_int_equal(ret, EOK);
+
+ usr_attrs[2] = sysdb_new_attrs(test_ctx);
+ assert_non_null(usr_attrs[2]);
+
+ ret = sysdb_attrs_add_string(usr_attrs[2], SYSDB_ORIG_DN,
+ "uid=user2,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2");
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 3, &result);
+ assert_int_equal(ret, EOK);
+ assert_ptr_equal(result, usr_attrs[1]);
+
+ ret = sysdb_try_to_find_expected_dn(dom, "xy", usr_attrs, 3, &result);
+ assert_int_equal(ret, EINVAL);
+
+ /* Make sure cn=users match is preferred */
+ talloc_free(usr_attrs[2]);
+ usr_attrs[2] = sysdb_new_attrs(test_ctx);
+ assert_non_null(usr_attrs[2]);
+
+ ret = sysdb_attrs_add_string(usr_attrs[2], SYSDB_ORIG_DN,
+ "uid=user2,cn=abc,cn=users,dc=child2,dc=test_sysdb_subdomains_2");
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 3, &result);
+ assert_int_equal(ret, EOK);
+ assert_ptr_equal(result, usr_attrs[2]);
+
+
+ talloc_free(usr_attrs[0]);
+ talloc_free(usr_attrs[1]);
+ talloc_free(usr_attrs[2]);
+}
+
int main(int argc, const char *argv[])
{
int rv;
@@ -542,6 +612,9 @@ int main(int argc, const char *argv[])
cmocka_unit_test_setup_teardown(test_sysdb_link_ad_multidom,
test_sysdb_subdom_setup,
test_sysdb_subdom_teardown),
+ cmocka_unit_test_setup_teardown(test_try_to_find_expected_dn,
+ test_sysdb_subdom_setup,
+ test_sysdb_subdom_teardown),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
--
2.7.3

View File

@ -1,18 +1,20 @@
From a9e5c97001638eca5d5b4d88463edfb0e8b01cc0 Mon Sep 17 00:00:00 2001
From ba9819a93951e0a38874c6d06abcba700b07d41d Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Sun, 11 Oct 2015 18:08:46 +0200
Subject: [PATCH 100/103] FO: Don't free rc-allocated structure
Subject: [PATCH 089/108] FO: Don't free rc-allocated structure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit 63af9215ea9114062fd87003161e6b5982bf9b1f)
(cherry picked from commit 5d485ce42a4d56581d44c7224e78083a4ff1e81b)
---
src/providers/fail_over.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index b076687ac6e571f7e27402fd11ac60183ea46951..b309f1c68d0f4219d4b97eb0c01416e53ea856d0 100644
index b51a6c99ce031a1566f5d021fcf41843891a2d1c..3e6f1c2a24aaf713288146cc25d9cc462f243160 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -507,7 +507,6 @@ create_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name)
@ -24,5 +26,5 @@ index b076687ac6e571f7e27402fd11ac60183ea46951..b309f1c68d0f4219d4b97eb0c01416e5
}
--
2.5.0
2.7.3

View File

@ -1,13 +1,14 @@
From 9b095121329b2cc5f929af61222ad94705e5d38e Mon Sep 17 00:00:00 2001
From 386984d350c841d9fcb7d002015a4bf174aaa51e Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Sun, 11 Oct 2015 15:31:44 +0200
Subject: [PATCH 101/103] tests: Reduce failover code duplication
Subject: [PATCH 090/108] tests: Reduce failover code duplication
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit 4a4af8e1b6a9bab7c7a34d86055a400376e3829e)
(cherry picked from commit 383bdbe8d40cba2d0848b2256716358c7f8e8f2d)
---
src/tests/cmocka/test_fo_srv.c | 88 +++++++++++++++++-------------------------
1 file changed, 35 insertions(+), 53 deletions(-)
@ -158,5 +159,5 @@ index e892bab0a261779363ea78a10038b15acefc49b7..109f664c84238cf9c1055a1cbc1a8c88
s1->next = s2;
--
2.5.0
2.7.3

View File

@ -1,7 +1,7 @@
From 24ef73fe8bbea12ceedddad1953c7bd94ce36f31 Mon Sep 17 00:00:00 2001
From 54d7922d287368fe419cafaa754aaf43b3ff1c93 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Sun, 11 Oct 2015 15:34:44 +0200
Subject: [PATCH 102/103] FO: Use refcount to keep track of servers returned to
Subject: [PATCH 091/108] FO: Use refcount to keep track of servers returned to
callers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -12,6 +12,7 @@ Resolves:
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit 10c07e188323a2f9824b5e34379f3b1a9b37759e)
(cherry picked from commit c532290fb1a85a63c3bc9ef95ba7d6248f0e94c1)
---
src/providers/data_provider_fo.c | 7 ++-
src/providers/dp_backend.h | 4 +-
@ -25,7 +26,7 @@ Reviewed-by: Pavel Březina <pbrezina@redhat.com>
9 files changed, 115 insertions(+), 39 deletions(-)
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index cd57340a0ba0ac7e474dc502bf1f1b4de0e1f778..4c4d7b233bb4bd22aa7c7dcd1fec955c92fb08e4 100644
index d1d8c4c5c94811ce73b550dc99166d3c913b95aa..39f57255af220b608d333da7c0bd1697788ea8f6 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -606,7 +606,7 @@ errno_t be_resolve_server_process(struct tevent_req *subreq,
@ -57,7 +58,7 @@ index cd57340a0ba0ac7e474dc502bf1f1b4de0e1f778..4c4d7b233bb4bd22aa7c7dcd1fec955c
}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 0ced851be8468ce21a9d283e26461fc47194557e..f90d0b9c5fe69b1b14caa090bb515c60746de154 100644
index ffeeca4a6bad976ae8922bc4964b839242290259..bc5f716ffb8b85244604e3830141d390b7979a7c 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -258,7 +258,9 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
@ -72,7 +73,7 @@ index 0ced851be8468ce21a9d283e26461fc47194557e..f90d0b9c5fe69b1b14caa090bb515c60
#define be_fo_set_port_status(ctx, service_name, server, status) \
_be_fo_set_port_status(ctx, service_name, server, status, \
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index b309f1c68d0f4219d4b97eb0c01416e53ea856d0..24aed9dfa469ad730d176244eb329522a43c6fd8 100644
index 3e6f1c2a24aaf713288146cc25d9cc462f243160..65d4fb690d270fa04a0e22f7db37bd8521ad3ba1 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -79,6 +79,8 @@ struct fo_service {
@ -291,7 +292,7 @@ index b309f1c68d0f4219d4b97eb0c01416e53ea856d0..24aed9dfa469ad730d176244eb329522
TEVENT_REQ_RETURN_ON_ERROR(req);
diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
index e49c6414a14eb6ca2cad333f8efbb58576811345..75bff8da1cc29dd6184b6ec0d3fad545eb7204c2 100644
index b8272a0a16015ff6b5d287b775c33a77e23eba67..f24b5715f13931965400c20562a1578aaf756908 100644
--- a/src/providers/fail_over.h
+++ b/src/providers/fail_over.h
@@ -128,7 +128,6 @@ int fo_add_server(struct fo_service *service,
@ -337,7 +338,7 @@ index e3e9601b356efd72e50ab86e8b7cdd048e4e70d4..7b7a16a612332639aa474a7ebea6b966
talloc_zfree(subreq);
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 217e80fd07abc41f2594d19397783683d44600cd..c94ba15bb17aa1641eb36781cc59ce158d48ca66 100644
index 2fab92e5d22a4dae870c5e9dde7ef162fc36cbe2..8d6a37b2ceb3347cb8092858889d07e5615e5c77 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -695,7 +695,7 @@ static void auth_resolve_done(struct tevent_req *subreq)
@ -350,10 +351,10 @@ index 217e80fd07abc41f2594d19397783683d44600cd..c94ba15bb17aa1641eb36781cc59ce15
if (ret) {
/* all servers have been tried and none
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 8f5227d263f995693f6e65bd238171538aa52af7..ef7a1594954b4cb11f35d2cd56b0c4806ead797a 100644
index 40256de99006815c97ee9390dfd2e997cf6fc072..f9074afb0c1340c7c2a50d4df0021eee4ae0d076 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1148,7 +1148,7 @@ static void sdap_kinit_kdc_resolved(struct tevent_req *subreq)
@@ -1160,7 +1160,7 @@ static void sdap_kinit_kdc_resolved(struct tevent_req *subreq)
struct tevent_req *tgtreq;
int ret;
@ -362,7 +363,7 @@ index 8f5227d263f995693f6e65bd238171538aa52af7..ef7a1594954b4cb11f35d2cd56b0c480
talloc_zfree(subreq);
if (ret != EOK) {
/* all servers have been tried and none
@@ -1508,7 +1508,7 @@ static void sdap_cli_resolve_done(struct tevent_req *subreq)
@@ -1520,7 +1520,7 @@ static void sdap_cli_resolve_done(struct tevent_req *subreq)
struct sdap_cli_connect_state);
int ret;
@ -471,10 +472,10 @@ index 109f664c84238cf9c1055a1cbc1a8c8870f2dc39..67f86fb17753bf90b88d007a6a1b309d
check_server(test_ctx, srv, 389, "ldap3.sssd.com");
diff --git a/src/tests/fail_over-tests.c b/src/tests/fail_over-tests.c
index b21ead38229be5d55df2de10bec3dd00a8566d71..7c296d116968ae059c75920c91059f6e83ea0508 100644
index c9bac68711cfcf624064b5881f5226d4f8449e39..020f9d474b6bc8cee4fe80098f9631c4e343cec6 100644
--- a/src/tests/fail_over-tests.c
+++ b/src/tests/fail_over-tests.c
@@ -154,7 +154,7 @@ test_resolve_service_callback(struct tevent_req *req)
@@ -156,7 +156,7 @@ test_resolve_service_callback(struct tevent_req *req)
task->test_ctx->tasks--;
@ -484,5 +485,5 @@ index b21ead38229be5d55df2de10bec3dd00a8566d71..7c296d116968ae059c75920c91059f6e
fail_if(recv_status != task->recv, "%s: Expected return of %d, got %d",
task->location, task->recv, recv_status);
--
2.5.0
2.7.3

View File

@ -1,7 +1,7 @@
From 9d620a935122683e0e6d19953484084a9feb21f5 Mon Sep 17 00:00:00 2001
From 2e4795b1b93ee740692491c8c4010e9103a0ecca Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Tue, 10 Nov 2015 07:41:10 +0000
Subject: [PATCH 103/103] FAIL_OVER: Fix warning value computed is not used
Subject: [PATCH 092/108] FAIL_OVER: Fix warning value computed is not used
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -11,12 +11,13 @@ src/providers/fail_over.c:861: warning: value computed is not used
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit acd615cffd144b69e2558a0fc45c6966423f2d02)
(cherry picked from commit d0baabaa4e86ef2cf899be5f1369e294688c4b8a)
---
src/providers/fail_over.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index 24aed9dfa469ad730d176244eb329522a43c6fd8..c60310d8f17b129be115a4d3724ac7e54549820e 100644
index 65d4fb690d270fa04a0e22f7db37bd8521ad3ba1..b6f29a2a3e1d389560475ae05a4c9a846d817fdb 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -858,7 +858,7 @@ void fo_ref_server(TALLOC_CTX *ref_ctx,
@ -29,5 +30,5 @@ index 24aed9dfa469ad730d176244eb329522a43c6fd8..c60310d8f17b129be115a4d3724ac7e5
}
--
2.5.0
2.7.3

View File

@ -1,7 +1,7 @@
From bb102b392ff298ecd8a499f6ddc3904c59dcbba2 Mon Sep 17 00:00:00 2001
From 34db150dae50363dd0f551175e160e9c238a251f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Wed, 18 Nov 2015 20:48:51 +0100
Subject: [PATCH 104/104] FO: Use tevent_req_defer_callback() when notifying
Subject: [PATCH 093/108] FO: Use tevent_req_defer_callback() when notifying
callers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -19,13 +19,14 @@ for more details.
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit a92f68763a57b211a1bf6b80b6dd80c4a1aa2738)
(cherry picked from commit bbfc3a4294c6a70426171e080c27c15d9706bec7)
---
src/providers/fail_over.c | 15 +++++++++++--
src/tests/cmocka/test_fo_srv.c | 49 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 59 insertions(+), 5 deletions(-)
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index c60310d..0b99098 100644
index b6f29a2a3e1d389560475ae05a4c9a846d817fdb..e945c9924597c7addeeb11090e1c1aee5596cb71 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -131,6 +131,7 @@ struct resolve_service_request {
@ -79,7 +80,7 @@ index c60310d..0b99098 100644
tevent_req_error(request->req, ret);
} else {
diff --git a/src/tests/cmocka/test_fo_srv.c b/src/tests/cmocka/test_fo_srv.c
index 67f86fb..a84ce43 100644
index 67f86fb17753bf90b88d007a6a1b309df830c152..a84ce4348d2e59aaab4fc9ac1bd4cfd853ff491d 100644
--- a/src/tests/cmocka/test_fo_srv.c
+++ b/src/tests/cmocka/test_fo_srv.c
@@ -575,10 +575,10 @@ static void test_fo_srv_before(struct tevent_req *req)
@ -162,5 +163,5 @@ index 67f86fb..a84ce43 100644
test_ctx->ctx->error = ERR_OK;
test_ctx->ctx->done = true;
--
2.5.0
2.7.3

View File

@ -0,0 +1,58 @@
From 1e596a5b6e72cfca67a3eeb7d9098d015a295545 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Mon, 19 Oct 2015 15:38:08 +0200
Subject: [PATCH 094/108] util: Continue if setlocale fails
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
setlocale needs some environment variables
to be set in order to work. These variables
are not present in some special cases. We
should not fail completely in these cases
but continue with the compatible C locale.
Resolves:
https://fedorahosted.org/sssd/ticket/2785
Reviewed-by: Michal Židek <mzidek@redhat.com>
(cherry picked from commit 43e06ff39584570817949dc5de118d2b7ca854c1)
(cherry picked from commit 4815471669a25566f6772c228c104a206ffa37f7)
---
src/sss_client/ssh/sss_ssh_client.c | 4 +++-
src/tools/tools_util.c | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/sss_client/ssh/sss_ssh_client.c b/src/sss_client/ssh/sss_ssh_client.c
index 0d206ef58f3a1353a8e066c272df0cf4e22ec4db..a198039ec4e2820ad388be41400411753459ecc9 100644
--- a/src/sss_client/ssh/sss_ssh_client.c
+++ b/src/sss_client/ssh/sss_ssh_client.c
@@ -50,7 +50,9 @@ int set_locale(void)
c = setlocale(LC_ALL, "");
if (c == NULL) {
- return EIO;
+ /* If setlocale fails, continue with the default
+ * locale. */
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to set locale\n");
}
errno = 0;
diff --git a/src/tools/tools_util.c b/src/tools/tools_util.c
index 3112171a6c06a50b7099f1c1b58ea1ad581c7cb3..82462f30690e4f695477eb5cc1aa4039c05109f9 100644
--- a/src/tools/tools_util.c
+++ b/src/tools/tools_util.c
@@ -259,7 +259,9 @@ int set_locale(void)
c = setlocale(LC_ALL, "");
if (c == NULL) {
- return EIO;
+ /* If setlocale fails, continue with the default
+ * locale. */
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to set locale\n");
}
errno = 0;
--
2.7.3

View File

@ -0,0 +1,48 @@
From 74c322cbc35889057af2e06b3941bb9cbde864a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Mon, 19 Oct 2015 15:49:02 +0200
Subject: [PATCH 095/108] server_setup: Log failed attempt to set locale
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Failed setlocale call could cause unexpected
behaviour. It is better to generate DEBUG
message if this happens.
Reviewed-by: Michal Židek <mzidek@redhat.com>
(cherry picked from commit a0c8aae6b31867f29e83e4f8a2a7ef037a82569e)
(cherry picked from commit 76ab3eb947f4d6fe6555d8ea0ae97dc3966f02ac)
---
src/util/server.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/util/server.c b/src/util/server.c
index 7e9b76f74ee5e76d2481eb425eff4811cc2e780e..7aa8d809663fe562a6ac25fc0f0ce7eddfcb4166 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -458,6 +458,7 @@ int server_setup(const char *name, int flags,
bool dm;
struct tevent_signal *tes;
struct logrotate_ctx *lctx;
+ char *locale;
ret = chown_debug_file(NULL, uid, gid);
if (ret != EOK) {
@@ -509,7 +510,12 @@ int server_setup(const char *name, int flags,
}
/* Set up locale */
- setlocale(LC_ALL, "");
+ locale = setlocale(LC_ALL, "");
+ if (locale == NULL) {
+ /* Just print debug message and continue */
+ DEBUG(SSSDBG_TRACE_FUNC, "Unable to set locale\n");
+ }
+
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
--
2.7.3

View File

@ -0,0 +1,35 @@
From d2752b748ab490438214fdb5b6e7d3ce476f4999 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Tue, 20 Oct 2015 18:18:01 +0200
Subject: [PATCH 096/108] tests: Run intgcheck without libsemanage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For now the libsemanage can not be used inside
intgcheck tests. See the tracking ticket
for this issue:
https://fedorahosted.org/sssd/ticket/2859
Reviewed-by: Michal Židek <mzidek@redhat.com>
(cherry picked from commit f1b9f9370b50a3d001722737f2538f5d3bb40e9c)
(cherry picked from commit 46a4ce2c853af464f24de63283fb8aa8a8460540)
---
Makefile.am | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile.am b/Makefile.am
index 9bd5d0ba895bf699c0b9a46f86419adbd266aece..8eb19ac2765d95747809d28d2625b5b8860e7449 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2709,6 +2709,7 @@ intgcheck:
--prefix="$$prefix" \
--with-ldb-lib-dir="$$prefix"/lib/ldb \
--enable-intgcheck-reqs \
+ --without-semanage \
$(INTGCHECK_CONFIGURE_FLAGS); \
$(MAKE) $(AM_MAKEFLAGS); \
: Force single-thread install to workaround concurrency issues; \
--
2.7.3

View File

@ -0,0 +1,165 @@
From 30bb28a7d8bea694fda7b745607eb1aacfa0af90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Tue, 20 Oct 2015 15:03:22 +0200
Subject: [PATCH 097/108] tests: Regression test with wrong LC_ALL
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ticket:
https://fedorahosted.org/sssd/ticket/2785
Test local domain tool with wrong LC_ALL
environment variable value.
NOTE: The memory cache files are not deleted
properly in the test teardown to work around the
problem described in ticket
https://fedorahosted.org/sssd/ticket/2726
Once the ticket above is solved, the teardown
will be updated to remove the memory cache
files.
Reviewed-by: Michal Židek <mzidek@redhat.com>
(cherry picked from commit 586f512ab8b6e5a03349598846141f43c1d505b8)
(cherry picked from commit 03f6667741bf111f0e50c8f2c4323e45ce53f707)
---
src/tests/intg/Makefile.am | 1 +
src/tests/intg/test_local_domain.py | 112 ++++++++++++++++++++++++++++++++++++
2 files changed, 113 insertions(+)
create mode 100644 src/tests/intg/test_local_domain.py
diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am
index f21880b61bfb07ac1dca65deda70fc50b4943586..7394997319142d581237ab8a37270bfd7bc974ca 100644
--- a/src/tests/intg/Makefile.am
+++ b/src/tests/intg/Makefile.am
@@ -8,6 +8,7 @@ dist_noinst_DATA = \
ldap_ent.py \
ldap_local_override_test.py \
ldap_test.py \
+ test_local_domain.py \
util.py \
test_memory_cache.py \
$(NULL)
diff --git a/src/tests/intg/test_local_domain.py b/src/tests/intg/test_local_domain.py
new file mode 100644
index 0000000000000000000000000000000000000000..c62de16ce04b640503250c926d6eb3d199ed0728
--- /dev/null
+++ b/src/tests/intg/test_local_domain.py
@@ -0,0 +1,112 @@
+#
+# SSSD LOCAL domain tests
+#
+# Copyright (c) 2015 Red Hat, Inc.
+# Author: Michal Zidek <mzidek@redhat.com>
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 only
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+import os
+import stat
+import pwd
+import time
+import config
+import signal
+import subprocess
+import pytest
+from util import unindent
+
+
+def stop_sssd():
+ pid_file = open(config.PIDFILE_PATH, "r")
+ pid = int(pid_file.read())
+ os.kill(pid, signal.SIGTERM)
+ while True:
+ try:
+ os.kill(pid, signal.SIGCONT)
+ except:
+ break
+ time.sleep(1)
+
+
+def create_conf_fixture(request, contents):
+ """Generate sssd.conf and add teardown for removing it"""
+ conf = open(config.CONF_PATH, "w")
+ conf.write(contents)
+ conf.close()
+ os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR)
+ request.addfinalizer(lambda: os.unlink(config.CONF_PATH))
+
+
+def create_sssd_fixture(request):
+ """Start sssd and add teardown for stopping it and removing state"""
+ if subprocess.call(["sssd", "-D", "-f"]) != 0:
+ raise Exception("sssd start failed")
+
+ def teardown():
+ try:
+ stop_sssd()
+ except:
+ pass
+ subprocess.call(["sss_cache", "-E"])
+ for path in os.listdir(config.DB_PATH):
+ os.unlink(config.DB_PATH + "/" + path)
+ # FIXME: Uncomment this when ticket #2726 is solved
+ # https://fedorahosted.org/sssd/ticket/2726
+ # for path in os.listdir(config.MCACHE_PATH):
+ # os.unlink(config.MCACHE_PATH + "/" + path)
+ request.addfinalizer(teardown)
+
+
+@pytest.fixture
+def local_domain_only(request):
+ conf = unindent("""\
+ [sssd]
+ domains = LOCAL
+ services = nss
+
+ [nss]
+ memcache_timeout = 0
+
+ [domain/LOCAL]
+ id_provider = local
+ min_id = 10000
+ max_id = 20000
+ """).format(**locals())
+ create_conf_fixture(request, conf)
+ create_sssd_fixture(request)
+ return None
+
+
+def assert_nonexistent_user(name):
+ with pytest.raises(KeyError):
+ pwd.getpwnam(name)
+
+
+def test_wrong_LC_ALL(local_domain_only):
+ """
+ Regression test for ticket
+ https://fedorahosted.org/sssd/ticket/2785
+
+ """
+ subprocess.check_call(["sss_useradd", "foo", "-M"])
+ pwd.getpwnam("foo")
+
+ # Change the LC_ALL variable to nonexistent locale
+ oldvalue = os.environ.get("LC_ALL", "")
+ os.environ["LC_ALL"] = "nonexistent_locale"
+
+ # sss_userdel must remove the user despite wrong LC_ALL
+ subprocess.check_call(["sss_userdel", "foo", "-R"])
+ assert_nonexistent_user("foo")
+ os.environ["LC_LOCAL"] = oldvalue
--
2.7.3

View File

@ -0,0 +1,47 @@
From 0f98c882b70a9011d488228b36df42cf320f62bf Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Fri, 19 Feb 2016 15:50:12 +0100
Subject: [PATCH 098/108] memberof: Don't allocate on a NULL context
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://fedorahosted.org/sssd/ticket/2959
In case no previous delete operation occured, the del_ctx->muops pointer we
allocate the diff structure was would be NULL, effectivelly leaking the
diff array during the memberof processing.
Allocating on del_ctx is safer as that pointer is always allocated and
prevents the leak.
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit cd7a272fb361626a45d54cd45daaab4bfe7ad93f)
---
src/ldb_modules/memberof.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 83d93196c34854d75fcd8ac91ad056f64b26b659..54e4b3ee2c74b746e8871cb3bb211bfcb25752e0 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -2145,7 +2145,7 @@ static int mbof_del_mod_entry(struct mbof_del_operation *delop)
if (!el || !el->num_values) {
return LDB_ERR_OPERATIONS_ERROR;
}
- diff = talloc_array(del_ctx->muops, struct ldb_dn *,
+ diff = talloc_array(del_ctx, struct ldb_dn *,
el->num_values + 1);
if (!diff) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -2241,6 +2241,7 @@ static int mbof_del_mod_entry(struct mbof_del_operation *delop)
if (ret != LDB_SUCCESS) {
return ret;
}
+ talloc_steal(del_ctx->muops, diff[i]);
}
}
--
2.7.3

View File

@ -0,0 +1,85 @@
From 8891e70a4ff58c271729523da59633744a6bcb54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 1 Mar 2016 14:00:26 +0100
Subject: [PATCH 099/108] IPA SUDO: download externalUser attribute
This allows configuration with id_provider = proxy
and sudo_provider = ipa when someone needs to fetch
rules for local users.
https://fedorahosted.org/sssd/ticket/2972
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 991c9f47fcb24704b880f60ab8ee77cfda056e2c)
(cherry picked from commit d4d2ffa6cf967231ae725973ee2665dbd0e2391b)
---
src/config/etc/sssd.api.d/sssd-ipa.conf | 1 +
src/db/sysdb_sudo.h | 1 +
src/providers/ipa/ipa_common.h | 1 +
src/providers/ipa/ipa_opts.c | 1 +
src/providers/ipa/ipa_sudo_conversion.c | 1 +
5 files changed, 5 insertions(+)
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 8cd20c0c621a513ca7bc85be6908de41d024b148..67a46102b4e8dfff2b44b21ac18c0ad8822d7f3a 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -258,6 +258,7 @@ ipa_sudorule_runasgroupcategory = str, None, false
ipa_sudorule_runasextuser = str, None, false
ipa_sudorule_runasextgroup = str, None, false
ipa_sudorule_runasextusergroup = str, None, false
+ipa_sudorule_externaluser = str, None, false
ipa_sudorule_entry_usn = str, None, false
ipa_sudocmdgroup_object_class = str, None, false
ipa_sudocmdgroup_uuid = str, None, false
diff --git a/src/db/sysdb_sudo.h b/src/db/sysdb_sudo.h
index ba90a68512c6c29134ab2f746220db9533a93dda..515f45ab8b8f51cf7b1d27c1ba28ed8182bce6c0 100644
--- a/src/db/sysdb_sudo.h
+++ b/src/db/sysdb_sudo.h
@@ -68,6 +68,7 @@
#define SYSDB_IPA_SUDORULE_RUNASEXTUSER "ipaSudoRunAsExtUser"
#define SYSDB_IPA_SUDORULE_RUNASEXTGROUP "ipaSudoRunAsExtGroup"
#define SYSDB_IPA_SUDORULE_RUNASEXTUSERGROUP "ipaSudoRunAsExtUserGroup"
+#define SYSDB_IPA_SUDORULE_EXTUSER "externalUser"
#define SYSDB_IPA_SUDOCMDGROUP_OC "ipasudocmdgrp"
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
index 24898ee3809b0bcb682321ba4cfa500acd7c795b..d1688bb6a226cd45318dd22380d0ff73d9b2ec47 100644
--- a/src/providers/ipa/ipa_common.h
+++ b/src/providers/ipa/ipa_common.h
@@ -156,6 +156,7 @@ enum ipa_sudorule_attrs {
IPA_AT_SUDORULE_RUNASEXTUSER,
IPA_AT_SUDORULE_RUNASEXTGROUP,
IPA_AT_SUDORULE_RUNASEXTUSERGROUP,
+ IPA_AT_SUDORULE_EXTUSER,
IPA_AT_SUDORULE_ENTRYUSN,
IPA_OPTS_SUDORULE
diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
index fe469852b527ad872502b3346c8c11ef9eea3bcd..5b0b44e2493ebba0f0cfdb63894a7c75533fc959 100644
--- a/src/providers/ipa/ipa_opts.c
+++ b/src/providers/ipa/ipa_opts.c
@@ -361,6 +361,7 @@ struct sdap_attr_map ipa_sudorule_map[] = {
{ "ipa_sudorule_runasextuser", "ipaSudoRunAsExtUser", SYSDB_IPA_SUDORULE_RUNASEXTUSER, NULL },
{ "ipa_sudorule_runasextgroup", "ipaSudoRunAsExtGroup", SYSDB_IPA_SUDORULE_RUNASEXTGROUP, NULL },
{ "ipa_sudorule_runasextusergroup", "ipaSudoRunAsExtUserGroup", SYSDB_IPA_SUDORULE_RUNASEXTUSERGROUP, NULL },
+ { "ipa_sudorule_externaluser", "externalUser", SYSDB_IPA_SUDORULE_EXTUSER, NULL },
{ "ipa_sudorule_entry_usn", "entryUSN", SYSDB_USN, NULL },
SDAP_ATTR_MAP_TERMINATOR
};
diff --git a/src/providers/ipa/ipa_sudo_conversion.c b/src/providers/ipa/ipa_sudo_conversion.c
index 02d7ebd5dd819f54b6d97b2251eca294d95a224b..ff63551c045003bc81c440ee63aeb28f3fe06647 100644
--- a/src/providers/ipa/ipa_sudo_conversion.c
+++ b/src/providers/ipa/ipa_sudo_conversion.c
@@ -809,6 +809,7 @@ convert_attributes(struct ipa_sudo_conv *conv,
{SYSDB_IPA_SUDORULE_RUNASEXTUSER, SYSDB_SUDO_CACHE_AT_RUNASUSER , NULL},
{SYSDB_IPA_SUDORULE_RUNASEXTGROUP, SYSDB_SUDO_CACHE_AT_RUNASGROUP , NULL},
{SYSDB_IPA_SUDORULE_RUNASEXTUSERGROUP, SYSDB_SUDO_CACHE_AT_RUNASUSER , convert_runasextusergroup},
+ {SYSDB_IPA_SUDORULE_EXTUSER, SYSDB_SUDO_CACHE_AT_USER , NULL},
{SYSDB_IPA_SUDORULE_ALLOWCMD, SYSDB_IPA_SUDORULE_ORIGCMD , NULL},
{SYSDB_IPA_SUDORULE_DENYCMD, SYSDB_IPA_SUDORULE_ORIGCMD , NULL},
{NULL, NULL, NULL}};
--
2.7.3

View File

@ -0,0 +1,201 @@
From 3d996e218cf24b85a4637d90bd0aeac6a95cd9cf Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Sat, 5 Mar 2016 15:15:20 +0100
Subject: [PATCH 100/108] UTIL: Fix indentation in dlinklist.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Reviewed-by: Michal Židek <mzidek@redhat.com>
(cherry picked from commit fee2997ff25938bca8dd8e3df1d6a5a44b5b7698)
(cherry picked from commit 52d29d5778114afb605fca36efeba2c99f3bff5f)
---
src/util/dlinklist.h | 130 +++++++++++++++++++++++++--------------------------
1 file changed, 65 insertions(+), 65 deletions(-)
diff --git a/src/util/dlinklist.h b/src/util/dlinklist.h
index ef09661f4be4d6e973173887f7790f214bf0f1dd..e8490496c4d8a8018edbeec776b2f09d2066236c 100644
--- a/src/util/dlinklist.h
+++ b/src/util/dlinklist.h
@@ -27,112 +27,112 @@
/* hook into the front of the list */
#define DLIST_ADD(list, p) \
do { \
- if (!(list)) { \
- (list) = (p); \
- (p)->next = (p)->prev = NULL; \
- } else { \
- (list)->prev = (p); \
- (p)->next = (list); \
- (p)->prev = NULL; \
- (list) = (p); \
- }\
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ (list)->prev = (p); \
+ (p)->next = (list); \
+ (p)->prev = NULL; \
+ (list) = (p); \
+ } \
} while (0)
/* remove an element from a list - element doesn't have to be in list. */
#define DLIST_REMOVE(list, p) \
do { \
- if ((p) == (list)) { \
- (list) = (p)->next; \
- if (list) (list)->prev = NULL; \
- } else { \
- if ((p)->prev) (p)->prev->next = (p)->next; \
- if ((p)->next) (p)->next->prev = (p)->prev; \
- } \
- if ((p) != (list)) (p)->next = (p)->prev = NULL; \
+ if ((p) == (list)) { \
+ (list) = (p)->next; \
+ if (list) (list)->prev = NULL; \
+ } else { \
+ if ((p)->prev) (p)->prev->next = (p)->next; \
+ if ((p)->next) (p)->next->prev = (p)->prev; \
+ } \
+ if ((p) != (list)) (p)->next = (p)->prev = NULL; \
} while (0)
/* promote an element to the top of the list */
#define DLIST_PROMOTE(list, p) \
do { \
- DLIST_REMOVE(list, p); \
- DLIST_ADD(list, p); \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD(list, p); \
} while (0)
/* hook into the end of the list - needs a tmp pointer */
#define DLIST_ADD_END(list, p, type) \
do { \
- if (!(list)) { \
- (list) = (p); \
- (p)->next = (p)->prev = NULL; \
- } else { \
- type tmp; \
- for (tmp = (list); tmp->next; tmp = tmp->next) { \
- /* no op */ \
- } \
- tmp->next = (p); \
- (p)->next = NULL; \
- (p)->prev = tmp; \
- } \
+ if (!(list)) { \
+ (list) = (p); \
+ (p)->next = (p)->prev = NULL; \
+ } else { \
+ type tmp; \
+ for (tmp = (list); tmp->next; tmp = tmp->next) { \
+ /* no op */ \
+ } \
+ tmp->next = (p); \
+ (p)->next = NULL; \
+ (p)->prev = tmp; \
+ } \
} while (0)
/* insert 'p' after the given element 'el' in a list. If el is NULL then
this is the same as a DLIST_ADD() */
#define DLIST_ADD_AFTER(list, p, el) \
do { \
- if (!(list) || !(el)) { \
- DLIST_ADD(list, p); \
- } else { \
- p->prev = el; \
- p->next = el->next; \
- el->next = p; \
- if (p->next) p->next->prev = p; \
- }\
+ if (!(list) || !(el)) { \
+ DLIST_ADD(list, p); \
+ } else { \
+ p->prev = el; \
+ p->next = el->next; \
+ el->next = p; \
+ if (p->next) p->next->prev = p; \
+ } \
} while (0)
/* demote an element to the end of the list, needs a tmp pointer */
#define DLIST_DEMOTE(list, p, type) \
do { \
- DLIST_REMOVE(list, p); \
- DLIST_ADD_END(list, p, type); \
+ DLIST_REMOVE(list, p); \
+ DLIST_ADD_END(list, p, type); \
} while (0)
/* concatenate two lists - putting all elements of the 2nd list at the
end of the first list */
#define DLIST_CONCATENATE(list1, list2, type) \
do { \
- if (!(list1)) { \
- (list1) = (list2); \
- } else { \
- type tmp; \
- for (tmp = (list1); tmp->next; tmp = tmp->next) { \
- /* no op */ \
- } \
- tmp->next = (list2); \
- if (list2) { \
- (list2)->prev = tmp; \
- } \
- } \
+ if (!(list1)) { \
+ (list1) = (list2); \
+ } else { \
+ type tmp; \
+ for (tmp = (list1); tmp->next; tmp = tmp->next) { \
+ /* no op */ \
+ } \
+ tmp->next = (list2); \
+ if (list2) { \
+ (list2)->prev = tmp; \
+ } \
+ } \
} while (0)
/* insert all elements from list2 after the given element 'el' in the
* first list */
#define DLIST_ADD_LIST_AFTER(list1, el, list2, type) \
do { \
- if (!(list1) || !(el) || !(list2)) { \
- DLIST_CONCATENATE(list1, list2, type); \
- } else { \
- type tmp; \
- for (tmp = (list2); tmp->next; tmp = tmp->next) { \
- /* no op */ \
- } \
- (list2)->prev = (el); \
- tmp->next = (el)->next; \
- (el)->next = (list2); \
- if (tmp->next != NULL) tmp->next->prev = tmp; \
+ if (!(list1) || !(el) || !(list2)) { \
+ DLIST_CONCATENATE(list1, list2, type); \
+ } else { \
+ type tmp; \
+ for (tmp = (list2); tmp->next; tmp = tmp->next) { \
+ /* no op */ \
+ } \
+ (list2)->prev = (el); \
+ tmp->next = (el)->next; \
+ (el)->next = (list2); \
+ if (tmp->next != NULL) tmp->next->prev = tmp; \
} \
} while (0);
#define DLIST_FOR_EACH(p, list) \
- for ((p) = (list); (p) != NULL; (p) = (p)->next)
+ for ((p) = (list); (p) != NULL; (p) = (p)->next)
#endif /* _DLINKLIST_H */
--
2.7.3

View File

@ -0,0 +1,145 @@
From 495ed57f10c184daf5b68f347dac0be01ca6841b Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Sat, 5 Mar 2016 15:31:04 +0100
Subject: [PATCH 101/108] UTIL: Fix warning misleading-indentation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Warnings are emited from macro generated code in dlinklist.h
e.g.
src/ldb_modules/memberof.c:4209:13: error: statement is indented as if it were
guarded by... [-Werror=misleading-indentation]
DLIST_DEMOTE(ctx->group_list, grp, struct mbof_member *);
^~~~~~~~~~~~
src/ldb_modules/memberof.c:4209:13: note: ...this if clause, but it is not
src/ldb_modules/memberof.c: In function mbof_member_update:
src/ldb_modules/memberof.c:4305:9: error: statement is indented as if it were
guarded by... [-Werror=misleading-indentation]
DLIST_PROMOTE(ctx->group_list, mem);
^~~~~~~~~~~~~
src/ldb_modules/memberof.c:4305:9: note: ...this if clause, but it is not
src/ldb_modules/memberof.c: In function mbof_rcmp_update:
src/ldb_modules/memberof.c:4408:9: error: statement is indented as if it were
guarded by... [-Werror=misleading-indentation]
DLIST_REMOVE(ctx->user_list, x);
^~~~~~~~~~~~
src/util/crypto/nss/nss_obfuscate.c: In function sss_password_decrypt:
src/util/crypto/nss/nss_obfuscate.c:419:5: error: statement is indented
as if it were guarded by... [-Werror=misleading-indentation]
SAFEALIGN_COPY_UINT16_CHECK(&meth, obfbuf+p, obflen, &p);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/python/pyhbac.c: In function PyInit_pyhbac:
src/python/pyhbac.c:1987:5: error: statement is indented as if it were
guarded by... [-Werror=misleading-indentation]
TYPE_READY(m, pyhbac_hbacrule_type, "HbacRule");
^~~~~~~~~~
src/python/pyhbac.c:1987:5: note: ...this if clause, but it is not
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Reviewed-by: Michal Židek <mzidek@redhat.com>
(cherry picked from commit c6278b2fa4a7ea389ed4086b2def16e0e6cbb184)
(cherry picked from commit 19580e01096f8a57e37414ef3f5f2d0a6528da34)
---
src/util/dlinklist.h | 24 ++++++++++++++++++------
src/util/sss_python.h | 5 +++--
src/util/util_safealign.h | 6 +++---
3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/src/util/dlinklist.h b/src/util/dlinklist.h
index e8490496c4d8a8018edbeec776b2f09d2066236c..4f6aef830e914c22654970081263d43461c1750f 100644
--- a/src/util/dlinklist.h
+++ b/src/util/dlinklist.h
@@ -43,12 +43,20 @@ do { \
do { \
if ((p) == (list)) { \
(list) = (p)->next; \
- if (list) (list)->prev = NULL; \
+ if (list) { \
+ (list)->prev = NULL; \
+ } \
} else { \
- if ((p)->prev) (p)->prev->next = (p)->next; \
- if ((p)->next) (p)->next->prev = (p)->prev; \
+ if ((p)->prev) { \
+ (p)->prev->next = (p)->next; \
+ } \
+ if ((p)->next) { \
+ (p)->next->prev = (p)->prev; \
+ } \
+ } \
+ if ((p) != (list)) { \
+ (p)->next = (p)->prev = NULL; \
} \
- if ((p) != (list)) (p)->next = (p)->prev = NULL; \
} while (0)
/* promote an element to the top of the list */
@@ -85,7 +93,9 @@ do { \
p->prev = el; \
p->next = el->next; \
el->next = p; \
- if (p->next) p->next->prev = p; \
+ if (p->next) { \
+ p->next->prev = p; \
+ } \
} \
} while (0)
@@ -128,7 +138,9 @@ do { \
(list2)->prev = (el); \
tmp->next = (el)->next; \
(el)->next = (list2); \
- if (tmp->next != NULL) tmp->next->prev = tmp; \
+ if (tmp->next != NULL) { \
+ tmp->next->prev = tmp; \
+ } \
} \
} while (0);
diff --git a/src/util/sss_python.h b/src/util/sss_python.h
index 7e2bac33656dcbac91bb4f4d32ec9fbc44bb4e52..b3fdaad646af430de6ad8fde7dd66efa608aa89a 100644
--- a/src/util/sss_python.h
+++ b/src/util/sss_python.h
@@ -31,8 +31,9 @@ sss_exception_with_doc(char *name, char *doc, PyObject *base, PyObject *dict);
/* Convenience macros */
#define TYPE_READY(module, type, name) do { \
- if (PyType_Ready(&type) < 0) \
- MODINITERROR; \
+ if (PyType_Ready(&type) < 0) { \
+ MODINITERROR; \
+ } \
Py_INCREF(&type); \
PyModule_AddObject(module, \
discard_const_p(char, name), \
diff --git a/src/util/util_safealign.h b/src/util/util_safealign.h
index ba216f6063a34524c40f961115d79b40ec4e1641..b1c9f8a0c11f4d13fca885aa4e28e7c4750f37fe 100644
--- a/src/util/util_safealign.h
+++ b/src/util/util_safealign.h
@@ -103,19 +103,19 @@ safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter)
* would excceed len. */
#define SAFEALIGN_COPY_UINT32_CHECK(dest, src, len, pctr) do { \
if ((*(pctr) + sizeof(uint32_t)) > (len) || \
- SIZE_T_OVERFLOW(*(pctr), sizeof(uint32_t))) return EINVAL; \
+ SIZE_T_OVERFLOW(*(pctr), sizeof(uint32_t))) { return EINVAL; } \
safealign_memcpy(dest, src, sizeof(uint32_t), pctr); \
} while(0)
#define SAFEALIGN_COPY_INT32_CHECK(dest, src, len, pctr) do { \
if ((*(pctr) + sizeof(int32_t)) > (len) || \
- SIZE_T_OVERFLOW(*(pctr), sizeof(int32_t))) return EINVAL; \
+ SIZE_T_OVERFLOW(*(pctr), sizeof(int32_t))) { return EINVAL; } \
safealign_memcpy(dest, src, sizeof(int32_t), pctr); \
} while(0)
#define SAFEALIGN_COPY_UINT16_CHECK(dest, src, len, pctr) do { \
if ((*(pctr) + sizeof(uint16_t)) > (len) || \
- SIZE_T_OVERFLOW(*(pctr), sizeof(uint16_t))) return EINVAL; \
+ SIZE_T_OVERFLOW(*(pctr), sizeof(uint16_t))) { return EINVAL; } \
safealign_memcpy(dest, src, sizeof(uint16_t), pctr); \
} while(0)
--
2.7.3

View File

@ -0,0 +1,646 @@
From b060ad6f32d5b0543e4bb6ae3c431a765e1122c1 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Fri, 4 Mar 2016 20:08:30 +0100
Subject: [PATCH 102/108] tests: Add a unit test for the external groups
resolution
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Adds a test that tests a complex nested group hierarchy. Also defines
the talloc chunk for group members to 1 to make sure the realloc branch
is always tested.
Unit test for: https://fedorahosted.org/sssd/ticket/2522
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit c6bda70d6131b5e8cd760ad690fae001d1765547)
(cherry picked from commit 663572daaaff96c6364eadc37f9b0475ad02d34e)
---
Makefile.am | 1 +
src/providers/ldap/sdap_async_nested_groups.c | 10 +-
src/tests/cmocka/test_nested_groups.c | 526 ++++++++++++++++++++++++++
3 files changed, 533 insertions(+), 4 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 8eb19ac2765d95747809d28d2625b5b8860e7449..5c6852821f2e49624d46cb88a50a7b0866684dd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2098,6 +2098,7 @@ nestedgroups_tests_SOURCES = \
$(NULL)
nestedgroups_tests_CFLAGS = \
$(AM_CFLAGS) \
+ -DEXTERNAL_MEMBERS_CHUNK=1 \
$(NULL)
nestedgroups_tests_LDADD = \
$(CMOCKA_LIBS) \
diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c
index f0d04fa0948abd58470785d07b8d42f3cfeb9eb0..e32c06a144ff534c97ebcf6bf54e65cff0a1b608 100644
--- a/src/providers/ldap/sdap_async_nested_groups.c
+++ b/src/providers/ldap/sdap_async_nested_groups.c
@@ -56,7 +56,9 @@ struct sdap_nested_group_member {
const char *group_filter;
};
-const size_t external_members_chunk = 16;
+#ifndef EXTERNAL_MEMBERS_CHUNK
+#define EXTERNAL_MEMBERS_CHUNK 16
+#endif /* EXTERNAL_MEMBERS_CHUNK */
struct sdap_external_missing_member {
const char **parent_group_dns;
@@ -341,7 +343,7 @@ static errno_t sdap_nested_group_external_add(hash_table_t *table,
}
ext_mem->parent_group_dns = talloc_zero_array(ext_mem,
const char *,
- external_members_chunk);
+ EXTERNAL_MEMBERS_CHUNK);
if (ext_mem->parent_group_dns == NULL) {
talloc_free(ext_mem);
return ENOMEM;
@@ -363,7 +365,7 @@ static errno_t sdap_nested_group_external_add(hash_table_t *table,
ext_mem->parent_group_dns,
const char *,
ext_mem->parent_dn_idx + \
- external_members_chunk);
+ EXTERNAL_MEMBERS_CHUNK);
if (ext_mem->parent_group_dns == NULL) {
talloc_free(ext_mem);
return ENOMEM;
@@ -2608,7 +2610,7 @@ sdap_nested_group_lookup_external_done(struct tevent_req *subreq)
&member);
talloc_free(subreq);
if (ret == EOK) {
- DEBUG(SSSDBG_TRACE_FUNC, "Refreshing member %lu\n", state->eniter);
+ DEBUG(SSSDBG_TRACE_FUNC, "Refreshed member %lu\n", state->eniter);
state->ext_members[state->eniter].missing_mem = \
state->entries[state->eniter].value.ptr;
state->ext_members[state->eniter].dom = member_dom;
diff --git a/src/tests/cmocka/test_nested_groups.c b/src/tests/cmocka/test_nested_groups.c
index a3345ef5e087fc90466ce8400dda549fa5d79af8..884965c9108ef159997936027ec8a0bc5bcd0708 100644
--- a/src/tests/cmocka/test_nested_groups.c
+++ b/src/tests/cmocka/test_nested_groups.c
@@ -36,6 +36,7 @@
#define TEST_CONF_DB "test_ldap_nested_groups_conf.ldb"
#define TEST_DOM_NAME "ldap_nested_groups_test"
#define TEST_ID_PROVIDER "ldap"
+#define TEST_EXT_MEMBER "extMember"
#define new_test(test) \
cmocka_unit_test_setup_teardown(nested_groups_test_ ## test, \
@@ -63,6 +64,12 @@ struct nested_groups_test_ctx {
struct sysdb_attrs **groups;
unsigned long num_users;
unsigned long num_groups;
+
+ /* External members tests */
+ struct sdap_ext_member_ctx *ext_ctx;
+ enum sysdb_member_type ext_member_type;
+ struct sss_domain_info *ext_dom;
+ struct sysdb_attrs *ext_member;
};
errno_t krb5_try_kdcip(struct confdb_ctx *cdb,
@@ -615,6 +622,10 @@ static int nested_groups_test_setup(void **state)
ret = sdap_idmap_init(test_ctx, test_ctx->sdap_id_ctx, &test_ctx->idmap_ctx);
assert_int_equal(ret, EOK);
test_ctx->sdap_opts->idmap_ctx = test_ctx->idmap_ctx;
+
+ test_ctx->ext_ctx = talloc_zero(test_ctx, struct sdap_ext_member_ctx);
+ assert_non_null(test_ctx->ext_ctx);
+
return 0;
}
@@ -624,6 +635,518 @@ static int nested_groups_test_teardown(void **state)
return 0;
}
+struct test_ext_pvt {
+ struct sss_domain_info *dom_head;
+};
+
+struct test_ext_member {
+ const char *sid;
+ const char *name;
+ id_t id;
+ enum sysdb_member_type member_type;
+} test_ext_member_table[] = {
+ { "S-1-5-21-3623811015-3361044348-30300820-10001",
+ "ext_user10001", 10001, SYSDB_MEMBER_USER },
+ { "S-1-5-21-3623811015-3361044348-30300820-20001",
+ "ext_group20001", 10001, SYSDB_MEMBER_GROUP },
+ { NULL, NULL, 0, 0 },
+};
+
+struct test_resolve_ext_state {
+ struct sss_domain_info *dom;
+ enum sysdb_member_type member_type;
+ struct sysdb_attrs *member;
+};
+
+static errno_t test_resolve_ext_save_obj(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *dom,
+ const char *name,
+ id_t id,
+ enum sysdb_member_type member_type,
+ struct sysdb_attrs **_member);
+
+struct tevent_req *test_resolve_ext_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *ext_member,
+ void *pvt)
+{
+ struct tevent_req *req;
+ struct test_resolve_ext_state *state;
+ errno_t ret;
+ struct test_ext_pvt *test_pvt = talloc_get_type(pvt, struct test_ext_pvt);
+ struct sysdb_attrs *member;
+
+ req = tevent_req_create(mem_ctx, &state, struct test_resolve_ext_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ for (size_t i = 0; test_ext_member_table[i].sid; i++) {
+ if (strcmp(ext_member, test_ext_member_table[i].sid) == 0) {
+ ret = test_resolve_ext_save_obj(state, test_pvt->dom_head,
+ test_ext_member_table[i].name,
+ test_ext_member_table[i].id,
+ test_ext_member_table[i].member_type,
+ &member);
+ if (ret != EOK) {
+ goto immediate;
+ }
+
+ state->dom = test_pvt->dom_head;
+ state->member_type = test_ext_member_table[i].member_type;
+ state->member = talloc_steal(state, member);
+
+ ret = EOK;
+ goto immediate;
+ }
+ }
+
+ ret = ENOENT;
+
+immediate:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ } else {
+ tevent_req_done(req);
+ }
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static errno_t test_resolve_ext_save_obj(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *dom,
+ const char *name,
+ id_t id,
+ enum sysdb_member_type member_type,
+ struct sysdb_attrs **_member)
+{
+ errno_t ret;
+ struct ldb_result *res;
+ char *home;
+ struct sysdb_attrs **members;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ if (member_type == SYSDB_MEMBER_USER) {
+ home = talloc_asprintf(tmp_ctx, "/home/%s", name);
+ if (home == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_store_user(dom, name, "*", id, id,
+ name, home, "/bin/bash", NULL, NULL,
+ NULL, 1000, time(NULL));
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sysdb_getpwnam(tmp_ctx, dom, name, &res);
+ if (ret != EOK) {
+ goto done;
+ }
+ } else if (member_type == SYSDB_MEMBER_GROUP) {
+ ret = sysdb_store_group(dom, name, id, NULL, 1000, time(NULL));
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = sysdb_getgrnam(tmp_ctx, dom, name, &res);
+ if (ret != EOK) {
+ goto done;
+ }
+ } else {
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = sysdb_msg2attrs(tmp_ctx, 1, res->msgs, &members);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ *_member = talloc_steal(mem_ctx, members[0]);
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static errno_t test_resolve_ext_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ enum sysdb_member_type *_member_type,
+ struct sss_domain_info **_dom,
+ struct sysdb_attrs **_member)
+{
+ struct test_resolve_ext_state *state = tevent_req_data(req,
+ struct test_resolve_ext_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ if (_member_type != NULL) {
+ *_member_type = state->member_type;
+ }
+
+ if (_dom) {
+ *_dom = state->dom;
+ }
+
+ if (_member != NULL) {
+ *_member = talloc_steal(mem_ctx, state->member);
+ }
+
+ return EOK;
+}
+
+static int nested_group_external_member_setup(void **state)
+{
+ struct nested_groups_test_ctx *test_ctx;
+ struct test_ext_pvt *ext_pvt;
+ int ret;
+
+ ret = nested_groups_test_setup((void **) &test_ctx);
+ assert_int_equal(ret, 0);
+
+ ext_pvt = talloc_zero(test_ctx->ext_ctx, struct test_ext_pvt);
+ assert_non_null(ext_pvt);
+ ext_pvt->dom_head = test_ctx->tctx->dom;
+
+ test_ctx->ext_ctx->ext_member_resolve_send = test_resolve_ext_send;
+ test_ctx->ext_ctx->ext_member_resolve_recv = test_resolve_ext_recv;
+ test_ctx->ext_ctx->pvt = ext_pvt;
+
+ *state = test_ctx;
+ return 0;
+}
+
+static int nested_group_external_member_teardown(void **state)
+{
+ struct nested_groups_test_ctx *test_ctx = talloc_get_type(*state,
+ struct nested_groups_test_ctx);
+ errno_t ret;
+ int i;
+
+ ret = sysdb_delete_group(test_ctx->tctx->dom, "rootgroup", 0);
+ if (ret != EOK && ret != ENOENT) {
+ return 1;
+ }
+
+ for (i = 0; test_ext_member_table[i].sid != NULL; i++) {
+ switch (test_ext_member_table[i].member_type) {
+ case SYSDB_MEMBER_USER:
+ ret = sysdb_delete_user(test_ctx->tctx->dom,
+ test_ext_member_table[i].name,
+ 0);
+ break;
+
+ case SYSDB_MEMBER_GROUP:
+ ret = sysdb_delete_group(test_ctx->tctx->dom,
+ test_ext_member_table[i].name,
+ 0);
+ break;
+
+ default:
+ continue;
+ }
+
+ if (ret != EOK && ret != ENOENT) {
+ return 1;
+ }
+ }
+
+ talloc_free(test_ctx->ext_ctx);
+ return nested_groups_test_setup(*state);
+}
+
+static void nested_external_done(struct tevent_req *req)
+{
+ struct nested_groups_test_ctx *ctx = NULL;
+
+ ctx = tevent_req_callback_data(req, struct nested_groups_test_ctx);
+
+ ctx->tctx->error = sdap_nested_group_lookup_external_recv(ctx, req);
+ talloc_zfree(req);
+
+ ctx->tctx->done = true;
+}
+
+static struct sysdb_attrs *
+mock_group_with_ext_members(struct nested_groups_test_ctx *test_ctx,
+ const char *name,
+ gid_t gid,
+ const char *ext_members[])
+{
+ struct sysdb_attrs *ext_group = NULL;
+ const struct sysdb_attrs **ext_group_reply;
+ int i;
+ errno_t ret;
+
+ ext_group_reply = talloc_zero_array(test_ctx,
+ const struct sysdb_attrs *,
+ 2);
+ if (ext_group_reply == NULL) {
+ return NULL;
+ }
+
+ ext_group = mock_sysdb_object(ext_group_reply, GROUP_BASE_DN, name,
+ SYSDB_GIDNUM, gid);
+ if (ext_group == NULL) {
+ talloc_free(ext_group_reply);
+ return NULL;
+ }
+
+ for (i = 0; ext_members[i] != NULL; i++) {
+ ret = sysdb_attrs_add_string(
+ ext_group,
+ test_ctx->sdap_opts->group_map[SDAP_AT_GROUP_EXT_MEMBER].sys_name,
+ ext_members[i]);
+ if (ret != EOK) {
+ talloc_free(ext_group_reply);
+ return NULL;
+ }
+ }
+
+ ext_group_reply[0] = ext_group;
+ will_return(sdap_get_generic_recv, 1);
+ will_return(sdap_get_generic_recv, ext_group_reply);
+ will_return(sdap_get_generic_recv, ERR_OK);
+
+ return ext_group;
+}
+
+static errno_t
+nested_group_test_save_group(struct nested_groups_test_ctx *test_ctx,
+ struct sysdb_attrs *ldap_attrs,
+ struct group *gr)
+{
+ errno_t ret;
+ struct sysdb_attrs *sysdb_grattrs = NULL;
+ const char *s;
+
+ sysdb_grattrs = sysdb_new_attrs(test_ctx);
+ if (sysdb_grattrs == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_get_string(ldap_attrs, SYSDB_ORIG_DN, &s);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sysdb_attrs_add_string(sysdb_grattrs, SYSDB_ORIG_DN, s);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sysdb_store_group(test_ctx->tctx->dom,
+ gr->gr_name, gr->gr_gid,
+ sysdb_grattrs, 0, time(NULL));
+ talloc_free(sysdb_grattrs);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return EOK;
+}
+
+static void nested_group_external_member_test(void **state)
+{
+ struct nested_groups_test_ctx *test_ctx = talloc_get_type(*state,
+ struct nested_groups_test_ctx);
+ struct tevent_req *req;
+ errno_t ret;
+ struct sysdb_attrs *rootgroup_ldap_attrs = NULL;
+ struct sysdb_attrs *nested_group_ldap_attrs = NULL;
+ struct sysdb_attrs *ext_group_ldap_attrs = NULL;
+ struct sysdb_attrs *ext_group_nested_ldap_attrs = NULL;
+ struct ldb_result *res;
+ struct group rootgroup;
+ struct group nested_group;
+ struct group ext_group;
+ struct group ext_group_nested;
+ const char *s;
+ const char *rootgroup_members[] = {
+ "cn=nested_group,"GROUP_BASE_DN,
+ "cn=extgroup,"GROUP_BASE_DN,
+ NULL
+ };
+ const char *nestedgroup_members[] = {
+ "cn=extgroup_nested,"GROUP_BASE_DN,
+ NULL
+ };
+ const char *extgroup_members[] = {
+ "S-1-5-21-3623811015-3361044348-30300820-10001",
+ NULL
+ };
+ const char *extgroup_nested_members[] = {
+ "S-1-5-21-3623811015-3361044348-30300820-10001",
+ "S-1-5-21-3623811015-3361044348-30300820-20001",
+ NULL
+ };
+ const struct sysdb_attrs *nested_group_reply[2] = { NULL };
+ struct ldb_message *msg;
+ struct ldb_message_element *member;
+ const char *sysdb_gr_attrs[] = { SYSDB_MEMBEROF,
+ NULL
+ };
+ TALLOC_CTX *req_mem_ctx = NULL;
+
+ /* LDAP provider doesn't support external groups by default */
+ test_ctx->sdap_opts->group_map[SDAP_AT_GROUP_MEMBER].name = \
+ discard_const(TEST_EXT_MEMBER);
+ test_ctx->sdap_opts->ext_ctx = test_ctx->ext_ctx;
+
+ rootgroup.gr_name = discard_const("rootgroup");
+ rootgroup.gr_gid = 1000;
+ rootgroup_ldap_attrs = mock_sysdb_group_rfc2307bis(test_ctx,
+ GROUP_BASE_DN,
+ rootgroup.gr_gid,
+ rootgroup.gr_name,
+ rootgroup_members);
+ assert_non_null(rootgroup_ldap_attrs);
+
+ nested_group.gr_name = discard_const("nested_group");
+ nested_group.gr_gid = 1001;
+ nested_group_ldap_attrs = mock_sysdb_group_rfc2307bis(test_ctx,
+ GROUP_BASE_DN,
+ nested_group.gr_gid,
+ nested_group.gr_name,
+ nestedgroup_members);
+ assert_non_null(nested_group_ldap_attrs);
+ nested_group_reply[0] = nested_group_ldap_attrs;
+ will_return(sdap_get_generic_recv, 1);
+ will_return(sdap_get_generic_recv, nested_group_reply);
+ will_return(sdap_get_generic_recv, ERR_OK);
+
+ ext_group.gr_name = discard_const("extgroup");
+ ext_group.gr_gid = 2001;
+ ext_group_ldap_attrs = mock_group_with_ext_members(test_ctx,
+ ext_group.gr_name,
+ ext_group.gr_gid,
+ extgroup_members);
+ assert_non_null(ext_group_ldap_attrs);
+
+ ext_group_nested.gr_name = discard_const("extgroup_nested");
+ ext_group_nested.gr_gid = 2002;
+ ext_group_nested_ldap_attrs = mock_group_with_ext_members(test_ctx,
+ ext_group_nested.gr_name,
+ ext_group_nested.gr_gid,
+ extgroup_nested_members);
+ assert_non_null(ext_group_nested_ldap_attrs);
+
+ /* run test, check for memory leaks */
+ req_mem_ctx = talloc_new(global_talloc_context);
+ assert_non_null(req_mem_ctx);
+ check_leaks_push(req_mem_ctx);
+
+ sss_will_return_always(sdap_has_deref_support, false);
+ req = sdap_nested_group_send(test_ctx, test_ctx->tctx->ev,
+ test_ctx->sdap_domain, test_ctx->sdap_opts,
+ test_ctx->sdap_handle, rootgroup_ldap_attrs);
+ assert_non_null(req);
+ tevent_req_set_callback(req, nested_groups_test_done, test_ctx);
+
+ ret = test_ev_loop(test_ctx->tctx);
+ assert_true(check_leaks_pop(req_mem_ctx) == true);
+ talloc_zfree(req_mem_ctx);
+ assert_int_equal(ret, ERR_OK);
+
+ /* Save the groups to sysdb so that external membership code can link
+ * external members against this group
+ */
+ ret = nested_group_test_save_group(test_ctx,
+ rootgroup_ldap_attrs,
+ &rootgroup);
+ assert_int_equal(ret, EOK);
+
+ ret = nested_group_test_save_group(test_ctx,
+ ext_group_ldap_attrs,
+ &ext_group);
+ assert_int_equal(ret, EOK);
+
+ ret = nested_group_test_save_group(test_ctx,
+ nested_group_ldap_attrs,
+ &nested_group);
+ assert_int_equal(ret, EOK);
+
+ ret = nested_group_test_save_group(test_ctx,
+ ext_group_nested_ldap_attrs,
+ &ext_group_nested);
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_add_group_member(test_ctx->tctx->dom,
+ rootgroup.gr_name,
+ ext_group.gr_name,
+ SYSDB_MEMBER_GROUP, false);
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_add_group_member(test_ctx->tctx->dom,
+ rootgroup.gr_name,
+ nested_group.gr_name,
+ SYSDB_MEMBER_GROUP, false);
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_add_group_member(test_ctx->tctx->dom,
+ nested_group.gr_name,
+ ext_group_nested.gr_name,
+ SYSDB_MEMBER_GROUP, false);
+ assert_int_equal(ret, EOK);
+
+ /* Resolve external members */
+ req_mem_ctx = talloc_new(global_talloc_context);
+ assert_non_null(req_mem_ctx);
+ check_leaks_push(req_mem_ctx);
+
+ req = sdap_nested_group_lookup_external_send(test_ctx, test_ctx->tctx->ev,
+ test_ctx->tctx->dom,
+ test_ctx->ext_ctx,
+ test_ctx->missing_external);
+ assert_non_null(req);
+ tevent_req_set_callback(req, nested_external_done, test_ctx);
+
+ test_ctx->tctx->done = false;
+ ret = test_ev_loop(test_ctx->tctx);
+ assert_true(check_leaks_pop(req_mem_ctx) == true);
+ talloc_zfree(req_mem_ctx);
+ assert_int_equal(ret, ERR_OK);
+
+ /* Make sure that extuser1001 is a member of rootgroup now */
+ ret = sysdb_initgroups(test_ctx, test_ctx->tctx->dom, "ext_user10001", &res);
+ assert_int_equal(ret, EOK);
+ s = ldb_msg_find_attr_as_string(res->msgs[1], SYSDB_NAME, NULL);
+ assert_string_equal(s, rootgroup.gr_name);
+ s = ldb_msg_find_attr_as_string(res->msgs[2], SYSDB_NAME, NULL);
+ assert_string_equal(s, nested_group.gr_name);
+
+ ret = sysdb_getgrnam(test_ctx, test_ctx->tctx->dom,
+ "ext_group20001", &res);
+ ret = sysdb_search_group_by_name(test_ctx,
+ test_ctx->tctx->dom,
+ "ext_group20001",
+ sysdb_gr_attrs,
+ &msg);
+ assert_int_equal(ret, EOK);
+ member = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
+ assert_int_equal(member->num_values, 2);
+
+ s = sysdb_group_strdn(test_ctx,
+ test_ctx->tctx->dom->name,
+ rootgroup.gr_name);
+ assert_non_null(s);
+ assert_string_equal(member->values[0].data, s);
+
+ s = sysdb_group_strdn(test_ctx,
+ test_ctx->tctx->dom->name,
+ nested_group.gr_name);
+ assert_non_null(s);
+ assert_string_equal(member->values[1].data, s);
+}
+
+
int main(int argc, const char *argv[])
{
int rv;
@@ -646,6 +1169,9 @@ int main(int argc, const char *argv[])
new_test(one_group_dup_group_members),
new_test(nested_chain),
new_test(nested_chain_with_error),
+ cmocka_unit_test_setup_teardown(nested_group_external_member_test,
+ nested_group_external_member_setup,
+ nested_group_external_member_teardown),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
--
2.7.3

View File

@ -0,0 +1,145 @@
From 78050338d2f356d279f37a416ba77a9568abc1bf Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Fri, 26 Feb 2016 16:06:50 +0100
Subject: [PATCH 103/108] CLIENT: Reduce code duplication
Patch for #2626 will be simpler with this small refactoring
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit a452d199bc125e8d53033d7c00383b4a275ab85e)
(cherry picked from commit c79e5f222e8de1ddc1cc260c1f3e5e204361580e)
---
src/sss_client/common.c | 68 +++++++++++++++++++++++--------------------------
1 file changed, 32 insertions(+), 36 deletions(-)
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 0d9106a04c30054e6acc9c0c420ccdd43590709a..827f0c2ac3fa12cbe5a282f25ff108fc83bab76c 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -829,6 +829,7 @@ int sss_pam_make_request(enum sss_cli_command cmd,
enum sss_status status;
char *envval;
struct stat stat_buf;
+ const char *socket_name;
sss_pam_lock();
@@ -841,7 +842,8 @@ int sss_pam_make_request(enum sss_cli_command cmd,
/* only root shall use the privileged pipe */
if (getuid() == 0 && getgid() == 0) {
- statret = stat(SSS_PAM_PRIV_SOCKET_NAME, &stat_buf);
+ socket_name = SSS_PAM_PRIV_SOCKET_NAME;
+ statret = stat(socket_name, &stat_buf);
if (statret != 0) {
ret = PAM_SERVICE_ERR;
goto out;
@@ -854,10 +856,9 @@ int sss_pam_make_request(enum sss_cli_command cmd,
ret = PAM_SERVICE_ERR;
goto out;
}
-
- status = sss_cli_check_socket(errnop, SSS_PAM_PRIV_SOCKET_NAME);
} else {
- statret = stat(SSS_PAM_SOCKET_NAME, &stat_buf);
+ socket_name = SSS_PAM_SOCKET_NAME;
+ statret = stat(socket_name, &stat_buf);
if (statret != 0) {
ret = PAM_SERVICE_ERR;
goto out;
@@ -870,9 +871,9 @@ int sss_pam_make_request(enum sss_cli_command cmd,
ret = PAM_SERVICE_ERR;
goto out;
}
-
- status = sss_cli_check_socket(errnop, SSS_PAM_SOCKET_NAME);
}
+
+ status = sss_cli_check_socket(errnop, socket_name);
if (status != SSS_STATUS_SUCCESS) {
ret = PAM_SERVICE_ERR;
goto out;
@@ -910,21 +911,32 @@ void sss_pam_close_fd(void)
sss_pam_unlock();
}
+static enum sss_status
+sss_cli_make_request_with_checks(enum sss_cli_command cmd,
+ struct sss_cli_req_data *rd,
+ uint8_t **repbuf, size_t *replen,
+ int *errnop,
+ const char *socket_name)
+{
+ enum sss_status ret = SSS_STATUS_UNAVAIL;
+
+ ret = sss_cli_check_socket(errnop, socket_name);
+ if (ret != SSS_STATUS_SUCCESS) {
+ return SSS_STATUS_UNAVAIL;
+ }
+
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+
+ return ret;
+}
+
int sss_sudo_make_request(enum sss_cli_command cmd,
struct sss_cli_req_data *rd,
uint8_t **repbuf, size_t *replen,
int *errnop)
{
- enum sss_status ret = SSS_STATUS_UNAVAIL;
-
- ret = sss_cli_check_socket(errnop, SSS_SUDO_SOCKET_NAME);
- if (ret != SSS_STATUS_SUCCESS) {
- return SSS_STATUS_UNAVAIL;
- }
-
- ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
-
- return ret;
+ return sss_cli_make_request_with_checks(cmd, rd, repbuf, replen, errnop,
+ SSS_SUDO_SOCKET_NAME);
}
int sss_autofs_make_request(enum sss_cli_command cmd,
@@ -932,16 +944,8 @@ int sss_autofs_make_request(enum sss_cli_command cmd,
uint8_t **repbuf, size_t *replen,
int *errnop)
{
- enum sss_status ret = SSS_STATUS_UNAVAIL;
-
- ret = sss_cli_check_socket(errnop, SSS_AUTOFS_SOCKET_NAME);
- if (ret != SSS_STATUS_SUCCESS) {
- return SSS_STATUS_UNAVAIL;
- }
-
- ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
-
- return ret;
+ return sss_cli_make_request_with_checks(cmd, rd, repbuf, replen, errnop,
+ SSS_AUTOFS_SOCKET_NAME);
}
int sss_ssh_make_request(enum sss_cli_command cmd,
@@ -949,16 +953,8 @@ int sss_ssh_make_request(enum sss_cli_command cmd,
uint8_t **repbuf, size_t *replen,
int *errnop)
{
- enum sss_status ret = SSS_STATUS_UNAVAIL;
-
- ret = sss_cli_check_socket(errnop, SSS_SSH_SOCKET_NAME);
- if (ret != SSS_STATUS_SUCCESS) {
- return SSS_STATUS_UNAVAIL;
- }
-
- ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
-
- return ret;
+ return sss_cli_make_request_with_checks(cmd, rd, repbuf, replen, errnop,
+ SSS_SSH_SOCKET_NAME);
}
--
2.7.3

View File

@ -0,0 +1,137 @@
From 459b0be7bef7551a4b901742336bdee41ed44bbe Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Wed, 17 Feb 2016 15:21:55 +0100
Subject: [PATCH 104/108] CLIENT: Retry request after EPIPE
We have a function sss_cli_check_socket which checks
socket in client code. The socket is reopened in case of some
issues e.g. responder terminated connections ...
We use syscall poll for checking status of socket.
It's not 100% reliable method because there is still
chance that responder will terminate socket after this check.
Here is a schema of sss_*_make_request functions:
sss_cli_check_socket
sss_cli_make_request_nochecks {
sss_cli_send_req {
poll
send
}
sss_cli_recv_rep {
poll
read
}
}
The syscall pool does not return EPIPE directly but we convert
special revents from poll to EPIPE. As it was mentioned earlier,
checking of socket in the sss_cli_check_socket is not 100% reliable.
It can happen very rarely due to TOCTOU issue (Time of check to time of use)
We can return EPIPE from the sss_cli_make_request_nochecks function
in case of failure in poll in sss_cli_send_req. The send function
in sss_cli_send_req can also return EPIPE is responder close socket
in the same time. The send function can succeed in sss_cli_send_req
but it does not mean that responder read the message. It can happen
that timer for closing socket can be handled before reading a message.
Therefore there is a still a chance that we might return EPIPE in case
of failure in poll in sss_cli_recv_rep.
Therefore we need to reconnect to responder(sss_cli_check_socket)
in case of EPIPE returned from sss_cli_make_request_nochecks and
try to do the same request one more time.
Resolves:
https://fedorahosted.org/sssd/ticket/2626
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 6748a4c9d75db997c724c1dcea541e0047742f52)
(cherry picked from commit 710d6a9e66b08990ce10cf72e7cc6c8c023806ea)
---
src/sss_client/common.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 827f0c2ac3fa12cbe5a282f25ff108fc83bab76c..20106b1b67e3cabe8dd4338b9358c8b2b5b86d57 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -734,6 +734,22 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
}
ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ if (ret == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
+ /* try reopen socket */
+ ret = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
+ if (ret != SSS_STATUS_SUCCESS) {
+#ifdef NONSTANDARD_SSS_NSS_BEHAVIOUR
+ *errnop = 0;
+ errno = 0;
+ return NSS_STATUS_NOTFOUND;
+#else
+ return NSS_STATUS_UNAVAIL;
+#endif
+ }
+
+ /* and make request one more time */
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ }
switch (ret) {
case SSS_STATUS_TRYAGAIN:
return NSS_STATUS_TRYAGAIN;
@@ -784,6 +800,16 @@ int sss_pac_make_request(enum sss_cli_command cmd,
}
ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ if (ret == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
+ /* try reopen socket */
+ ret = sss_cli_check_socket(errnop, SSS_PAC_SOCKET_NAME);
+ if (ret != SSS_STATUS_SUCCESS) {
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ /* and make request one more time */
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ }
switch (ret) {
case SSS_STATUS_TRYAGAIN:
return NSS_STATUS_TRYAGAIN;
@@ -888,6 +914,18 @@ int sss_pam_make_request(enum sss_cli_command cmd,
}
status = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ if (status == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
+ /* try reopen socket */
+ status = sss_cli_check_socket(errnop, socket_name);
+ if (status != SSS_STATUS_SUCCESS) {
+ ret = PAM_SERVICE_ERR;
+ goto out;
+ }
+
+ /* and make request one more time */
+ status = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ }
+
if (status == SSS_STATUS_SUCCESS) {
ret = PAM_SUCCESS;
} else {
@@ -926,6 +964,16 @@ sss_cli_make_request_with_checks(enum sss_cli_command cmd,
}
ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ if (ret == SSS_STATUS_UNAVAIL && *errnop == EPIPE) {
+ /* try reopen socket */
+ ret = sss_cli_check_socket(errnop, socket_name);
+ if (ret != SSS_STATUS_SUCCESS) {
+ return SSS_STATUS_UNAVAIL;
+ }
+
+ /* and make request one more time */
+ ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+ }
return ret;
}
--
2.7.3

View File

@ -0,0 +1,82 @@
From e4b015773306a7c404dd45de56cc8592a7c8513b Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 7 Mar 2016 17:07:16 +0100
Subject: [PATCH 105/108] pam_sss: reorder pam_message array
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There are different expectations about how the pam_message array is
organized, details can be found in the pam_conv man page. E.g. sudo was
not able to handle the Linux-PAM style but expected the Solaris PAM
style. With this patch both styles should work as expected.
Resolves https://fedorahosted.org/sssd/ticket/2971
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit 957e0a8675359d90fa50067b704578d01f565bba)
(cherry picked from commit 4a01e6a6fd66e622b80739472a0aa06d1c79a6a9)
---
src/sss_client/pam_sss.c | 36 ++++++++++++++----------------------
1 file changed, 14 insertions(+), 22 deletions(-)
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index b4f7efe49017870186f1cd9e91603033a5354770..5b2307c1b59e2de5d52fdc871b12afaa90780f76 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -1260,8 +1260,7 @@ static int prompt_2fa(pam_handle_t *pamh, struct pam_items *pi,
int ret;
const struct pam_conv *conv;
const struct pam_message *mesg[2] = { NULL, NULL };
- struct pam_message *m1;
- struct pam_message *m2;
+ struct pam_message m[2] = { {0}, {0} };
struct pam_response *resp = NULL;
size_t needed_size;
@@ -1270,29 +1269,22 @@ static int prompt_2fa(pam_handle_t *pamh, struct pam_items *pi,
return ret;
}
- m1 = malloc(sizeof(struct pam_message));
- if (m1 == NULL) {
- D(("Malloc failed."));
- return PAM_SYSTEM_ERR;
- }
+ m[0].msg_style = PAM_PROMPT_ECHO_OFF;
+ m[0].msg = prompt_fa1;
+ m[1].msg_style = PAM_PROMPT_ECHO_OFF;
+ m[1].msg = prompt_fa2;
- m2 = malloc(sizeof(struct pam_message));
- if (m2 == NULL) {
- D(("Malloc failed."));
- free(m1);
- return PAM_SYSTEM_ERR;
- }
- m1->msg_style = PAM_PROMPT_ECHO_OFF;
- m1->msg = prompt_fa1;
- m2->msg_style = PAM_PROMPT_ECHO_OFF;
- m2->msg = prompt_fa2;
-
- mesg[0] = (const struct pam_message *) m1;
- mesg[1] = (const struct pam_message *) m2;
+ mesg[0] = (const struct pam_message *) m;
+ /* The following assignment might look a bit odd but is recommended in the
+ * pam_conv man page to make sure that the second argument of the PAM
+ * conversation function can be interpreted in two different ways.
+ * Basically it is important that both the actual struct pam_message and
+ * the pointers to the struct pam_message are arrays. Since the assignment
+ * makes clear that mesg[] and (*mesg)[] are arrays it should be kept this
+ * way and not be replaced by other equivalent assignments. */
+ mesg[1] = & (( *mesg )[1]);
ret = conv->conv(2, mesg, &resp, conv->appdata_ptr);
- free(m1);
- free(m2);
if (ret != PAM_SUCCESS) {
D(("Conversation failure: %s.", pam_strerror(pamh, ret)));
return ret;
--
2.7.3

View File

@ -0,0 +1,28 @@
From 141773889b17dae7ad3c3ba20bab28bb9bf5e6ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 4 Mar 2016 10:40:21 +0100
Subject: [PATCH 106/108] IPA SUDO: fix typo
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit b0c4eb194cf1414d3440e0cccfb9af9074388c08)
(cherry picked from commit 6ece710965c30cc34fb32e87c0350fbac5f36dad)
---
src/providers/ipa/ipa_sudo_conversion.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/providers/ipa/ipa_sudo_conversion.c b/src/providers/ipa/ipa_sudo_conversion.c
index ff63551c045003bc81c440ee63aeb28f3fe06647..84de01e622d611d4fee9f9b12e3147d54654626b 100644
--- a/src/providers/ipa/ipa_sudo_conversion.c
+++ b/src/providers/ipa/ipa_sudo_conversion.c
@@ -228,7 +228,7 @@ process_rulemember(TALLOC_CTX *mem_ctx,
ret = store_rulemember(mem_ctx, &rulemember->cmds,
conv->cmds, members[i]);
if (ret == EOK) {
- DEBUG(SSSDBG_TRACE_INTERNAL, "Found sudo command group %s\n",
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Found sudo command %s\n",
members[i]);
} else if (ret != EEXIST) {
goto done;
--
2.7.3

View File

@ -0,0 +1,223 @@
From f5b220db53b2fd88009d9d85b275b5158d22e3c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 4 Mar 2016 11:01:35 +0100
Subject: [PATCH 107/108] IPA SUDO: support old ipasudocmd rdn
FreeIPA versions older than 3.1 have rdn sudoCmd instead of ipaUniqueID.
Resolves:
https://fedorahosted.org/sssd/ticket/2969
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 84060f52e782b079337ee7a99bb7ad17e8c84fbb)
(cherry picked from commit 1434e5609fb7f6b234811717ff2b6ff495272707)
---
src/providers/ipa/ipa_sudo_conversion.c | 125 ++++++++++++++++++++++++++------
1 file changed, 103 insertions(+), 22 deletions(-)
diff --git a/src/providers/ipa/ipa_sudo_conversion.c b/src/providers/ipa/ipa_sudo_conversion.c
index 84de01e622d611d4fee9f9b12e3147d54654626b..278fee600369e3002cc177313c1ce9f6131c08f7 100644
--- a/src/providers/ipa/ipa_sudo_conversion.c
+++ b/src/providers/ipa/ipa_sudo_conversion.c
@@ -38,8 +38,8 @@
#define MATCHDN_CMDGROUPS MATCHDN(SUDO_DN_CMDGROUPS)
#define MATCHDN_CMDS MATCHDN(SUDO_DN_CMDS)
-#define MATCHRDN_CMDGROUPS(map) (map)[IPA_AT_SUDOCMDGROUP_NAME].name, MATCHDN_CMDGROUPS
-#define MATCHRDN_CMDS(map) (map)[IPA_AT_SUDOCMD_UUID].name, MATCHDN_CMDS
+#define MATCHRDN_CMDGROUPS(map) (map)[IPA_AT_SUDOCMDGROUP_NAME].name, MATCHDN_CMDGROUPS
+#define MATCHRDN_CMDS(attr, map) (map)[attr].name, MATCHDN_CMDS
#define MATCHRDN_USER(map) (map)[SDAP_AT_USER_NAME].name, "cn", "users", "cn", "accounts"
#define MATCHRDN_GROUP(map) (map)[SDAP_AT_GROUP_NAME].name, "cn", "groups", "cn", "accounts"
@@ -187,6 +187,32 @@ done:
return ret;
}
+static bool is_ipacmdgroup(struct ipa_sudo_conv *conv, const char *dn)
+{
+ if (ipa_check_rdn_bool(conv->sysdb, dn,
+ MATCHRDN_CMDGROUPS(conv->map_cmdgroup))) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool is_ipacmd(struct ipa_sudo_conv *conv, const char *dn)
+{
+ if (ipa_check_rdn_bool(conv->sysdb, dn,
+ MATCHRDN_CMDS(IPA_AT_SUDOCMD_UUID, conv->map_cmd))) {
+ return true;
+ }
+
+ /* For older versions of FreeIPA than 3.1. */
+ if (ipa_check_rdn_bool(conv->sysdb, dn,
+ MATCHRDN_CMDS(IPA_AT_SUDOCMD_CMD, conv->map_cmd))) {
+ return true;
+ }
+
+ return false;
+}
+
static errno_t
process_rulemember(TALLOC_CTX *mem_ctx,
struct ipa_sudo_conv *conv,
@@ -213,8 +239,7 @@ process_rulemember(TALLOC_CTX *mem_ctx,
}
for (i = 0; members[i] != NULL; i++) {
- if (ipa_check_rdn_bool(conv->sysdb, members[i],
- MATCHRDN_CMDGROUPS(conv->map_cmdgroup))) {
+ if (is_ipacmdgroup(conv, members[i])) {
ret = store_rulemember(mem_ctx, &rulemember->cmdgroups,
conv->cmdgroups, members[i]);
if (ret == EOK) {
@@ -223,8 +248,7 @@ process_rulemember(TALLOC_CTX *mem_ctx,
} else if (ret != EEXIST) {
goto done;
}
- } else if (ipa_check_rdn_bool(conv->sysdb, members[i],
- MATCHRDN_CMDS(conv->map_cmd))) {
+ } else if (is_ipacmd(conv, members[i])) {
ret = store_rulemember(mem_ctx, &rulemember->cmds,
conv->cmds, members[i]);
if (ret == EOK) {
@@ -552,13 +576,75 @@ ipa_sudo_conv_has_cmds(struct ipa_sudo_conv *conv)
return hash_count(conv->cmds) == 0;
}
+typedef errno_t (*ipa_sudo_conv_rdn_fn)(TALLOC_CTX *mem_ctx,
+ struct sdap_attr_map *map,
+ struct sysdb_ctx *sysdb,
+ const char *dn,
+ char **_rdn_val,
+ const char **_rdn_attr);
+
+static errno_t get_sudo_cmdgroup_rdn(TALLOC_CTX *mem_ctx,
+ struct sdap_attr_map *map,
+ struct sysdb_ctx *sysdb,
+ const char *dn,
+ char **_rdn_val,
+ const char **_rdn_attr)
+{
+ char *rdn_val;
+ errno_t ret;
+
+ ret = ipa_get_rdn(mem_ctx, sysdb, dn, &rdn_val,
+ MATCHRDN_CMDGROUPS(map));
+ if (ret != EOK) {
+ return ret;
+ }
+
+ *_rdn_val = rdn_val;
+ *_rdn_attr = map[IPA_AT_SUDOCMDGROUP_NAME].name;
+
+ return EOK;
+}
+
+static errno_t get_sudo_cmd_rdn(TALLOC_CTX *mem_ctx,
+ struct sdap_attr_map *map,
+ struct sysdb_ctx *sysdb,
+ const char *dn,
+ char **_rdn_val,
+ const char **_rdn_attr)
+{
+ char *rdn_val;
+ errno_t ret;
+
+ ret = ipa_get_rdn(mem_ctx, sysdb, dn, &rdn_val,
+ MATCHRDN_CMDS(IPA_AT_SUDOCMD_UUID, map));
+ if (ret == EOK) {
+ *_rdn_val = rdn_val;
+ *_rdn_attr = map[IPA_AT_SUDOCMD_UUID].name;
+
+ return EOK;
+ } else if (ret != ENOENT) {
+ return ret;
+ }
+
+ /* For older versions of FreeIPA than 3.1. */
+ ret = ipa_get_rdn(mem_ctx, sysdb, dn, &rdn_val,
+ MATCHRDN_CMDS(IPA_AT_SUDOCMD_CMD, map));
+ if (ret != EOK) {
+ return ret;
+ }
+
+ *_rdn_val = rdn_val;
+ *_rdn_attr = map[IPA_AT_SUDOCMD_CMD].name;;
+
+ return EOK;
+}
+
static char *
build_filter(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
hash_table_t *table,
- const char *class,
- const char *rdn_attr,
- const char *category)
+ struct sdap_attr_map *map,
+ ipa_sudo_conv_rdn_fn rdn_fn)
{
TALLOC_CTX *tmp_ctx;
hash_key_t *keys;
@@ -566,6 +652,7 @@ build_filter(TALLOC_CTX *mem_ctx,
unsigned long int i;
char *filter;
char *rdn_val;
+ const char *rdn_attr;
char *safe_rdn;
errno_t ret;
int hret;
@@ -590,8 +677,7 @@ build_filter(TALLOC_CTX *mem_ctx,
}
for (i = 0; i < count; i++) {
- ret = ipa_get_rdn(tmp_ctx, sysdb, keys[i].str, &rdn_val,
- rdn_attr, MATCHDN(category));
+ ret = rdn_fn(tmp_ctx, map, sysdb, keys[i].str, &rdn_val, &rdn_attr);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get member %s [%d]: %s\n",
keys[i].str, ret, sss_strerror(ret));
@@ -612,8 +698,9 @@ build_filter(TALLOC_CTX *mem_ctx,
}
}
+ /* objectClass is always first */
filter = talloc_asprintf(filter, "(&(objectClass=%s)(|%s))",
- class, filter);
+ map[0].name, filter);
if (filter == NULL) {
ret = ENOMEM;
goto done;
@@ -637,22 +724,16 @@ char *
ipa_sudo_conv_cmdgroup_filter(TALLOC_CTX *mem_ctx,
struct ipa_sudo_conv *conv)
{
- const char *rdn_attr = conv->map_cmdgroup[IPA_AT_SUDOCMDGROUP_NAME].name;
- const char *class = conv->map_cmdgroup[IPA_OC_SUDOCMDGROUP].name;
-
- return build_filter(mem_ctx, conv->sysdb, conv->cmdgroups, class,
- rdn_attr, SUDO_DN_CMDGROUPS);
+ return build_filter(mem_ctx, conv->sysdb, conv->cmdgroups,
+ conv->map_cmdgroup, get_sudo_cmdgroup_rdn);
}
char *
ipa_sudo_conv_cmd_filter(TALLOC_CTX *mem_ctx,
struct ipa_sudo_conv *conv)
{
- const char *rdn_attr = conv->map_cmd[IPA_AT_SUDOCMD_UUID].name;
- const char *class = conv->map_cmd[IPA_OC_SUDOCMD].name;
-
- return build_filter(mem_ctx, conv->sysdb, conv->cmds, class,
- rdn_attr, SUDO_DN_CMDS);
+ return build_filter(mem_ctx, conv->sysdb, conv->cmds,
+ conv->map_cmd, get_sudo_cmd_rdn);
}
struct ipa_sudo_conv_result_ctx {
--
2.7.3

View File

@ -0,0 +1,219 @@
From d0ad557eef9bcdf475b15e40f8f80e3827d3c630 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 4 Mar 2016 12:10:35 +0100
Subject: [PATCH 108/108] SUDO: be able to parse modifyTimestamp correctly
We were unable to parse modifyTimestamp where a non-numeric part
(timezone) was involved. The format is YYYYMMDDHHmmssZ. It may
also contain fraction or different timezone, everytime separated
from the datetime by character. This patch gets the numberic part
and then appends the string part again to get value usable in filter.
Resolves:
https://fedorahosted.org/sssd/ticket/2970
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit ef5e33f7db1e314226b0077596e38ef16305cba5)
(cherry picked from commit 35c8d4f76c9299105cbc6a6d2c49170e46f2abde)
---
src/providers/ipa/ipa_sudo_refresh.c | 24 ++++++++---------
src/providers/ldap/sdap.h | 2 +-
src/providers/ldap/sdap_sudo_refresh.c | 17 ++++++------
src/providers/ldap/sdap_sudo_shared.c | 48 ++++++++++++++++++++++++++++------
4 files changed, 62 insertions(+), 29 deletions(-)
diff --git a/src/providers/ipa/ipa_sudo_refresh.c b/src/providers/ipa/ipa_sudo_refresh.c
index 7871802ef7462ce98f6ff43bc33da57ff123ff6f..e7219d3147c860a0162bfe8e5004fe6d22de7f25 100644
--- a/src/providers/ipa/ipa_sudo_refresh.c
+++ b/src/providers/ipa/ipa_sudo_refresh.c
@@ -153,7 +153,7 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
struct tevent_req *req;
char *cmdgroups_filter;
char *search_filter;
- unsigned long usn;
+ const char *usn;
errno_t ret;
req = tevent_req_create(mem_ctx, &state,
@@ -166,29 +166,29 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
/* Download all rules from LDAP that are newer than usn */
if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
- usn = 0;
+ usn = "0";
+ search_filter = NULL;
} else {
- usn = srv_opts->max_sudo_value + 1;
+ usn = srv_opts->max_sudo_value;
+ search_filter = talloc_asprintf(state, "(%s>=%s)",
+ sudo_ctx->sudorule_map[IPA_AT_SUDORULE_ENTRYUSN].name, usn);
+ if (search_filter == NULL) {
+ ret = ENOMEM;
+ goto immediately;
+ }
}
- cmdgroups_filter = talloc_asprintf(state, "(%s>=%lu)",
+ cmdgroups_filter = talloc_asprintf(state, "(%s>=%s)",
sudo_ctx->sudocmdgroup_map[IPA_AT_SUDOCMDGROUP_ENTRYUSN].name, usn);
if (cmdgroups_filter == NULL) {
ret = ENOMEM;
goto immediately;
}
- search_filter = talloc_asprintf(state, "(%s>=%lu)",
- sudo_ctx->sudorule_map[IPA_AT_SUDORULE_ENTRYUSN].name, usn);
- if (search_filter == NULL) {
- ret = ENOMEM;
- goto immediately;
- }
-
/* Do not remove any rules that are already in the sysdb. */
DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
- "(USN > %lu)\n", usn);
+ "(USN >= %s)\n", usn);
subreq = ipa_sudo_refresh_send(state, ev, sudo_ctx, cmdgroups_filter,
search_filter, NULL);
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index e0e05da0c8270a8f131870bc755da862e43783cb..44b8cfb1c971e059db5d8a12613db9c0e67d13a6 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -485,7 +485,7 @@ struct sdap_server_opts {
char *max_user_value;
char *max_group_value;
char *max_service_value;
- unsigned long max_sudo_value;
+ char *max_sudo_value;
bool posix_checked;
};
diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
index 5ba858019e0bda91a9e0919ed2b0345d9faf085e..62a97dd12cd8b92f719494f173d028cb7c66928c 100644
--- a/src/providers/ldap/sdap_sudo_refresh.c
+++ b/src/providers/ldap/sdap_sudo_refresh.c
@@ -167,7 +167,7 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
struct sdap_server_opts *srv_opts = id_ctx->srv_opts;
struct sdap_sudo_smart_refresh_state *state = NULL;
char *search_filter = NULL;
- unsigned long usn;
+ const char *usn;
int ret;
req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
@@ -182,14 +182,15 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
/* Download all rules from LDAP that are newer than usn */
if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
- usn = 0;
+ usn = "0";
+ search_filter = talloc_asprintf(state, "(objectclass=%s)",
+ map[SDAP_OC_SUDORULE].name);
} else {
- usn = srv_opts->max_sudo_value + 1;
+ usn = srv_opts->max_sudo_value;
+ search_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%s))",
+ map[SDAP_OC_SUDORULE].name,
+ map[SDAP_AT_SUDO_USN].name, usn);
}
-
- search_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%lu))",
- map[SDAP_OC_SUDORULE].name,
- map[SDAP_AT_SUDO_USN].name, usn);
if (search_filter == NULL) {
ret = ENOMEM;
goto immediately;
@@ -199,7 +200,7 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
* sysdb_filter = NULL; */
DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
- "(USN > %lu)\n", usn);
+ "(USN >= %s)\n", usn);
subreq = sdap_sudo_refresh_send(state, sudo_ctx, search_filter, NULL);
if (subreq == NULL) {
diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
index 72f55e14baa8f8cf896205fb20f14d5f446cfb0a..b9e5182a2f11d56b5cff0b77fd83282654eae94c 100644
--- a/src/providers/ldap/sdap_sudo_shared.c
+++ b/src/providers/ldap/sdap_sudo_shared.c
@@ -120,11 +120,38 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
return EOK;
}
+static char *
+sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
+ unsigned long usn,
+ const char *leftover)
+{
+ const char *str = leftover == NULL ? "" : leftover;
+ char *newusn;
+
+ /* We increment USN number so that we can later use simplify filter
+ * (just usn >= last+1 instaed of usn >= last && usn != last).
+ */
+ usn++;
+
+ /* Convert back to string appending non-converted values since it
+ * is an indicator that modifyTimestamp is used instead of entryUSN.
+ * modifyTimestamp contains also timezone specification, usually Z.
+ * We can't really handle any errors here so we just use what we got. */
+ newusn = talloc_asprintf(mem_ctx, "%lu%s", usn, str);
+ if (newusn == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
+ return NULL;
+ }
+
+ return newusn;
+}
+
void
sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
const char *usn)
{
- unsigned int usn_number;
+ unsigned long usn_number;
+ char *newusn;
char *endptr = NULL;
errno_t ret;
@@ -140,24 +167,29 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
errno = 0;
usn_number = strtoul(usn, &endptr, 10);
- if (endptr != NULL && *endptr != '\0') {
- DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s\n", usn);
- return;
- } else if (errno != 0) {
+ if (errno != 0) {
ret = errno;
DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s [%d]: %s\n",
usn, ret, sss_strerror(ret));
return;
}
- if (usn_number > srv_opts->max_sudo_value) {
- srv_opts->max_sudo_value = usn_number;
+ newusn = sdap_sudo_new_usn(srv_opts, usn_number, endptr);
+ if (newusn == NULL) {
+ return;
+ }
+
+ if (sysdb_compare_usn(newusn, srv_opts->max_sudo_value) > 0) {
+ talloc_zfree(srv_opts->max_sudo_value);
+ srv_opts->max_sudo_value = newusn;
+ } else {
+ talloc_zfree(newusn);
}
if (usn_number > srv_opts->last_usn) {
srv_opts->last_usn = usn_number;
}
- DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%lu]\n",
+ DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
srv_opts->max_sudo_value);
}
--
2.7.3

View File

@ -114,11 +114,33 @@ Patch0078: 0078-Add-a-new-option-ldap_group_external_member.patch
Patch0079: 0079-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch
Patch0080: 0080-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch
Patch0081: 0081-build-detect-endianness-at-configure-time.patch
Patch0100: 0100-FO-Don-t-free-rc-allocated-structure.patch
Patch0101: 0101-tests-Reduce-failover-code-duplication.patch
Patch0102: 0102-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch
Patch0103: 0103-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch
Patch0104: 0104-FO-Use-tevent_req_defer_callback-when-notifying-call.patch
patch0082: 0082-IPA-lookup-idview-name-even-if-there-is-no-master-do.patch
patch0083: 0083-IPA-invalidate-override-data-if-original-view-is-mis.patch
patch0084: 0084-GPO-Add-Cockpit-to-the-Remote-Interactive-defaults.patch
patch0085: 0085-GPO-Add-other-display-managers-to-interactive-logon.patch
patch0086: 0086-CI-Use-yum-deprecated-instead-of-dnf.patch
patch0087: 0087-remove-user-certificate-if-not-found-on-the-server.patch
patch0088: 0088-sdap-improve-filtering-of-multiple-results-in-GC-loo.patch
patch0089: 0089-FO-Don-t-free-rc-allocated-structure.patch
patch0090: 0090-tests-Reduce-failover-code-duplication.patch
patch0091: 0091-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch
patch0092: 0092-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch
patch0093: 0093-FO-Use-tevent_req_defer_callback-when-notifying-call.patch
patch0094: 0094-util-Continue-if-setlocale-fails.patch
patch0095: 0095-server_setup-Log-failed-attempt-to-set-locale.patch
patch0096: 0096-tests-Run-intgcheck-without-libsemanage.patch
patch0097: 0097-tests-Regression-test-with-wrong-LC_ALL.patch
patch0098: 0098-memberof-Don-t-allocate-on-a-NULL-context.patch
patch0099: 0099-IPA-SUDO-download-externalUser-attribute.patch
patch0100: 0100-UTIL-Fix-indentation-in-dlinklist.h.patch
patch0101: 0101-UTIL-Fix-warning-misleading-indentation.patch
patch0102: 0102-tests-Add-a-unit-test-for-the-external-groups-resolu.patch
patch0103: 0103-CLIENT-Reduce-code-duplication.patch
patch0104: 0104-CLIENT-Retry-request-after-EPIPE.patch
patch0105: 0105-pam_sss-reorder-pam_message-array.patch
patch0106: 0106-IPA-SUDO-fix-typo.patch
patch0107: 0107-IPA-SUDO-support-old-ipasudocmd-rdn.patch
patch0108: 0108-SUDO-be-able-to-parse-modifyTimestamp-correctly.patch
### Dependencies ###
@ -1104,6 +1126,12 @@ fi
%{_libdir}/%{name}/modules/libwbclient.so
%changelog
* Tue Mar 22 2016 Lukas Slebodnik <lslebodn@redhat.com> - 1.13.3-6
- Resolves: rhbz#1276868 - Sudo PAM Login should support multiple password
prompts (e.g. Password + Token)
- Resolves: rhbz#1313041 - ssh with sssd proxy fails with "Connection closed
by remote host" if locale not available
* Thu Feb 25 2016 Lukas Slebodnik <lslebodn@redhat.com> - 1.13.3-5
- Resolves: rhbz#1310664 - [RFE] IPA: resolve external group memberships of IPA
groups during getgrnam and getgrgid