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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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 <awilliam@redhat.com>
+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 <awilliam@redhat.com>
+---
+ 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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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 <http://www.gnu.org/licenses/>.
+@@ -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", _("<descrypt|bigcrypt|md5|sha256|sha512>")),
+         Option.UnsupportedValued ("ldaploadcacert", _("<URL>")),
+-        Option.UnsupportedFeature("requiresmartcard"),
+         Option.UnsupportedValued ("smartcardmodule", _("<module>")),
+         Option.UnsupportedValued ("smbsecurity", _("<user|server|domain|ads>")),
+         Option.UnsupportedValued ("smbrealm", _("<realm>")),
+-- 
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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(&regex, 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(&regex, 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(&regex);
++    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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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 <module>
+    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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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 <pbrezina@redhat.com>
++
++    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 <http://www.gnu.org/licenses/>.
++*/
++
++#include <errno.h>
++#include <string.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <selinux/selinux.h>
++#include <selinux/label.h>
++
++#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 <http://www.gnu.org/licenses/>.
+ */
+ 
+-#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?= <pbrezina@redhat.com>
+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?= <pbrezina@redhat.com>
+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 <selinux/label.h>
+ 
+ #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?= <pbrezina@redhat.com>
+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 <jakub.hrozek@posteo.se>
+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?= <pbrezina@redhat.com>
+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 <jhrozek@redhat.com> - 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 <pbrezina@redhat.com> - 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 <pbrezina@redhat.com> - 1.0-11
+- require libselinux needed by (RHBZ #1664650)
+
+* Fri Jan 11 2019 Pavel Březina <pbrezina@redhat.com> - 1.0-10
+- invalid selinux context for files under /etc/authselect (RHBZ #1664650)
+
+* Tue Dec 4 2018 Pavel Březina <pbrezina@redhat.com> - 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 <pbrezina@redhat.com> - 1.0-8
+- add official rhel translations (RHBZ #1608286)
+
+* Mon Dec 3 2018 Pavel Březina <pbrezina@redhat.com> - 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 <pbrezina@redhat.com> - 1.0-6
+- Remove mention of Fedora Change page from compat tool (RHBZ #1644309)
+
+* Wed Oct 10 2018 Pavel Březina <pbrezina@redhat.com> - 1.0-5
+- Support for "require smartcard for login option" (RHBZ #1611012)
+
+* Mon Oct 1 2018 Pavel Březina <pbrezina@redhat.com> - 1.0-4
+- add official rhel translations (RHBZ #1608286)
+
+* Fri Sep 28 2018 Pavel Březina <pbrezina@redhat.com> - 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 <pbrezina@redhat.com> - 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 <pbrezina@redhat.com> - 1.0-1
+- Rebase to 1.0 (RHBZ #1614235)
+
+* Wed Aug 01 2018 Charalampos Stratakis <cstratak@redhat.com> - 0.4-4
+- Rebuild for platform-python
+
+* Mon May 14 2018 Pavel Březina <pbrezina@redhat.com> - 0.4-3
+- Disable sssd as sudo rules source with sssd profile by default (RHBZ #1573403)
+
+* Wed Apr 25 2018 Christian Heimes <cheimes@redhat.com> - 0.4-2
+- Don't disable oddjobd.service (RHBZ #1571844)
+
+* Mon Apr 9 2018 Pavel Březina <pbrezina@redhat.com> - 0.4-1
+- rebasing to 0.4
+
+* Tue Mar 6 2018 Pavel Březina <pbrezina@redhat.com> - 0.3.2-1
+- rebasing to 0.3.2
+- authselect-compat now only suggests packages, not recommends
+
+* Mon Mar 5 2018 Pavel Březina <pbrezina@redhat.com> - 0.3.1-1
+- rebasing to 0.3.1
+
+* Tue Feb 20 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.3-3
+- Provide authconfig
+
+* Tue Feb 20 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 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 <pbrezina@redhat.com> - 0.3-1
+- rebasing to 0.3
+* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.2-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+* Wed Jan 10 2018 Pavel Březina <pbrezina@redhat.com> - 0.2-2
+- fix rpmlint errors
+* Wed Jan 10 2018 Pavel Březina <pbrezina@redhat.com> - 0.2-1
+- rebasing to 0.2
+* Mon Jul 31 2017 Jakub Hrozek <jakub.hrozek@posteo.se> - 0.1-1
+- initial packaging