diff --git a/0082-IPA-lookup-idview-name-even-if-there-is-no-master-do.patch b/0082-IPA-lookup-idview-name-even-if-there-is-no-master-do.patch new file mode 100644 index 0000000..5f4ab40 --- /dev/null +++ b/0082-IPA-lookup-idview-name-even-if-there-is-no-master-do.patch @@ -0,0 +1,143 @@ +From 75dabe3ec5398359f4cccfcd616959cd921cced2 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +(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 + diff --git a/0083-IPA-invalidate-override-data-if-original-view-is-mis.patch b/0083-IPA-invalidate-override-data-if-original-view-is-mis.patch new file mode 100644 index 0000000..620f97a --- /dev/null +++ b/0083-IPA-invalidate-override-data-if-original-view-is-mis.patch @@ -0,0 +1,52 @@ +From 55fa5564a9835e9697555d1bfeb9336bcce2415f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +(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 + diff --git a/0084-GPO-Add-Cockpit-to-the-Remote-Interactive-defaults.patch b/0084-GPO-Add-Cockpit-to-the-Remote-Interactive-defaults.patch new file mode 100644 index 0000000..f58c689 --- /dev/null +++ b/0084-GPO-Add-Cockpit-to-the-Remote-Interactive-defaults.patch @@ -0,0 +1,62 @@ +From 99c197025ad61a9ecd7ae3bcd02e9569415fb90a Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +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 +(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 + + ++ ++ ++ cockpit ++ ++ + + + +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 + diff --git a/0085-GPO-Add-other-display-managers-to-interactive-logon.patch b/0085-GPO-Add-other-display-managers-to-interactive-logon.patch new file mode 100644 index 0000000..cef5819 --- /dev/null +++ b/0085-GPO-Add-other-display-managers-to-interactive-logon.patch @@ -0,0 +1,79 @@ +From 665fae391bbb6c5173ec0086247f20d95a0c9026 Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +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 +(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 + + ++ ++ ++ lightdm ++ ++ ++ ++ ++ lxdm ++ ++ ++ ++ ++ sddm ++ ++ ++ ++ ++ xdm ++ ++ + + + +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 + diff --git a/0086-CI-Use-yum-deprecated-instead-of-dnf.patch b/0086-CI-Use-yum-deprecated-instead-of-dnf.patch new file mode 100644 index 0000000..3c918c6 --- /dev/null +++ b/0086-CI-Use-yum-deprecated-instead-of-dnf.patch @@ -0,0 +1,70 @@ +From a4b24aeab9f44b5fd937b456acc223a18d045bae Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +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 +(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: + + ALL=(ALL:ALL) NOPASSWD: /usr/bin/yum --assumeyes install -- * + ++on Fedora distros: ++ ++ # We need to use yum-deprecated on Fedora because of BZ1215208. ++ ALL=(ALL:ALL) NOPASSWD: /usr/bin/yum-deprecated --assumeyes install -- * ++ + and Debian-based distros: + + 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 + diff --git a/0087-remove-user-certificate-if-not-found-on-the-server.patch b/0087-remove-user-certificate-if-not-found-on-the-server.patch new file mode 100644 index 0000000..6057cc1 --- /dev/null +++ b/0087-remove-user-certificate-if-not-found-on-the-server.patch @@ -0,0 +1,120 @@ +From 4cf4c4a60aa226ed4a9e3da253ec9a598e9481a4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +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 +(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 + diff --git a/0088-sdap-improve-filtering-of-multiple-results-in-GC-loo.patch b/0088-sdap-improve-filtering-of-multiple-results-in-GC-loo.patch new file mode 100644 index 0000000..4e8f42b --- /dev/null +++ b/0088-sdap-improve-filtering-of-multiple-results-in-GC-loo.patch @@ -0,0 +1,392 @@ +From 3968a8ddb1b0e55db8217031f92feb4d2ee25c4d Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +(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 + diff --git a/0100-FO-Don-t-free-rc-allocated-structure.patch b/0089-FO-Don-t-free-rc-allocated-structure.patch similarity index 64% rename from 0100-FO-Don-t-free-rc-allocated-structure.patch rename to 0089-FO-Don-t-free-rc-allocated-structure.patch index ad2eaf7..c0f9e92 100644 --- a/0100-FO-Don-t-free-rc-allocated-structure.patch +++ b/0089-FO-Don-t-free-rc-allocated-structure.patch @@ -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 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 +(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 diff --git a/0101-tests-Reduce-failover-code-duplication.patch b/0090-tests-Reduce-failover-code-duplication.patch similarity index 96% rename from 0101-tests-Reduce-failover-code-duplication.patch rename to 0090-tests-Reduce-failover-code-duplication.patch index 2e2d272..77c777e 100644 --- a/0101-tests-Reduce-failover-code-duplication.patch +++ b/0090-tests-Reduce-failover-code-duplication.patch @@ -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 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 (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 diff --git a/0102-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch b/0091-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch similarity index 94% rename from 0102-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch rename to 0091-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch index f683974..58e1e50 100644 --- a/0102-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch +++ b/0091-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch @@ -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 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 (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 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 diff --git a/0103-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch b/0092-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch similarity index 75% rename from 0103-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch rename to 0092-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch index 9d15eab..d3e9d61 100644 --- a/0103-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch +++ b/0092-FAIL_OVER-Fix-warning-value-computed-is-not-used.patch @@ -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 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 (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 diff --git a/0104-FO-Use-tevent_req_defer_callback-when-notifying-call.patch b/0093-FO-Use-tevent_req_defer_callback-when-notifying-call.patch similarity index 93% rename from 0104-FO-Use-tevent_req_defer_callback-when-notifying-call.patch rename to 0093-FO-Use-tevent_req_defer_callback-when-notifying-call.patch index bcf5517..c22b763 100644 --- a/0104-FO-Use-tevent_req_defer_callback-when-notifying-call.patch +++ b/0093-FO-Use-tevent_req_defer_callback-when-notifying-call.patch @@ -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 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 (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 diff --git a/0094-util-Continue-if-setlocale-fails.patch b/0094-util-Continue-if-setlocale-fails.patch new file mode 100644 index 0000000..343ba0b --- /dev/null +++ b/0094-util-Continue-if-setlocale-fails.patch @@ -0,0 +1,58 @@ +From 1e596a5b6e72cfca67a3eeb7d9098d015a295545 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +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 +(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 + diff --git a/0095-server_setup-Log-failed-attempt-to-set-locale.patch b/0095-server_setup-Log-failed-attempt-to-set-locale.patch new file mode 100644 index 0000000..ded588c --- /dev/null +++ b/0095-server_setup-Log-failed-attempt-to-set-locale.patch @@ -0,0 +1,48 @@ +From 74c322cbc35889057af2e06b3941bb9cbde864a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +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 +(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 + diff --git a/0096-tests-Run-intgcheck-without-libsemanage.patch b/0096-tests-Run-intgcheck-without-libsemanage.patch new file mode 100644 index 0000000..7bf132e --- /dev/null +++ b/0096-tests-Run-intgcheck-without-libsemanage.patch @@ -0,0 +1,35 @@ +From d2752b748ab490438214fdb5b6e7d3ce476f4999 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +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 +(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 + diff --git a/0097-tests-Regression-test-with-wrong-LC_ALL.patch b/0097-tests-Regression-test-with-wrong-LC_ALL.patch new file mode 100644 index 0000000..70334d0 --- /dev/null +++ b/0097-tests-Regression-test-with-wrong-LC_ALL.patch @@ -0,0 +1,165 @@ +From 30bb28a7d8bea694fda7b745607eb1aacfa0af90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +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 +(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 ++# ++# 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 . ++# ++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 + diff --git a/0098-memberof-Don-t-allocate-on-a-NULL-context.patch b/0098-memberof-Don-t-allocate-on-a-NULL-context.patch new file mode 100644 index 0000000..cc14eab --- /dev/null +++ b/0098-memberof-Don-t-allocate-on-a-NULL-context.patch @@ -0,0 +1,47 @@ +From 0f98c882b70a9011d488228b36df42cf320f62bf Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +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 +(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 + diff --git a/0099-IPA-SUDO-download-externalUser-attribute.patch b/0099-IPA-SUDO-download-externalUser-attribute.patch new file mode 100644 index 0000000..4aae770 --- /dev/null +++ b/0099-IPA-SUDO-download-externalUser-attribute.patch @@ -0,0 +1,85 @@ +From 8891e70a4ff58c271729523da59633744a6bcb54 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +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 +(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 + diff --git a/0100-UTIL-Fix-indentation-in-dlinklist.h.patch b/0100-UTIL-Fix-indentation-in-dlinklist.h.patch new file mode 100644 index 0000000..a647925 --- /dev/null +++ b/0100-UTIL-Fix-indentation-in-dlinklist.h.patch @@ -0,0 +1,201 @@ +From 3d996e218cf24b85a4637d90bd0aeac6a95cd9cf Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +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 +Reviewed-by: Michal Židek +(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 + diff --git a/0101-UTIL-Fix-warning-misleading-indentation.patch b/0101-UTIL-Fix-warning-misleading-indentation.patch new file mode 100644 index 0000000..357dd89 --- /dev/null +++ b/0101-UTIL-Fix-warning-misleading-indentation.patch @@ -0,0 +1,145 @@ +From 495ed57f10c184daf5b68f347dac0be01ca6841b Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +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 +Reviewed-by: Michal Židek +(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 + diff --git a/0102-tests-Add-a-unit-test-for-the-external-groups-resolu.patch b/0102-tests-Add-a-unit-test-for-the-external-groups-resolu.patch new file mode 100644 index 0000000..ec45f2f --- /dev/null +++ b/0102-tests-Add-a-unit-test-for-the-external-groups-resolu.patch @@ -0,0 +1,646 @@ +From b060ad6f32d5b0543e4bb6ae3c431a765e1122c1 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +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 + +(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 + diff --git a/0103-CLIENT-Reduce-code-duplication.patch b/0103-CLIENT-Reduce-code-duplication.patch new file mode 100644 index 0000000..2329a45 --- /dev/null +++ b/0103-CLIENT-Reduce-code-duplication.patch @@ -0,0 +1,145 @@ +From 78050338d2f356d279f37a416ba77a9568abc1bf Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +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 +(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 + diff --git a/0104-CLIENT-Retry-request-after-EPIPE.patch b/0104-CLIENT-Retry-request-after-EPIPE.patch new file mode 100644 index 0000000..ac19333 --- /dev/null +++ b/0104-CLIENT-Retry-request-after-EPIPE.patch @@ -0,0 +1,137 @@ +From 459b0be7bef7551a4b901742336bdee41ed44bbe Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +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 +(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 + diff --git a/0105-pam_sss-reorder-pam_message-array.patch b/0105-pam_sss-reorder-pam_message-array.patch new file mode 100644 index 0000000..7671041 --- /dev/null +++ b/0105-pam_sss-reorder-pam_message-array.patch @@ -0,0 +1,82 @@ +From e4b015773306a7c404dd45de56cc8592a7c8513b Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +(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 + diff --git a/0106-IPA-SUDO-fix-typo.patch b/0106-IPA-SUDO-fix-typo.patch new file mode 100644 index 0000000..2bf98b1 --- /dev/null +++ b/0106-IPA-SUDO-fix-typo.patch @@ -0,0 +1,28 @@ +From 141773889b17dae7ad3c3ba20bab28bb9bf5e6ba Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 4 Mar 2016 10:40:21 +0100 +Subject: [PATCH 106/108] IPA SUDO: fix typo + +Reviewed-by: Jakub Hrozek +(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 + diff --git a/0107-IPA-SUDO-support-old-ipasudocmd-rdn.patch b/0107-IPA-SUDO-support-old-ipasudocmd-rdn.patch new file mode 100644 index 0000000..ae97a87 --- /dev/null +++ b/0107-IPA-SUDO-support-old-ipasudocmd-rdn.patch @@ -0,0 +1,223 @@ +From f5b220db53b2fd88009d9d85b275b5158d22e3c1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +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 +(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 + diff --git a/0108-SUDO-be-able-to-parse-modifyTimestamp-correctly.patch b/0108-SUDO-be-able-to-parse-modifyTimestamp-correctly.patch new file mode 100644 index 0000000..8d4364d --- /dev/null +++ b/0108-SUDO-be-able-to-parse-modifyTimestamp-correctly.patch @@ -0,0 +1,219 @@ +From d0ad557eef9bcdf475b15e40f8f80e3827d3c630 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +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 +(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 + diff --git a/sssd.spec b/sssd.spec index d86e1ad..1fa6b46 100644 --- a/sssd.spec +++ b/sssd.spec @@ -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 - 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 - 1.13.3-5 - Resolves: rhbz#1310664 - [RFE] IPA: resolve external group memberships of IPA groups during getgrnam and getgrgid