diff --git a/.authselect.metadata b/.authselect.metadata new file mode 100644 index 0000000..ef2fd75 --- /dev/null +++ b/.authselect.metadata @@ -0,0 +1,2 @@ +816e7213fea7653c5b4a7dde804287b310e9df9a SOURCES/authselect-1.0.tar.gz +c858c61f42ad793d0fe8f619429866c6df23511b SOURCES/translations-1.0-12.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88b93d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/authselect-1.0.tar.gz +SOURCES/translations-1.0-12.tar.gz diff --git a/SOURCES/0001-lib-fix-profile-origin-debug-message.patch b/SOURCES/0001-lib-fix-profile-origin-debug-message.patch new file mode 100644 index 0000000..2278323 --- /dev/null +++ b/SOURCES/0001-lib-fix-profile-origin-debug-message.patch @@ -0,0 +1,30 @@ +From 607235797f0503178f81b5a2074803fdddd84071 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 4 Sep 2018 12:33:21 +0200 +Subject: [PATCH 01/16] lib: fix profile origin debug message + +Previously, we failed to match the location and always print that +the selected profile is a default profile. +--- + src/lib/profiles/read.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/lib/profiles/read.c b/src/lib/profiles/read.c +index 002329090cec29eee7969a5f04634ba1bb214a4c..a3a3e62788a3b3ae493a22a8b8e10170d572fc6f 100644 +--- a/src/lib/profiles/read.c ++++ b/src/lib/profiles/read.c +@@ -125,9 +125,9 @@ authselect_profile_open(const char *id, + return ret; + } + +- if (strcmp(location, DIR_CUSTOM_PROFILES) == 0) { ++ if (strcmp(locations[i], DIR_CUSTOM_PROFILES) == 0) { + INFO("Profile [%s] is a custom profile", id); +- } else if (strcmp(location, DIR_VENDOR_PROFILES) == 0) { ++ } else if (strcmp(locations[i], DIR_VENDOR_PROFILES) == 0) { + INFO("Profile [%s] is a vendor profile", id); + } else { + INFO("Profile [%s] is a default profile", id); +-- +2.17.1 + diff --git a/SOURCES/0002-man-remove-duplicate-of-with-pamaccess.patch b/SOURCES/0002-man-remove-duplicate-of-with-pamaccess.patch new file mode 100644 index 0000000..895394d --- /dev/null +++ b/SOURCES/0002-man-remove-duplicate-of-with-pamaccess.patch @@ -0,0 +1,24 @@ +From 3b6ba3c895dfc7a3c6b3fa43d2c76070e45b0d94 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 4 Sep 2018 12:39:16 +0200 +Subject: [PATCH 02/16] man: remove duplicate of with-pamaccess + +--- + src/man/authselect-migration.7.adoc | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/man/authselect-migration.7.adoc b/src/man/authselect-migration.7.adoc +index 47544a53efd70b55a75d68d5bcbf3c89f875d7e7..35ba484d576ab8a3d923a124f6b1577085deedd4 100644 +--- a/src/man/authselect-migration.7.adoc ++++ b/src/man/authselect-migration.7.adoc +@@ -85,7 +85,6 @@ configuration file for required services. + |--enablefaillock |with-faillock + |--enablepamaccess |with-pamaccess + |--enablewinbindkrb5 |with-krb5 +-|--enablepamaccess |with-pamaccess + |================================================== + + .Examples +-- +2.17.1 + diff --git a/SOURCES/0003-Don-t-write-options-without-value-to-pwquality-conf-.patch b/SOURCES/0003-Don-t-write-options-without-value-to-pwquality-conf-.patch new file mode 100644 index 0000000..6778ddb --- /dev/null +++ b/SOURCES/0003-Don-t-write-options-without-value-to-pwquality-conf-.patch @@ -0,0 +1,49 @@ +From bf05c4a72237eacf649b09888bdf536e0b7721a5 Mon Sep 17 00:00:00 2001 +From: Adam Williamson +Date: Tue, 28 Aug 2018 11:49:35 -0700 +Subject: [PATCH 03/16] Don't write options without value to pwquality conf + (#1618865) + +Per https://bugzilla.redhat.com/show_bug.cgi?id=1618865 , it is +incorrect to write lines like this in a pwquality config file: + +minlen= +minclass= +maxrepeat= +maxclassrepeat= + +There should either be an actual integer value, or the line +should be omitted entirely. Including the option with no value +is wrong and breaks pwquality. This should fix the problem by +only writing the lines if the option is actually set. + +Signed-off-by: Adam Williamson +--- + src/compat/authcompat.py.in.in | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index abe1e585954ccd5ac555339f23c175e941c76ea3..1b4f531b021c1e2e8fd99bd081094da365c0c64e 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -319,10 +319,13 @@ class Configuration: + def write(self): + config = EnvironmentFile(Path.System('pwquality.conf')) + +- config.set("minlen", self.get("passminlen")) +- config.set("minclass", self.get("passminclass")) +- config.set("maxrepeat", self.get("passmaxrepeat")) +- config.set("maxclassrepeat", self.get("passmaxclassrepeat")) ++ # for each if these options, we want to write a line to the config ++ # *only if* it is set to an actual value, see ++ # https://bugzilla.redhat.com/show_bug.cgi?id=1618865 ++ for pwval in ["minlen", "minclass", "maxrepeat", "maxclassrepeat"]: ++ if self.isset("pass{0}".format(pwval)): ++ config.set(pwval, self.get("pass{0}".format(pwval))) ++ + config.set("lcredit", self.getBoolAsValue("reqlower", -1, 0)) + config.set("ucredit", self.getBoolAsValue("requpper", -1, 0)) + config.set("dcredit", self.getBoolAsValue("reqdigit", -1, 0)) +-- +2.17.1 + diff --git a/SOURCES/0004-compat-write-only-options-set-on-command-line-to-pwq.patch b/SOURCES/0004-compat-write-only-options-set-on-command-line-to-pwq.patch new file mode 100644 index 0000000..eeeadfa --- /dev/null +++ b/SOURCES/0004-compat-write-only-options-set-on-command-line-to-pwq.patch @@ -0,0 +1,72 @@ +From 474404051fe461a1be5d175b3f13da54ddbe0a37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 4 Sep 2018 11:36:43 +0200 +Subject: [PATCH 04/16] compat: write only options set on command line to + pwquality.conf + +This will not overwrite pwquality.conf if for exapmle "authconfig --update" +is called. Without this patch the values would get overriden with empty +values. +--- + src/compat/authcompat.py.in.in | 36 ++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 1b4f531b021c1e2e8fd99bd081094da365c0c64e..4fa9a6afc1d62aa9dde41b525d473168e6dc2901 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -166,7 +166,10 @@ class Configuration: + def getBool(self, name): + return self.options.getBool(name) + +- def getBoolAsValue(self, name, if_true, if_false): ++ def getBoolAsValue(self, name, if_true, if_false, AllowNone=False): ++ if AllowNone and not self.isset(name): ++ return None ++ + value = self.getBool(name) + if value: + return if_true +@@ -318,19 +321,28 @@ class Configuration: + + def write(self): + config = EnvironmentFile(Path.System('pwquality.conf')) ++ value_set = False + +- # for each if these options, we want to write a line to the config +- # *only if* it is set to an actual value, see +- # https://bugzilla.redhat.com/show_bug.cgi?id=1618865 +- for pwval in ["minlen", "minclass", "maxrepeat", "maxclassrepeat"]: +- if self.isset("pass{0}".format(pwval)): +- config.set(pwval, self.get("pass{0}".format(pwval))) ++ pwopts = { ++ "minlen" : self.get("passminlen"), ++ "minclass" : self.get("passminclass"), ++ "maxrepeat" : self.get("passmaxrepeat"), ++ "maxclassrepeat" : self.get("passmaxclassrepeat"), ++ "lcredit" : self.getBoolAsValue("reqlower", -1, 0, AllowNone=True), ++ "ucredit" : self.getBoolAsValue("requpper", -1, 0, AllowNone=True), ++ "dcredit" : self.getBoolAsValue("reqdigit", -1, 0, AllowNone=True), ++ "ocredit" : self.getBoolAsValue("reqother", -1, 0, AllowNone=True) ++ } + +- config.set("lcredit", self.getBoolAsValue("reqlower", -1, 0)) +- config.set("ucredit", self.getBoolAsValue("requpper", -1, 0)) +- config.set("dcredit", self.getBoolAsValue("reqdigit", -1, 0)) +- config.set("ocredit", self.getBoolAsValue("reqother", -1, 0)) +- config.write() ++ # Write options only if their are actually set ++ for opt, value in pwopts.items(): ++ if value is not None: ++ print(opt + "=" + str(value)) ++ config.set(opt, value) ++ value_set = True ++ ++ if value_set: ++ config.write() + + class MakeHomedir(Base): + def __init__(self, options): +-- +2.17.1 + diff --git a/SOURCES/0005-compat-fix-regular-expression-for-environment-files.patch b/SOURCES/0005-compat-fix-regular-expression-for-environment-files.patch new file mode 100644 index 0000000..08ad514 --- /dev/null +++ b/SOURCES/0005-compat-fix-regular-expression-for-environment-files.patch @@ -0,0 +1,31 @@ +From 8e735cff141bb080409f71b15f31f2aea2ef182e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 4 Sep 2018 11:38:38 +0200 +Subject: [PATCH 05/16] compat: fix regular expression for environment files + +Any word character (\w) was not enough as it does not accept e.g. '-'. +Therefore line like 'ocredit=-1' was incorrectly parse returning only +'1' as value instead of '-1'. +--- + src/compat/authcompat_EnvironmentFile.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/compat/authcompat_EnvironmentFile.py b/src/compat/authcompat_EnvironmentFile.py +index 529497e61903b3fb89f560b8e0ac0bb38111b46a..5738c6cafaf75109a5c1dbb9d3f040686a4945e1 100644 +--- a/src/compat/authcompat_EnvironmentFile.py ++++ b/src/compat/authcompat_EnvironmentFile.py +@@ -34,9 +34,9 @@ class EnvironmentFile: + self.environment = [] + + delimiter_re = delimiter_re if delimiter_re is not None else delimiter +- self.pattern = re.compile('^(\s*)(\S*)([^\n\w]*)(' + ++ self.pattern = re.compile('^(\s*)(\S*)([^\n\S]*)(' + + delimiter_re + +- ')([^\n\w]*)(.*)$', ++ ')([^\n\S]*)(.*)$', + re.MULTILINE) + + self.read() +-- +2.17.1 + diff --git a/SOURCES/0006-compat-fix-typo-in-compat-tool-that-produces-TypeErr.patch b/SOURCES/0006-compat-fix-typo-in-compat-tool-that-produces-TypeErr.patch new file mode 100644 index 0000000..2958adc --- /dev/null +++ b/SOURCES/0006-compat-fix-typo-in-compat-tool-that-produces-TypeErr.patch @@ -0,0 +1,28 @@ +From b2c1f2874b08a0002bbdfac71b7631da1c3f3322 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 24 Sep 2018 12:10:42 +0200 +Subject: [PATCH 06/16] compat: fix typo in compat tool that produces + "TypeError: 'int' object is not callable" + +Resolves: +https://github.com/pbrezina/authselect/issues/92 +--- + src/compat/authcompat_EnvironmentFile.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/compat/authcompat_EnvironmentFile.py b/src/compat/authcompat_EnvironmentFile.py +index 5738c6cafaf75109a5c1dbb9d3f040686a4945e1..9c12f7c675fe29a76161f83e7fcaa06b3a3fab35 100644 +--- a/src/compat/authcompat_EnvironmentFile.py ++++ b/src/compat/authcompat_EnvironmentFile.py +@@ -204,7 +204,7 @@ class EnvironmentFile: + i = value.find("\\", i) + if i < 0: + break +- if i + 1 >= length(value): ++ if i + 1 >= len(value): + value = value[0:i] + break + +-- +2.17.1 + diff --git a/SOURCES/0007-compat-use-current-configuration-unless-other-profil.patch b/SOURCES/0007-compat-use-current-configuration-unless-other-profil.patch new file mode 100644 index 0000000..10797ff --- /dev/null +++ b/SOURCES/0007-compat-use-current-configuration-unless-other-profil.patch @@ -0,0 +1,119 @@ +From 313ccd75397ae3a1801e1532f460519c657adae6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 11 Sep 2018 11:03:36 +0200 +Subject: [PATCH 07/16] compat: use current configuration unless other profile + is selected + +This makes sure that 'authconfig --updateall' or 'authconfig --enablexyz --updateall' +will not override current authselect profile if /etc/authconfig/sysconfig does not +exist. + +Resolves: +https://github.com/pbrezina/authselect/issues/82 +--- + src/compat/authcompat.py.in.in | 61 ++++++++++++++++++++++++++++------ + 1 file changed, 50 insertions(+), 11 deletions(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 4fa9a6afc1d62aa9dde41b525d473168e6dc2901..96b2c69ce2c10afe6b689a8c4b64aa1e83245b34 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -39,9 +39,11 @@ def eprint(*args, **kwargs): + class Command: + TEST = False + +- def __init__(self, command, args, input=None): ++ def __init__(self, command, args, input=None, check=True): + self.args = [command] + args + self.input = input.encode() if input is not None else None ++ self.check = check ++ self.result = None + + def run(self): + print(_("Executing: %s") % ' '.join(self.args)) +@@ -49,10 +51,10 @@ class Command: + if self.TEST: + return + +- subprocess.run(self.args, check=True, +- input=self.input, +- stdout=subprocess.PIPE, +- stderr=subprocess.PIPE) ++ self.result = subprocess.run(self.args, check=self.check, ++ input=self.input, ++ stdout=subprocess.PIPE, ++ stderr=subprocess.PIPE) + + class Service: + def __init__(self, name): +@@ -506,24 +508,61 @@ class AuthCompat: + 'winbindkrb5' : 'with-krb5' + } + +- profile = "sssd" +- if self.options.getBool("nis"): ++ # Read current configuration first. ++ (profile, features) = self.getCurrentAuthselectConfig() ++ ++ # Change profile if requested. ++ if (self.options.getBool("ldap") or self.options.getBool("ldapauth") or ++ self.options.getBool("sssd") or self.options.getBool("sssdauth")): ++ profile = "sssd" ++ elif self.options.getBool("nis"): + profile = "nis" + elif self.options.getBool("winbind"): + profile = "winbind" + ++ # Default to sssd ++ if profile is None: ++ profile = "sssd" ++ ++ # Add enabled and remove disabled features. ++ for option, feature in map.items(): ++ if not self.options.isset(option): ++ continue ++ ++ enabled = self.options.getBool(option) ++ if enabled: ++ features.append(feature) ++ else: ++ while feature in features: ++ features.remove(feature) ++ ++ # Remove duplicates. The order is not kept but that does not matter. ++ features = list(set(features)) ++ + # Always run with --force. This is either first call of authconfig + # in installation script or it is run on already configured system. + # We want to use authselect in both cases anyway, since authconfig + # would change the configuration either way. +- args = ["select", profile, "--force"] +- for option, feature in map.items(): +- if self.options.getBool(option): +- args.append(feature) ++ args = ["select", profile] ++ args.extend(features) ++ args.append("--force") + + cmd = Command(Path.System('cmd-authselect'), args) + cmd.run() + ++ def getCurrentAuthselectConfig(self): ++ cmd = Command(Path.System('cmd-authselect'), ['check'], check=False) ++ cmd.run() ++ ++ if cmd.result.returncode != 0: ++ return (None, []) ++ ++ cmd = Command(Path.System('cmd-authselect'), ['current', '--raw']) ++ cmd.run() ++ ++ current = cmd.result.stdout.decode("utf-8").split() ++ return (current[0], current[1:]) ++ + def writeConfiguration(self): + configs = [ + Configuration.LDAP(self.options), +-- +2.17.1 + diff --git a/SOURCES/0008-compat-do-not-disable-service-if-its-option-is-not-s.patch b/SOURCES/0008-compat-do-not-disable-service-if-its-option-is-not-s.patch new file mode 100644 index 0000000..ca32ae8 --- /dev/null +++ b/SOURCES/0008-compat-do-not-disable-service-if-its-option-is-not-s.patch @@ -0,0 +1,115 @@ +From 0f4fec2cf1f4a2430e97a44209de27dd18332c1a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 13 Sep 2018 11:15:05 +0200 +Subject: [PATCH 08/16] compat: do not disable service if its option is not set + +If we run 'authconfig --updateall' with empty /etc/sysconfig/authconfig +file we may actually end up disabling services that were started by user. + +This patch makes sure that if a service was not explicitly disabled on +command line or in sysconfig file we do not touch its state. + +Resolves: +https://github.com/pbrezina/authselect/issues/82 +--- + src/compat/authcompat.py.in.in | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 96b2c69ce2c10afe6b689a8c4b64aa1e83245b34..532227b69f3bb3d124078915bd846009bee7df7a 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -208,9 +208,16 @@ class Configuration: + super(Configuration.Kerberos, self).__init__(options) + + def isEnabled(self): +- return self.isset("krb5realm") or self.isset("krb5realmdns") ++ if not self.isset("krb5realm") and not self.isset("krb5realmdns"): ++ return None ++ ++ return self.get("krb5realm") != "" or self.getBool("krb5realmdns") + + def cleanup(self): ++ # Do not remove the file if these options are not set ++ if not self.isset("krb5realm") and not self.isset("krb5realmdns"): ++ return ++ + self.removeFile(Path.System('krb5.conf')) + + def write(self): +@@ -240,7 +247,7 @@ class Configuration: + nisdomain = self.get("nisdomain") + config = EnvironmentFile(Path.System('network')) + +- if nisdomain is None and config.get("NISDOMAIN") is None: ++ if nisdomain is None: + return + + config.set("NISDOMAIN", nisdomain) +@@ -251,6 +258,9 @@ class Configuration: + super(Configuration.SSSD, self).__init__(options, ServiceName="sssd") + + def isEnabled(self): ++ if not self.isset("ldap") and not self.isset("sssd"): ++ return None ++ + return self.getBool("ldap") or self.getBool("sssd") + + def cleanup(self): +@@ -288,6 +298,9 @@ class Configuration: + super(Configuration.Winbind, self).__init__(options, ServiceName="winbind") + + def isEnabled(self): ++ if not self.isset("winbind") and not self.isset("winbindauth"): ++ return None ++ + return self.getBool("winbind") or self.getBool("winbindauth") + + def write(self): +@@ -351,6 +364,9 @@ class Configuration: + super(Configuration.MakeHomedir, self).__init__(options, ServiceName="oddjobd") + + def isEnabled(self): ++ if not self.isset("mkhomedir"): ++ return None ++ + return self.getBool("mkhomedir") + + def disableService(self, nostop): +@@ -365,6 +381,9 @@ class Configuration: + self.ypbind = Service("ypbind") + + def isEnabled(self): ++ if not self.isset("nis"): ++ return None ++ + return self.getBool("nis") + + def enableService(self, nostart): +@@ -554,7 +573,7 @@ class AuthCompat: + cmd = Command(Path.System('cmd-authselect'), ['check'], check=False) + cmd.run() + +- if cmd.result.returncode != 0: ++ if cmd.result is None or cmd.result.returncode != 0: + return (None, []) + + cmd = Command(Path.System('cmd-authselect'), ['current', '--raw']) +@@ -582,7 +601,13 @@ class AuthCompat: + # Enable or disable service if needed + nostart = self.options.getBool("nostart") + try: +- if config.isEnabled(): ++ enabled = config.isEnabled() ++ ++ # Skip service management if it can not be decided ++ if enabled is None: ++ continue ++ ++ if enabled: + config.enableService(nostart) + else: + config.disableService(nostart) +-- +2.17.1 + diff --git a/SOURCES/0009-nis-add-all-maps-supported-by-nss_nis.patch b/SOURCES/0009-nis-add-all-maps-supported-by-nss_nis.patch new file mode 100644 index 0000000..ebf9510 --- /dev/null +++ b/SOURCES/0009-nis-add-all-maps-supported-by-nss_nis.patch @@ -0,0 +1,37 @@ +From 65fb0c895d2e3f19c8a080407813cf67231340e9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 13 Sep 2018 12:25:05 +0200 +Subject: [PATCH 09/16] nis: add all maps supported by nss_nis + +Resolves: +https://github.com/pbrezina/authselect/issues/86 +--- + profiles/nis/nsswitch.conf | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/profiles/nis/nsswitch.conf b/profiles/nis/nsswitch.conf +index decf6204090c0cc60679d8760de8fbe6fb3ba3b7..20bcea11342b23b2eef7f2c93a912046dc00ec3d 100644 +--- a/profiles/nis/nsswitch.conf ++++ b/profiles/nis/nsswitch.conf +@@ -1,6 +1,14 @@ +-passwd: files nis +-group: files nis +-shadow: files nis +-netgroup: files nis ++aliases: files nis + automount: files nis ++ethers: files nis ++group: files nis + hosts: files nis dns myhostname ++initgroups: files nis ++netgroup: files nis ++networks: files nis ++passwd: files nis ++protocols: files nis ++publickey: files nis ++rpc: files nis ++services: files nis ++shadow: files nis +-- +2.17.1 + diff --git a/SOURCES/0010-nis-add-systemd-module-to-nsswitch.conf.patch b/SOURCES/0010-nis-add-systemd-module-to-nsswitch.conf.patch new file mode 100644 index 0000000..3aab068 --- /dev/null +++ b/SOURCES/0010-nis-add-systemd-module-to-nsswitch.conf.patch @@ -0,0 +1,33 @@ +From 03635249198389f51417dfc89de37487b25a4171 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 13 Sep 2018 12:25:46 +0200 +Subject: [PATCH 10/16] nis: add systemd module to nsswitch.conf + +Resolves: +https://github.com/pbrezina/authselect/issues/89 +--- + profiles/nis/nsswitch.conf | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/profiles/nis/nsswitch.conf b/profiles/nis/nsswitch.conf +index 20bcea11342b23b2eef7f2c93a912046dc00ec3d..4397deb1ef347d5cb8798926f553c373f8c15649 100644 +--- a/profiles/nis/nsswitch.conf ++++ b/profiles/nis/nsswitch.conf +@@ -1,12 +1,12 @@ + aliases: files nis + automount: files nis + ethers: files nis +-group: files nis ++group: files nis systemd + hosts: files nis dns myhostname + initgroups: files nis + netgroup: files nis + networks: files nis +-passwd: files nis ++passwd: files nis systemd + protocols: files nis + publickey: files nis + rpc: files nis +-- +2.17.1 + diff --git a/SOURCES/0011-nis-add-nis-option-to-pam_unix-in-password-phase.patch b/SOURCES/0011-nis-add-nis-option-to-pam_unix-in-password-phase.patch new file mode 100644 index 0000000..286229b --- /dev/null +++ b/SOURCES/0011-nis-add-nis-option-to-pam_unix-in-password-phase.patch @@ -0,0 +1,43 @@ +From 9764ce2873a05ec9e81c6979177122f9846a9ee2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 13 Sep 2018 14:30:55 +0200 +Subject: [PATCH 11/16] nis: add nis option to pam_unix in password phase + +This option will allow nis users to change their passwords with 'passwd'. + +Resolves: +https://github.com/pbrezina/authselect/issues/87 +--- + profiles/nis/password-auth | 2 +- + profiles/nis/system-auth | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/profiles/nis/password-auth b/profiles/nis/password-auth +index 8f18616eb2d2c228880989ea4cce86b6588b2190..78028e19bbad3965f5232c6b6177d8780d7e1c04 100644 +--- a/profiles/nis/password-auth ++++ b/profiles/nis/password-auth +@@ -14,7 +14,7 @@ account sufficient pam_succeed_if.so uid < + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass local_users_only +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok ++password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok nis + password required pam_deny.so + + session optional pam_keyinit.so revoke +diff --git a/profiles/nis/system-auth b/profiles/nis/system-auth +index e0bc4ef2fb4efc825927d13c0ff4b0083e5134ea..2909a546a49f991128c48285fa90a1937fa03513 100644 +--- a/profiles/nis/system-auth ++++ b/profiles/nis/system-auth +@@ -15,7 +15,7 @@ account sufficient pam_succeed_if.so uid < + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass local_users_only +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok ++password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok nis + password required pam_deny.so + + session optional pam_keyinit.so revoke +-- +2.17.1 + diff --git a/SOURCES/0012-nis-with-nispwquality-will-enable-pwquality-for-nis-.patch b/SOURCES/0012-nis-with-nispwquality-will-enable-pwquality-for-nis-.patch new file mode 100644 index 0000000..526ea57 --- /dev/null +++ b/SOURCES/0012-nis-with-nispwquality-will-enable-pwquality-for-nis-.patch @@ -0,0 +1,59 @@ +From 9f3ec1c3a6aa0670479668355c11fd9e7cb4bb7d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 13 Sep 2018 14:37:57 +0200 +Subject: [PATCH 12/16] nis: with-nispwquality will enable pwquality for nis + users + +Resolves: +https://github.com/pbrezina/authselect/issues/88 +--- + profiles/nis/README | 5 +++++ + profiles/nis/password-auth | 2 +- + profiles/nis/system-auth | 2 +- + 3 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/profiles/nis/README b/profiles/nis/README +index 6335fcfb051f01b7acdd4fde689de0d77c0d43a1..b4ffb8b56d8f9930ee5b70f34d0ba7a2dc35dae0 100644 +--- a/profiles/nis/README ++++ b/profiles/nis/README +@@ -33,6 +33,11 @@ with-silent-lastlog:: + with-pamaccess:: + Check access.conf during account authorization. + ++with-nispwquality:: ++ If this option is set pam_pwquality module will check password quality ++ for NIS users as well as local users during password change. Without this ++ option only local users passwords are checked. ++ + EXAMPLES + -------- + * Enable NIS with no additional modules +diff --git a/profiles/nis/password-auth b/profiles/nis/password-auth +index 78028e19bbad3965f5232c6b6177d8780d7e1c04..159da35740cfdf1396a8bc8a97c397919f056797 100644 +--- a/profiles/nis/password-auth ++++ b/profiles/nis/password-auth +@@ -13,7 +13,7 @@ account sufficient pam_localuser.so + account sufficient pam_succeed_if.so uid < 1000 quiet + account required pam_permit.so + +-password requisite pam_pwquality.so try_first_pass local_users_only ++password requisite pam_pwquality.so try_first_pass {if not "with-nispwquality":local_users_only} + password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok nis + password required pam_deny.so + +diff --git a/profiles/nis/system-auth b/profiles/nis/system-auth +index 2909a546a49f991128c48285fa90a1937fa03513..5f941f264b6adf2ca5cdc67685ed227ecc180ac7 100644 +--- a/profiles/nis/system-auth ++++ b/profiles/nis/system-auth +@@ -14,7 +14,7 @@ account sufficient pam_localuser.so + account sufficient pam_succeed_if.so uid < 1000 quiet + account required pam_permit.so + +-password requisite pam_pwquality.so try_first_pass local_users_only ++password requisite pam_pwquality.so try_first_pass {if not "with-nispwquality":local_users_only} + password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok nis + password required pam_deny.so + +-- +2.17.1 + diff --git a/SOURCES/0013-profiles-add-without-nullok.patch b/SOURCES/0013-profiles-add-without-nullok.patch new file mode 100644 index 0000000..2b842b2 --- /dev/null +++ b/SOURCES/0013-profiles-add-without-nullok.patch @@ -0,0 +1,196 @@ +From 325b2f075e57c8495aa040542265fbcbf0f6ff64 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 18 Sep 2018 14:04:46 +0200 +Subject: [PATCH 13/16] profiles: add without-nullok + +Resolves: +https://github.com/pbrezina/authselect/issues/94 +--- + profiles/nis/README | 3 +++ + profiles/nis/password-auth | 4 ++-- + profiles/nis/system-auth | 4 ++-- + profiles/sssd/README | 3 +++ + profiles/sssd/password-auth | 4 ++-- + profiles/sssd/system-auth | 4 ++-- + profiles/winbind/README | 3 +++ + profiles/winbind/password-auth | 4 ++-- + profiles/winbind/system-auth | 4 ++-- + 9 files changed, 21 insertions(+), 12 deletions(-) + +diff --git a/profiles/nis/README b/profiles/nis/README +index b4ffb8b56d8f9930ee5b70f34d0ba7a2dc35dae0..34789b1e7643f0df082d40e0e87cb3d0823bba56 100644 +--- a/profiles/nis/README ++++ b/profiles/nis/README +@@ -38,6 +38,9 @@ with-nispwquality:: + for NIS users as well as local users during password change. Without this + option only local users passwords are checked. + ++without-nullok:: ++ Do not add nullok parameter to pam_unix. ++ + EXAMPLES + -------- + * Enable NIS with no additional modules +diff --git a/profiles/nis/password-auth b/profiles/nis/password-auth +index 159da35740cfdf1396a8bc8a97c397919f056797..615544d16f7fc8551cb06a221825526f12cbfc64 100644 +--- a/profiles/nis/password-auth ++++ b/profiles/nis/password-auth +@@ -1,7 +1,7 @@ + auth required pam_env.so + auth required pam_faildelay.so delay=2000000 + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} +-auth sufficient pam_unix.so nullok try_first_pass ++auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} + auth required pam_deny.so +@@ -14,7 +14,7 @@ account sufficient pam_succeed_if.so uid < + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass {if not "with-nispwquality":local_users_only} +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok nis ++password sufficient pam_unix.so sha512 shadow {if not "without-nullok":nullok} try_first_pass use_authtok nis + password required pam_deny.so + + session optional pam_keyinit.so revoke +diff --git a/profiles/nis/system-auth b/profiles/nis/system-auth +index 5f941f264b6adf2ca5cdc67685ed227ecc180ac7..a41828d8972537b1b24d0ff21cd52976fba6646d 100644 +--- a/profiles/nis/system-auth ++++ b/profiles/nis/system-auth +@@ -2,7 +2,7 @@ auth required pam_env.so + auth required pam_faildelay.so delay=2000000 + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} + auth sufficient pam_fprintd.so {include if "with-fingerprint"} +-auth sufficient pam_unix.so nullok try_first_pass ++auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} + auth required pam_deny.so +@@ -15,7 +15,7 @@ account sufficient pam_succeed_if.so uid < + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass {if not "with-nispwquality":local_users_only} +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok nis ++password sufficient pam_unix.so sha512 shadow {if not "without-nullok":nullok} try_first_pass use_authtok nis + password required pam_deny.so + + session optional pam_keyinit.so revoke +diff --git a/profiles/sssd/README b/profiles/sssd/README +index 34693ba3c02b1005c5cca889316ccc0958c94eef..a2fbf66323f4893391474de49f323c06123a2ebf 100644 +--- a/profiles/sssd/README ++++ b/profiles/sssd/README +@@ -56,6 +56,9 @@ with-sudo:: + with-pamaccess:: + Check access.conf during account authorization. + ++without-nullok:: ++ Do not add nullok parameter to pam_unix. ++ + EXAMPLES + -------- + +diff --git a/profiles/sssd/password-auth b/profiles/sssd/password-auth +index 82082b03e3223010b5d3f3eff348b2e3882fcfc4..e35c8d6943b8289d8b65d7a47b2dad8143b6132b 100644 +--- a/profiles/sssd/password-auth ++++ b/profiles/sssd/password-auth +@@ -3,7 +3,7 @@ auth required pam_faildelay.so delay= + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} + auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet + auth [default=1 ignore=ignore success=ok] pam_localuser.so +-auth sufficient pam_unix.so nullok try_first_pass ++auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth sufficient pam_sss.so forward_pass + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} +@@ -18,7 +18,7 @@ account [default=bad success=ok user_unknown=ignore] pam_sss.so + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass local_users_only +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok ++password sufficient pam_unix.so sha512 shadow {if not "without-nullok":nullok} try_first_pass use_authtok + password sufficient pam_sss.so use_authtok + password required pam_deny.so + +diff --git a/profiles/sssd/system-auth b/profiles/sssd/system-auth +index 00a360d034a363f9d29f1281a502e11939f00836..02922b16903372598052e36f3713ca5c3f4c8418 100644 +--- a/profiles/sssd/system-auth ++++ b/profiles/sssd/system-auth +@@ -4,7 +4,7 @@ auth required pam_faillock.so preauth + auth sufficient pam_fprintd.so {include if "with-fingerprint"} + auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet + auth [default=1 ignore=ignore success=ok] pam_localuser.so +-auth sufficient pam_unix.so nullok try_first_pass ++auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth sufficient pam_sss.so forward_pass + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} +@@ -19,7 +19,7 @@ account [default=bad success=ok user_unknown=ignore] pam_sss.so + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass local_users_only +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok ++password sufficient pam_unix.so sha512 shadow {if not "without-nullok":nullok} try_first_pass use_authtok + password sufficient pam_sss.so use_authtok + password required pam_deny.so + +diff --git a/profiles/winbind/README b/profiles/winbind/README +index fe3f879f4e76ecc877053c63ed9b0da93a12afa8..a824c7e78954bafffa6500e45a6e826835fd2b58 100644 +--- a/profiles/winbind/README ++++ b/profiles/winbind/README +@@ -48,6 +48,9 @@ with-silent-lastlog:: + with-pamaccess:: + Check access.conf during account authorization. + ++without-nullok:: ++ Do not add nullok parameter to pam_unix. ++ + EXAMPLES + -------- + * Enable winbind with no additional modules +diff --git a/profiles/winbind/password-auth b/profiles/winbind/password-auth +index c7498f06f0ddaab4804444a213454b0ef56886e4..c984d817c537c48a358c644083a4f8979181dd1d 100644 +--- a/profiles/winbind/password-auth ++++ b/profiles/winbind/password-auth +@@ -1,7 +1,7 @@ + auth required pam_env.so + auth required pam_faildelay.so delay=2000000 + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} +-auth sufficient pam_unix.so nullok try_first_pass ++auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth sufficient pam_winbind.so {if "with-krb5":krb5_auth} use_first_pass + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} +@@ -16,7 +16,7 @@ account [default=bad success=ok user_unknown=ignore] pam_winbind.so {if "wit + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass local_users_only +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok ++password sufficient pam_unix.so sha512 shadow {if not "without-nullok":nullok} try_first_pass use_authtok + password sufficient pam_winbind.so {if "with-krb5":krb5_auth} use_authtok + password required pam_deny.so + +diff --git a/profiles/winbind/system-auth b/profiles/winbind/system-auth +index 4d433ae6ec7782203f240ce66c6e6a7551bb42d6..33dc491c2125c7fe06d6475369f1654a900c7050 100644 +--- a/profiles/winbind/system-auth ++++ b/profiles/winbind/system-auth +@@ -2,7 +2,7 @@ auth required pam_env.so + auth required pam_faildelay.so delay=2000000 + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} + auth sufficient pam_fprintd.so {include if "with-fingerprint"} +-auth sufficient pam_unix.so nullok try_first_pass ++auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth sufficient pam_winbind.so {if "with-krb5":krb5_auth} use_first_pass + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} +@@ -17,7 +17,7 @@ account [default=bad success=ok user_unknown=ignore] pam_winbind.so {if "wit + account required pam_permit.so + + password requisite pam_pwquality.so try_first_pass local_users_only +-password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_authtok ++password sufficient pam_unix.so sha512 shadow {if not "without-nullok":nullok} try_first_pass use_authtok + password sufficient pam_winbind.so {if "with-krb5":krb5_auth} use_authtok + password required pam_deny.so + +-- +2.17.1 + diff --git a/SOURCES/0014-profiles-add-options-to-exclude-lines-from-nsswitch..patch b/SOURCES/0014-profiles-add-options-to-exclude-lines-from-nsswitch..patch new file mode 100644 index 0000000..8b545a7 --- /dev/null +++ b/SOURCES/0014-profiles-add-options-to-exclude-lines-from-nsswitch..patch @@ -0,0 +1,210 @@ +From be3cea05e06cbfcfbd684b46c49fcdc8f8f5b880 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 18 Sep 2018 14:28:18 +0200 +Subject: [PATCH 14/16] profiles: add options to exclude lines from + nsswitch.conf + +There is a common use case that users want to change lines in nsswitch.conf +but do not want to create a whole custom profile. This applies especially +to nis profile as it sets all nsswitch databases and thus renders recently +added user-nsswitch.conf useless. + +For distributing company wide configuration, custom profiles should be used though. + +Resolves: +https://github.com/pbrezina/authselect/issues/95 +--- + profiles/nis/README | 50 ++++++++++++++++++++++++++++++++++ + profiles/nis/nsswitch.conf | 28 +++++++++---------- + profiles/sssd/README | 26 ++++++++++++++++++ + profiles/sssd/nsswitch.conf | 12 ++++---- + profiles/winbind/README | 14 ++++++++++ + profiles/winbind/nsswitch.conf | 4 +-- + 6 files changed, 112 insertions(+), 22 deletions(-) + +diff --git a/profiles/nis/README b/profiles/nis/README +index 34789b1e7643f0df082d40e0e87cb3d0823bba56..3911959c59287d2d5425ef304f744ff4cd5b408d 100644 +--- a/profiles/nis/README ++++ b/profiles/nis/README +@@ -41,6 +41,56 @@ with-nispwquality:: + without-nullok:: + Do not add nullok parameter to pam_unix. + ++DISABLE SPECIFIC NSSWITCH DATABASES ++----------------------------------- ++ ++Normally, nsswitch databases set by the profile overwrites values set in ++user-nsswitch.conf. The following options can force authselect to ++ignore value set by the profile and use the one set in user-nsswitch.conf ++instead. ++ ++with-custom-aliases:: ++Ignore "aliases" map set by the profile. ++ ++with-custom-automount:: ++Ignore "automount" map set by the profile. ++ ++with-custom-ethers:: ++Ignore "ethers" map set by the profile. ++ ++with-custom-group:: ++Ignore "group" map set by the profile. ++ ++with-custom-hosts:: ++Ignore "hosts" map set by the profile. ++ ++with-custom-initgroups:: ++Ignore "initgroups" map set by the profile. ++ ++with-custom-netgroup:: ++Ignore "netgroup" map set by the profile. ++ ++with-custom-networks:: ++Ignore "networks" map set by the profile. ++ ++with-custom-passwd:: ++Ignore "passwd" map set by the profile. ++ ++with-custom-protocols:: ++Ignore "protocols" map set by the profile. ++ ++with-custom-publickey:: ++Ignore "publickey" map set by the profile. ++ ++with-custom-rpc:: ++Ignore "rpc" map set by the profile. ++ ++with-custom-services:: ++Ignore "services" map set by the profile. ++ ++with-custom-shadow:: ++Ignore "shadow" map set by the profile. ++ + EXAMPLES + -------- + * Enable NIS with no additional modules +diff --git a/profiles/nis/nsswitch.conf b/profiles/nis/nsswitch.conf +index 4397deb1ef347d5cb8798926f553c373f8c15649..f5451657f3d8b988b633304d549a3242257715d3 100644 +--- a/profiles/nis/nsswitch.conf ++++ b/profiles/nis/nsswitch.conf +@@ -1,14 +1,14 @@ +-aliases: files nis +-automount: files nis +-ethers: files nis +-group: files nis systemd +-hosts: files nis dns myhostname +-initgroups: files nis +-netgroup: files nis +-networks: files nis +-passwd: files nis systemd +-protocols: files nis +-publickey: files nis +-rpc: files nis +-services: files nis +-shadow: files nis ++aliases: files nis {exclude if "with-custom-aliases"} ++automount: files nis {exclude if "with-custom-automount"} ++ethers: files nis {exclude if "with-custom-ethers"} ++group: files nis systemd {exclude if "with-custom-group"} ++hosts: files nis dns myhostname {exclude if "with-custom-hosts"} ++initgroups: files nis {exclude if "with-custom-initgroups"} ++netgroup: files nis {exclude if "with-custom-netgroup"} ++networks: files nis {exclude if "with-custom-networks"} ++passwd: files nis systemd {exclude if "with-custom-passwd"} ++protocols: files nis {exclude if "with-custom-protocols"} ++publickey: files nis {exclude if "with-custom-publickey"} ++rpc: files nis {exclude if "with-custom-rpc"} ++services: files nis {exclude if "with-custom-services"} ++shadow: files nis {exclude if "with-custom-shadow"} +\ No newline at end of file +diff --git a/profiles/sssd/README b/profiles/sssd/README +index a2fbf66323f4893391474de49f323c06123a2ebf..42293ab39c628c285921b8b47c4a763fd0215472 100644 +--- a/profiles/sssd/README ++++ b/profiles/sssd/README +@@ -59,6 +59,32 @@ with-pamaccess:: + without-nullok:: + Do not add nullok parameter to pam_unix. + ++DISABLE SPECIFIC NSSWITCH DATABASES ++----------------------------------- ++ ++Normally, nsswitch databases set by the profile overwrites values set in ++user-nsswitch.conf. The following options can force authselect to ++ignore value set by the profile and use the one set in user-nsswitch.conf ++instead. ++ ++with-custom-passwd:: ++Ignore "passwd" database set by the profile. ++ ++with-custom-group:: ++Ignore "group" database set by the profile. ++ ++with-custom-netgroup:: ++Ignore "netgroup" database set by the profile. ++ ++with-custom-automount:: ++Ignore "automount" database set by the profile. ++ ++with-custom-services:: ++Ignore "services" database set by the profile. ++ ++with-custom-sudoers:: ++Ignore "sudoers" database set by the profile. ++ + EXAMPLES + -------- + +diff --git a/profiles/sssd/nsswitch.conf b/profiles/sssd/nsswitch.conf +index 5d05102ee8836f5bbce5f0527b87b1559fbe664e..9734bbbe68e7cf73a4a560e3573162d353e551e8 100644 +--- a/profiles/sssd/nsswitch.conf ++++ b/profiles/sssd/nsswitch.conf +@@ -1,6 +1,6 @@ +-passwd: sss files systemd +-group: sss files systemd +-netgroup: sss files +-automount: sss files +-services: sss files +-sudoers: files sss {include if "with-sudo"} ++passwd: sss files systemd {exclude if "with-custom-passwd"} ++group: sss files systemd {exclude if "with-custom-group"} ++netgroup: sss files {exclude if "with-custom-netgroup"} ++automount: sss files {exclude if "with-custom-automount"} ++services: sss files {exclude if "with-custom-services"} ++sudoers: files sss {include if "with-sudo"} +diff --git a/profiles/winbind/README b/profiles/winbind/README +index a824c7e78954bafffa6500e45a6e826835fd2b58..cd1606800d77eeb93be918f17fe47c2586b2519d 100644 +--- a/profiles/winbind/README ++++ b/profiles/winbind/README +@@ -51,6 +51,20 @@ with-pamaccess:: + without-nullok:: + Do not add nullok parameter to pam_unix. + ++DISABLE SPECIFIC NSSWITCH DATABASES ++----------------------------------- ++ ++Normally, nsswitch databases set by the profile overwrites values set in ++user-nsswitch.conf. The following options can force authselect to ++ignore value set by the profile and use the one set in user-nsswitch.conf ++instead. ++ ++with-custom-passwd:: ++Ignore "passwd" database set by the profile. ++ ++with-custom-group:: ++Ignore "group" database set by the profile. ++ + EXAMPLES + -------- + * Enable winbind with no additional modules +diff --git a/profiles/winbind/nsswitch.conf b/profiles/winbind/nsswitch.conf +index 3018a7526ece30236969ce69dce729998c9a57de..8a23bd71935eb26c5093e4b2080b1d91b6de5582 100644 +--- a/profiles/winbind/nsswitch.conf ++++ b/profiles/winbind/nsswitch.conf +@@ -1,2 +1,2 @@ +-passwd: files winbind systemd +-group: files winbind systemd ++passwd: files winbind systemd {exclude if "with-custom-passwd"} ++group: files winbind systemd {exclude if "with-custom-group"} +-- +2.17.1 + diff --git a/SOURCES/0015-compat-do-not-stop-rpcbind-only-start-it.patch b/SOURCES/0015-compat-do-not-stop-rpcbind-only-start-it.patch new file mode 100644 index 0000000..11d49ef --- /dev/null +++ b/SOURCES/0015-compat-do-not-stop-rpcbind-only-start-it.patch @@ -0,0 +1,43 @@ +From c8456ad275ce96648927e9146de23ee73e334f09 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 25 Sep 2018 10:58:50 +0200 +Subject: [PATCH 15/16] compat: do not stop rpcbind, only start it + +Stopping rpcbind on a nis server will also stop ypserv as it depends +on rpcbind. There is no need to actually restart this service so we +only make sure that it is up and running. + +Resolves: +https://github.com/pbrezina/authselect/issues/100 +--- + src/compat/authcompat.py.in.in | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 532227b69f3bb3d124078915bd846009bee7df7a..0be644222a44185cb08ff696afad5adf05995093 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -80,8 +80,9 @@ class Service: + cmd = Command(Path.System("cmd-systemctl"), ["disable", self.name]) + self.runsystemd(cmd, False, 1) + +- def start(self): +- self.stop() ++ def start(self, Restart=True): ++ if Restart: ++ self.stop() + cmd = Command(Path.System("cmd-systemctl"), ["start", self.name]) + self.runsystemd(cmd, True, 5) + +@@ -404,7 +405,7 @@ class Configuration: + self.ypbind.enable() + + if not nostart: +- self.rpcbind.start() ++ self.rpcbind.start(Restart=False) + self.ypbind.start() + + def disableService(self, nostop): +-- +2.17.1 + diff --git a/SOURCES/0016-sssd-document-that-this-profile-can-be-used-also-wit.patch b/SOURCES/0016-sssd-document-that-this-profile-can-be-used-also-wit.patch new file mode 100644 index 0000000..cc4c75a --- /dev/null +++ b/SOURCES/0016-sssd-document-that-this-profile-can-be-used-also-wit.patch @@ -0,0 +1,43 @@ +From 766fb1c67f0b0cef0734756704d603df7d322a4c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 26 Sep 2018 13:32:31 +0200 +Subject: [PATCH 16/16] sssd: document that this profile can be used also with + sssd disabled + +https://github.com/pbrezina/authselect/issues/99 +--- + profiles/sssd/README | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/profiles/sssd/README b/profiles/sssd/README +index 42293ab39c628c285921b8b47c4a763fd0215472..c597afecff112e8af7905de9b6a8db77d5c3227c 100644 +--- a/profiles/sssd/README ++++ b/profiles/sssd/README +@@ -1,5 +1,5 @@ +-Enable SSSD for system authentication +-===================================== ++Enable SSSD for system authentication (also for local users only) ++================================================================= + + Selecting this profile will enable SSSD as the source of identity + and authentication providers. +@@ -12,6 +12,16 @@ to connect to multiple different account sources. + More information about SSSD can be found on its project page: + https://pagure.io/SSSD/sssd + ++By default, local users are served from SSSD rather then local files if SSSD ++is enabled (however they authenticate via pam_unix). This have a performance ++benefit since SSSD caches the files content in fast in-memory cache and thus ++reduces number of disk operations. ++ ++However, if you do not want to keep SSSD running on your machine, you can ++keep this profile selected and just disable SSSD service. The resulting ++configuration will still work correctly even with SSSD disabled and local users ++and groups will be read from local files directly. ++ + SSSD CONFIGURATION + ------------------ + +-- +2.17.1 + diff --git a/SOURCES/0017-sssd-add-support-for-local-users-authentication-via-.patch b/SOURCES/0017-sssd-add-support-for-local-users-authentication-via-.patch new file mode 100644 index 0000000..9563104 --- /dev/null +++ b/SOURCES/0017-sssd-add-support-for-local-users-authentication-via-.patch @@ -0,0 +1,30 @@ +From 088a2b92742cab5e1d8f71452c2ae0c0f183a6fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 8 Oct 2018 12:34:09 +0200 +Subject: [PATCH 1/2] sssd: add support for local users authentication via + smart card + +Resolves: +https://github.com/pbrezina/authselect/issues/23 +--- + profiles/sssd/system-auth | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/profiles/sssd/system-auth b/profiles/sssd/system-auth +index 02922b16903372598052e36f3713ca5c3f4c8418..a3d351cd5c37fb065892a0b71ec5323fd13a957d 100644 +--- a/profiles/sssd/system-auth ++++ b/profiles/sssd/system-auth +@@ -3,7 +3,9 @@ auth required pam_faildelay.so delay= + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} + auth sufficient pam_fprintd.so {include if "with-fingerprint"} + auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet +-auth [default=1 ignore=ignore success=ok] pam_localuser.so ++auth [default=1 ignore=ignore success=ok] pam_localuser.so {exclude if "with-smartcard"} ++auth [default=2 ignore=ignore success=ok] pam_localuser.so {include if "with-smartcard"} ++auth [success=done authinfo_unavail=ignore ignore=ignore default=die] pam_sss.so try_cert_auth {include if "with-smartcard"} + auth sufficient pam_unix.so {if not "without-nullok":nullok} try_first_pass + auth requisite pam_succeed_if.so uid >= 1000 quiet_success + auth sufficient pam_sss.so forward_pass +-- +2.17.1 + diff --git a/SOURCES/0018-sssd-add-with-smartcard-required-feature.patch b/SOURCES/0018-sssd-add-with-smartcard-required-feature.patch new file mode 100644 index 0000000..4d8dc72 --- /dev/null +++ b/SOURCES/0018-sssd-add-with-smartcard-required-feature.patch @@ -0,0 +1,81 @@ +From 396089c2acc76bef59040d22c4170673ac4009bf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 8 Oct 2018 12:58:41 +0200 +Subject: [PATCH 2/2] sssd: add with-smartcard-required feature + +Resolves: +https://github.com/pbrezina/authselect/issues/104 +--- + profiles/sssd/README | 6 ++++++ + profiles/sssd/dconf-db | 1 + + profiles/sssd/fingerprint-auth | 1 + + profiles/sssd/password-auth | 1 + + profiles/sssd/system-auth | 1 + + 5 files changed, 10 insertions(+) + +diff --git a/profiles/sssd/README b/profiles/sssd/README +index c597afecff112e8af7905de9b6a8db77d5c3227c..acbb635729c2b4a69a91cafe4bec76b030967967 100644 +--- a/profiles/sssd/README ++++ b/profiles/sssd/README +@@ -53,6 +53,12 @@ with-smartcard:: + + with-smartcard-lock-on-removal:: + Lock screen when a smartcard is removed. ++ Note: "with-smartcard" must be set as well. ++ ++with-smartcard-required:: ++ Smartcard authentication is required. No other means of authentication ++ (including password) will be enabled. ++ Note: "with-smartcard" must be set as well. + + with-fingerprint:: + Enable authentication with fingerprint reader through *pam_fprintd*. +diff --git a/profiles/sssd/dconf-db b/profiles/sssd/dconf-db +index cf22698fcc8a292c1bf68466f943595ca54c7b27..b24f783eb700713386d66857de2532482d15ce7c 100644 +--- a/profiles/sssd/dconf-db ++++ b/profiles/sssd/dconf-db +@@ -1,6 +1,7 @@ + [org/gnome/login-screen] + enable-smartcard-authentication={if "with-smartcard":true|false} + enable-fingerprint-authentication={if "with-fingerprint":true|false} ++enable-password-authentication={if "with-smartcard-required":false|true} + + [org/gnome/settings-daemon/peripherals/smartcard] {include if "with-smartcard-lock-on-removal"} + removal-action='lock-screen' {include if "with-smartcard-lock-on-removal"} +diff --git a/profiles/sssd/fingerprint-auth b/profiles/sssd/fingerprint-auth +index 01a5d21748f8e84acde23a0926782cf817fefc79..01b70f3533149d00700859f3e0a1c3f2abb33a8a 100644 +--- a/profiles/sssd/fingerprint-auth ++++ b/profiles/sssd/fingerprint-auth +@@ -1,5 +1,6 @@ + {continue if "with-fingerprint"} + auth required pam_env.so ++auth required pam_deny.so # Smartcard authentication is required {include if "with-smartcard-required"} + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} + auth sufficient pam_fprintd.so + auth required pam_faillock.so authfail deny=4 unlock_time=1200 {include if "with-faillock"} +diff --git a/profiles/sssd/password-auth b/profiles/sssd/password-auth +index e35c8d6943b8289d8b65d7a47b2dad8143b6132b..3205f261dd8c898baf292c252ebdb346fcb779bb 100644 +--- a/profiles/sssd/password-auth ++++ b/profiles/sssd/password-auth +@@ -1,5 +1,6 @@ + auth required pam_env.so + auth required pam_faildelay.so delay=2000000 ++auth required pam_deny.so # Smartcard authentication is required {include if "with-smartcard-required"} + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} + auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet + auth [default=1 ignore=ignore success=ok] pam_localuser.so +diff --git a/profiles/sssd/system-auth b/profiles/sssd/system-auth +index a3d351cd5c37fb065892a0b71ec5323fd13a957d..982cada1f774e6d53dd75c9f5dbc0603337cd70b 100644 +--- a/profiles/sssd/system-auth ++++ b/profiles/sssd/system-auth +@@ -1,6 +1,7 @@ + auth required pam_env.so + auth required pam_faildelay.so delay=2000000 + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} ++auth [success=done ignore=ignore default=die] pam_sss.so require_cert_auth ignore_authinfo_unavail {include if "with-smartcard-required"} + auth sufficient pam_fprintd.so {include if "with-fingerprint"} + auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet + auth [default=1 ignore=ignore success=ok] pam_localuser.so {exclude if "with-smartcard"} +-- +2.17.1 + diff --git a/SOURCES/0019-sssd-remove-with-sudo-duplicate-from-readme.patch b/SOURCES/0019-sssd-remove-with-sudo-duplicate-from-readme.patch new file mode 100644 index 0000000..9884540 --- /dev/null +++ b/SOURCES/0019-sssd-remove-with-sudo-duplicate-from-readme.patch @@ -0,0 +1,28 @@ +From ea730381abb2bd5e7a33ed5e3a71e19ce939b32f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 12 Nov 2018 12:10:21 +0100 +Subject: [PATCH 01/15] sssd: remove with-sudo duplicate from readme + +Resolves: +https://github.com/pbrezina/authselect/issues/108 +--- + profiles/sssd/README | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/profiles/sssd/README b/profiles/sssd/README +index acbb635729c2b4a69a91cafe4bec76b030967967..016f2019cd60aef1194a1cfa740955b51cfe0b24 100644 +--- a/profiles/sssd/README ++++ b/profiles/sssd/README +@@ -43,9 +43,6 @@ with-mkhomedir:: + with-ecryptfs:: + Enable automatic per-user ecryptfs. + +-with-sudo:: +- Use SSSD as a source of sudo rules. +- + with-smartcard:: + Enable authentication with smartcards through SSSD. Please note that + smartcard support must be also explicitly enabled within +-- +2.17.2 + diff --git a/SOURCES/0020-profiles-end-all-files-with-new-line.patch b/SOURCES/0020-profiles-end-all-files-with-new-line.patch new file mode 100644 index 0000000..828137e --- /dev/null +++ b/SOURCES/0020-profiles-end-all-files-with-new-line.patch @@ -0,0 +1,45 @@ +From 9cb658e150fc3fc55187ad0487d16963473547ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 12 Nov 2018 12:17:39 +0100 +Subject: [PATCH 02/15] profiles: end all files with new line + +Resolves: +https://github.com/pbrezina/authselect/issues/103 +--- + profiles/nis/dconf-locks | 2 +- + profiles/nis/nsswitch.conf | 2 +- + profiles/winbind/dconf-locks | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/profiles/nis/dconf-locks b/profiles/nis/dconf-locks +index 7a03033ec33e99ce86e7520103c3da9db570edd6..8a36fa9568344338272786394aece872185d0ab3 100644 +--- a/profiles/nis/dconf-locks ++++ b/profiles/nis/dconf-locks +@@ -1,2 +1,2 @@ + /org/gnome/login-screen/enable-smartcard-authentication +-/org/gnome/login-screen/enable-fingerprint-authentication +\ No newline at end of file ++/org/gnome/login-screen/enable-fingerprint-authentication +diff --git a/profiles/nis/nsswitch.conf b/profiles/nis/nsswitch.conf +index f5451657f3d8b988b633304d549a3242257715d3..9bee7d839f84ff39d54cb6ead9dea38e51736b4d 100644 +--- a/profiles/nis/nsswitch.conf ++++ b/profiles/nis/nsswitch.conf +@@ -11,4 +11,4 @@ protocols: files nis {exclude if "with-custom-protocols"} + publickey: files nis {exclude if "with-custom-publickey"} + rpc: files nis {exclude if "with-custom-rpc"} + services: files nis {exclude if "with-custom-services"} +-shadow: files nis {exclude if "with-custom-shadow"} +\ No newline at end of file ++shadow: files nis {exclude if "with-custom-shadow"} +diff --git a/profiles/winbind/dconf-locks b/profiles/winbind/dconf-locks +index 7a03033ec33e99ce86e7520103c3da9db570edd6..8a36fa9568344338272786394aece872185d0ab3 100644 +--- a/profiles/winbind/dconf-locks ++++ b/profiles/winbind/dconf-locks +@@ -1,2 +1,2 @@ + /org/gnome/login-screen/enable-smartcard-authentication +-/org/gnome/login-screen/enable-fingerprint-authentication +\ No newline at end of file ++/org/gnome/login-screen/enable-fingerprint-authentication +-- +2.17.2 + diff --git a/SOURCES/0021-compat-add-support-for-with-smartcard-required-enabl.patch b/SOURCES/0021-compat-add-support-for-with-smartcard-required-enabl.patch new file mode 100644 index 0000000..0bbf488 --- /dev/null +++ b/SOURCES/0021-compat-add-support-for-with-smartcard-required-enabl.patch @@ -0,0 +1,71 @@ +From c939585dc440e2b2ccaeea82ce3cf42c990dbe23 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 12 Nov 2018 12:49:39 +0100 +Subject: [PATCH 03/15] compat: add support for with-smartcard-required + (--enablerequiresmartcard) + +Resolves: +https://github.com/pbrezina/authselect/issues/109 +--- + src/compat/authcompat.py.in.in | 15 ++++++++------- + src/compat/authcompat_Options.py | 4 ++-- + 2 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 42cc6f3c0e38d8e14d62bd5acdc171176a6cb51f..accb3385ade908c07451ee4824d6b62b012ea317 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -518,13 +518,14 @@ class AuthCompat: + + def runAuthselect(self): + map = { +- 'smartcard' : 'with-smartcard', +- 'fingerprint' : 'with-fingerprint', +- 'ecryptfs' : 'with-ecryptfs', +- 'mkhomedir' : 'with-mkhomedir', +- 'faillock' : 'with-faillock', +- 'pamaccess' : 'with-pamaccess', +- 'winbindkrb5' : 'with-krb5' ++ 'smartcard' : 'with-smartcard', ++ 'requiresmartcard' : 'with-smartcard-required', ++ 'fingerprint' : 'with-fingerprint', ++ 'ecryptfs' : 'with-ecryptfs', ++ 'mkhomedir' : 'with-mkhomedir', ++ 'faillock' : 'with-faillock', ++ 'pamaccess' : 'with-pamaccess', ++ 'winbindkrb5' : 'with-krb5' + } + + # Read current configuration first. +diff --git a/src/compat/authcompat_Options.py b/src/compat/authcompat_Options.py +index e77b4407c7cd385b66a8a97795cece7f33571ff6..c8f52ab6773c4cd5371f32121dba8053f3443261 100644 +--- a/src/compat/authcompat_Options.py ++++ b/src/compat/authcompat_Options.py +@@ -13,7 +13,7 @@ + # 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. ++# GNU General Public License for morerequi details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . +@@ -91,6 +91,7 @@ class Options: + Option.Feature("rfc2307bis", _("use of RFC-2307bis schema for LDAP user information lookups")), + Option.Feature("smartcard", _("authentication with smart card by default")), + Option.Valued ("smartcardaction", _("<0=Lock|1=Ignore>"), _("action to be taken on smart card removal")), ++ Option.Feature("requiresmartcard",_("require smart card for authentication by default")), + Option.Feature("fingerprint", _("authentication with fingerprint readers by default")), + Option.Feature("ecryptfs", _("automatic per-user ecryptfs")), + Option.Feature("krb5", _("Kerberos authentication by default")), +@@ -146,7 +147,6 @@ class Options: + Option.UnsupportedSwitch ("usemd5"), + Option.UnsupportedValued ("passalgo", _("")), + Option.UnsupportedValued ("ldaploadcacert", _("")), +- Option.UnsupportedFeature("requiresmartcard"), + Option.UnsupportedValued ("smartcardmodule", _("")), + Option.UnsupportedValued ("smbsecurity", _("")), + Option.UnsupportedValued ("smbrealm", _("")), +-- +2.17.2 + diff --git a/SOURCES/0022-compat-support-with-smartcard-lock-on-removal-smartc.patch b/SOURCES/0022-compat-support-with-smartcard-lock-on-removal-smartc.patch new file mode 100644 index 0000000..88f1e54 --- /dev/null +++ b/SOURCES/0022-compat-support-with-smartcard-lock-on-removal-smartc.patch @@ -0,0 +1,33 @@ +From 0556b44eabdc9be59eb4fb4a72fc4e644b657ea1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 12 Nov 2018 12:51:55 +0100 +Subject: [PATCH 04/15] compat: support with-smartcard-lock-on-removal + (--smartcardaction=0) + +Resolves: +https://github.com/pbrezina/authselect/issues/110 +--- + src/compat/authcompat.py.in.in | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index accb3385ade908c07451ee4824d6b62b012ea317..666dcd0df57962a789a8882c26535d95d3e75cf2 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -556,6 +556,13 @@ class AuthCompat: + while feature in features: + features.remove(feature) + ++ # Add lock-on-smartcard-removal if requested ++ if self.options.isset("smartcardaction"): ++ if int(self.options.get("smartcardaction")) == 0: ++ features.append("with-smartcard-lock-on-removal") ++ else: ++ features.remove("with-smartcard-lock-on-removal") ++ + # Remove duplicates. The order is not kept but that does not matter. + features = list(set(features)) + +-- +2.17.2 + diff --git a/SOURCES/0023-profiles-mention-pam_oddjob_mkhomedir-in-requirement.patch b/SOURCES/0023-profiles-mention-pam_oddjob_mkhomedir-in-requirement.patch new file mode 100644 index 0000000..a78db77 --- /dev/null +++ b/SOURCES/0023-profiles-mention-pam_oddjob_mkhomedir-in-requirement.patch @@ -0,0 +1,58 @@ +From 5f1615d85c038b98b631d808c70e3557264b8a56 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 12 Nov 2018 13:05:50 +0100 +Subject: [PATCH 05/15] profiles: mention pam_oddjob_mkhomedir in requirements + +Resolves: +https://github.com/pbrezina/authselect/issues/111 +--- + profiles/nis/REQUIREMENTS | 3 ++- + profiles/sssd/REQUIREMENTS | 3 ++- + profiles/winbind/REQUIREMENTS | 3 ++- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/profiles/nis/REQUIREMENTS b/profiles/nis/REQUIREMENTS +index 920d57eb1374633776c379eea75d8a9632abe4b3..12b5879e8530a8c0bc3dfb4dc3c29dc38c4dcc07 100644 +--- a/profiles/nis/REQUIREMENTS ++++ b/profiles/nis/REQUIREMENTS +@@ -2,6 +2,7 @@ Make sure that NIS service is configured and enabled. See NIS documentation for + {include if "with-fingerprint"} + - with-fingerprint is selected, make sure fprintd service is configured and enabled {include if "with-fingerprint"} + {include if "with-mkhomedir"} +-- with-mkhomedir is selected, make sure oddjobd service is enabled {include if "with-mkhomedir"} ++- with-mkhomedir is selected, make sure pam_oddjob_mkhomedir module {include if "with-mkhomedir"} ++ is present and oddjobd service is enabled {include if "with-mkhomedir"} + - systemctl enable oddjobd.service {include if "with-mkhomedir"} + - systemctl start oddjobd.service {include if "with-mkhomedir"} +\ No newline at end of file +diff --git a/profiles/sssd/REQUIREMENTS b/profiles/sssd/REQUIREMENTS +index 2516ac35796cd4b38842b2269938b37aea7a845c..7fcfed9cccae346faa0f4dace1873a772453ddc0 100644 +--- a/profiles/sssd/REQUIREMENTS ++++ b/profiles/sssd/REQUIREMENTS +@@ -5,6 +5,7 @@ Make sure that SSSD service is configured and enabled. See SSSD documentation fo + {include if "with-fingerprint"} + - with-fingerprint is selected, make sure fprintd service is configured and enabled {include if "with-fingerprint"} + {include if "with-mkhomedir"} +-- with-mkhomedir is selected, make sure oddjobd service is enabled {include if "with-mkhomedir"} ++- with-mkhomedir is selected, make sure pam_oddjob_mkhomedir module {include if "with-mkhomedir"} ++ is present and oddjobd service is enabled {include if "with-mkhomedir"} + - systemctl enable oddjobd.service {include if "with-mkhomedir"} + - systemctl start oddjobd.service {include if "with-mkhomedir"} +\ No newline at end of file +diff --git a/profiles/winbind/REQUIREMENTS b/profiles/winbind/REQUIREMENTS +index f3bad76114c6ae996e62d4088dc7d70113d12fe6..786538caf83104d114820f56516bf3e68dce86fe 100644 +--- a/profiles/winbind/REQUIREMENTS ++++ b/profiles/winbind/REQUIREMENTS +@@ -2,6 +2,7 @@ Make sure that winbind service is configured and enabled. See winbind documentat + {include if "with-fingerprint"} + - with-fingerprint is selected, make sure fprintd service is configured and enabled {include if "with-fingerprint"} + {include if "with-mkhomedir"} +-- with-mkhomedir is selected, make sure oddjobd service is enabled {include if "with-mkhomedir"} ++- with-mkhomedir is selected, make sure pam_oddjob_mkhomedir module {include if "with-mkhomedir"} ++ is present and oddjobd service is enabled {include if "with-mkhomedir"} + - systemctl enable oddjobd.service {include if "with-mkhomedir"} + - systemctl start oddjobd.service {include if "with-mkhomedir"} +\ No newline at end of file +-- +2.17.2 + diff --git a/SOURCES/0024-lib-fix-memory-leak-in-authselect_profile_free.patch b/SOURCES/0024-lib-fix-memory-leak-in-authselect_profile_free.patch new file mode 100644 index 0000000..291bbcb --- /dev/null +++ b/SOURCES/0024-lib-fix-memory-leak-in-authselect_profile_free.patch @@ -0,0 +1,29 @@ +From 6445037ae9ba55abd1bd7ca2f0028081c26c0b16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 20 Nov 2018 12:18:49 +0100 +Subject: [PATCH 06/15] lib: fix memory leak in authselect_profile_free + +Resolves: +https://github.com/pbrezina/authselect/issues/116 +--- + src/lib/authselect_profile.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/lib/authselect_profile.c b/src/lib/authselect_profile.c +index 6f949a4ef6fb4159f89038a9cd705de475b5cf22..8a12a082802fbc4f3c8cb3af7379ad26372dcc0c 100644 +--- a/src/lib/authselect_profile.c ++++ b/src/lib/authselect_profile.c +@@ -130,6 +130,10 @@ authselect_profile_free(struct authselect_profile *profile) + free(profile->path); + } + ++ if (profile->name != NULL) { ++ free(profile->name); ++ } ++ + if (profile->description != NULL) { + free(profile->description); + } +-- +2.17.2 + diff --git a/SOURCES/0025-lib-fix-memory-leak-in-authselect_config_validate_ex.patch b/SOURCES/0025-lib-fix-memory-leak-in-authselect_config_validate_ex.patch new file mode 100644 index 0000000..6523748 --- /dev/null +++ b/SOURCES/0025-lib-fix-memory-leak-in-authselect_config_validate_ex.patch @@ -0,0 +1,28 @@ +From 91f35e84a9051b709fb7cf1b0ec02a8434258dd9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 20 Nov 2018 12:25:01 +0100 +Subject: [PATCH 07/15] lib: fix memory leak in + authselect_config_validate_existing + +Resolves: +https://github.com/pbrezina/authselect/issues/115 +--- + src/lib/files/config.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/lib/files/config.c b/src/lib/files/config.c +index 14434a819acc0bf3246c51be7090133d868a9571..e2859b04d3aeb40d510c0e87dc251adb1ff38b47 100644 +--- a/src/lib/files/config.c ++++ b/src/lib/files/config.c +@@ -201,6 +201,8 @@ authselect_config_validate_existing(const char *profile_id, + /* Check that symlinks exist and point to generated files. */ + result &= authselect_symlinks_validate(); + ++ authselect_files_free(files); ++ + return result; + } + +-- +2.17.2 + diff --git a/SOURCES/0026-profiles-make-session-pam_systemd-required.patch b/SOURCES/0026-profiles-make-session-pam_systemd-required.patch new file mode 100644 index 0000000..4c3d538 --- /dev/null +++ b/SOURCES/0026-profiles-make-session-pam_systemd-required.patch @@ -0,0 +1,157 @@ +From de0168f1ebb871b80c2552f1ef8dd8f145dacf29 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 20 Nov 2018 13:07:19 +0100 +Subject: [PATCH 08/15] profiles: make session pam_systemd required + +There was a time when pam_systemd was optional but today +if pam_systemd fails to register a session it's catastrophic +and we should just fail the whole pam conversation. + +Resolves: +https://github.com/pbrezina/authselect/issues/118 +--- + profiles/nis/fingerprint-auth | 2 +- + profiles/nis/password-auth | 2 +- + profiles/nis/system-auth | 2 +- + profiles/sssd/fingerprint-auth | 2 +- + profiles/sssd/password-auth | 2 +- + profiles/sssd/smartcard-auth | 2 +- + profiles/sssd/system-auth | 2 +- + profiles/winbind/fingerprint-auth | 2 +- + profiles/winbind/password-auth | 2 +- + profiles/winbind/system-auth | 2 +- + 10 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/profiles/nis/fingerprint-auth b/profiles/nis/fingerprint-auth +index 278487b2a0f9ce103afebb0809ffffa2cfbbba7e..dc9e53ba28974eb75828220d9b80d626106b9652 100644 +--- a/profiles/nis/fingerprint-auth ++++ b/profiles/nis/fingerprint-auth +@@ -17,7 +17,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/nis/password-auth b/profiles/nis/password-auth +index 615544d16f7fc8551cb06a221825526f12cbfc64..d22dcef9529ca51a1812ae0733b543d13f6ae235 100644 +--- a/profiles/nis/password-auth ++++ b/profiles/nis/password-auth +@@ -20,7 +20,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/nis/system-auth b/profiles/nis/system-auth +index a41828d8972537b1b24d0ff21cd52976fba6646d..d394d3e1200755d2233d4f86e3866620539fc18d 100644 +--- a/profiles/nis/system-auth ++++ b/profiles/nis/system-auth +@@ -21,7 +21,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/fingerprint-auth b/profiles/sssd/fingerprint-auth +index 01b70f3533149d00700859f3e0a1c3f2abb33a8a..3bdaf3e71ba7afc66864f9c2acbf584c0b77a82d 100644 +--- a/profiles/sssd/fingerprint-auth ++++ b/profiles/sssd/fingerprint-auth +@@ -19,7 +19,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/password-auth b/profiles/sssd/password-auth +index 3205f261dd8c898baf292c252ebdb346fcb779bb..1e529184cdc04a94fb4f2b52f733cf6df73b7fda 100644 +--- a/profiles/sssd/password-auth ++++ b/profiles/sssd/password-auth +@@ -26,7 +26,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/smartcard-auth b/profiles/sssd/smartcard-auth +index b16ba0f44ca4c896c1980a292cf78f12d7f2f06d..b89a23a111560877785c9d17fd65c0bfd3f3ae22 100644 +--- a/profiles/sssd/smartcard-auth ++++ b/profiles/sssd/smartcard-auth +@@ -16,7 +16,7 @@ account required pam_permit.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/system-auth b/profiles/sssd/system-auth +index 982cada1f774e6d53dd75c9f5dbc0603337cd70b..22dba5b2d3db23855724ddb05528e5013c63c5af 100644 +--- a/profiles/sssd/system-auth ++++ b/profiles/sssd/system-auth +@@ -29,7 +29,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/winbind/fingerprint-auth b/profiles/winbind/fingerprint-auth +index 0beff74eba83f12c4ad5a6147a6194608cd047e3..92649461564dd4e6f78f467dc1be455f29edfe08 100644 +--- a/profiles/winbind/fingerprint-auth ++++ b/profiles/winbind/fingerprint-auth +@@ -18,7 +18,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/winbind/password-auth b/profiles/winbind/password-auth +index c984d817c537c48a358c644083a4f8979181dd1d..fb59e295c3a220acfdf633f69a0204328150a5c3 100644 +--- a/profiles/winbind/password-auth ++++ b/profiles/winbind/password-auth +@@ -23,7 +23,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/winbind/system-auth b/profiles/winbind/system-auth +index 33dc491c2125c7fe06d6475369f1654a900c7050..bb75c327db3315c22a22f375a5cc633e33c30c19 100644 +--- a/profiles/winbind/system-auth ++++ b/profiles/winbind/system-auth +@@ -24,7 +24,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +--session optional pam_systemd.so ++session required pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +-- +2.17.2 + diff --git a/SOURCES/0027-lib-add-authselect_profile_features-to-list-supporte.patch b/SOURCES/0027-lib-add-authselect_profile_features-to-list-supporte.patch new file mode 100644 index 0000000..55446ad --- /dev/null +++ b/SOURCES/0027-lib-add-authselect_profile_features-to-list-supporte.patch @@ -0,0 +1,305 @@ +From 3935dd9f2ac3aab9027783e45f499401476f52cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 19 Nov 2018 15:04:42 +0100 +Subject: [PATCH 09/15] lib: add authselect_profile_features to list supported + features + +The feature list is automatically obtained from profile's template files. + +Related to: +https://github.com/pbrezina/authselect/issues/107 +--- + include/authselect.h | 12 +++++ + src/lib/authselect_profile.c | 51 ++++++++++++++++++++++ + src/lib/util/string_array.c | 36 +++++++++++++++ + src/lib/util/string_array.h | 20 +++++++++ + src/lib/util/template.c | 85 ++++++++++++++++++++++++++++++++++-- + src/lib/util/template.h | 11 +++++ + 6 files changed, 211 insertions(+), 4 deletions(-) + +diff --git a/include/authselect.h b/include/authselect.h +index d52d460e38132cf81e8a03b88a530c634a2c8937..462f54291e8283d5778005ac1747dd03258584be 100644 +--- a/include/authselect.h ++++ b/include/authselect.h +@@ -273,6 +273,18 @@ char ** + authselect_profile_nsswitch_maps(const struct authselect_profile *profile, + const char **features); + ++/** ++ * List features supported by the profile. ++ * ++ * It is necessary to free the returned pointer with @authselect_array_free. ++ * ++ * @param profile Pointer to structure obtained by @authselect_profile. ++ * ++ * @return NULL-terminated array of supported features, NULL on error. ++ */ ++char ** ++authselect_profile_features(const struct authselect_profile *profile); ++ + /** + * Free authconfig_profile structure obtained by @authselect_profile. + * +diff --git a/src/lib/authselect_profile.c b/src/lib/authselect_profile.c +index 8a12a082802fbc4f3c8cb3af7379ad26372dcc0c..d0cf17b8b7a414a41427c88039687725dcf1a560 100644 +--- a/src/lib/authselect_profile.c ++++ b/src/lib/authselect_profile.c +@@ -115,6 +115,57 @@ authselect_profile_nsswitch_maps(const struct authselect_profile *profile, + return maps; + } + ++_PUBLIC_ char ** ++authselect_profile_features(const struct authselect_profile *profile) ++{ ++ char **features; ++ char **array; ++ errno_t ret; ++ int i; ++ ++ if (profile == NULL) { ++ return NULL; ++ } ++ ++ features = string_array_create(10); ++ if (features == NULL) { ++ ERROR("Unable to create array (out of memory)"); ++ return NULL; ++ } ++ ++ struct authselect_generated files[] = PROFILE_FILES(profile->files); ++ ++ for (i = 0; files[i].path != NULL; i++) { ++ array = template_list_features(files[i].content); ++ if (array == NULL) { ++ ERROR("Unable to obtain feature list (out of memory)"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ features = string_array_concat(features, array, true); ++ string_array_free(array); ++ ++ if (features == NULL) { ++ ERROR("Unable to obtain feature list (out of memory)"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ string_array_sort(features); ++ ++ ret = EOK; ++ ++done: ++ if (ret != EOK) { ++ string_array_free(features); ++ return NULL; ++ } ++ ++ return features; ++} ++ + _PUBLIC_ void + authselect_profile_free(struct authselect_profile *profile) + { +diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c +index a074e23ee504792da7f1a9262e15c549de5747d3..43e30d0008b5709f97da9c43f8f2c28ef2475df5 100644 +--- a/src/lib/util/string_array.c ++++ b/src/lib/util/string_array.c +@@ -159,3 +159,39 @@ string_array_del_value(char **array, const char *value) + + return array; + } ++ ++char ** ++string_array_concat(char **to, char **items, bool unique) ++{ ++ int i; ++ ++ if (items == NULL) { ++ return to; ++ } ++ ++ for (i = 0; items[i] != NULL; i++) { ++ to = string_array_add_value(to, items[i], unique); ++ if (to == NULL) { ++ return NULL; ++ } ++ } ++ ++ return to; ++} ++ ++static int ++string_array_sort_callback(const void *a, const void *b) ++{ ++ return strcmp(*(char* const*)a, *(char* const*)b); ++} ++ ++void ++string_array_sort(char **array) ++{ ++ if (array == NULL) { ++ return; ++ } ++ ++ qsort(array, string_array_count(array), sizeof(char *), ++ string_array_sort_callback); ++} +diff --git a/src/lib/util/string_array.h b/src/lib/util/string_array.h +index 9545685b2553228a109ab51e7c6a0fd16698fa3e..06aa46c008058163e5557d51e18258fa4e9a1523 100644 +--- a/src/lib/util/string_array.h ++++ b/src/lib/util/string_array.h +@@ -118,4 +118,24 @@ string_array_add_value(char **array, const char *value, bool unique); + char ** + string_array_del_value(char **array, const char *value); + ++/** ++ * Concatenate two array. Array @items values will be appended to arra @to. ++ * ++ * @param to NULL-terminated destination array. ++ * @param items NULL-terminated array to be appended into @to. ++ * @param unique If true, value will not be added if it is already present. ++ * ++ * @return Array or NULL if reallocation fails. ++ */ ++char ** ++string_array_concat(char **to, char **items, bool unique); ++ ++/** ++ * Alphabetically sort a NULL-terminated string array. ++ * ++ * @param array NULL-terminated string array. ++ */ ++void ++string_array_sort(char **array); ++ + #endif /* _STRING_ARRAY_H_ */ +diff --git a/src/lib/util/template.c b/src/lib/util/template.c +index e38d1d7f1db2c90f1281e97f3ebbdd9d9d1a935d..fb373c0fd83e04c6c78d5f57d3d8e50e54c0377b 100644 +--- a/src/lib/util/template.c ++++ b/src/lib/util/template.c +@@ -325,10 +325,27 @@ template_process_matches(const char *match_string, + return ret; + } + +- *_op = op; +- *_feature = feature; +- *_if_true = if_true; +- *_if_false = if_false; ++ if (_op != NULL) { ++ *_op = op; ++ } ++ ++ if (_feature != NULL) { ++ *_feature = feature; ++ } else { ++ free(feature); ++ } ++ ++ if (_if_true != NULL) { ++ *_if_true = if_true; ++ } else { ++ free(if_true); ++ } ++ ++ if (_if_false != NULL) { ++ *_if_false = if_false; ++ } else { ++ free(if_false); ++ } + + return EOK; + } +@@ -478,6 +495,66 @@ template_generate_preamble() + return preamble; + } + ++char ** ++template_list_features(const char *template) ++{ ++ regmatch_t m[RE_MATCHES]; ++ const char *match_string; ++ char **features; ++ char *feature; ++ regex_t regex; ++ errno_t ret; ++ int reret; ++ ++ features = string_array_create(10); ++ if (features == NULL) { ++ return NULL; ++ } ++ ++ if (template == NULL) { ++ return features; ++ } ++ ++ reret = regcomp(®ex, OP_RE, REG_EXTENDED | REG_NEWLINE); ++ if (reret != REG_NOERROR) { ++ ERROR("Unable to compile regular expression: regex error %d", reret); ++ ret = EFAULT; ++ goto done; ++ } ++ ++ match_string = template; ++ while ((reret = regexec(®ex, match_string, RE_MATCHES, m, 0)) == REG_NOERROR) { ++ ret = template_process_matches(match_string, m, NULL, &feature, ++ NULL, NULL); ++ if (ret != EOK) { ++ ERROR("Unable to process match [%d]: %s", ret, strerror(ret)); ++ goto done; ++ } ++ ++ features = string_array_add_value(features, feature, true); ++ free(feature); ++ ++ match_string += m[0].rm_eo; ++ } ++ ++ if (reret != REG_NOMATCH) { ++ ERROR("Unable to search string: regex error %d", reret); ++ ret = EFAULT; ++ goto done; ++ } ++ ++ ret = EOK; ++ ++done: ++ if (ret != EOK) { ++ string_array_free(features); ++ return NULL; ++ } ++ ++ regfree(®ex); ++ return features; ++} ++ + errno_t + template_write(const char *filepath, + const char *content, +diff --git a/src/lib/util/template.h b/src/lib/util/template.h +index 57e076c257a8cdcbc9c2c8f4f5266b4c21f27941..1c412dcf15a7f0d5a5897b78b8b52ff67b7c3f95 100644 +--- a/src/lib/util/template.h ++++ b/src/lib/util/template.h +@@ -37,6 +37,17 @@ char * + template_generate(const char *template, + const char **features); + ++/** ++ * Find all features available withint the @template and return them in ++ * NULL-terminated array. ++ * ++ * @param template Template. ++ * ++ * @return List of features in NULL-terminated array or NULL on error. ++ */ ++char ** ++template_list_features(const char *template); ++ + /** + * Write generated file preamble together with its content to a file. + * If the file does not exist, it is created, otherwise its content +-- +2.17.2 + diff --git a/SOURCES/0028-lib-refuse-to-activate-profile-if-unsupported-featur.patch b/SOURCES/0028-lib-refuse-to-activate-profile-if-unsupported-featur.patch new file mode 100644 index 0000000..deae9a0 --- /dev/null +++ b/SOURCES/0028-lib-refuse-to-activate-profile-if-unsupported-featur.patch @@ -0,0 +1,239 @@ +From 85bbc387c3f7bcfd094b78e2fc2779e27aca348f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 20 Nov 2018 11:56:09 +0100 +Subject: [PATCH 10/15] lib: refuse to activate profile if unsupported feature + was selected + +Resolves: +https://github.com/pbrezina/authselect/issues/107 +--- + include/authselect.h | 1 + + src/lib/authselect.c | 44 +++++++++++++++++++++++++++++++++++++ + src/lib/util/string.c | 40 +++++++++++++++++++++++++++++++++ + src/lib/util/string.h | 6 +++++ + src/lib/util/string_array.c | 30 +++++++++++++++++++++++++ + src/lib/util/string_array.h | 15 +++++++++++++ + src/tests/Makefile.am | 1 + + 7 files changed, 137 insertions(+) + +diff --git a/include/authselect.h b/include/authselect.h +index 462f54291e8283d5778005ac1747dd03258584be..110f22a864157f898541be573e800ed7d6c38e0a 100644 +--- a/include/authselect.h ++++ b/include/authselect.h +@@ -70,6 +70,7 @@ enum authselect_profile_type { + * authselect and @force_overwrite must be set to true to force + * overwrite the existing files. + * - ENOENT if the profile was not found. ++ * - EINVAL if unsupported feature was provided. + * - Other errno code on generic error. + */ + int +diff --git a/src/lib/authselect.c b/src/lib/authselect.c +index 3148f63b60534480b05b1ddb5587e4ed09aaa84a..1b4337e2e0eae4f298e59f90cc9c8659891e23f3 100644 +--- a/src/lib/authselect.c ++++ b/src/lib/authselect.c +@@ -29,6 +29,45 @@ + #include "lib/files/files.h" + #include "lib/profiles/profiles.h" + ++static bool ++authselect_check_features(const struct authselect_profile *profile, ++ const char **features) ++{ ++ const char *similar; ++ bool result = true; ++ char **supported; ++ int i; ++ ++ if (features == NULL) { ++ return true; ++ } ++ ++ supported = authselect_profile_features(profile); ++ if (supported == NULL) { ++ ERROR("Unable to obtain supported features"); ++ return false; ++ } ++ ++ for (i = 0; features[i] != NULL; i++) { ++ if (string_array_has_value(supported, features[i])) { ++ continue; ++ } ++ ++ result = false; ++ similar = string_array_find_similar(features[i], supported, 5); ++ if (similar != NULL) { ++ ERROR("Unknown profile feature [%s], did you mean [%s]?", ++ features[i], similar); ++ } else { ++ ERROR("Unknown profile feature [%s]", features[i]); ++ } ++ } ++ ++ string_array_free(supported); ++ ++ return result; ++} ++ + _PUBLIC_ void + authselect_set_debug_fn(authselect_debug_fn fn, void *pvt) + { +@@ -53,6 +92,11 @@ authselect_activate(const char *profile_id, + return ret; + } + ++ if (!authselect_check_features(profile, features)) { ++ ret = EINVAL; ++ goto done; ++ } ++ + if (force_overwrite) { + INFO("Enforcing activation!"); + ret = authselect_profile_activate(profile, features); +diff --git a/src/lib/util/string.c b/src/lib/util/string.c +index 73ae778663bd8db024620a58987833ede60307d1..e6803bcd4e41adc05eaa623089009b17ccd4f49b 100644 +--- a/src/lib/util/string.c ++++ b/src/lib/util/string.c +@@ -329,3 +329,43 @@ string_replace_shake(char *str, size_t original_length) + str[pos] = '\0'; + } + } ++ ++static int ++min3(unsigned int a, unsigned int b, unsigned int c) ++{ ++ if (a < b && a < c) { ++ return a; ++ } else if (b < a && b < c) { ++ return b; ++ } ++ ++ return c; ++} ++ ++int ++string_levenshtein(const char *a, const char *b) ++{ ++ unsigned int len_a = strlen(a); ++ unsigned int len_b = strlen(b); ++ unsigned int x; ++ unsigned int y; ++ unsigned int last_diag; ++ unsigned int old_diag; ++ unsigned int column[len_a + 1]; ++ ++ for (y = 1; y <= len_a; y++) { ++ column[y] = y; ++ } ++ ++ for (x = 1; x <= len_b; x++) { ++ column[0] = x; ++ for (y = 1, last_diag = x - 1; y <= len_a; y++) { ++ old_diag = column[y]; ++ column[y] = min3(column[y] + 1, column[y - 1] + 1, ++ last_diag + (a[y - 1] == b[x - 1] ? 0 : 1)); ++ last_diag = old_diag; ++ } ++ } ++ ++ return column[len_a]; ++} +diff --git a/src/lib/util/string.h b/src/lib/util/string.h +index d7ca04491e5ceff20bd1d6e136ea151166156546..e550d853d3fa0699909b84cc9febdae9d5884b9f 100644 +--- a/src/lib/util/string.h ++++ b/src/lib/util/string.h +@@ -179,4 +179,10 @@ string_remove_remainder(char *str, size_t from); + void + string_replace_shake(char *str, size_t original_length); + ++/** ++ * Compute Levenshtein distance of two strings. ++ */ ++int ++string_levenshtein(const char *a, const char *b); ++ + #endif /* _STRING_H_ */ +diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c +index 43e30d0008b5709f97da9c43f8f2c28ef2475df5..e56d66bdcce7c8a1cf99f9b91068614c4b8d3d81 100644 +--- a/src/lib/util/string_array.c ++++ b/src/lib/util/string_array.c +@@ -25,6 +25,7 @@ + + #include "common/common.h" + #include "lib/util/string_array.h" ++#include "lib/util/string.h" + + char ** + string_array_create(size_t num_items) +@@ -195,3 +196,32 @@ string_array_sort(char **array) + qsort(array, string_array_count(array), sizeof(char *), + string_array_sort_callback); + } ++ ++const char * ++string_array_find_similar(const char *value, char **array, int max_distance) ++{ ++ const char *word = NULL; ++ int current; ++ int best; ++ int i; ++ ++ for (i = 0; array[i] != NULL; i++) { ++ current = string_levenshtein(value, array[i]); ++ if (word == NULL) { ++ best = current; ++ word = array[i]; ++ continue; ++ } ++ ++ if (current < best) { ++ best = current; ++ word = array[i]; ++ } ++ } ++ ++ if (best > max_distance) { ++ return NULL; ++ } ++ ++ return word; ++} +diff --git a/src/lib/util/string_array.h b/src/lib/util/string_array.h +index 06aa46c008058163e5557d51e18258fa4e9a1523..ba9760b5d66a9619ca8edea5e3418c5cfbbec929 100644 +--- a/src/lib/util/string_array.h ++++ b/src/lib/util/string_array.h +@@ -138,4 +138,19 @@ string_array_concat(char **to, char **items, bool unique); + void + string_array_sort(char **array); + ++/** ++ * Find similar word inside a NULL-terminated array, based on Levenshtein ++ * distance algorithm. ++ * ++ * @param value Value to search in @array. ++ * @param array NULL-terminated string array. ++ * @param max_distance Maximum distance between two strings. If the real ++ * distance is greater then this value, those string ++ * are not considered as similar. ++ * ++ * @return Most similar word that was found or NULL if non was found. ++ */ ++const char * ++string_array_find_similar(const char *value, char **array, int max_distance); ++ + #endif /* _STRING_ARRAY_H_ */ +diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am +index 1cfebeab6bf3b36e760372b05482fd9f322feab1..e1505e6b5787a669065e5ea3c7acf55ea110c4da 100644 +--- a/src/tests/Makefile.am ++++ b/src/tests/Makefile.am +@@ -23,6 +23,7 @@ check_PROGRAMS = $(TESTS) + test_util_string_array_SOURCES = \ + test_util_string_array.c \ + ../lib/util/string_array.c \ ++ ../lib/util/string.c \ + $(NULL) + test_util_string_array_CFLAGS = \ + $(AM_CFLAGS) +-- +2.17.2 + diff --git a/SOURCES/0029-lib-remove-no-longer-supported-features-in-apply-cha.patch b/SOURCES/0029-lib-remove-no-longer-supported-features-in-apply-cha.patch new file mode 100644 index 0000000..13e2133 --- /dev/null +++ b/SOURCES/0029-lib-remove-no-longer-supported-features-in-apply-cha.patch @@ -0,0 +1,69 @@ +From 62746460cce0620a8f2150971019f0c535caa360 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 20 Nov 2018 12:07:22 +0100 +Subject: [PATCH 11/15] lib: remove no longer supported features in + apply-changes + +Resolves: +https://github.com/pbrezina/authselect/issues/107 +--- + src/lib/authselect.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/src/lib/authselect.c b/src/lib/authselect.c +index 1b4337e2e0eae4f298e59f90cc9c8659891e23f3..e0b8b1246b0e7139494d90cca4e0ebed3eb66376 100644 +--- a/src/lib/authselect.c ++++ b/src/lib/authselect.c +@@ -145,17 +145,49 @@ done: + _PUBLIC_ int + authselect_apply_changes(void) + { ++ struct authselect_profile *profile; + char *profile_id; + char **features; ++ char **supported; + errno_t ret; ++ int i; + + ret = authselect_current_configuration(&profile_id, &features); + if (ret != EOK) { + return ret; + } + ++ ret = authselect_profile(profile_id, &profile); ++ if (ret != EOK) { ++ ERROR("Unable to find profile [%s] [%d]: %s", ++ profile_id, ret, strerror(ret)); ++ goto done; ++ } ++ ++ supported = authselect_profile_features(profile); ++ if (supported == NULL) { ++ ERROR("Unable to obtain supported features"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ for (i = 0; features[i] != NULL; i++) { ++ if (string_array_has_value(supported, features[i])) { ++ continue; ++ } ++ ++ WARN("Profile feature [%s] is no longer supported, removing it...", ++ features[i]); ++ ++ features = string_array_del_value(features, features[i]); ++ i--; ++ } ++ + ret = authselect_activate(profile_id, (const char **)features, false); + ++done: ++ authselect_profile_free(profile); ++ string_array_free(supported); + string_array_free(features); + free(profile_id); + +-- +2.17.2 + diff --git a/SOURCES/0030-compat-write-to-sysconfig-after-all-changes-are-done.patch b/SOURCES/0030-compat-write-to-sysconfig-after-all-changes-are-done.patch new file mode 100644 index 0000000..9fee909 --- /dev/null +++ b/SOURCES/0030-compat-write-to-sysconfig-after-all-changes-are-done.patch @@ -0,0 +1,53 @@ +From 644b46d3f301ac1b237818b8dc59f178c8fe14fe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Sat, 24 Nov 2018 13:01:28 +0100 +Subject: [PATCH 12/15] compat: write to sysconfig after all changes are done + +Before this patch we were writing to sysconfig before we check that +authconfig is run as root. This produce following traceback: + +Truncated backtrace: +authcompat_EnvironmentFile.py:77:write:PermissionError: [Errno 13] Permission denied: '/etc/sysconfig/authconfig' + +Traceback (most recent call last): + File "/usr/sbin/authconfig", line 650, in + main() + File "/usr/sbin/authconfig", line 629, in main + authcompat = AuthCompat() + File "/usr/sbin/authconfig", line 463, in __init__ + self.sysconfig.write() + File "/usr/lib/python3.7/site-packages/authselect/authcompat_EnvironmentFile.py", line 77, in write + with open(self.filename, "w") as f: +PermissionError: [Errno 13] Permission denied: '/etc/sysconfig/authconfig' + +Now we write to sysconfig after writing all changes. + +Resolves: +https://github.com/pbrezina/authselect/issues/119 +--- + src/compat/authcompat.py.in.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 666dcd0df57962a789a8882c26535d95d3e75cf2..e4b8c05c6a11a215529ba66f8b36b72a6ac18448 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -460,7 +460,6 @@ class AuthCompat: + self.options.parse() + self.options.applysysconfig(self.sysconfig) + self.options.updatesysconfig(self.sysconfig) +- self.sysconfig.write() + + def printWarning(self): + print(_("Running authconfig compatibility tool.")) +@@ -646,6 +645,7 @@ def main(): + try: + authcompat.runAuthselect() + authcompat.writeConfiguration() ++ authcompat.sysconfig.write() + except subprocess.CalledProcessError as result: + eprint(_("Command [%s] failed with %d, stderr:") + % (' '.join(result.cmd), result.returncode)) +-- +2.17.2 + diff --git a/SOURCES/0031-util-remove-duplicate-values-correctly-in-string_arr.patch b/SOURCES/0031-util-remove-duplicate-values-correctly-in-string_arr.patch new file mode 100644 index 0000000..a501665 --- /dev/null +++ b/SOURCES/0031-util-remove-duplicate-values-correctly-in-string_arr.patch @@ -0,0 +1,222 @@ +From 85933ccfa7a1068f16fde557fe825c750899659a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 28 Nov 2018 13:45:33 +0100 +Subject: [PATCH 13/15] util: remove duplicate values correctly in + string_array_del_value + +--- + src/lib/util/string_array.c | 27 ++++-- + src/tests/test_util_string_array.c | 146 ++++++++++++++++++++++++++++- + 2 files changed, 163 insertions(+), 10 deletions(-) + +diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c +index e56d66bdcce7c8a1cf99f9b91068614c4b8d3d81..a8afa5ab8edbb26d6f946619f9ce0b83c511bb8c 100644 +--- a/src/lib/util/string_array.c ++++ b/src/lib/util/string_array.c +@@ -140,24 +140,33 @@ string_array_add_value(char **array, const char *value, bool unique) + char ** + string_array_del_value(char **array, const char *value) + { +- bool found = false; +- int i; ++ size_t count; ++ size_t pos; ++ size_t i; + +- if (!string_array_has_value(array, value)) { +- return array; ++ if (array == NULL) { ++ return NULL; + } + +- for (i = 0; array[i] != NULL; i++) { +- if (strcmp(value, array[i]) == 0) { ++ count = string_array_count(array); ++ for (i = 0; i < count; i++) { ++ if (strcmp(array[i], value) == 0) { + free(array[i]); +- found = true; ++ array[i] = NULL; + } ++ } + +- if (found) { +- array[i] = array[i + 1]; ++ for (i = 0, pos = 0; i < count; i++) { ++ if (array[i] != NULL) { ++ array[pos] = array[i]; ++ pos++; + } + } + ++ for (; pos < count; pos++) { ++ array[pos] = NULL; ++ } ++ + return array; + } + +diff --git a/src/tests/test_util_string_array.c b/src/tests/test_util_string_array.c +index 4f6812e9396f04bbbfb72bda8a9022501f074faf..249cb96acea3c4feac910702572cafb1025d9496 100644 +--- a/src/tests/test_util_string_array.c ++++ b/src/tests/test_util_string_array.c +@@ -32,11 +32,155 @@ void test_string_array_create(void **state) + string_array_free(array); + } + ++void test_string_array_del_value__single(void **state) ++{ ++ char **array; ++ const char *values[] = {"1", "2", "3", "4", "5", NULL}; ++ const char *expected[] = {"1", "3", "4", "5", NULL}; ++ int i; ++ ++ array = string_array_create(10); ++ assert_non_null(array); ++ ++ /* Fill array. */ ++ for (i = 0; values[i] != NULL; i++) { ++ array = string_array_add_value(array, values[i], false); ++ assert_non_null(array); ++ assert_non_null(array[i]); ++ } ++ assert_null(array[i]); ++ ++ /* Delete value. */ ++ array = string_array_del_value(array, "2"); ++ assert_non_null(array); ++ ++ /* Test values. */ ++ for (i = 0; expected[i] != NULL; i++) { ++ assert_non_null(array[i]); ++ assert_string_equal(array[i], expected[i]); ++ } ++ assert_null(array[i]); ++ ++ string_array_free(array); ++} ++ ++void test_string_array_del_value__single_repeated(void **state) ++{ ++ char **array; ++ const char *values[] = {"1", "2", "2", "3", "2", "4", "2", "5", NULL}; ++ const char *expected[] = {"1", "3", "4", "5", NULL}; ++ int i; ++ ++ array = string_array_create(10); ++ assert_non_null(array); ++ ++ /* Fill array. */ ++ for (i = 0; values[i] != NULL; i++) { ++ array = string_array_add_value(array, values[i], false); ++ assert_non_null(array); ++ assert_non_null(array[i]); ++ } ++ assert_null(array[i]); ++ ++ /* Delete value. */ ++ array = string_array_del_value(array, "2"); ++ assert_non_null(array); ++ ++ /* Test values. */ ++ for (i = 0; expected[i] != NULL; i++) { ++ assert_non_null(array[i]); ++ assert_string_equal(array[i], expected[i]); ++ } ++ assert_null(array[i]); ++ ++ string_array_free(array); ++} ++ ++void test_string_array_del_value__multiple(void **state) ++{ ++ char **array; ++ const char *values[] = {"1", "2", "3", "4", "5", NULL}; ++ const char *expected[] = {"1", "4", NULL}; ++ int i; ++ ++ array = string_array_create(10); ++ assert_non_null(array); ++ ++ /* Fill array. */ ++ for (i = 0; values[i] != NULL; i++) { ++ array = string_array_add_value(array, values[i], false); ++ assert_non_null(array); ++ assert_non_null(array[i]); ++ } ++ assert_null(array[i]); ++ ++ /* Delete value. */ ++ array = string_array_del_value(array, "2"); ++ assert_non_null(array); ++ ++ array = string_array_del_value(array, "3"); ++ assert_non_null(array); ++ ++ array = string_array_del_value(array, "5"); ++ assert_non_null(array); ++ ++ /* Test values. */ ++ for (i = 0; expected[i] != NULL; i++) { ++ assert_non_null(array[i]); ++ assert_string_equal(array[i], expected[i]); ++ } ++ assert_null(array[i]); ++ ++ string_array_free(array); ++} ++ ++void test_string_array_del_value__multiple_repeated(void **state) ++{ ++ char **array; ++ const char *values[] = {"1", "2", "2", "3", "3", "2", "4", "2", "5", "5", NULL}; ++ const char *expected[] = {"1", "4", NULL}; ++ int i; ++ ++ array = string_array_create(10); ++ assert_non_null(array); ++ ++ /* Fill array. */ ++ for (i = 0; values[i] != NULL; i++) { ++ array = string_array_add_value(array, values[i], false); ++ assert_non_null(array); ++ assert_non_null(array[i]); ++ } ++ assert_null(array[i]); ++ ++ /* Delete value. */ ++ array = string_array_del_value(array, "2"); ++ assert_non_null(array); ++ ++ array = string_array_del_value(array, "3"); ++ assert_non_null(array); ++ ++ array = string_array_del_value(array, "5"); ++ assert_non_null(array); ++ ++ /* Test values. */ ++ for (i = 0; expected[i] != NULL; i++) { ++ assert_non_null(array[i]); ++ assert_string_equal(array[i], expected[i]); ++ } ++ assert_null(array[i]); ++ ++ string_array_free(array); ++} ++ + int main(int argc, const char *argv[]) + { + + const struct CMUnitTest tests[] = { +- cmocka_unit_test(test_string_array_create) ++ cmocka_unit_test(test_string_array_create), ++ cmocka_unit_test(test_string_array_del_value__single), ++ cmocka_unit_test(test_string_array_del_value__single_repeated), ++ cmocka_unit_test(test_string_array_del_value__multiple), ++ cmocka_unit_test(test_string_array_del_value__multiple_repeated) + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +-- +2.17.2 + diff --git a/SOURCES/0032-util-do-not-return-value-from-string_array_del_value.patch b/SOURCES/0032-util-do-not-return-value-from-string_array_del_value.patch new file mode 100644 index 0000000..7112b92 --- /dev/null +++ b/SOURCES/0032-util-do-not-return-value-from-string_array_del_value.patch @@ -0,0 +1,150 @@ +From 67b5d7778cad682bf8046973900caf2fa3353d0e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 28 Nov 2018 13:59:51 +0100 +Subject: [PATCH 14/15] util: do not return value from string_array_del_value + +It is not needed. +--- + src/lib/authselect.c | 9 ++------- + src/lib/util/string_array.c | 6 +++--- + src/lib/util/string_array.h | 2 +- + src/tests/test_util_string_array.c | 28 ++++++++-------------------- + 4 files changed, 14 insertions(+), 31 deletions(-) + +diff --git a/src/lib/authselect.c b/src/lib/authselect.c +index e0b8b1246b0e7139494d90cca4e0ebed3eb66376..0f8d4a8b6d0b0faef81daf176486108ed0ea74db 100644 +--- a/src/lib/authselect.c ++++ b/src/lib/authselect.c +@@ -179,7 +179,7 @@ authselect_apply_changes(void) + WARN("Profile feature [%s] is no longer supported, removing it...", + features[i]); + +- features = string_array_del_value(features, features[i]); ++ string_array_del_value(features, features[i]); + i--; + } + +@@ -247,15 +247,10 @@ authselect_feature_disable(const char *feature) + return ret; + } + +- features = string_array_del_value(features, feature); +- if (features == NULL) { +- ret = ENOMEM; +- goto done; +- } ++ string_array_del_value(features, feature); + + ret = authselect_activate(profile_id, (const char **)features, false); + +-done: + string_array_free(features); + free(profile_id); + +diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c +index a8afa5ab8edbb26d6f946619f9ce0b83c511bb8c..e8871dc067fbf3d461d1ee9579813ddc81eef676 100644 +--- a/src/lib/util/string_array.c ++++ b/src/lib/util/string_array.c +@@ -137,7 +137,7 @@ string_array_add_value(char **array, const char *value, bool unique) + return string_array_add_value_safe(array, value, strlen(value), unique); + } + +-char ** ++void + string_array_del_value(char **array, const char *value) + { + size_t count; +@@ -145,7 +145,7 @@ string_array_del_value(char **array, const char *value) + size_t i; + + if (array == NULL) { +- return NULL; ++ return; + } + + count = string_array_count(array); +@@ -167,7 +167,7 @@ string_array_del_value(char **array, const char *value) + array[pos] = NULL; + } + +- return array; ++ return; + } + + char ** +diff --git a/src/lib/util/string_array.h b/src/lib/util/string_array.h +index ba9760b5d66a9619ca8edea5e3418c5cfbbec929..5842db174563982528e20354138ef5792346fb37 100644 +--- a/src/lib/util/string_array.h ++++ b/src/lib/util/string_array.h +@@ -115,7 +115,7 @@ string_array_add_value(char **array, const char *value, bool unique); + * + * @return Array without the value. + */ +-char ** ++void + string_array_del_value(char **array, const char *value); + + /** +diff --git a/src/tests/test_util_string_array.c b/src/tests/test_util_string_array.c +index 249cb96acea3c4feac910702572cafb1025d9496..ad76f8b190b823210b5e30ae828dce6518596e3b 100644 +--- a/src/tests/test_util_string_array.c ++++ b/src/tests/test_util_string_array.c +@@ -51,8 +51,7 @@ void test_string_array_del_value__single(void **state) + assert_null(array[i]); + + /* Delete value. */ +- array = string_array_del_value(array, "2"); +- assert_non_null(array); ++ string_array_del_value(array, "2"); + + /* Test values. */ + for (i = 0; expected[i] != NULL; i++) { +@@ -83,8 +82,7 @@ void test_string_array_del_value__single_repeated(void **state) + assert_null(array[i]); + + /* Delete value. */ +- array = string_array_del_value(array, "2"); +- assert_non_null(array); ++ string_array_del_value(array, "2"); + + /* Test values. */ + for (i = 0; expected[i] != NULL; i++) { +@@ -115,14 +113,9 @@ void test_string_array_del_value__multiple(void **state) + assert_null(array[i]); + + /* Delete value. */ +- array = string_array_del_value(array, "2"); +- assert_non_null(array); +- +- array = string_array_del_value(array, "3"); +- assert_non_null(array); +- +- array = string_array_del_value(array, "5"); +- assert_non_null(array); ++ string_array_del_value(array, "2"); ++ string_array_del_value(array, "3"); ++ string_array_del_value(array, "5"); + + /* Test values. */ + for (i = 0; expected[i] != NULL; i++) { +@@ -153,14 +146,9 @@ void test_string_array_del_value__multiple_repeated(void **state) + assert_null(array[i]); + + /* Delete value. */ +- array = string_array_del_value(array, "2"); +- assert_non_null(array); +- +- array = string_array_del_value(array, "3"); +- assert_non_null(array); +- +- array = string_array_del_value(array, "5"); +- assert_non_null(array); ++ string_array_del_value(array, "2"); ++ string_array_del_value(array, "3"); ++ string_array_del_value(array, "5"); + + /* Test values. */ + for (i = 0; expected[i] != NULL; i++) { +-- +2.17.2 + diff --git a/SOURCES/0033-util-fix-buffer-error-in-textfile_copy.patch b/SOURCES/0033-util-fix-buffer-error-in-textfile_copy.patch new file mode 100644 index 0000000..55606b3 --- /dev/null +++ b/SOURCES/0033-util-fix-buffer-error-in-textfile_copy.patch @@ -0,0 +1,27 @@ +From b2c0ab76560757296ce387f6ff2c43c983e8961d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 30 Nov 2018 11:51:38 +0100 +Subject: [PATCH 15/15] util: fix buffer error in textfile_copy() + +Resolves: +https://github.com/pbrezina/authselect/issues/123 +--- + src/lib/util/textfile.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/util/textfile.c b/src/lib/util/textfile.c +index 7ee5df677b519f2433d9dfa235ad72551f7ded67..3394042eaf0db9508675cbd0aedc0cc13ea6546c 100644 +--- a/src/lib/util/textfile.c ++++ b/src/lib/util/textfile.c +@@ -249,7 +249,7 @@ textfile_copy(const char *source, + /* eof not error */ + } + +- bytes_written = fwrite(buf, sizeof(char), sizeof(buf), fdest); ++ bytes_written = fwrite(buf, sizeof(char), bytes_read, fdest); + if (bytes_written != bytes_read) { + if (ferror(fdest) != 0) { + ret = EIO; +-- +2.17.2 + diff --git a/SOURCES/0034-lib-fix-coverity-warnings.patch b/SOURCES/0034-lib-fix-coverity-warnings.patch new file mode 100644 index 0000000..fcba163 --- /dev/null +++ b/SOURCES/0034-lib-fix-coverity-warnings.patch @@ -0,0 +1,73 @@ +From d770acde179d2cb2a9318f36405433737065169a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 4 Dec 2018 11:09:04 +0100 +Subject: [PATCH] lib: fix coverity warnings + +Resolves: +https://github.com/pbrezina/authselect/issues/126 +--- + src/lib/authselect.c | 2 +- + src/lib/util/string.c | 2 ++ + src/lib/util/string_array.c | 2 +- + src/lib/util/template.c | 4 ++-- + 4 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/lib/authselect.c b/src/lib/authselect.c +index 0f8d4a8b6d0b0faef81daf176486108ed0ea74db..ce34d2a44d1a59cb574331733929d551c5aec075 100644 +--- a/src/lib/authselect.c ++++ b/src/lib/authselect.c +@@ -146,9 +146,9 @@ _PUBLIC_ int + authselect_apply_changes(void) + { + struct authselect_profile *profile; ++ char **supported = NULL; + char *profile_id; + char **features; +- char **supported; + errno_t ret; + int i; + +diff --git a/src/lib/util/string.c b/src/lib/util/string.c +index e6803bcd4e41adc05eaa623089009b17ccd4f49b..0f3936681c6c8af1be940f92a21dfc15dafe4e42 100644 +--- a/src/lib/util/string.c ++++ b/src/lib/util/string.c +@@ -353,6 +353,8 @@ string_levenshtein(const char *a, const char *b) + unsigned int old_diag; + unsigned int column[len_a + 1]; + ++ memset(column, 0, (len_a + 1) * sizeof(unsigned int)); ++ + for (y = 1; y <= len_a; y++) { + column[y] = y; + } +diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c +index e8871dc067fbf3d461d1ee9579813ddc81eef676..dcf667e2e6e0c918a0c4eacad2486fdc182d8cf6 100644 +--- a/src/lib/util/string_array.c ++++ b/src/lib/util/string_array.c +@@ -228,7 +228,7 @@ string_array_find_similar(const char *value, char **array, int max_distance) + } + } + +- if (best > max_distance) { ++ if (word == NULL || best > max_distance) { + return NULL; + } + +diff --git a/src/lib/util/template.c b/src/lib/util/template.c +index fb373c0fd83e04c6c78d5f57d3d8e50e54c0377b..0eedd2b04146f201a5c37f45c1d08f01c079d61f 100644 +--- a/src/lib/util/template.c ++++ b/src/lib/util/template.c +@@ -130,8 +130,8 @@ template_match_get_values(const char *match_string, + char **_if_true, + char **_if_false) + { +- regmatch_t *m_true; +- regmatch_t *m_false; ++ regmatch_t *m_true = NULL; ++ regmatch_t *m_false = NULL; + char *if_true; + char *if_false; + +-- +2.17.2 + diff --git a/SOURCES/0035-lib-label-temporary-files-with-correct-selinux-conte.patch b/SOURCES/0035-lib-label-temporary-files-with-correct-selinux-conte.patch new file mode 100644 index 0000000..8738540 --- /dev/null +++ b/SOURCES/0035-lib-label-temporary-files-with-correct-selinux-conte.patch @@ -0,0 +1,350 @@ +From 721aa7e45ba56530c571743de4762605560f90cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 10 Jan 2019 13:26:49 +0100 +Subject: [PATCH] lib: label temporary files with correct selinux context + +Resolves: +https://github.com/pbrezina/authselect/issues/128 +--- + configure.ac | 1 + + rpm/authselect.spec.in | 1 + + src/build_macros.m4 | 13 +++ + src/lib/Makefile.am | 3 + + src/lib/util/selinux.c | 143 +++++++++++++++++++++++++++++ + src/lib/util/{util.h => selinux.h} | 37 +++++--- + src/lib/util/template.c | 16 +--- + src/lib/util/util.h | 1 + + 8 files changed, 192 insertions(+), 23 deletions(-) + create mode 100644 src/lib/util/selinux.c + copy src/lib/util/{util.h => selinux.h} (50%) + +diff --git a/configure.ac b/configure.ac +index 0ddb875439133d10a9ece8b92a2df1719065d349..667d41c1f67264850fd9e175598214d751078a7e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -37,6 +37,7 @@ m4_include(external/po4a.m4) + dnl Required libraries + REQUIRE_POPT + REQUIRE_CMOCKA ++REQUIRE_SELINUX + + dnl Optional build dependencies - man pages generation + CHECK_ASCIIDOC_TOOLS +diff --git a/rpm/authselect.spec.in b/rpm/authselect.spec.in +index c56ad4e2e0e23c902471fbacdb8bc3742bd8fa2d..f47c77ac3768ccf9c049c9ba512209fad059e418 100644 +--- a/rpm/authselect.spec.in ++++ b/rpm/authselect.spec.in +@@ -24,6 +24,7 @@ BuildRequires: gettext-devel + BuildRequires: po4a + BuildRequires: %{_bindir}/a2x + BuildRequires: libcmocka-devel >= 1.0.0 ++BuildRequires: libselinux-devel + Requires: authselect-libs%{?_isa} = %{version}-%{release} + Suggests: sssd + Suggests: samba-winbind +diff --git a/src/build_macros.m4 b/src/build_macros.m4 +index 5da871ec8cadfa200630420b5fe932d8af0473a3..dfedd47fd84c7201cfad30621761a3c1c564bc18 100644 +--- a/src/build_macros.m4 ++++ b/src/build_macros.m4 +@@ -28,3 +28,16 @@ AC_DEFUN([REQUIRE_CMOCKA], + ) + AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes]) + ]) ++ ++AC_DEFUN([REQUIRE_SELINUX], ++[ ++ AC_CHECK_HEADERS(selinux/selinux.h, ++ [AC_CHECK_LIB(selinux, is_selinux_enabled, ++ [SELINUX_LIBS="-lselinux"], ++ [AC_MSG_ERROR([SELinux library is missing])] ++ )], ++ [AC_MSG_ERROR([SELinux headers are missing])] ++ ) ++ AC_SUBST(SELINUX_LIBS) ++]) ++ +diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am +index 2726062c421f7836ebc69fbbc0f5410cf3d19803..6c1191c702efbf52d45c7204311e4e9d1e64de3b 100644 +--- a/src/lib/Makefile.am ++++ b/src/lib/Makefile.am +@@ -15,6 +15,7 @@ noinst_HEADERS = \ + files/files.h \ + profiles/profiles.h \ + util/file.h \ ++ util/selinux.h \ + util/string_array.h \ + util/string.h \ + util/template.h \ +@@ -55,6 +56,7 @@ libauthselect_la_SOURCES = \ + profiles/list.c \ + profiles/read.c \ + util/file.c \ ++ util/selinux.c \ + util/string_array.c \ + util/string.c \ + util/template.c \ +@@ -62,6 +64,7 @@ libauthselect_la_SOURCES = \ + $(NULL) + libauthselect_la_LIBADD = \ + $(top_builddir)/src/common/libcommon.la \ ++ $(SELINUX_LIBS) \ + $(NULL) + libauthselect_la_CFLAGS = \ + $(AM_CFLAGS) \ +diff --git a/src/lib/util/selinux.c b/src/lib/util/selinux.c +new file mode 100644 +index 0000000000000000000000000000000000000000..05c8d7b19b13e1eff6086faa58657c3e41a44cc0 +--- /dev/null ++++ b/src/lib/util/selinux.c +@@ -0,0 +1,143 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ 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 ++#include ++#include ++#include ++ ++#include "common/common.h" ++ ++errno_t ++selinux_get_default_context(const char *path, ++ char **_context) ++{ ++ struct selabel_handle *handle; ++ char *context; ++ errno_t ret; ++ ++ handle = selabel_open(SELABEL_CTX_FILE, NULL, 0); ++ if (handle == NULL) { ++ ret = errno; ++ ERROR("Unable to create selable context [%d]: %s", ret, strerror(ret)); ++ return ret; ++ } ++ ++ ret = selabel_lookup(handle, &context, path, 0); ++ if (ret != 0) { ++ ret = errno; ++ if (ret == ENOENT) { ++ return ENOENT; ++ } ++ ++ ERROR("Unable to lookup selinux context [%d]: %s", ret, strerror(ret)); ++ } else { ++ *_context = context; ++ ret = EOK; ++ } ++ ++ selabel_close(handle); ++ ++ return ret; ++} ++ ++errno_t ++selinux_mkstemp_of(const char *filepath, ++ char **_tmpfile) ++{ ++ char *original_context = NULL; ++ char *default_context = NULL; ++ char *tmpfile = NULL; ++ errno_t ret; ++ int seret; ++ int fd; ++ ++ seret = getfscreatecon(&original_context); ++ if (seret != 0) { ++ ERROR("Unable to get current fscreate selinux context!"); ++ return EIO; ++ } ++ ++ tmpfile = format("%s.XXXXXX", filepath); ++ if (tmpfile == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = selinux_get_default_context(filepath, &default_context); ++ if (ret == ENOENT) { ++ default_context = NULL; ++ } else if (ret != EOK) { ++ ERROR("Unable to get default selinux context for [%s] [%d]: %s!", ++ filepath, ret, strerror(ret)); ++ goto done; ++ } ++ ++ seret = setfscreatecon(default_context); ++ if (seret != 0) { ++ ERROR("Unable to set fscreate selinux context!"); ++ ret = EIO; ++ goto done; ++ } ++ ++ fd = mkstemp(tmpfile); ++ if (fd == -1) { ++ ret = errno; ++ ++ seret = setfscreatecon(original_context); ++ if (seret != 0) { ++ ERROR("Unable to restore fscreate selinux context!"); ++ ret = EIO; ++ goto done; ++ } ++ ++ goto done; ++ } ++ ++ close(fd); ++ ++ seret = setfscreatecon(original_context); ++ if (seret != 0) { ++ ERROR("Unable to restore fscreate selinux context!"); ++ ret = EIO; ++ goto done; ++ } ++ ++ *_tmpfile = tmpfile; ++ ++ ret = EOK; ++ ++done: ++ if (original_context != NULL) { ++ freecon(original_context); ++ } ++ ++ if (default_context != NULL) { ++ freecon(default_context); ++ } ++ ++ if (ret != EOK) { ++ free(tmpfile); ++ } ++ ++ return ret; ++} +diff --git a/src/lib/util/util.h b/src/lib/util/selinux.h +similarity index 50% +copy from src/lib/util/util.h +copy to src/lib/util/selinux.h +index b81990722d62ccf466c0687454c82ea3ee171436..26f2374140562dd085145845ed3092a0ddcf924e 100644 +--- a/src/lib/util/util.h ++++ b/src/lib/util/selinux.h +@@ -18,20 +18,33 @@ + along with this program. If not, see . + */ + +-#ifndef _UTIL_H_ +-#define _UTIL_H_ ++#ifndef _SELINUX_H_ ++#define _SELINUX_H_ ++ ++#include "common/errno_t.h" + + /** +- * Many of the utility functions are not as effective as they can be but +- * this is OK since authselect works only with small configuration files +- * therefore we can prefer clean and simple code over performance. ++ * Get default security context for @path. ++ * ++ * @param path Path to the file. ++ * ++ * @return EOK on success, ENOENT if context was not found, other errno code ++ * is returned on failure. + */ ++errno_t ++selinux_get_default_context(const char *path); + +-#include "common/common.h" +-#include "lib/util/file.h" +-#include "lib/util/string.h" +-#include "lib/util/string_array.h" +-#include "lib/util/template.h" +-#include "lib/util/textfile.h" ++/** ++ * Create temporary file created on @filepath.XXXXXX with security context ++ * set to default security context of @filepath. ++ * ++ * @param filepath File for which a temporary file should be created. ++ * @param _tmpfile Create temporary file. ++ * ++ * @return EOK on success, other errno code on failure. ++ */ ++errno_t ++selinux_mkstemp_of(const char *filepath, ++ char **_tmpfile); + +-#endif /* _UTIL_H_ */ ++#endif /* _SELINUX_H_ */ +diff --git a/src/lib/util/template.c b/src/lib/util/template.c +index 0eedd2b04146f201a5c37f45c1d08f01c079d61f..9773dcbf1ecbde4fe2408f1b816dce129747806f 100644 +--- a/src/lib/util/template.c ++++ b/src/lib/util/template.c +@@ -27,6 +27,7 @@ + #include "common/common.h" + #include "lib/util/template.h" + #include "lib/util/textfile.h" ++#include "lib/util/selinux.h" + #include "lib/util/string.h" + #include "lib/util/string_array.h" + +@@ -594,23 +595,16 @@ template_write_temporary(const char *filepath, + mode_t oldmask; + char *tmpfile; + errno_t ret; +- int fd; +- +- tmpfile = format("%s.XXXXXX", filepath); +- if (tmpfile == NULL) { +- return ENOMEM; +- } + + oldmask = umask(mode); + +- fd = mkstemp(tmpfile);; +- if (fd == -1) { +- ret = errno; ++ ret = selinux_mkstemp_of(filepath, &tmpfile); ++ if (ret != EOK) { ++ ERROR("Unable to create temporary file for [%s] [%d]: %s", ++ filepath, ret, strerror(ret)); + goto done; + } + +- close(fd); +- + ret = template_write(tmpfile, content, mode); + if (ret != EOK) { + goto done; +diff --git a/src/lib/util/util.h b/src/lib/util/util.h +index b81990722d62ccf466c0687454c82ea3ee171436..e75afaef316fc8f8fd4d2aabbab7be1aa24e9ac7 100644 +--- a/src/lib/util/util.h ++++ b/src/lib/util/util.h +@@ -29,6 +29,7 @@ + + #include "common/common.h" + #include "lib/util/file.h" ++#include "lib/util/selinux.h" + #include "lib/util/string.h" + #include "lib/util/string_array.h" + #include "lib/util/template.h" +-- +2.17.2 + diff --git a/SOURCES/0036-authselect-fix-memory-leak-of-maps.patch b/SOURCES/0036-authselect-fix-memory-leak-of-maps.patch new file mode 100644 index 0000000..bf653d5 --- /dev/null +++ b/SOURCES/0036-authselect-fix-memory-leak-of-maps.patch @@ -0,0 +1,24 @@ +From 196b795ec659da30e6f59446227886062d29fe1a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 10 Oct 2018 14:38:24 +0200 +Subject: [PATCH 01/21] authselect: fix memory leak of maps + +--- + src/cli/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/cli/main.c b/src/cli/main.c +index 6179af6af5d727328c2dd452363035130ac82dd4..9d60db3da6f483bc42233341a1a01d0013a6a809 100644 +--- a/src/cli/main.c ++++ b/src/cli/main.c +@@ -186,6 +186,7 @@ static errno_t activate(struct cli_cmdline *cmdline) + + done: + free(requirements); ++ authselect_array_free(maps); + authselect_profile_free(profile); + if (features != NULL) { + free(features); +-- +2.17.2 + diff --git a/SOURCES/0037-lib-make-selinux-functions-work-with-selinux-disable.patch b/SOURCES/0037-lib-make-selinux-functions-work-with-selinux-disable.patch new file mode 100644 index 0000000..4a50d0b --- /dev/null +++ b/SOURCES/0037-lib-make-selinux-functions-work-with-selinux-disable.patch @@ -0,0 +1,267 @@ +From 29add823913b66e0637d27d962ad5c5f9c85de70 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 28 Jan 2019 12:13:54 +0100 +Subject: [PATCH] lib: make selinux functions work with selinux disabled + +Resolves: +https://github.com/pbrezina/authselect/issues/133 +--- + src/lib/util/file.c | 38 +++++++++++++++++++++++++++++++++ + src/lib/util/file.h | 13 +++++++++++- + src/lib/util/selinux.c | 47 ++++++++++++++++------------------------- + src/lib/util/selinux.h | 8 ++++--- + src/lib/util/template.c | 23 ++++++-------------- + 5 files changed, 79 insertions(+), 50 deletions(-) + +diff --git a/src/lib/util/file.c b/src/lib/util/file.c +index fa231f771a7d0cdd449b69c4bf7b00d93aefc375..2e23ce39ec04e6aaf79f16410f9ac08dc3f9d54c 100644 +--- a/src/lib/util/file.c ++++ b/src/lib/util/file.c +@@ -329,3 +329,41 @@ file_make_path(const char *path, mode_t mode) + return EOK; + + } ++ ++errno_t ++file_mktmp_for(const char *path, mode_t mode, char **_tmpfile) ++{ ++ mode_t oldmask; ++ char *tmpfile; ++ errno_t ret; ++ int fd; ++ ++ oldmask = umask(mode); ++ ++ tmpfile = format("%s.XXXXXX", path); ++ if (tmpfile == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ fd = mkstemp(tmpfile); ++ if (fd == -1) { ++ ret = errno; ++ goto done; ++ } ++ ++ close(fd); ++ ++ *_tmpfile = tmpfile; ++ ++ ret = EOK; ++ ++done: ++ if (ret != EOK) { ++ free(tmpfile); ++ } ++ ++ umask(oldmask); ++ ++ return ret; ++} +diff --git a/src/lib/util/file.h b/src/lib/util/file.h +index 49ebef37443bf137439bad27fd75283c25c9c3e5..6d5823791bfcc581304200d0c2d37b41c3d7b95d 100644 +--- a/src/lib/util/file.h ++++ b/src/lib/util/file.h +@@ -133,7 +133,7 @@ file_get_parent_directory(const char *filepath); + /** + * Create all directories in a path. Path must end with a directory not a file. + * +- * @param filename Path to the file whose directories should be created. ++ * @param path Path to the file whose directories should be created. + * @param mode Directory mode. + * + * @return EOK on success, other errno code on error. +@@ -141,4 +141,15 @@ file_get_parent_directory(const char *filepath); + errno_t + file_make_path(const char *path, mode_t mode); + ++/** ++ * Make temporary file for @path so it can be first written and then safelly ++ * renamed to @path. ++ * ++ * @param path Path to the file whose directories should be created. ++ * @param mode Temporary file mode. ++ * @param _tmpfile Path to created temporary file. ++ */ ++errno_t ++file_mktmp_for(const char *path, mode_t mode, char **_tmpfile); ++ + #endif /* _FILE_H_ */ +diff --git a/src/lib/util/selinux.c b/src/lib/util/selinux.c +index 9b0e0ff26b768d88f67a42985c5d5bafb8aa58ec..01b68087b265c0ef1c1087f626df8e20de086338 100644 +--- a/src/lib/util/selinux.c ++++ b/src/lib/util/selinux.c +@@ -26,6 +26,7 @@ + #include + + #include "common/common.h" ++#include "lib/util/file.h" + + errno_t + selinux_get_default_context(const char *path, +@@ -61,15 +62,19 @@ selinux_get_default_context(const char *path, + } + + errno_t +-selinux_mkstemp_of(const char *filepath, +- char **_tmpfile) ++selinux_mkstemp_for(const char *filepath, ++ mode_t mode, ++ char **_tmpfile) + { + char *original_context = NULL; + char *default_context = NULL; +- char *tmpfile = NULL; ++ char *tmpfile; + errno_t ret; + int seret; +- int fd; ++ ++ if (is_selinux_enabled() != 1) { ++ return file_mktmp_for(filepath, mode, _tmpfile); ++ } + + seret = getfscreatecon(&original_context); + if (seret != 0) { +@@ -77,12 +82,6 @@ selinux_mkstemp_of(const char *filepath, + return EIO; + } + +- tmpfile = format("%s.XXXXXX", filepath); +- if (tmpfile == NULL) { +- ret = ENOMEM; +- goto done; +- } +- + ret = selinux_get_default_context(filepath, &default_context); + if (ret == ENOENT) { + default_context = NULL; +@@ -92,6 +91,7 @@ selinux_mkstemp_of(const char *filepath, + goto done; + } + ++ /* Set desired fs create context. */ + seret = setfscreatecon(default_context); + if (seret != 0) { + ERROR("Unable to set fscreate selinux context!"); +@@ -99,22 +99,9 @@ selinux_mkstemp_of(const char *filepath, + goto done; + } + +- fd = mkstemp(tmpfile); +- if (fd == -1) { +- ret = errno; +- +- seret = setfscreatecon(original_context); +- if (seret != 0) { +- ERROR("Unable to restore fscreate selinux context!"); +- ret = EIO; +- goto done; +- } +- +- goto done; +- } +- +- close(fd); ++ ret = file_mktmp_for(filepath, mode, &tmpfile); + ++ /* Restore original fs create context. */ + seret = setfscreatecon(original_context); + if (seret != 0) { + ERROR("Unable to restore fscreate selinux context!"); +@@ -122,6 +109,12 @@ selinux_mkstemp_of(const char *filepath, + goto done; + } + ++ /* Check result of file_mktmp_for() */ ++ if (ret != EOK) { ++ free(tmpfile); ++ goto done; ++ } ++ + *_tmpfile = tmpfile; + + ret = EOK; +@@ -135,9 +128,5 @@ done: + freecon(default_context); + } + +- if (ret != EOK) { +- free(tmpfile); +- } +- + return ret; + } +diff --git a/src/lib/util/selinux.h b/src/lib/util/selinux.h +index 26f2374140562dd085145845ed3092a0ddcf924e..8abfb3fb5d244b32570cc9e573b2e12df14177e1 100644 +--- a/src/lib/util/selinux.h ++++ b/src/lib/util/selinux.h +@@ -39,12 +39,14 @@ selinux_get_default_context(const char *path); + * set to default security context of @filepath. + * + * @param filepath File for which a temporary file should be created. +- * @param _tmpfile Create temporary file. ++ * @param mode Temporary file mode. ++ * @param _tmpfile Created temporary file. + * + * @return EOK on success, other errno code on failure. + */ + errno_t +-selinux_mkstemp_of(const char *filepath, +- char **_tmpfile); ++selinux_mkstemp_for(const char *filepath, ++ mode_t mode, ++ char **_tmpfile); + + #endif /* _SELINUX_H_ */ +diff --git a/src/lib/util/template.c b/src/lib/util/template.c +index 9773dcbf1ecbde4fe2408f1b816dce129747806f..1f3464912d8fe7afe8a7f0920fe31eb5c2dfaba5 100644 +--- a/src/lib/util/template.c ++++ b/src/lib/util/template.c +@@ -592,36 +592,25 @@ template_write_temporary(const char *filepath, + mode_t mode, + char **_tmpfile) + { +- mode_t oldmask; + char *tmpfile; + errno_t ret; + +- oldmask = umask(mode); +- +- ret = selinux_mkstemp_of(filepath, &tmpfile); ++ ret = selinux_mkstemp_for(filepath, mode, &tmpfile); + if (ret != EOK) { + ERROR("Unable to create temporary file for [%s] [%d]: %s", + filepath, ret, strerror(ret)); +- goto done; ++ return ret; + } + + ret = template_write(tmpfile, content, mode); +- if (ret != EOK) { +- goto done; +- } +- +- *_tmpfile = tmpfile; +- +- ret = EOK; +- +-done: +- umask(oldmask); +- + if (ret != EOK) { + free(tmpfile); ++ return ret; + } + +- return ret; ++ *_tmpfile = tmpfile; ++ ++ return EOK; + } + + bool +-- +2.17.2 + diff --git a/SOURCES/0038-sssd-require-smartcard-only-for-specific-services.patch b/SOURCES/0038-sssd-require-smartcard-only-for-specific-services.patch new file mode 100644 index 0000000..535881f --- /dev/null +++ b/SOURCES/0038-sssd-require-smartcard-only-for-specific-services.patch @@ -0,0 +1,29 @@ +From c7f20a9d79ef8e9a681994b27554dcd5df1d36c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 4 Feb 2019 12:38:39 +0100 +Subject: [PATCH 2/3] sssd: require smartcard only for specific services + +Otherwise even services like su or sudo can not perform password authentication +which is not desired. + +Resolves: +https://github.com/pbrezina/authselect/issues/134 +--- + profiles/sssd/system-auth | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/profiles/sssd/system-auth b/profiles/sssd/system-auth +index 22dba5b2d3db23855724ddb05528e5013c63c5af..c21d18ec855978d4f10abc3f1f95ac1cfb563d58 100644 +--- a/profiles/sssd/system-auth ++++ b/profiles/sssd/system-auth +@@ -1,6 +1,7 @@ + auth required pam_env.so + auth required pam_faildelay.so delay=2000000 + auth required pam_faillock.so preauth silent deny=4 unlock_time=1200 {include if "with-faillock"} ++auth [success=1 default=ignore] pam_succeed_if.so service notin login:gdm:xdm:kdm:xscreensaver:gnome-screensaver:kscreensaver quiet use_uid {include if "with-smartcard-required"} + auth [success=done ignore=ignore default=die] pam_sss.so require_cert_auth ignore_authinfo_unavail {include if "with-smartcard-required"} + auth sufficient pam_fprintd.so {include if "with-fingerprint"} + auth [default=1 ignore=ignore success=ok] pam_succeed_if.so uid >= 1000 quiet +-- +2.17.2 + diff --git a/SOURCES/0039-Revert-profiles-make-session-pam_systemd-required.patch b/SOURCES/0039-Revert-profiles-make-session-pam_systemd-required.patch new file mode 100644 index 0000000..0bb7b93 --- /dev/null +++ b/SOURCES/0039-Revert-profiles-make-session-pam_systemd-required.patch @@ -0,0 +1,152 @@ +From a21f75d8194df780f83aff0f36d270f56af7f182 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 25 Feb 2019 21:48:18 +0100 +Subject: [PATCH] Revert "profiles: make session pam_systemd required" + +This reverts commit 297f48d60dd9fe4ba3fd2bdd1bdd5276ffa557d6. +--- + profiles/nis/fingerprint-auth | 2 +- + profiles/nis/password-auth | 2 +- + profiles/nis/system-auth | 2 +- + profiles/sssd/fingerprint-auth | 2 +- + profiles/sssd/password-auth | 2 +- + profiles/sssd/smartcard-auth | 2 +- + profiles/sssd/system-auth | 2 +- + profiles/winbind/fingerprint-auth | 2 +- + profiles/winbind/password-auth | 2 +- + profiles/winbind/system-auth | 2 +- + 10 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/profiles/nis/fingerprint-auth b/profiles/nis/fingerprint-auth +index dc9e53b..278487b 100644 +--- a/profiles/nis/fingerprint-auth ++++ b/profiles/nis/fingerprint-auth +@@ -17,7 +17,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/nis/password-auth b/profiles/nis/password-auth +index 60781bb..2ce77fd 100644 +--- a/profiles/nis/password-auth ++++ b/profiles/nis/password-auth +@@ -22,7 +22,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/nis/system-auth b/profiles/nis/system-auth +index 3edbf34..d1f270a 100644 +--- a/profiles/nis/system-auth ++++ b/profiles/nis/system-auth +@@ -23,7 +23,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/fingerprint-auth b/profiles/sssd/fingerprint-auth +index 3bdaf3e..01b70f3 100644 +--- a/profiles/sssd/fingerprint-auth ++++ b/profiles/sssd/fingerprint-auth +@@ -19,7 +19,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/password-auth b/profiles/sssd/password-auth +index fbd6647..c61630d 100644 +--- a/profiles/sssd/password-auth ++++ b/profiles/sssd/password-auth +@@ -28,7 +28,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/smartcard-auth b/profiles/sssd/smartcard-auth +index 5ec5e1d..82e82cc 100644 +--- a/profiles/sssd/smartcard-auth ++++ b/profiles/sssd/smartcard-auth +@@ -16,7 +16,7 @@ account required pam_permit.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/sssd/system-auth b/profiles/sssd/system-auth +index 2879592..d70c7da 100644 +--- a/profiles/sssd/system-auth ++++ b/profiles/sssd/system-auth +@@ -32,7 +32,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/winbind/fingerprint-auth b/profiles/winbind/fingerprint-auth +index 9264946..0beff74 100644 +--- a/profiles/winbind/fingerprint-auth ++++ b/profiles/winbind/fingerprint-auth +@@ -18,7 +18,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/winbind/password-auth b/profiles/winbind/password-auth +index b694bed..455add4 100644 +--- a/profiles/winbind/password-auth ++++ b/profiles/winbind/password-auth +@@ -25,7 +25,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +diff --git a/profiles/winbind/system-auth b/profiles/winbind/system-auth +index 88e1c07..5b383f7 100644 +--- a/profiles/winbind/system-auth ++++ b/profiles/winbind/system-auth +@@ -26,7 +26,7 @@ password required pam_deny.so + session optional pam_keyinit.so revoke + session required pam_limits.so + session optional pam_ecryptfs.so unwrap {include if "with-ecryptfs"} +-session required pam_systemd.so ++-session optional pam_systemd.so + session optional pam_oddjob_mkhomedir.so umask=0077 {include if "with-mkhomedir"} + session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid + session required pam_unix.so +-- +2.19.2 + diff --git a/SOURCES/0901-rhel8-remove-mention-of-Fedora-Change-page-in-compat.patch b/SOURCES/0901-rhel8-remove-mention-of-Fedora-Change-page-in-compat.patch new file mode 100644 index 0000000..c2bc01b --- /dev/null +++ b/SOURCES/0901-rhel8-remove-mention-of-Fedora-Change-page-in-compat.patch @@ -0,0 +1,24 @@ +From 009be0fc33866a590de8720cb0f3dab811e10059 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 30 Oct 2018 14:08:12 +0100 +Subject: [PATCH] rhel8: remove mention of Fedora Change page in compat tool + +--- + src/compat/authcompat.py.in.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in +index 0be644222a44185cb08ff696afad5adf05995093..42cc6f3c0e38d8e14d62bd5acdc171176a6cb51f 100755 +--- a/src/compat/authcompat.py.in.in ++++ b/src/compat/authcompat.py.in.in +@@ -469,7 +469,6 @@ class AuthCompat: + "It does not provide all capabilities of authconfig.\n")) + print(_("IMPORTANT: authconfig is replaced by authselect, " + "please update your scripts.")) +- print(_("See Fedora 28 Change Page: https://fedoraproject.org/wiki/Changes/AuthselectAsDefault")) + print(_("See man authselect-migration(7) to help you with migration to authselect")) + + options = self.options.getSetButUnsupported() +-- +2.17.2 + diff --git a/SPECS/authselect.spec b/SPECS/authselect.spec new file mode 100644 index 0000000..6482129 --- /dev/null +++ b/SPECS/authselect.spec @@ -0,0 +1,388 @@ +Name: authselect +Version: 1.0 +Release: 13%{?dist} +Summary: Configures authentication and identity sources from supported profiles +URL: https://github.com/pbrezina/authselect + +License: GPLv3+ +Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz +%if 0%{?rhel} +Source1: translations-1.0-12.tar.gz +%endif + +%global makedir %{_builddir}/%{name}-%{version} + +Patch0001: 0001-lib-fix-profile-origin-debug-message.patch +Patch0002: 0002-man-remove-duplicate-of-with-pamaccess.patch +Patch0003: 0003-Don-t-write-options-without-value-to-pwquality-conf-.patch +Patch0004: 0004-compat-write-only-options-set-on-command-line-to-pwq.patch +Patch0005: 0005-compat-fix-regular-expression-for-environment-files.patch +Patch0006: 0006-compat-fix-typo-in-compat-tool-that-produces-TypeErr.patch +Patch0007: 0007-compat-use-current-configuration-unless-other-profil.patch +Patch0008: 0008-compat-do-not-disable-service-if-its-option-is-not-s.patch +Patch0009: 0009-nis-add-all-maps-supported-by-nss_nis.patch +Patch0010: 0010-nis-add-systemd-module-to-nsswitch.conf.patch +Patch0011: 0011-nis-add-nis-option-to-pam_unix-in-password-phase.patch +Patch0012: 0012-nis-with-nispwquality-will-enable-pwquality-for-nis-.patch +Patch0013: 0013-profiles-add-without-nullok.patch +Patch0014: 0014-profiles-add-options-to-exclude-lines-from-nsswitch..patch +Patch0015: 0015-compat-do-not-stop-rpcbind-only-start-it.patch +Patch0016: 0016-sssd-document-that-this-profile-can-be-used-also-wit.patch +Patch0017: 0017-sssd-add-support-for-local-users-authentication-via-.patch +Patch0018: 0018-sssd-add-with-smartcard-required-feature.patch +Patch0019: 0019-sssd-remove-with-sudo-duplicate-from-readme.patch +Patch0020: 0020-profiles-end-all-files-with-new-line.patch +Patch0021: 0021-compat-add-support-for-with-smartcard-required-enabl.patch +Patch0022: 0022-compat-support-with-smartcard-lock-on-removal-smartc.patch +Patch0023: 0023-profiles-mention-pam_oddjob_mkhomedir-in-requirement.patch +Patch0024: 0024-lib-fix-memory-leak-in-authselect_profile_free.patch +Patch0025: 0025-lib-fix-memory-leak-in-authselect_config_validate_ex.patch +Patch0026: 0026-profiles-make-session-pam_systemd-required.patch +Patch0027: 0027-lib-add-authselect_profile_features-to-list-supporte.patch +Patch0028: 0028-lib-refuse-to-activate-profile-if-unsupported-featur.patch +Patch0029: 0029-lib-remove-no-longer-supported-features-in-apply-cha.patch +Patch0030: 0030-compat-write-to-sysconfig-after-all-changes-are-done.patch +Patch0031: 0031-util-remove-duplicate-values-correctly-in-string_arr.patch +Patch0032: 0032-util-do-not-return-value-from-string_array_del_value.patch +Patch0033: 0033-util-fix-buffer-error-in-textfile_copy.patch +Patch0034: 0034-lib-fix-coverity-warnings.patch +Patch0035: 0035-lib-label-temporary-files-with-correct-selinux-conte.patch +Patch0036: 0036-authselect-fix-memory-leak-of-maps.patch +Patch0037: 0037-lib-make-selinux-functions-work-with-selinux-disable.patch +Patch0038: 0038-sssd-require-smartcard-only-for-specific-services.patch +Patch0039: 0039-Revert-profiles-make-session-pam_systemd-required.patch + +# Downstream only +Patch0901: 0901-rhel8-remove-mention-of-Fedora-Change-page-in-compat.patch + +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: findutils +BuildRequires: libtool +BuildRequires: m4 +BuildRequires: gcc +BuildRequires: pkgconfig +BuildRequires: pkgconfig(popt) +BuildRequires: gettext-devel +BuildRequires: po4a +BuildRequires: %{_bindir}/a2x +BuildRequires: libcmocka-devel >= 1.0.0 +BuildRequires: libselinux-devel +Requires: authselect-libs%{?_isa} = %{version}-%{release} +Suggests: sssd +Suggests: samba-winbind +Suggests: fprintd-pam +Suggests: oddjob-mkhomedir + +%description +Authselect is designed to be a replacement for authconfig but it takes +a different approach to configure the system. Instead of letting +the administrator build the PAM stack with a tool (which may potentially +end up with a broken configuration), it would ship several tested stacks +(profiles) that solve a use-case and are well tested and supported. +At the same time, some obsolete features of authconfig are not +supported by authselect. + +%package libs +Summary: Utility library used by the authselect tool +Requires: libselinux +# Required by scriptlets +Requires: coreutils +Requires: findutils +Requires: gawk +Requires: grep +Requires: sed +Requires: systemd + +%description libs +Common library files for authselect. This package is used by the authselect +command line tool and any other potential front-ends. + +%package compat +Summary: Tool to provide minimum backwards compatibility with authconfig +Obsoletes: authconfig < 7.0.1-6 +Provides: authconfig +BuildRequires: python3-devel +Requires: authselect%{?_isa} = %{version}-%{release} +Suggests: sssd +Suggests: realmd +Suggests: samba-winbind +Suggests: oddjob-mkhomedir +# Required by scriptlets +Requires: sed + +%description compat +This package will replace %{_sbindir}/authconfig with a tool that will +translate some of the authconfig calls into authselect calls. It provides +only minimum backward compatibility and users are encouraged to migrate +to authselect completely. + +%package devel +Summary: Development libraries and headers for authselect +Requires: authselect-libs%{?_isa} = %{version}-%{release} + +%description devel +System header files and development libraries for authselect. Useful if +you develop a front-end for the authselect library. + + +%prep +%setup -q + +for p in %patches ; do + %__patch -p1 -i $p +done + +# Install RHEL translations +# It is not possible to use wildcards here so we need to use 'find' +%if 0%{?rhel} +find "%{makedir}/po" "%{makedir}/src/man/po" -name "*.po" -delete +%__rm "%{makedir}/po/LINGUAS" +%setup -T -D -a 1 +%endif + +%build +autoreconf -if +%configure --with-pythonbin="%{__python3}" +%make_build + +%check +%make_build check + +%install +%make_install + +# Find translations +%find_lang %{name} +%find_lang %{name} %{name}.8.lang --with-man +%find_lang %{name}-migration %{name}-migration.7.lang --with-man +%find_lang %{name}-profiles %{name}-profiles.5.lang --with-man + +# We want this file to contain only manual page translations +sed -i '/LC_MESSAGES/d' %{name}.8.lang + +# Remove .la and .a files created by libtool +find $RPM_BUILD_ROOT -name "*.la" -exec rm -f {} \; +find $RPM_BUILD_ROOT -name "*.a" -exec rm -f {} \; + +%ldconfig_scriptlets libs + +%files libs -f %{name}.lang -f %{name}-profiles.5.lang +%dir %{_sysconfdir}/authselect +%dir %{_sysconfdir}/authselect/custom +%dir %{_localstatedir}/lib/authselect +%dir %{_datadir}/authselect +%dir %{_datadir}/authselect/vendor +%dir %{_datadir}/authselect/default +%dir %{_datadir}/authselect/default/nis/ +%dir %{_datadir}/authselect/default/sssd/ +%dir %{_datadir}/authselect/default/winbind/ +%{_datadir}/authselect/default/nis/dconf-db +%{_datadir}/authselect/default/nis/dconf-locks +%{_datadir}/authselect/default/nis/fingerprint-auth +%{_datadir}/authselect/default/nis/nsswitch.conf +%{_datadir}/authselect/default/nis/password-auth +%{_datadir}/authselect/default/nis/postlogin +%{_datadir}/authselect/default/nis/README +%{_datadir}/authselect/default/nis/REQUIREMENTS +%{_datadir}/authselect/default/nis/system-auth +%{_datadir}/authselect/default/sssd/dconf-db +%{_datadir}/authselect/default/sssd/dconf-locks +%{_datadir}/authselect/default/sssd/fingerprint-auth +%{_datadir}/authselect/default/sssd/nsswitch.conf +%{_datadir}/authselect/default/sssd/password-auth +%{_datadir}/authselect/default/sssd/postlogin +%{_datadir}/authselect/default/sssd/README +%{_datadir}/authselect/default/sssd/REQUIREMENTS +%{_datadir}/authselect/default/sssd/smartcard-auth +%{_datadir}/authselect/default/sssd/system-auth +%{_datadir}/authselect/default/winbind/dconf-db +%{_datadir}/authselect/default/winbind/dconf-locks +%{_datadir}/authselect/default/winbind/fingerprint-auth +%{_datadir}/authselect/default/winbind/nsswitch.conf +%{_datadir}/authselect/default/winbind/password-auth +%{_datadir}/authselect/default/winbind/postlogin +%{_datadir}/authselect/default/winbind/README +%{_datadir}/authselect/default/winbind/REQUIREMENTS +%{_datadir}/authselect/default/winbind/system-auth +%{_libdir}/libauthselect.so.* +%{_mandir}/man5/authselect-profiles.5* +%{_datadir}/doc/authselect/COPYING +%{_datadir}/doc/authselect/README.md +%license COPYING +%doc README.md + +%files compat +%{_sbindir}/authconfig +%{python3_sitelib}/authselect/ + +%files devel +%{_includedir}/authselect.h +%{_libdir}/libauthselect.so +%{_libdir}/pkgconfig/authselect.pc + +%files -f %{name}.8.lang -f %{name}-migration.7.lang +%{_bindir}/authselect +%{_mandir}/man8/authselect.8* +%{_mandir}/man7/authselect-migration.7* + +%global validfile %{_localstatedir}/lib/rpm-state/%{name}.config-valid + +%pre libs +rm -f %{validfile} +if [ $1 -gt 1 ] ; then + # Remember if the current configuration is valid + %{_bindir}/authselect check &> /dev/null + if [ $? -eq 0 ]; then + touch %{validfile} + fi +fi + +exit 0 + +%posttrans libs +# Copy nsswitch.conf to user-nsswitch.conf if it was not yet created +if [ ! -f %{_localstatedir}/lib/authselect/user-nsswitch-created ]; then + cp -n %{_sysconfdir}/nsswitch.conf %{_sysconfdir}/authselect/user-nsswitch.conf &> /dev/null + touch %{_localstatedir}/lib/authselect/user-nsswitch-created &> /dev/null + + # If we are upgrading from older version, we want to remove these comments. + sed -i '/^# Generated by authselect on .*$/{$!{ + N;N # Read also next two lines + /# Generated by authselect on .*\n# Do not modify this file manually.\n/d + }}' %{_sysconfdir}/authselect/user-nsswitch.conf &> /dev/null +fi + +# If the configuration is valid and we are upgrading from older version +# we need to create these files since they were added in 1.0. +if [ -f %{validfile} ]; then + FILES="nsswitch.conf system-auth password-auth fingerprint-auth \ + smartcard-auth postlogin dconf-db dconf-locks" + + for FILE in $FILES ; do + cp -n %{_sysconfdir}/authselect/$FILE \ + %{_localstatedir}/lib/authselect/$FILE &> /dev/null + done + + rm -f %{validfile} +fi + +# Apply any changes to profiles (validates configuration first internally) +%{_bindir}/authselect apply-changes &> /dev/null + +# Enable with-sudo feature if sssd-sudo responder is enabled. RHBZ#1582111 +CURRENT=`%{_bindir}/authselect current --raw 2> /dev/null` +if [ $? -eq 0 ]; then + PROFILE=`echo $CURRENT | awk '{print $1;}'` + + if [ $PROFILE == "sssd" ] ; then + if grep -E "services[[:blank:]]*=[[:blank:]]*.*sudo" /etc/sssd/sssd.conf &> /dev/null ; then + %{_bindir}/authselect enable-feature with-sudo &> /dev/null + elif systemctl is-active sssd-sudo.service sssd-sudo.socket --quiet || systemctl is-enabled sssd-sudo.socket --quiet ; then + %{_bindir}/authselect enable-feature with-sudo &> /dev/null + fi + fi +fi + +exit 0 + +%posttrans compat +# Fix for RHBZ#1618865 +# Remove invalid lines from pwquality.conf generated by authconfig compat tool +# - previous version could write some options without value, which is invalid +# - we delete all options without value from existing file +sed -i -E '/^\w+=$/d' %{_sysconfdir}/security/pwquality.conf.d/10-authconfig-pwquality.conf &> /dev/null +exit 0 + +%changelog +* Mon Feb 25 2019 Jakub Hrozek - 1.0-13 +- Revert pam_systemd.so to be optional +- Resolves: #rhbz1643928 - pam_systemd shouldn't be optional in system-auth + +* Mon Feb 4 2019 Pavel Březina - 1.0-12 +- make authselect work with selinux disabled (RHBZ #1668025) +- require smartcard authentication only for specific services (RHBZ #1665058) +- update translations (RHBZ #1608286) + +* Fri Jan 11 2019 Pavel Březina - 1.0-11 +- require libselinux needed by (RHBZ #1664650) + +* Fri Jan 11 2019 Pavel Březina - 1.0-10 +- invalid selinux context for files under /etc/authselect (RHBZ #1664650) + +* Tue Dec 4 2018 Pavel Březina - 1.0-9 +- fix sources for official rhel translations (RHBZ #1608286) +- fix coverity warnings for authselect enable-features should error on unknown features (RHBZ #1651637) + +* Mon Dec 3 2018 Pavel Březina - 1.0-8 +- add official rhel translations (RHBZ #1608286) + +* Mon Dec 3 2018 Pavel Březina - 1.0-7 +- pam_systemd shouldn't be optional in system-auth (RHBZ #1643928) +- compat tool: support --enablerequiresmartcard (RHBZ #1649277) +- compat tool: support --smartcardaction=0 (RHBZ #1649279) +- remove ecryptfs from authselect since it is not present in rhel8 (RHBZ #1649282) +- authselect enable-features should error on unknown features (RHBZ #1651637) + +* Wed Oct 31 2018 Pavel Březina - 1.0-6 +- Remove mention of Fedora Change page from compat tool (RHBZ #1644309) + +* Wed Oct 10 2018 Pavel Březina - 1.0-5 +- Support for "require smartcard for login option" (RHBZ #1611012) + +* Mon Oct 1 2018 Pavel Březina - 1.0-4 +- add official rhel translations (RHBZ #1608286) + +* Fri Sep 28 2018 Pavel Březina - 1.0-3 +- scriptlet can fail if coreutils is not installed (RHBZ #1630896) +- fix typo (require systemd instead of systemctl) + +* Thu Sep 27 2018 Pavel Březina - 1.0-2 +- authconfig --update overwrites current profile (RHBZ #1628492) +- authselect profile nis enhancements (RHBZ #1628493) +- scriptlet can fail if coreutils is not installed (RHBZ #1630896) +- authconfig --update --enablenis stops ypserv (RHBZ #1632567) +- compat tool generates invalid pwquality configuration (RHBZ #1628491) + +* Mon Aug 13 2018 Pavel Březina - 1.0-1 +- Rebase to 1.0 (RHBZ #1614235) + +* Wed Aug 01 2018 Charalampos Stratakis - 0.4-4 +- Rebuild for platform-python + +* Mon May 14 2018 Pavel Březina - 0.4-3 +- Disable sssd as sudo rules source with sssd profile by default (RHBZ #1573403) + +* Wed Apr 25 2018 Christian Heimes - 0.4-2 +- Don't disable oddjobd.service (RHBZ #1571844) + +* Mon Apr 9 2018 Pavel Březina - 0.4-1 +- rebasing to 0.4 + +* Tue Mar 6 2018 Pavel Březina - 0.3.2-1 +- rebasing to 0.3.2 +- authselect-compat now only suggests packages, not recommends + +* Mon Mar 5 2018 Pavel Březina - 0.3.1-1 +- rebasing to 0.3.1 + +* Tue Feb 20 2018 Igor Gnatenko - 0.3-3 +- Provide authconfig + +* Tue Feb 20 2018 Igor Gnatenko - 0.3-2 +- Properly own all appropriate directories +- Remove unneeded %%defattr +- Remove deprecated Group tag +- Make Obsoletes versioned +- Remove unneeded ldconfig scriptlets + +* Tue Feb 20 2018 Pavel Březina - 0.3-1 +- rebasing to 0.3 +* Wed Feb 07 2018 Fedora Release Engineering - 0.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild +* Wed Jan 10 2018 Pavel Březina - 0.2-2 +- fix rpmlint errors +* Wed Jan 10 2018 Pavel Březina - 0.2-1 +- rebasing to 0.2 +* Mon Jul 31 2017 Jakub Hrozek - 0.1-1 +- initial packaging