diff --git a/SOURCES/0112-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch b/SOURCES/0112-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch new file mode 100644 index 0000000..5d2d383 --- /dev/null +++ b/SOURCES/0112-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch @@ -0,0 +1,62 @@ +From c981d4f4a40ac6cb3650ae1934b0931b0ea5b6f6 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Sun, 17 Jun 2018 21:48:36 +0200 +Subject: [PATCH] TESTS: Extend the schema with sshPublicKey attribute +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This will allow to store the users with a sshPublicKey attribute +provided that they have the right objectclass as well. + +Related to: +https://pagure.io/SSSD/sssd/issue/3747 + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 1575ec97e080656f69b3f93e641c76e74ffb8182) + +DOWNSTREAM: +Resolves: rhbz#1594178 - Login with sshkeys stored in ipa not working after update to RHEL-7.5 [rhel-7.5.z] +--- + src/tests/intg/data/ssh_schema.ldif | 11 +++++++++++ + src/tests/intg/ds_openldap.py | 6 ++++++ + 2 files changed, 17 insertions(+) + create mode 100644 src/tests/intg/data/ssh_schema.ldif + +diff --git a/src/tests/intg/data/ssh_schema.ldif b/src/tests/intg/data/ssh_schema.ldif +new file mode 100644 +index 0000000000000000000000000000000000000000..efe05706b9ded5614a7f3f5e0bab28a7eb869daa +--- /dev/null ++++ b/src/tests/intg/data/ssh_schema.ldif +@@ -0,0 +1,11 @@ ++dn: cn=openssh-lpk,cn=schema,cn=config ++objectClass: olcSchemaConfig ++cn: openssh-lpk ++olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MAY ( sshPublicKey $ uid ) ++ ) +diff --git a/src/tests/intg/ds_openldap.py b/src/tests/intg/ds_openldap.py +index 842ff910803658834841c8f9181f3c4af29b955a..c9a4b6de8c53c6644b3de9047d657ee35ce06512 100644 +--- a/src/tests/intg/ds_openldap.py ++++ b/src/tests/intg/ds_openldap.py +@@ -186,6 +186,12 @@ class DSOpenLDAP(DS): + db_config_file.write(db_config) + db_config_file.close() + ++ # Import ad schema ++ subprocess.check_call( ++ ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config", ++ "-l", "data/ssh_schema.ldif"], ++ ) ++ + def _start_daemon(self): + """Start the instance.""" + if subprocess.call(["slapd", "-F", self.conf_slapd_d_dir, +-- +2.14.4 + diff --git a/SOURCES/0113-TESTS-Allow-adding-sshPublicKey-for-users.patch b/SOURCES/0113-TESTS-Allow-adding-sshPublicKey-for-users.patch new file mode 100644 index 0000000..630e1b0 --- /dev/null +++ b/SOURCES/0113-TESTS-Allow-adding-sshPublicKey-for-users.patch @@ -0,0 +1,78 @@ +From db4a80c1e798872d4b1196ef9a768b35e7962d28 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Sun, 17 Jun 2018 22:06:22 +0200 +Subject: [PATCH] TESTS: Allow adding sshPublicKey for users +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds the objectclass and allows storing a list of sshPublicKey +attributes for users. Since there is no harm in adding the extra +objectclass, we can do it unconditionally. + +Related to: +https://pagure.io/SSSD/sssd/issue/3747 + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 56cda832e9f61c52e9cfde1f0864507de718ffbb) +--- + src/tests/intg/ldap_ent.py | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/tests/intg/ldap_ent.py b/src/tests/intg/ldap_ent.py +index 6b6d8f903cbcc277d892c3212ca382f4aaadc671..a4c987969d3dcefba2af69e095b220180e0fa54c 100644 +--- a/src/tests/intg/ldap_ent.py ++++ b/src/tests/intg/ldap_ent.py +@@ -24,7 +24,8 @@ def user(base_dn, uid, uidNumber, gidNumber, + homeDirectory=None, + loginShell=None, + cn=None, +- sn=None): ++ sn=None, ++ sshPubKey=()): + """ + Generate an RFC2307(bis) user add-modlist for passing to ldap.add* + """ +@@ -33,7 +34,8 @@ def user(base_dn, uid, uidNumber, gidNumber, + user = ( + "uid=" + uid + ",ou=Users," + base_dn, + [ +- ('objectClass', [b'top', b'inetOrgPerson', b'posixAccount']), ++ ('objectClass', [b'top', b'inetOrgPerson', ++ b'posixAccount', b'ldapPublicKey']), + ('cn', [uidNumber if cn is None else cn.encode('utf-8')]), + ('sn', [b'User' if sn is None else sn.encode('utf-8')]), + ('uidNumber', [uidNumber]), +@@ -51,6 +53,9 @@ def user(base_dn, uid, uidNumber, gidNumber, + ) + if gecos is not None: + user[1].append(('gecos', [gecos.encode('utf-8')])) ++ if len(sshPubKey) > 0: ++ pubkeys = [key.encode('utf-8') for key in sshPubKey] ++ user[1].append(('sshPublicKey', pubkeys)) + return user + + +@@ -118,7 +123,8 @@ class List(list): + homeDirectory=None, + loginShell=None, + cn=None, +- sn=None): ++ sn=None, ++ sshPubKey=()): + """Add an RFC2307(bis) user add-modlist.""" + self.append(user(base_dn or self.base_dn, + uid, uidNumber, gidNumber, +@@ -127,7 +133,8 @@ class List(list): + homeDirectory=homeDirectory, + loginShell=loginShell, + cn=cn, +- sn=sn)) ++ sn=sn, ++ sshPubKey=sshPubKey)) + + def add_group(self, cn, gidNumber, member_uids=[], + base_dn=None): +-- +2.14.4 + diff --git a/SOURCES/0114-TESTS-Add-a-basic-SSH-responder-test.patch b/SOURCES/0114-TESTS-Add-a-basic-SSH-responder-test.patch new file mode 100644 index 0000000..8dbcf01 --- /dev/null +++ b/SOURCES/0114-TESTS-Add-a-basic-SSH-responder-test.patch @@ -0,0 +1,276 @@ +From 612dda4bbd706be9e7c3674e4d0420f9ebd1ea83 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 18 Jun 2018 09:12:13 +0200 +Subject: [PATCH] TESTS: Add a basic SSH responder test +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds a basic test that makes sure that a list of SSH public keys can be +retrieved. This is to make sure we don't break the SSH integration later +on. + +Related: +https://pagure.io/SSSD/sssd/issue/3747 + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 804c5b538ad89a1a3897b93f39d716fa50530842) +--- + src/tests/intg/Makefile.am | 1 + + src/tests/intg/test_ssh_pubkey.py | 232 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 233 insertions(+) + create mode 100644 src/tests/intg/test_ssh_pubkey.py + +diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am +index 209e5a0c73db99b11aa6967f30db23933d21acb0..285ce21f04dddb6388c595470eac8f31bc224a60 100644 +--- a/src/tests/intg/Makefile.am ++++ b/src/tests/intg/Makefile.am +@@ -35,6 +35,7 @@ dist_noinst_DATA = \ + data/ad_data.ldif \ + data/ad_schema.ldif \ + test_pysss_nss_idmap.py \ ++ test_ssh_pubkey.py \ + $(NULL) + + config.py: config.py.m4 +diff --git a/src/tests/intg/test_ssh_pubkey.py b/src/tests/intg/test_ssh_pubkey.py +new file mode 100644 +index 0000000000000000000000000000000000000000..fbf55566e341373873057ec4e3af1d7f83202aa7 +--- /dev/null ++++ b/src/tests/intg/test_ssh_pubkey.py +@@ -0,0 +1,232 @@ ++# ++# ssh public key integration test ++# ++# Copyright (c) 2018 Red Hat, Inc. ++# ++# 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 signal ++import subprocess ++import time ++import ldap ++import ldap.modlist ++import pytest ++ ++import config ++import ds_openldap ++import ent ++import ldap_ent ++from util import unindent, get_call_output ++ ++LDAP_BASE_DN = "dc=example,dc=com" ++ ++USER1_PUBKEY1 = "ssh-dss AAAAB3NzaC1kc3MAAACBAPMkvcU53RVhBtjwiC3IqeRIWR9Qwdv8\ ++DmZzEsDD3Csd6jYxMsPZoXcPrHqwYcEj1s5MVqhdSFS0Cjz13e7gO6OMLInO3xMBSSFHjfp9RE1H\ ++pgc4WisazzyJaW9EMkQo/DqvkFkKh31oqAmxcSbLAFJRg4TTIqm18qu8IRKS6m/RAAAAFQC97TA5\ ++JSsMsaX1bRszC7y4PhMBvQAAAIEAt9Yo9v/h9W4nDbzUdkGwNRszlPEK+T12bJv0O9Fk6subD3Do\ ++6A4Qru/Nr6voXoq8b018Wb7iFWvKOoz5uT/plWBKLXL2NN7ovTR+dUJIzvwurQZroukmU1EghNey\ ++lkSHmDlxSoMK6Nh21uGu6l+b6x5pXNaZHMpsywG4kY8SoC0AAACAAWLHneEGvqkYA8La4Eob+Hjj\ ++mAKilx8byxm3Kfb1XO+ZrR6XxadofZOaUYRMpPKgFjKAKPxJftPLiDjWM7lSe6h8df0dUMLVXt6m\ ++eA83kE0uK5JOOGJfJDqmRed2YnfxUDNNFQGT4xFWGrNtYNbGyw9BWKbkooAsLqaO04zP3Rs= \ ++user1@LDAP" ++ ++USER1_PUBKEY2 = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwHUUF3HPH+DkU6j8k7Q1wHG\ ++RJY9NeLqSav3h95mTSCQYPSC7I9RTJ4OORgqCbEzrP/DYrrn4TtQ9dhRJar3ZY+F36SH5yFIXORb\ ++lAIbFU+/anahBuFS9vHi1MqFPckGmwJ4QCpjQhdYxo1ro0e1RuGSaQNp/w9N6S/fDz4Cj4I99xDz\ ++SeQeGHxYv0e60plQ8dUajmnaGmYRJHF9a6Ban7IWySActCja7eQP2zIRXEZMpuhl1E0U4y+gHTFI\ ++gD3zQai3QrXm8RUrQURIJ0u6BlGS910OPbHqLpLTFWG08L8sNUcYzC+DY6yoCSO0n/Df3pVRS4C9\ ++5Krf3FqppMTjdfQ== user1@LDAP" ++ ++ ++@pytest.fixture(scope="module") ++def ds_inst(request): ++ """LDAP server instance fixture""" ++ ds_inst = ds_openldap.DSOpenLDAP( ++ config.PREFIX, 10389, LDAP_BASE_DN, ++ "cn=admin", "Secret123" ++ ) ++ ++ try: ++ ds_inst.setup() ++ except: ++ ds_inst.teardown() ++ raise ++ request.addfinalizer(ds_inst.teardown) ++ return ds_inst ++ ++ ++@pytest.fixture(scope="module") ++def ldap_conn(request, ds_inst): ++ """LDAP server connection fixture""" ++ ldap_conn = ds_inst.bind() ++ ldap_conn.ds_inst = ds_inst ++ request.addfinalizer(ldap_conn.unbind_s) ++ return ldap_conn ++ ++ ++def create_ldap_entries(ldap_conn, ent_list=None): ++ """Add LDAP entries from ent_list""" ++ if ent_list is not None: ++ for entry in ent_list: ++ ldap_conn.add_s(entry[0], entry[1]) ++ ++ ++def cleanup_ldap_entries(ldap_conn, ent_list=None): ++ """Remove LDAP entries added by create_ldap_entries""" ++ if ent_list is None: ++ for ou in ("Users", "Groups", "Netgroups", "Services", "Policies"): ++ for entry in ldap_conn.search_s("ou=" + ou + "," + ++ ldap_conn.ds_inst.base_dn, ++ ldap.SCOPE_ONELEVEL, ++ attrlist=[]): ++ ldap_conn.delete_s(entry[0]) ++ else: ++ for entry in ent_list: ++ ldap_conn.delete_s(entry[0]) ++ ++ ++def create_ldap_cleanup(request, ldap_conn, ent_list=None): ++ """Add teardown for removing all user/group LDAP entries""" ++ request.addfinalizer(lambda: cleanup_ldap_entries(ldap_conn, ent_list)) ++ ++ ++def create_ldap_fixture(request, ldap_conn, ent_list=None): ++ """Add LDAP entries and add teardown for removing them""" ++ create_ldap_entries(ldap_conn, ent_list) ++ create_ldap_cleanup(request, ldap_conn, ent_list) ++ ++ ++SCHEMA_RFC2307_BIS = "rfc2307bis" ++ ++ ++def format_basic_conf(ldap_conn, schema): ++ """Format a basic SSSD configuration""" ++ schema_conf = "ldap_schema = " + schema + "\n" ++ schema_conf += "ldap_group_object_class = groupOfNames\n" ++ return unindent("""\ ++ [sssd] ++ domains = LDAP ++ services = nss, ssh ++ ++ [nss] ++ ++ [ssh] ++ debug_level=10 ++ ++ [domain/LDAP] ++ {schema_conf} ++ id_provider = ldap ++ auth_provider = ldap ++ ldap_uri = {ldap_conn.ds_inst.ldap_url} ++ ldap_search_base = {ldap_conn.ds_inst.base_dn} ++ ldap_sudo_use_host_filter = false ++ debug_level=10 ++ """).format(**locals()) ++ ++ ++def create_conf_file(contents): ++ """Create sssd.conf with specified contents""" ++ conf = open(config.CONF_PATH, "w") ++ conf.write(contents) ++ conf.close() ++ os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR) ++ ++ ++def cleanup_conf_file(): ++ """Remove sssd.conf, if it exists""" ++ if os.path.lexists(config.CONF_PATH): ++ os.unlink(config.CONF_PATH) ++ ++ ++def create_conf_cleanup(request): ++ """Add teardown for removing sssd.conf""" ++ request.addfinalizer(cleanup_conf_file) ++ ++ ++def create_conf_fixture(request, contents): ++ """ ++ Create sssd.conf with specified contents and add teardown for removing it ++ """ ++ create_conf_file(contents) ++ create_conf_cleanup(request) ++ ++ ++def create_sssd_process(): ++ """Start the SSSD process""" ++ if subprocess.call(["sssd", "-D", "-f"]) != 0: ++ raise Exception("sssd start failed") ++ ++ ++def get_sssd_pid(): ++ pid_file = open(config.PIDFILE_PATH, "r") ++ pid = int(pid_file.read()) ++ return pid ++ ++ ++def cleanup_sssd_process(): ++ """Stop the SSSD process and remove its state""" ++ try: ++ pid = get_sssd_pid() ++ os.kill(pid, signal.SIGTERM) ++ while True: ++ try: ++ os.kill(pid, signal.SIGCONT) ++ except: ++ break ++ time.sleep(1) ++ except: ++ pass ++ for path in os.listdir(config.DB_PATH): ++ os.unlink(config.DB_PATH + "/" + path) ++ for path in os.listdir(config.MCACHE_PATH): ++ os.unlink(config.MCACHE_PATH + "/" + path) ++ ++ ++def create_sssd_fixture(request): ++ """Start SSSD and add teardown for stopping it and removing its state""" ++ create_sssd_process() ++ create_sssd_cleanup(request) ++ ++ ++def create_sssd_cleanup(request): ++ """Add teardown for stopping SSSD and removing its state""" ++ request.addfinalizer(cleanup_sssd_process) ++ ++ ++@pytest.fixture ++def add_user_with_ssh_key(request, ldap_conn): ++ ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) ++ ent_list.add_user("user1", 1001, 2001, ++ sshPubKey=(USER1_PUBKEY1, USER1_PUBKEY2)) ++ ent_list.add_user("user2", 1002, 2001) ++ create_ldap_fixture(request, ldap_conn, ent_list) ++ ++ conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) ++ create_conf_fixture(request, conf) ++ create_sssd_fixture(request) ++ return None ++ ++ ++def test_ssh_pubkey_retrieve(add_user_with_ssh_key): ++ """ ++ Test that we can retrieve an SSH public key for a user who has one ++ and can't retrieve a key for a user who does not have one. ++ """ ++ sshpubkey = get_call_output(["sss_ssh_authorizedkeys", "user1"]) ++ assert sshpubkey == USER1_PUBKEY1 + '\n' + USER1_PUBKEY2 + '\n' ++ ++ sshpubkey = get_call_output(["sss_ssh_authorizedkeys", "user2"]) ++ assert len(sshpubkey) == 0 +-- +2.14.4 + diff --git a/SOURCES/0115-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch b/SOURCES/0115-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch new file mode 100644 index 0000000..711e447 --- /dev/null +++ b/SOURCES/0115-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch @@ -0,0 +1,88 @@ +From d1b01f0a04e54c55183fd5cee4b713e28e4e2cd7 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 28 May 2018 21:41:49 +0200 +Subject: [PATCH] SSH: Do not exit abruptly if SSHD closes its end of the pipe + before reading all the SSH keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://pagure.io/SSSD/sssd/issue/3747 + +Before writing the keys to sshd, ignore SIGPIPE so that if the pipe +towards the authorizedkeys helper is closed, the sss_ssh_authorizedkeys +helper is not terminated with SIGPIPE, but instead proceeds and then the +write(2) calls would non-terminally fail with EPIPE. + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit cb138d7d060611e891d341db08477e41f9a3d17d) +--- + src/sss_client/ssh/sss_ssh_authorizedkeys.c | 35 ++++++++++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c +index 782a9f44379bff5346c896b3e03570720632c0be..b0280fbf8b0ed0501d792973241b826fc4a7a04d 100644 +--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c ++++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include "util/util.h" + #include "util/crypto/sss_crypto.h" +@@ -99,8 +100,16 @@ int main(int argc, const char **argv) + goto fini; + } + ++ /* if sshd closes its end of the pipe, we don't want sss_ssh_authorizedkeys ++ * to exit abruptly, but to finish gracefully instead because the valid ++ * key can be present in the data already written ++ */ ++ signal(SIGPIPE, SIG_IGN); ++ + /* print results */ + for (i = 0; i < ent->num_pubkeys; i++) { ++ char *repr_break = NULL; ++ + ret = sss_ssh_format_pubkey(mem_ctx, &ent->pubkeys[i], &repr); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, +@@ -109,7 +118,31 @@ int main(int argc, const char **argv) + continue; + } + +- printf("%s\n", repr); ++ /* OpenSSH expects a linebreak after each key */ ++ repr_break = talloc_asprintf(mem_ctx, "%s\n", repr); ++ talloc_zfree(repr); ++ if (repr_break == NULL) { ++ ret = ENOMEM; ++ goto fini; ++ } ++ ++ ret = sss_atomic_write_s(STDOUT_FILENO, repr_break, strlen(repr_break)); ++ /* Avoid spiking memory with too many large keys */ ++ talloc_zfree(repr_break); ++ if (ret < 0) { ++ ret = errno; ++ if (ret == EPIPE) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "SSHD closed the pipe before all keys could be written\n"); ++ /* Return 0 so that openssh doesn't abort pubkey auth */ ++ ret = 0; ++ goto fini; ++ } ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "sss_atomic_write_s() failed (%d): %s\n", ++ ret, strerror(ret)); ++ goto fini; ++ } + } + + ret = EXIT_SUCCESS; +-- +2.14.4 + diff --git a/SOURCES/0116-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch b/SOURCES/0116-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch new file mode 100644 index 0000000..494b327 --- /dev/null +++ b/SOURCES/0116-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch @@ -0,0 +1,213 @@ +From 187b9f28f1ea2e3fa4b5e3385050701fdc1d0f69 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 28 May 2018 21:49:41 +0200 +Subject: [PATCH] TESTS: Add a helper binary that can trigger the SIGPIPE to + authorizedkeys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds a test tool that simulates the behaviour of OpenSSH in the sense +that it starts to read the output from the sss_ssh_authorizedkeys tool, +but then closes the pipe before reading the whole output. + +Related: +https://pagure.io/SSSD/sssd/issue/3747 + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 909c16edb26a3c48b10a49e7919a35d13d31c52e) +--- + Makefile.am | 15 ++++- + src/tests/test_ssh_client.c | 133 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 147 insertions(+), 1 deletion(-) + create mode 100644 src/tests/test_ssh_client.c + +diff --git a/Makefile.am b/Makefile.am +index 5917bd904054055a259eb69217282e4fb914c700..01fa4e43e48dcb722056d614e19f02687d32014b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -331,6 +331,7 @@ endif # HAVE_CMOCKA + check_PROGRAMS = \ + stress-tests \ + krb5-child-test \ ++ test_ssh_client \ + $(non_interactive_cmocka_based_tests) \ + $(non_interactive_check_based_tests) + +@@ -2294,6 +2295,18 @@ krb5_child_test_LDADD = \ + $(SSSD_INTERNAL_LTLIBS) \ + libsss_test_common.la + ++test_ssh_client_SOURCES = \ ++ src/tests/test_ssh_client.c \ ++ $(NULL) ++test_ssh_client_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ -DSSH_CLIENT_DIR=\"$(abs_top_builddir)\" \ ++ $(NULL) ++test_ssh_client_LDADD = \ ++ $(SSSD_INTERNAL_LTLIBS) \ ++ $(SSSD_LIBS) \ ++ $(NULL) ++ + if BUILD_DBUS_TESTS + + sbus_tests_SOURCES = \ +@@ -3418,7 +3431,6 @@ test_iobuf_LDADD = \ + $(SSSD_LIBS) \ + $(NULL) + +- + EXTRA_simple_access_tests_DEPENDENCIES = \ + $(ldblib_LTLIBRARIES) + simple_access_tests_SOURCES = \ +@@ -3607,6 +3619,7 @@ intgcheck-prepare: + $(INTGCHECK_CONFIGURE_FLAGS) \ + CFLAGS="$$CFLAGS -DKCM_PEER_UID=$$(id -u)"; \ + $(MAKE) $(AM_MAKEFLAGS) ; \ ++ $(MAKE) $(AM_MAKEFLAGS) test_ssh_client; \ + : Force single-thread install to workaround concurrency issues; \ + $(MAKE) $(AM_MAKEFLAGS) -j1 install; \ + : Remove .la files from LDB module directory to avoid loader warnings; \ +diff --git a/src/tests/test_ssh_client.c b/src/tests/test_ssh_client.c +new file mode 100644 +index 0000000000000000000000000000000000000000..8f963941f3249561178436d6f6dfc376780a4cda +--- /dev/null ++++ b/src/tests/test_ssh_client.c +@@ -0,0 +1,133 @@ ++/* ++ Copyright (C) 2018 Red Hat ++ ++ This program 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; either version 3 of the License, or ++ (at your option) any later version. ++ ++ 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 . ++*/ ++ ++#include ++#include ++#include "util/util.h" ++ ++#ifdef SSH_CLIENT_DIR ++#define SSH_AK_CLIENT_PATH SSH_CLIENT_DIR"/sss_ssh_authorizedkeys" ++#else ++#error "The path to the ssh authorizedkeys helper is not defined" ++#endif /* SSH_CLIENT_DIR */ ++ ++int main(int argc, const char *argv[]) ++{ ++ poptContext pc; ++ int opt; ++ struct poptOption long_options[] = { ++ POPT_AUTOHELP ++ SSSD_DEBUG_OPTS ++ POPT_TABLEEND ++ }; ++ struct stat sb; ++ int ret; ++ int status; ++ int p[2]; ++ pid_t pid; ++ const char *pc_user = NULL; ++ char *av[3]; ++ char buf[5]; /* Ridiculously small buffer by design */ ++ ++ /* Set debug level to invalid value so we can decide if -d 0 was used. */ ++ debug_level = SSSDBG_INVALID; ++ ++ pc = poptGetContext(argv[0], argc, argv, long_options, 0); ++ poptSetOtherOptionHelp(pc, "USER"); ++ while((opt = poptGetNextOpt(pc)) != -1) { ++ switch(opt) { ++ default: ++ fprintf(stderr, "\nInvalid option %s: %s\n\n", ++ poptBadOption(pc, 0), poptStrerror(opt)); ++ poptPrintUsage(pc, stderr, 0); ++ return 3; ++ } ++ } ++ ++ pc_user = poptGetArg(pc); ++ if (pc_user == NULL) { ++ fprintf(stderr, "No user specified\n"); ++ return 3; ++ } ++ ++ poptFreeContext(pc); ++ ++ DEBUG_CLI_INIT(debug_level); ++ ++ ret = stat(SSH_AK_CLIENT_PATH, &sb); ++ if (ret != 0) { ++ ret = errno; ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Could not stat %s [%d]: %s\n", ++ SSH_AK_CLIENT_PATH, ret, strerror(ret)); ++ return 3; ++ } ++ ++ ret = pipe(p); ++ if (ret != 0) { ++ perror("pipe"); ++ return 3; ++ } ++ ++ switch (pid = fork()) { ++ case -1: ++ ret = errno; ++ close(p[0]); ++ close(p[1]); ++ DEBUG(SSSDBG_CRIT_FAILURE, "fork failed: %d\n", ret); ++ return 3; ++ case 0: ++ /* child */ ++ av[0] = discard_const(SSH_AK_CLIENT_PATH); ++ av[1] = discard_const(pc_user); ++ av[2] = NULL; ++ ++ close(p[0]); ++ ret = dup2(p[1], STDOUT_FILENO); ++ if (ret == -1) { ++ perror("dup2"); ++ return 3; ++ } ++ ++ execv(av[0], av); ++ return 3; ++ default: ++ /* parent */ ++ break; ++ } ++ ++ close(p[1]); ++ read(p[0], buf, sizeof(buf)); ++ close(p[0]); ++ ++ pid = waitpid(pid, &status, 0); ++ if (pid == -1) { ++ perror("waitpid"); ++ return 3; ++ } ++ ++ if (WIFEXITED(status)) { ++ printf("sss_ssh_authorizedkeys exited with return code %d\n", WEXITSTATUS(status)); ++ return 0; ++ } else if (WIFSIGNALED(status)) { ++ printf("sss_ssh_authorizedkeys exited with signal %d\n", WTERMSIG(status)); ++ return 1; ++ } ++ ++ printf("sss_ssh_authorizedkeys exited for another reason\n"); ++ return 2; ++} +-- +2.14.4 + diff --git a/SOURCES/0117-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch b/SOURCES/0117-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch new file mode 100644 index 0000000..c791974 --- /dev/null +++ b/SOURCES/0117-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch @@ -0,0 +1,94 @@ +From 103a22b85df5c371aefb08e476a3ab950e6882a3 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 19 Jun 2018 11:39:02 +0200 +Subject: [PATCH] TESTS: Add a regression test for SIGHUP handling in + sss_ssh_authorizedkeys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A regression test for: +https://pagure.io/SSSD/sssd/issue/3747 + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 4cc3c1a1b1070c12bcc4351880d8207e47b37496) +--- + src/tests/intg/test_ssh_pubkey.py | 58 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/src/tests/intg/test_ssh_pubkey.py b/src/tests/intg/test_ssh_pubkey.py +index fbf55566e341373873057ec4e3af1d7f83202aa7..8fb41c62d87ec210c9aad8582023fe1cb00f2b4e 100644 +--- a/src/tests/intg/test_ssh_pubkey.py ++++ b/src/tests/intg/test_ssh_pubkey.py +@@ -24,6 +24,8 @@ import time + import ldap + import ldap.modlist + import pytest ++import string ++import random + + import config + import ds_openldap +@@ -230,3 +232,59 @@ def test_ssh_pubkey_retrieve(add_user_with_ssh_key): + + sshpubkey = get_call_output(["sss_ssh_authorizedkeys", "user2"]) + assert len(sshpubkey) == 0 ++ ++ ++@pytest.fixture() ++def sighup_client(request): ++ test_ssh_cli_path = os.path.join(config.ABS_BUILDDIR, ++ "..", "..", "..", "test_ssh_client") ++ assert os.access(test_ssh_cli_path, os.X_OK) ++ return test_ssh_cli_path ++ ++ ++@pytest.fixture ++def add_user_with_many_keys(request, ldap_conn): ++ # Generate a large list of unique ssh pubkeys ++ pubkey_list = [] ++ while len(pubkey_list) < 50: ++ new_pubkey = list(USER1_PUBKEY1) ++ new_pubkey[10] = random.choice(string.ascii_uppercase) ++ new_pubkey[11] = random.choice(string.ascii_uppercase) ++ new_pubkey[12] = random.choice(string.ascii_uppercase) ++ str_new_pubkey = ''.join(c for c in new_pubkey) ++ if str_new_pubkey in pubkey_list: ++ continue ++ pubkey_list.append(str_new_pubkey) ++ ++ ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) ++ ent_list.add_user("user1", 1001, 2001, sshPubKey=pubkey_list) ++ create_ldap_fixture(request, ldap_conn, ent_list) ++ ++ conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS) ++ create_conf_fixture(request, conf) ++ create_sssd_fixture(request) ++ return None ++ ++ ++def test_ssh_sighup(add_user_with_many_keys, sighup_client): ++ """ ++ A regression test for https://pagure.io/SSSD/sssd/issue/3747 ++ ++ OpenSSH can close its end of the pipe towards sss_ssh_authorizedkeys ++ before all of the output is read. In that case, older versions ++ of sss_ssh_authorizedkeys were receiving a SIGPIPE ++ """ ++ cli_path = sighup_client ++ ++ # python actually does the sensible, but unexpected (for a C programmer) ++ # thing and handles SIGPIPE. In order to reproduce the bug, we need ++ # to unset the SIGPIPE handler ++ signal.signal(signal.SIGPIPE, signal.SIG_DFL) ++ ++ process = subprocess.Popen([cli_path, "user1"], ++ stdout=subprocess.PIPE, ++ stderr=subprocess.PIPE) ++ _, _ = process.communicate() ++ # If the test tool detects that sss_ssh_authorizedkeys was killed with a ++ # signal, it would have returned 1 ++ assert process.returncode == 0 +-- +2.14.4 + diff --git a/SOURCES/0118-TESTS-Order-list-of-entries-in-some-lists.patch b/SOURCES/0118-TESTS-Order-list-of-entries-in-some-lists.patch new file mode 100644 index 0000000..8e7ca54 --- /dev/null +++ b/SOURCES/0118-TESTS-Order-list-of-entries-in-some-lists.patch @@ -0,0 +1,175 @@ +From 1a73dbe9747aec2818fabd179e0fb46695d66433 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 13 Nov 2017 16:15:21 +0100 +Subject: [PATCH] TESTS: Order list of entries in some lists +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some tests started to fail because we depended on specific +order of users in groups or messages in ldb results to be +returned and that order changed. + +This patch adds a simple helper functions into these tests +that order the entries before comparison with expected results. +more deterministic. + +Resolves: +https://pagure.io/SSSD/sssd/issue/3563 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit caae0e53e6091806634943699f4398b6a20273b4) + +DOWNSTREAM: +Resolves: rhbz#1596292 - home dir disappear in sssd cache on the IPA master for AD users [rhel-7.5.z] +--- + src/tests/cmocka/test_nss_srv.c | 22 +++++++++++++++++++ + src/tests/cmocka/test_sysdb_views.c | 42 ++++++++++++++++++++++++++++++++----- + 2 files changed, 59 insertions(+), 5 deletions(-) + +diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c +index 6aa726153183b5a871a75d398727ea7132358ca6..21bd80fb7f6562f6a31452bac6a26c109fef4cb1 100644 +--- a/src/tests/cmocka/test_nss_srv.c ++++ b/src/tests/cmocka/test_nss_srv.c +@@ -585,6 +585,25 @@ static errno_t delete_group(struct nss_test_ctx *ctx, + return ret; + } + ++static int cmp_func(const void *a, const void *b) ++{ ++ char *str1 = *(char **)discard_const(a); ++ char *str2 = *(char **)discard_const(b); ++ ++ return strcmp(str1, str2); ++} ++ ++static void order_string_array(char **_list, int size) ++{ ++ if (size < 2 || _list == NULL || *_list == NULL) { ++ /* Nothing to do */ ++ return; ++ } ++ ++ qsort(_list, size, sizeof(char *), cmp_func); ++ return; ++} ++ + static void assert_groups_equal(struct group *expected, + struct group *gr, const int nmem) + { +@@ -594,6 +613,9 @@ static void assert_groups_equal(struct group *expected, + assert_string_equal(gr->gr_name, expected->gr_name); + assert_string_equal(gr->gr_passwd, expected->gr_passwd); + ++ order_string_array(gr->gr_mem, nmem); ++ order_string_array(expected->gr_mem, nmem); ++ + for (i = 0; i < nmem; i++) { + assert_string_equal(gr->gr_mem[i], expected->gr_mem[i]); + } +diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c +index 0378254b4440b29c3182faf2adde8c3db8a4ce97..dd3eb50f9310ff925734dcf51a669d08a638aefd 100644 +--- a/src/tests/cmocka/test_sysdb_views.c ++++ b/src/tests/cmocka/test_sysdb_views.c +@@ -22,6 +22,7 @@ + along with this program. If not, see . + */ + ++#include + #include + #include + #include +@@ -612,6 +613,31 @@ static int test_enum_users_setup(void **state) + return 0; + } + ++static int cmp_func(const void *a, const void *b) ++{ ++ const char *str1; ++ const char *str2; ++ struct ldb_message *msg1 = *(struct ldb_message **)discard_const(a); ++ struct ldb_message *msg2 = *(struct ldb_message **)discard_const(b); ++ ++ str1 = ldb_msg_find_attr_as_string(msg1, SYSDB_NAME, NULL); ++ str2 = ldb_msg_find_attr_as_string(msg2, SYSDB_NAME, NULL); ++ ++ return strcmp(str1, str2); ++} ++ ++/* Make the order of ldb results deterministic */ ++static void order_ldb_res_msgs(struct ldb_result *res) ++{ ++ if (res == NULL || res->count < 2) { ++ /* Nothing to do */ ++ return; ++ } ++ ++ qsort(res->msgs, res->count, sizeof(struct ldb_message *), cmp_func); ++ return; ++} ++ + static void assert_user_attrs(struct ldb_message *msg, + struct sss_domain_info *dom, + const char *shortname, +@@ -660,8 +686,9 @@ static void check_enumpwent(int ret, struct sss_domain_info *dom, + assert_int_equal(ret, EOK); + assert_int_equal(res->count, N_ELEMENTS(users)-1); + +- assert_user_attrs(res->msgs[0], dom, "barney", views); +- assert_user_attrs(res->msgs[1], dom, "alice", views); ++ order_ldb_res_msgs(res); ++ assert_user_attrs(res->msgs[0], dom, "alice", views); ++ assert_user_attrs(res->msgs[1], dom, "barney", views); + assert_user_attrs(res->msgs[2], dom, "bob", views); + } + +@@ -703,6 +730,7 @@ static void test_sysdb_enumpwent_filter(void **state) + ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "b*", 0, &res); + assert_int_equal(ret, EOK); + assert_int_equal(res->count, 2); ++ order_ldb_res_msgs(res); + assert_user_attrs(res->msgs[0], test_ctx->domain, "barney", false); + assert_user_attrs(res->msgs[1], test_ctx->domain, "bob", false); + +@@ -749,6 +777,7 @@ static void test_sysdb_enumpwent_filter_views(void **state) + "b*", NULL, &res); + assert_int_equal(ret, EOK); + assert_int_equal(res->count, 2); ++ order_ldb_res_msgs(res); + assert_user_attrs(res->msgs[0], test_ctx->domain, "barney", true); + assert_user_attrs(res->msgs[1], test_ctx->domain, "bob", true); + +@@ -896,10 +925,11 @@ static void check_enumgrent(int ret, struct sss_domain_info *dom, + { + assert_int_equal(ret, EOK); + assert_int_equal(res->count, N_ELEMENTS(groups)-1); +- assert_group_attrs(res->msgs[0], dom, "three", +- views ? TEST_GID_OVERRIDE_BASE + 2 : 0); +- assert_group_attrs(res->msgs[1], dom, "one", ++ order_ldb_res_msgs(res); ++ assert_group_attrs(res->msgs[0], dom, "one", + views ? TEST_GID_OVERRIDE_BASE : 0); ++ assert_group_attrs(res->msgs[1], dom, "three", ++ views ? TEST_GID_OVERRIDE_BASE + 2 : 0); + assert_group_attrs(res->msgs[2], dom, "two", + views ? TEST_GID_OVERRIDE_BASE + 1 : 0); + } +@@ -942,6 +972,7 @@ static void test_sysdb_enumgrent_filter(void **state) + ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "t*", 0, &res); + assert_int_equal(ret, EOK); + assert_int_equal(res->count, 2); ++ order_ldb_res_msgs(res); + assert_group_attrs(res->msgs[0], test_ctx->domain, "three", 0); + assert_group_attrs(res->msgs[1], test_ctx->domain, "two", 0); + +@@ -988,6 +1019,7 @@ static void test_sysdb_enumgrent_filter_views(void **state) + "t*", NULL, &res); + assert_int_equal(ret, EOK); + assert_int_equal(res->count, 2); ++ order_ldb_res_msgs(res); + assert_group_attrs(res->msgs[0], test_ctx->domain, + "three", TEST_GID_OVERRIDE_BASE + 2); + assert_group_attrs(res->msgs[1], test_ctx->domain, "two", +-- +2.14.4 + diff --git a/SOURCES/0119-sysdb-add-sysdb_getgrgid_attrs.patch b/SOURCES/0119-sysdb-add-sysdb_getgrgid_attrs.patch new file mode 100644 index 0000000..747a123 --- /dev/null +++ b/SOURCES/0119-sysdb-add-sysdb_getgrgid_attrs.patch @@ -0,0 +1,171 @@ +From f46dc8010a7d5fbb398e282d680703e1bd5963f4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 29 May 2018 15:33:34 +0200 +Subject: [PATCH] sysdb: add sysdb_getgrgid_attrs() + +sysdb_getgrgid() is the only MPG aware by GID request but only supports +a fixes set of attributes. The new call allows to add additional +arguments. + +Related to https://pagure.io/SSSD/sssd/issue/3748 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 8aa56a9e8744a7611fa26a254c4f9228e919c8ed) +--- + src/db/sysdb.h | 6 ++++++ + src/db/sysdb_ops.c | 3 +++ + src/db/sysdb_search.c | 31 ++++++++++++++++++++++++++----- + src/tests/sysdb-tests.c | 37 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 72 insertions(+), 5 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 2660314a75a574d7f5625c8672e5261587056d1a..affd1c9053e43ff24c98cc8fb23eec2c4b69f955 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -779,6 +779,12 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx, + gid_t gid, + struct ldb_result **res); + ++int sysdb_getgrgid_attrs(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ gid_t gid, ++ const char **attrs, ++ struct ldb_result **res); ++ + int sysdb_enumgrent(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + struct ldb_result **res); +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 024683317cab99743681db804f7026c8dbb33a38..c0d343bdabd324cbe8b9745c65c2a6e5a56321e1 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -709,6 +709,9 @@ int sysdb_search_group_by_name(TALLOC_CTX *mem_ctx, + return sysdb_search_by_name(mem_ctx, domain, name, SYSDB_GROUP, attrs, msg); + } + ++/* Please note that sysdb_search_group_by_gid() is not aware of MPGs. If MPG ++ * support is needed either the caller must handle it or sysdb_getgrgid() or ++ * sysdb_getgrgid_attrs() should be used. */ + int sysdb_search_group_by_gid(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + gid_t gid, +diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c +index 9f37cbcd50a778145518c15b6146ad812a5b4fa3..3d78a38b36e65febd50e41fc1d1be29eceeb7649 100644 +--- a/src/db/sysdb_search.c ++++ b/src/db/sysdb_search.c +@@ -1036,24 +1036,37 @@ done: + return ret; + } + +-int sysdb_getgrgid(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- gid_t gid, +- struct ldb_result **_res) ++int sysdb_getgrgid_attrs(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ gid_t gid, ++ const char **additional_attrs, ++ struct ldb_result **_res) + { + TALLOC_CTX *tmp_ctx; + unsigned long int ul_gid = gid; +- static const char *attrs[] = SYSDB_GRSRC_ATTRS; + const char *fmt_filter; + struct ldb_dn *base_dn; + struct ldb_result *res; + int ret; ++ static const char *default_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **attrs = NULL; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + ++ if (additional_attrs == NULL) { ++ attrs = default_attrs; ++ } else { ++ ret = add_strings_lists(tmp_ctx, additional_attrs, default_attrs, ++ false, discard_const(&attrs)); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "add_strings_lists failed.\n"); ++ goto done; ++ } ++ } ++ + if (domain->mpg) { + fmt_filter = SYSDB_GRGID_MPG_FILTER; + base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, +@@ -1092,6 +1105,14 @@ done: + return ret; + } + ++int sysdb_getgrgid(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ gid_t gid, ++ struct ldb_result **_res) ++{ ++ return sysdb_getgrgid_attrs(mem_ctx, domain, gid, NULL, _res); ++} ++ + int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name_filter, +diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c +index fc9936968bcde8370c7054ba303de4463b35e15a..30574679f51362d03d7b9e3f8a1d55889817e4c1 100644 +--- a/src/tests/sysdb-tests.c ++++ b/src/tests/sysdb-tests.c +@@ -1114,6 +1114,42 @@ done: + } + END_TEST + ++START_TEST (test_sysdb_getgrgid_attrs) ++{ ++ struct sysdb_test_ctx *test_ctx; ++ struct test_data *data; ++ struct ldb_result *res; ++ int ret; ++ const char *attrs[] = { SYSDB_CREATE_TIME, NULL }; ++ uint64_t ctime; ++ ++ /* Setup */ ++ ret = setup_sysdb_tests(&test_ctx); ++ if (ret != EOK) { ++ fail("Could not set up the test"); ++ return; ++ } ++ ++ data = test_data_new_group(test_ctx, _i); ++ fail_if(data == NULL, "OOM"); ++ ++ ret = sysdb_getgrgid_attrs(test_ctx, ++ test_ctx->domain, ++ data->gid, attrs, &res); ++ if (ret) { ++ fail("sysdb_getgrgid_attrs failed for gid %d (%d: %s)", ++ data->gid, ret, strerror(ret)); ++ goto done; ++ } ++ ++ ctime = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_CREATE_TIME, 0); ++ fail_unless(ctime != 0, "Missing create time"); ++ ++done: ++ talloc_free(test_ctx); ++} ++END_TEST ++ + START_TEST (test_sysdb_search_groups) + { + struct sysdb_test_ctx *test_ctx; +@@ -7072,6 +7108,7 @@ Suite *create_sysdb_suite(void) + + /* Verify the groups can be queried by GID */ + tcase_add_loop_test(tc_sysdb, test_sysdb_getgrgid, 28010, 28020); ++ tcase_add_loop_test(tc_sysdb, test_sysdb_getgrgid_attrs, 28010, 28020); + + /* Find the users by GID using a filter */ + tcase_add_loop_test(tc_sysdb, test_sysdb_search_groups, 28010, 28020); +-- +2.14.4 + diff --git a/SOURCES/0120-ipa-use-mpg-aware-group-lookup-in-get_object_from_ca.patch b/SOURCES/0120-ipa-use-mpg-aware-group-lookup-in-get_object_from_ca.patch new file mode 100644 index 0000000..b5ea5f9 --- /dev/null +++ b/SOURCES/0120-ipa-use-mpg-aware-group-lookup-in-get_object_from_ca.patch @@ -0,0 +1,61 @@ +From a6de362d3cfe16550eb16d01900f44c9aeb8cc50 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 29 May 2018 15:42:55 +0200 +Subject: [PATCH] ipa: use mpg aware group lookup in get_object_from_cache() + +Since with algorithmic id-mapping SSSD automatically creates user +private groups for AD user with the help of magic private groups (mpg) +get_object_from_cache() should use mpg aware calls to make sure the +right user object is found when handling a request to look up a user +private group. + +Only the lookup by gid had to be modified because +sysdb_search_group_by_name() used for lookups by name is aware of MPGs. + +Related to https://pagure.io/SSSD/sssd/issue/3748 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 032221568fe4287686d0ebb11b5c1fe51cc4735f) +--- + src/providers/ipa/ipa_subdomains_id.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index d40671086854f9c1a3f8bc7fc711009298dc31c8..3943579b07c7b2d32dde192b97b86eb036b91885 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -1030,7 +1030,14 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx, + + switch (ar->entry_type & BE_REQ_TYPE_MASK) { + case BE_REQ_GROUP: +- ret = sysdb_search_group_by_gid(mem_ctx, dom, id, attrs, &msg); ++ ret = sysdb_getgrgid_attrs(mem_ctx, dom, id, attrs, &res); ++ if (ret == EOK) { ++ if (res->count == 0) { ++ ret = ENOENT; ++ } else { ++ msg = res->msgs[0]; ++ } ++ } + break; + case BE_REQ_INITGROUPS: + case BE_REQ_USER: +@@ -1038,7 +1045,14 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx, + ret = sysdb_search_user_by_uid(mem_ctx, dom, id, attrs, &msg); + if (ret == ENOENT && (ar->entry_type & BE_REQ_TYPE_MASK) + == BE_REQ_USER_AND_GROUP) { +- ret = sysdb_search_group_by_gid(mem_ctx, dom, id, attrs, &msg); ++ ret = sysdb_getgrgid_attrs(mem_ctx, dom, id, attrs, &res); ++ if (ret == EOK) { ++ if (res->count == 0) { ++ ret = ENOENT; ++ } else { ++ msg = res->msgs[0]; ++ } ++ } + } + break; + default: +-- +2.14.4 + diff --git a/SOURCES/0121-ipa-allow-mpg-group-objects-in-apply_subdomain_homed.patch b/SOURCES/0121-ipa-allow-mpg-group-objects-in-apply_subdomain_homed.patch new file mode 100644 index 0000000..b785997 --- /dev/null +++ b/SOURCES/0121-ipa-allow-mpg-group-objects-in-apply_subdomain_homed.patch @@ -0,0 +1,47 @@ +From 8bbee851484f7fa51af542ed2757e2eea36bf535 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 29 May 2018 15:44:28 +0200 +Subject: [PATCH] ipa: allow mpg group objects in apply_subdomain_homedir() + +Since with algorithmic id-mapping SSSD automatically creates user +private groups for AD user with the help of magic private groups (mpg) +apply_subdomain_homedir() should be aware the in mpg domains a group +lookup might actually return a user object. Since the related sysdb +calls are clever and replace the objectcategory so that it matches the +original request type we have to check for the group category in the mpg +case as well. apply_subdomain_homedir() checks the uidNumber later as +well to make sure the object has the needed attributes for a user. + +Related to https://pagure.io/SSSD/sssd/issue/3748 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit e66517dcf63f1d4aaf866c22371dac7740ce0a48) +--- + src/providers/ipa/ipa_subdomains_id.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index 3943579b07c7b2d32dde192b97b86eb036b91885..c2064d33029a27a2c5d4b5344034ce90f8e746b8 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -895,9 +895,16 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, + goto done; + } + ++ /* The object is a user if SYSDB_OBJECTCATEGORY is SYSDB_USER_CLASS or in ++ * case of a MPG group lookup if SYSDB_OBJECTCATEGORY is SYSDB_GROUP_CLASS. ++ */ + for (c = 0; c < msg_el->num_values; c++) { + if (strncmp(SYSDB_USER_CLASS, (const char *)msg_el->values[c].data, +- msg_el->values[c].length) == 0) { ++ msg_el->values[c].length) == 0 ++ || (dom->mpg ++ && strncmp(SYSDB_GROUP_CLASS, ++ (const char *)msg_el->values[c].data, ++ msg_el->values[c].length) == 0)) { + break; + } + } +-- +2.14.4 + diff --git a/SOURCES/0122-AD-LDAP-do-not-fall-back-to-mpg-user-lookup-on-GC-co.patch b/SOURCES/0122-AD-LDAP-do-not-fall-back-to-mpg-user-lookup-on-GC-co.patch new file mode 100644 index 0000000..68dba38 --- /dev/null +++ b/SOURCES/0122-AD-LDAP-do-not-fall-back-to-mpg-user-lookup-on-GC-co.patch @@ -0,0 +1,68 @@ +From 4dbfa49f50fd785f374209c2e59205e79533788e Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 29 May 2018 15:46:33 +0200 +Subject: [PATCH] AD/LDAP: do not fall back to mpg user lookup on GC connection + +For MPG domains a group lookup might fall back to a user lookup to check +if the request is for a user private group. Since we cannot be sure that +all needed attributes for a user are replicated to the Global Catalog we +do not want to lookup the user during the fall back from the Global +Catalog. + +Since we cannot skip Global Catalog lookups for groups completely due to +membership to groups with universal scope this patch adds a flag to tell +the lower level lookup calls to not fall back on connections to a Global +Catalog. + +Related to https://pagure.io/SSSD/sssd/issue/3748 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit ad6ab352879264fdade8861aff53aa035a2e2240) +--- + src/providers/ad/ad_common.c | 1 + + src/providers/ldap/ldap_common.h | 2 ++ + src/providers/ldap/ldap_id.c | 3 ++- + 3 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c +index 2a1647173b76b410371315eb364e9a3785714a93..1dca2fe279cb7d6d647aed42e3b3fabfb34b7dac 100644 +--- a/src/providers/ad/ad_common.c ++++ b/src/providers/ad/ad_common.c +@@ -1375,6 +1375,7 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, + if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) { + clist[cindex] = ad_ctx->gc_ctx; + clist[cindex]->ignore_mark_offline = true; ++ clist[cindex]->no_mpg_user_fallback = true; + cindex++; + } + +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index 44dbc3fb0678412f46366321e0be836313380949..21cb57b0e7b265972db74ac78a3c1fb4ba2a9529 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -57,6 +57,8 @@ struct sdap_id_conn_ctx { + struct sdap_id_conn_ctx *prev, *next; + /* do not go offline, try another connection */ + bool ignore_mark_offline; ++ /* do not fall back to user lookups for mpg domains on this connection */ ++ bool no_mpg_user_fallback; + }; + + struct sdap_id_ctx { +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index 3824f8f9aa8d2892664f1182376bedf6fb8627f6..365d90fd1cdfba86c719b3669d057444a7449d66 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -1076,7 +1076,8 @@ static void groups_get_done(struct tevent_req *subreq) + } + + if (ret == ENOENT +- && state->domain->mpg == true) { ++ && state->domain->mpg == true ++ && !state->conn->no_mpg_user_fallback) { + /* The requested filter did not find a group. Before giving up, we must + * also check if the GID can be resolved through a primary group of a + * user +-- +2.14.4 + diff --git a/SOURCES/0123-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch b/SOURCES/0123-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch new file mode 100644 index 0000000..85fe196 --- /dev/null +++ b/SOURCES/0123-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch @@ -0,0 +1,45 @@ +From 7f698a050cea2baad34c84f8ae9e611dbf03ac7f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Thu, 12 Jul 2018 23:55:03 +0200 +Subject: [PATCH] deskprofile: don't bail if we fail to save one profile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Due to different reasons (a bug on fleet-commander, for instance?) we +may face the situation where one profile ends up stored in freeipa on a +half-broken state (with no data, for instance). + +In case it happens, we should try our best to save the not broken +profiles and just skip the broken ones instead of bailing the whole +operation. + +Resolves: +https://pagure.io/SSSD/sssd/issue/3773 + +Signed-off-by: Fabiano Fidêncio +Reviewed-by: Jakub Hrozek +(cherry picked from commit efd6702e5f70bb3df0f840dd3ce9f8f9264661ba) + +DOWNSTREAM: +Resolves: rhbz#1601360 - SSSD bails out saving desktop profiles in case an invalid profile is found [rhel-7.5.z] +--- + src/providers/ipa/ipa_session.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c +index 3c7dd33c30ac6331319fc62cac466c4fbf04c0a5..a93c21224ee4d539d412e61ea06cbde3b928416a 100644 +--- a/src/providers/ipa/ipa_session.c ++++ b/src/providers/ipa/ipa_session.c +@@ -766,7 +766,7 @@ ipa_pam_session_handler_save_deskprofile_rules( + DEBUG(SSSDBG_OP_FAILURE, + "Failed to save a Desktop Profile Rule to disk [%d]: %s\n", + ret, sss_strerror(ret)); +- goto done; ++ continue; + } + } + +-- +2.14.4 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 197046c..475c27c 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -48,7 +48,7 @@ Name: sssd Version: 1.16.0 -Release: 19%{?dist}.5 +Release: 19%{?dist}.8 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -170,6 +170,18 @@ Patch0108: 0108-NSS-nss_clear_netgroup_hash_table-do-not-free-data.patch Patch0109: 0109-winbind-idmap-plugin-support-inferface-version-6.patch Patch0110: 0110-winbind-idmap-plugin-fix-detection.patch Patch0111: 0111-Do-not-keep-allocating-external-groups-on-a-long-liv.patch +Patch0112: 0112-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch +Patch0113: 0113-TESTS-Allow-adding-sshPublicKey-for-users.patch +Patch0114: 0114-TESTS-Add-a-basic-SSH-responder-test.patch +Patch0115: 0115-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch +Patch0116: 0116-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch +Patch0117: 0117-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch +Patch0118: 0118-TESTS-Order-list-of-entries-in-some-lists.patch +Patch0119: 0119-sysdb-add-sysdb_getgrgid_attrs.patch +Patch0120: 0120-ipa-use-mpg-aware-group-lookup-in-get_object_from_ca.patch +Patch0121: 0121-ipa-allow-mpg-group-objects-in-apply_subdomain_homed.patch +Patch0122: 0122-AD-LDAP-do-not-fall-back-to-mpg-user-lookup-on-GC-co.patch +Patch0123: 0123-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch #This patch should not be removed in RHEL-7 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec @@ -1317,6 +1329,15 @@ systemctl try-restart sssd >/dev/null 2>&1 || : } %changelog +* Thu Jul 26 2018 Jakub Hrozek - 1.16.0-19.8 +- Resolves: rhbz#1601360 - SSSD bails out saving desktop profiles in case an invalid profile is found [rhel-7.5.z] + +* Tue Jul 24 2018 Jakub Hrozek - 1.16.0-19.7 +- Resolves: rhbz#1596292 - home dir disappear in sssd cache on the IPA master for AD users [rhel-7.5.z] + +* Fri Jul 20 2018 Jakub Hrozek - 1.16.0-19.6 +- Resolves: rhbz#1594178 - Login with sshkeys stored in ipa not working after update to RHEL-7.5 [rhel-7.5.z] + * Thu May 31 2018 Fabiano Fidêncio - 1.16.0-19.5 - Resolves: rhbz#1583746 - The SSSD IPA provider allocates information about external groups on a long lived memory context, causing memory growth of the sssd_be process [rhel-7.5.z]