You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
authselect/SOURCES/0006-configure-drop-authcon...

1511 lines
53 KiB

From 3687d4e28a45b1896165e2e1d029fc81bf5a2a11 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 23 Feb 2024 13:25:50 +0100
Subject: [PATCH 06/11] configure: drop authconfig compat tool
authconfig-compat tool is now dropped and it can no longer be
enabled via configure switch
---
Makefile.am | 1 -
configure.ac | 2 -
po/POTFILES.in | 6 -
src/compat/Makefile.am | 47 --
src/compat/authcompat.py.in.in | 665 -----------------------
src/compat/authcompat_ConfigSnippet.py | 92 ----
src/compat/authcompat_EnvironmentFile.py | 216 --------
src/compat/authcompat_Options.py | 326 -----------
src/compat/snippets/authconfig-krb.conf | 14 -
src/compat/snippets/authconfig-sssd.conf | 18 -
src/conf_macros.m4 | 9 -
11 files changed, 1396 deletions(-)
delete mode 100644 src/compat/Makefile.am
delete mode 100755 src/compat/authcompat.py.in.in
delete mode 100644 src/compat/authcompat_ConfigSnippet.py
delete mode 100644 src/compat/authcompat_EnvironmentFile.py
delete mode 100644 src/compat/authcompat_Options.py
delete mode 100644 src/compat/snippets/authconfig-krb.conf
delete mode 100644 src/compat/snippets/authconfig-sssd.conf
diff --git a/Makefile.am b/Makefile.am
index 1c9b88d47f809cb218d19887734769f12b944bb4..befa38ba16f2ff6659fe452c4e4f8d9f646b3d84 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,6 @@ SUBDIRS= \
po \
profiles \
src/common \
- src/compat \
src/lib \
src/cli \
src/tests \
diff --git a/configure.ac b/configure.ac
index 3a355bb78dd8040cd91f32e5602a55bf34a9563b..612763702cda22737ad841dd246dafbb607c0bed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,8 +51,6 @@ AC_CONFIG_FILES([Makefile
profiles/Makefile
rpm/authselect.spec
src/common/Makefile
- src/compat/authcompat.py.in
- src/compat/Makefile
src/cli/Makefile
src/lib/Makefile
src/lib/authselect.pc
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2e7fbc89bbffe3a7584cf48bb99509d0912854e9..1380ba855ab4c9c2d35f956736cb195d4890042d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -26,9 +26,3 @@ src/common/format.c
# Command line tool
src/cli/cli_tool.c
src/cli/main.c
-
-# Compat tool
-src/compat/authcompat_ConfigSnippet.py
-src/compat/authcompat_EnvironmentFile.py
-src/compat/authcompat_Options.py
-src/compat/authcompat.py.in.in
diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am
deleted file mode 100644
index 5928e53a22d432247a2ce1e120dcad699d3c961e..0000000000000000000000000000000000000000
--- a/src/compat/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-if BUILD_COMPAT
-expand_prefix = \
- ( \
- $(SED) -e 's,$${exec_prefix},$(exec_prefix),g' | \
- $(SED) -e 's,$${prefix},$(prefix),g' \
- )
-
-generated_files = \
- authcompat.py \
- $(NULL)
-
-expand_files:
- for FILE in $(generated_files) ; do \
- $(expand_prefix) < $$FILE.in > $$FILE ; \
- done
-
-.PHONY: expand_files
-BUILT_SOURCES = expand_files
-
-CLEANFILES = \
- $(generated_files) \
- $(NULL)
-
-pkgpython_SCRIPTS = \
- authcompat.py \
- $(NULL)
-
-dist_pkgpython_DATA = \
- authcompat_ConfigSnippet.py \
- authcompat_EnvironmentFile.py \
- authcompat_Options.py \
- $(NULL)
-
-snippetsdir = $(pkgpythondir)/snippets
-dist_snippets_DATA = \
- snippets/authconfig-krb.conf \
- snippets/authconfig-sssd.conf \
- $(NULL)
-
-# Create symbolic link that will replace authconfig
-install-exec-hook:
- $(MKDIR_P) $(DESTDIR)/$(sbindir)
- $(LN_S) -f $(pkgpythondir)/authcompat.py $(DESTDIR)/$(sbindir)/authconfig
-
-uninstall-local:
- $(RM) $(DESTDIR)/$(sbindir)/authconfig
-endif
diff --git a/src/compat/authcompat.py.in.in b/src/compat/authcompat.py.in.in
deleted file mode 100755
index 6bea49829410e280ea06d19e265bad552ac93b02..0000000000000000000000000000000000000000
--- a/src/compat/authcompat.py.in.in
+++ /dev/null
@@ -1,665 +0,0 @@
-#!@PYTHON_BIN@
-# -*- coding: utf-8 -*-
-#
-# 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/>.
-#
-
-import os
-import sys
-import locale
-import gettext
-import subprocess
-
-
-from authcompat_Options import Options
-from authcompat_EnvironmentFile import EnvironmentFile
-from authcompat_ConfigSnippet import ConfigSnippet
-
-_ = gettext.gettext
-
-
-def eprint(*args, **kwargs):
- print(*args, file=sys.stderr, **kwargs)
-
-
-class Command:
- TEST = False
-
- 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))
-
- if self.TEST:
- return
-
- self.result = subprocess.run(self.args, check=self.check,
- input=self.input,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
-
-class Service:
- def __init__(self, name):
- self.name = name + '.service'
-
- def runsystemd(self, command, required, enoent_code):
- try:
- command.run()
- except subprocess.CalledProcessError as result:
- if required and result.returncode == enoent_code:
- eprint(_("Service %s was not found. Please install the service.")
- % self.name)
- elif result.returncode != enoent_code:
- eprint(_("Command [%s] failed with %d, stderr:")
- % (' '.join(result.cmd), result.returncode))
- eprint(result.stderr.decode())
-
- def enable(self):
- cmd = Command(Path.System("cmd-systemctl"), ["enable", self.name])
- self.runsystemd(cmd, True, 1)
-
- def disable(self):
- cmd = Command(Path.System("cmd-systemctl"), ["disable", self.name])
- self.runsystemd(cmd, False, 1)
-
- def start(self, Restart=True):
- if Restart:
- self.stop()
- cmd = Command(Path.System("cmd-systemctl"), ["start", self.name])
- self.runsystemd(cmd, True, 5)
-
- def stop(self):
- cmd = Command(Path.System("cmd-systemctl"), ["stop", self.name])
- self.runsystemd(cmd, False, 5)
-
-
-class Path:
- LocalDir = os.path.dirname(os.path.realpath(__file__))
- Config = EnvironmentFile(LocalDir + "/authcompat_paths")
-
- Files = {
- 'ldap.conf': '@sysconfdir@/openldap/ldap.conf',
- 'krb5.conf': '@sysconfdir@/krb5.conf.d/authconfig-krb.conf',
- 'sssd.conf': '@sysconfdir@/sssd/conf.d/authconfig-sssd.conf',
- 'authconfig': '@sysconfdir@/sysconfig/authconfig',
- 'network': '@sysconfdir@/sysconfig/network',
- 'pwquality.conf': '@sysconfdir@/security/pwquality.conf.d/10-authconfig-pwquality.conf',
- 'yp.conf': '@sysconfdir@/yp.conf',
- 'cmd-systemctl': '@bindir@/systemctl',
- 'cmd-authselect': '@bindir@/authselect',
- 'cmd-realm': '@sbindir@/realm',
- 'cmd-domainname': '@bindir@/domainname',
- 'cmd-setsebool': '@sbindir@/setsebool'
- }
-
- @staticmethod
- def Local(relpath):
- return "%s/%s" % (Path.LocalDir, relpath)
-
- @staticmethod
- def System(name):
- return Path.Files[name]
-
-
-class Configuration:
- class Base(object):
- def __init__(self, options, ServiceName=None):
- self.options = options
- self.service = None
- if ServiceName is not None:
- self.service = Service(ServiceName)
-
- def isEnabled(self):
- return True
-
- def isDisabled(self):
- return not self.isEnabled()
-
- def enableService(self, nostart):
- if self.service is None:
- return
-
- self.service.enable()
-
- if not nostart:
- self.service.start()
-
- def disableService(self, nostop):
- if self.service is None:
- return
-
- self.service.disable()
-
- if not nostop:
- self.service.stop()
-
- def cleanup(self):
- return
-
- def write(self):
- return
-
- def get(self, name):
- return self.options.get(name)
-
- def isset(self, name):
- return self.options.isset(name)
-
- def getTrueOrNone(self, name):
- return self.options.getTrueOrNone(name)
-
- def getBool(self, name):
- return self.options.getBool(name)
-
- 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
-
- return if_false
-
- def removeFile(self, filename):
- print(_("Removing file: %s") % filename)
- if self.options.getBool("test-call"):
- return
-
- try:
- os.remove(filename)
- except FileNotFoundError:
- return
-
- class LDAP(Base):
- def __init__(self, options):
- super(Configuration.LDAP, self).__init__(options)
-
- def write(self):
- config = EnvironmentFile(Path.System('ldap.conf'), " ",
- delimiter_re=r"\s\t", quotes=False)
- if self.isset("ldapserver"):
- config.set("URI", self.get("ldapserver"))
-
- if self.isset("ldapbasedn"):
- config.set("BASE", self.get("ldapbasedn"))
-
- config.write()
-
- class Kerberos(Base):
- def __init__(self, options):
- super(Configuration.Kerberos, self).__init__(options)
-
- def isEnabled(self):
- 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):
- if self.isDisabled():
- return
-
- path = Path.Local("snippets/authconfig-krb.conf")
- config = ConfigSnippet(path, Path.System('krb5.conf'))
- realm = self.get("krb5realm")
-
- keys = {
- 'realm': self.get("krb5realm"),
- 'kdc-srv': self.get("krb5kdcdns"),
- 'realm-srv': self.get("krb5realmdns"),
- 'kdc': self.get("krb5kdc") if realm else None,
- 'adminserver': self.get("krb5adminserver") if realm else None,
- 'domain': realm.lower() if realm else None
- }
-
- config.write(keys)
-
- class Network(Base):
- def __init__(self, options):
- super(Configuration.Network, self).__init__(options)
-
- def write(self):
- nisdomain = self.get("nisdomain")
- config = EnvironmentFile(Path.System('network'))
-
- if nisdomain is None:
- return
-
- config.set("NISDOMAIN", nisdomain)
- config.write()
-
- class SSSD(Base):
- def __init__(self, options):
- 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):
- self.removeFile(Path.System('sssd.conf'))
-
- def write(self):
- # Authconfig would not generate sssd in this case so we should not
- # either. Even if --enablesssd[auth] was provided the configuration
- # would not be generated.
- if not self.getBool("ldap"):
- return
-
- path = Path.Local("snippets/authconfig-sssd.conf")
- config = ConfigSnippet(path, Path.System('sssd.conf'))
-
- schema = "rfc2307bis" if self.getBool("rfc2307bis") else None
-
- keys = {
- 'ldap-uri': self.get("ldapserver"),
- 'ldap-basedn': self.get("ldapbasedn"),
- 'ldap-tls': self.getTrueOrNone("ldaptls"),
- 'ldap-schema': schema,
- 'krb5': self.getTrueOrNone("krb5"),
- 'kdc-uri': self.get("krb5kdc"),
- 'kpasswd-uri': self.get("krb5adminserver"),
- 'realm': self.get("krb5realm"),
- 'cache-creds': self.getTrueOrNone("cachecreds"),
- 'cert-auth': self.getTrueOrNone("smartcard")
- }
-
- config.write(keys)
- os.chmod(Path.System('sssd.conf'), mode=0o600)
-
- class Winbind(Base):
- def __init__(self, options):
- 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):
- if not self.isset("winbindjoin"):
- return
-
- creds = self.options.get("winbindjoin").split("%", 1)
-
- user = creds[0]
- password = None
- if len(creds) > 1:
- password = creds[1] + '\n'
-
- args = [
- 'join',
- '-U', '"%s"' % user,
- '--client-software', 'winbind'
- ]
-
- if self.isset("smbworkgroup"):
- args.append(self.get("smbworkgroup"))
-
- cmd = Command(Path.System('cmd-realm'), args, input=password)
- try:
- cmd.run()
- except FileNotFoundError:
- eprint(_("%s was not found. Please, install realmd.")
- % Path.System('cmd-realm'))
-
- class PWQuality(Base):
- def __init__(self, options):
- super(Configuration.PWQuality, self).__init__(options)
-
- def write(self):
- config = EnvironmentFile(Path.System('pwquality.conf'))
- value_set = False
-
- 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)
- }
-
- # 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):
- 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):
- # Never disable the service in case it is already running as
- # other applications may depend on it.
- return
-
- class NIS(Base):
- def __init__(self, options):
- super(Configuration.NIS, self).__init__(options)
- self.rpcbind = Service("rpcbind")
- self.ypbind = Service("ypbind")
-
- def isEnabled(self):
- if not self.isset("nis"):
- return None
-
- return self.getBool("nis")
-
- def enableService(self, nostart):
- if not self.isset("nisdomain"):
- return
-
- nisdom = self.get("nisdomain")
-
- if not nostart:
- cmd = Command(Path.System('cmd-domainname'), [nisdom])
- cmd.run()
-
- cmd = Command(Path.System('cmd-setsebool'),
- ['-P', 'allow_ypbind', '1'])
- cmd.run()
-
- self.rpcbind.enable()
- self.ypbind.enable()
-
- if not nostart:
- self.rpcbind.start(Restart=False)
- self.ypbind.start()
-
- def disableService(self, nostop):
- if not nostop:
- cmd = Command(Path.System('cmd-domainname'), ["(none)"])
- cmd.run()
-
- cmd = Command(Path.System('cmd-setsebool'),
- ['-P', 'allow_ypbind', '0'])
- cmd.run()
-
- self.rpcbind.disable()
- self.ypbind.disable()
-
- if not nostop:
- self.rpcbind.stop()
- self.ypbind.stop()
-
- def write(self):
- if not self.isset("nisdomain"):
- return
-
- output = "domain " + self.get("nisdomain")
-
- additional_servers = []
- if self.isset("nisserver"):
- servers = self.get("nisserver").split(",")
- additional_servers = servers[1:]
- output += " server " + servers[0] + "\n"
- else:
- output += " broadcast\n"
-
- for server in additional_servers:
- output += "ypserver " + server + "\n"
-
- filename = Path.System('yp.conf')
- if self.getBool("test-call"):
- print("========== BEGIN Content of [%s] ==========" % filename)
- print(output)
- print("========== END Content of [%s] ==========\n" % filename)
- return
-
- with open(filename, "w") as f:
- f.write(output)
-
-
-class AuthCompat:
- def __init__(self):
- self.sysconfig = EnvironmentFile(Path.System('authconfig'))
- self.options = Options()
-
- self.options.parse()
- self.options.applysysconfig(self.sysconfig)
- self.options.updatesysconfig(self.sysconfig)
-
- def printWarning(self):
- print(_("Running authconfig compatibility tool."))
- print(_("The purpose of this tool is to enable authentication against "
- "chosen services with authselect and minimum configuration. "
- "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()
- if options:
- print(_("Warning: These options are not supported anymore "
- "and have no effect:"))
- for name in options:
- print(" --%s" % name)
-
- print("")
-
- def printOptions(self):
- for option in Options.List:
- print("%s=%s" % (option.name, option.value))
-
- def printSysconfig(self):
- for line in self.sysconfig.getall():
- print("%s=%s" % (line.name, line.value))
-
- def canContinue(self):
- disallowed = ["test", "probe", "restorebackup", "restorelastbackup"]
- required = ["update", "updateall", "kickstart"]
-
- if not self.options.getBool("test") and os.getuid() != 0:
- print(_("authconfig can only be run as root"))
- return False
-
- for option in disallowed:
- if self.options.getBool(option):
- print(_("Error: option --%s is no longer supported and we "
- "cannot continue if it is set." % option))
- return False
-
- if self.options.getBool("winbind") != self.options.getBool("winbindauth"):
- print(_("Error: Both --enablewinbind and --enablewinbindauth must be set."))
- return False
-
- # We require one of these options to perform changes
- # We encourage to use --updateall since we no longer support just pure
- # --update or --kickstart, they will act as --updateall.
- for option in required:
- if self.options.getBool(option):
- return True
-
- print(_("Error: Please, provide --updateall option."))
- return False
-
- def runAuthselect(self):
- map = {
- '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.
- (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)
-
- # 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))
-
- # 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]
- 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 is None or 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),
- Configuration.Network(self.options),
- Configuration.Kerberos(self.options),
- Configuration.SSSD(self.options),
- Configuration.Winbind(self.options),
- Configuration.PWQuality(self.options),
- Configuration.MakeHomedir(self.options),
- Configuration.NIS(self.options)
- ]
-
- for config in configs:
- # Configuration decides if it needs to write something or not
- config.write()
-
- # Enable or disable service if needed
- nostart = self.options.getBool("nostart")
- try:
- 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)
- config.cleanup()
- except subprocess.CalledProcessError as result:
- # This is not fatal error.
- eprint(_("Command [%s] failed with %d, stderr:")
- % (' '.join(result.cmd), result.returncode))
- eprint(result.stderr.decode())
-
-
-def main():
- try:
- locale.setlocale(locale.LC_ALL, '')
- except locale.Error:
- sys.stderr.write('Warning: Unsupported locale setting.\n')
-
- authcompat = AuthCompat()
- authcompat.printWarning()
-
- Command.TEST = authcompat.options.getBool("test-call")
- EnvironmentFile.TEST = authcompat.options.getBool("test-call")
- ConfigSnippet.TEST = authcompat.options.getBool("test-call")
-
- if not authcompat.canContinue():
- sys.exit(1)
-
- 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))
- eprint(result.stderr.decode())
-
- sys.exit(0)
-
-
-if __name__ == "__main__":
- main()
diff --git a/src/compat/authcompat_ConfigSnippet.py b/src/compat/authcompat_ConfigSnippet.py
deleted file mode 100644
index 01033ea0ab71e0eb235f03f1fb2a6aec124e2286..0000000000000000000000000000000000000000
--- a/src/compat/authcompat_ConfigSnippet.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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/>.
-#
-
-import errno
-import os
-import re
-
-
-class ConfigSnippet:
- TEST = False
-
- AllKeysRE = re.compile(r'\${\??(?P<key>[\w-]*)}')
- DummyKeysRE = re.compile(r'\${\?[\w-]*}')
-
- def __init__(self, template, destination):
- with open(template, "r") as f:
- self.template = f.read()
-
- self.destination = destination
-
- def generate(self, values):
- # First remove lines containing key that is not set
- lines = self.template.split('\n')
- remove = []
-
- for idx, line in enumerate(lines):
- for match in self.AllKeysRE.finditer(line):
- key = match.group("key")
- if key not in values or values[key] is None:
- remove.append(idx)
- break
-
- for idx in sorted(remove, reverse=True):
- del lines[idx]
-
- # Build output string
- output = '\n'.join(lines)
-
- # Remove all dummy keys ${?key}
- output = self.DummyKeysRE.sub("", output)
-
- # Replace values
- for key, value in values.items():
- if value is None:
- continue
-
- if type(value) is bool:
- value = "true" if value else "false"
-
- output = output.replace("${%s}" % key, value)
-
- return output
-
- def write(self, values, to_stdout=False):
- output = self.generate(values)
-
- if self.TEST:
- print("========== BEGIN Content of [%s] ==========" % self.destination)
- print(output)
- print("========== END Content of [%s] ==========\n" % self.destination)
- return
-
- dirname = os.path.dirname(self.destination)
- if not os.path.exists(dirname):
- try:
- os.makedirs(dirname)
- except OSError as exception:
- if exception.errno == errno.EEXIST and os.path.isdir(dirname):
- pass
- else:
- raise
-
- with open(self.destination, "w") as f:
- f.write(output)
diff --git a/src/compat/authcompat_EnvironmentFile.py b/src/compat/authcompat_EnvironmentFile.py
deleted file mode 100644
index 2dabd5963ce1aa7160801415f3bf69d4a793cdd1..0000000000000000000000000000000000000000
--- a/src/compat/authcompat_EnvironmentFile.py
+++ /dev/null
@@ -1,216 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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/>.
-#
-
-import errno
-import os
-import re
-
-
-class EnvironmentFile:
- TEST = False
-
- def __init__(self, filename,
- delimiter='=', delimiter_re=None,
- quotes=True):
- self.filename = filename
- self.delimiter = delimiter
- self.quotes = quotes
- self.environment = []
-
- delimiter_re = delimiter_re if delimiter_re is not None else delimiter
- self.pattern = re.compile(r'^(\s*)(\S*)([^\n\S]*)('
- + delimiter_re
- + r')([^\n\S]*)(.*)$',
- re.MULTILINE)
-
- self.read()
-
- def read(self):
- try:
- with open(self.filename, "r") as f:
- lines = f.readlines()
- except FileNotFoundError:
- return
-
- for line in lines:
- parsed = self.Line.Parse(line, self.pattern,
- self.delimiter, self.quotes)
- self.environment.append(parsed)
-
- def write(self):
- output = ""
- for line in self.environment:
- output = output + line.getLine()
-
- if self.TEST:
- print("========== BEGIN Content of [%s] ==========" % self.filename)
- print(output)
- print("========== END Content of [%s] ==========\n" % self.filename)
- return
-
- dirname = os.path.dirname(self.filename)
- if not os.path.exists(dirname):
- try:
- os.makedirs(dirname)
- except OSError as exception:
- if exception.errno == errno.EEXIST and os.path.isdir(dirname):
- pass
- else:
- raise
-
- with open(self.filename, "w") as f:
- f.write(output)
-
- def get(self, name, default=None):
- value = None
- for line in self.environment:
- if line.isVariable() and line.name == name:
- value = line.value
-
- if value is None:
- return default
-
- if value.lower() in [None, "no", "false", "f", "n"]:
- return False
- elif value.lower() in ["yes", "true", "t", "y"]:
- return True
-
- return value
-
- def getall(self):
- lines = []
- for line in self.environment:
- if line.isVariable():
- lines.append(line)
-
- return lines
-
- def set(self, name, value):
- if type(value) is bool:
- value = "yes" if value else "no"
-
- for line in self.environment:
- if line.isVariable() and line.name == name:
- line.set(name, value)
- return
-
- line = self.Line(self.delimiter, self.quotes)
- line.set(name, value)
- self.environment.append(line)
-
- class Line:
- def __init__(self, delimiter, quotes,
- name=None, value=None, original=None, fmt=None):
- self.delimiter = delimiter
- self.quotes = quotes
- self.name = name
- self.value = value
- self.original = original
- self.fmt = fmt
-
- def isVariable(self):
- return self.fmt is not None
-
- def isOriginal(self):
- return self.original is not None
-
- def set(self, name, value):
- self.name = name
- self.value = value
- if self.fmt is None:
- self.fmt = "${name}%s${value}\n" % self.delimiter
-
- def getLine(self):
- if self.isOriginal():
- return self.original
-
- value = self.value if self.value is not None else ""
- replacement = {
- 'name': self.name,
- 'value': self.Escape(value, self.quotes)
- }
-
- line = self.fmt
- for key, value in replacement.items():
- line = line.replace("${" + key + "}", str(value))
-
- return line
-
- @staticmethod
- def Parse(line, pattern, delimiter, quotes):
- match = pattern.match(line)
- if line.startswith('#') or not line.strip() or not match:
- return EnvironmentFile.Line(delimiter, quotes, original=line)
-
- name = match.group(2)
- value = EnvironmentFile.Line.Unescape(match.group(6), quotes)
- fmt = "%s${name}%s%s%s${value}\n" % (match.group(1),
- match.group(3),
- match.group(4),
- match.group(5))
-
- return EnvironmentFile.Line(delimiter, quotes, name=name,
- value=value, fmt=fmt)
-
- @staticmethod
- def Escape(value, quotes):
- if value is None:
- return ""
-
- value = str(value)
- value = value.replace("\\", "\\\\")
- value = value.replace("\"", "\\\"")
- value = value.replace("'", "\\\'")
- value = value.replace("$", "\\$")
- value = value.replace("~", "\\~")
- value = value.replace("`", "\\`")
-
- if quotes:
- if value.find(" ") > 0 or value.find("\t") > 0:
- value = "\"" + value + "\""
-
- return value
-
- @staticmethod
- def Unescape(value, quotes):
- if not value:
- return value
-
- value = str(value)
-
- length = len(value)
- if quotes:
- if (value[0] == "\"" or value[0] == "'") and value[0] == value[length - 1]:
- value = value[1:length - 1]
-
- i = 0
- while True:
- i = value.find("\\", i)
- if i < 0:
- break
- if i + 1 >= len(value):
- value = value[0:i]
- break
-
- value = value[0:i] + value[i + 1:]
- i += 1
-
- return value
diff --git a/src/compat/authcompat_Options.py b/src/compat/authcompat_Options.py
deleted file mode 100644
index d26dedabdfb9519861076b58cddd0dd0eb04b7cb..0000000000000000000000000000000000000000
--- a/src/compat/authcompat_Options.py
+++ /dev/null
@@ -1,326 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 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/>.
-#
-
-import argparse
-import gettext
-
-_ = gettext.gettext
-
-
-class Option:
- def __init__(self, name, metavar, help, feature, supported):
- self.name = name
- self.metavar = metavar
- self.help = help
- self.feature = feature
- self.supported = supported
- self.value = None
- self.from_sysconfig = False
-
- def set(self, new_value):
- self.value = new_value
-
- def set_from_sysconfig(self, new_value):
- self.set(new_value)
- self.from_sysconfig = True
-
- def isset(self):
- return self.value is not None
-
- @staticmethod
- def Valued(name, metavar, help):
- return Option(name, metavar, help, feature=False, supported=True)
-
- @staticmethod
- def Switch(name, help):
- return Option(name, None, help, feature=False, supported=True)
-
- @staticmethod
- def Feature(name, help):
- return Option(name, None, help, feature=True, supported=True)
-
- @staticmethod
- def UnsupportedValued(name, metavar):
- return Option(name, metavar, None, feature=False, supported=False)
-
- @staticmethod
- def UnsupportedFeature(name):
- return Option(name, None, None, feature=True, supported=False)
-
- @staticmethod
- def UnsupportedSwitch(name):
- return Option(name, None, None, feature=False, supported=False)
-
-
-class Options:
- List = [
- # These options are still supported in authconfig compatibility
- # layers. The tool will do its best to translate them to authselect
- # call and where needed, it will generate a configuration file.
- #
- # However, they will just make sure that an authentication against
- # expected service is working. They may not result in the exact same
- # configuration as authconfig would generate.
- Option.Feature("nis", _("NIS for user information by default")),
- Option.Valued("nisdomain", _("<domain>"), _("default NIS domain")),
- Option.Valued("nisserver", _("<server>"), _("default NIS server")),
- Option.Feature("ldap", _("LDAP for user information by default")),
- Option.Feature("ldapauth", _("LDAP for authentication by default")),
- Option.Valued("ldapserver", _("<server>"), _("default LDAP server hostname or URI")),
- Option.Valued("ldapbasedn", _("<dn>"), _("default LDAP base DN")),
- Option.Feature("ldaptls", _("use of TLS with LDAP (RFC-2830)")),
- Option.Feature("ldapstarttls", _("use of TLS for identity lookups with LDAP (RFC-2830)")),
- 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")),
- Option.Valued("krb5kdc", _("<server>"), _("default Kerberos KDC")),
- Option.Valued("krb5adminserver", _("<server>"), _("default Kerberos admin server")),
- Option.Valued("krb5realm", _("<realm>"), _("default Kerberos realm")),
- Option.Feature("krb5kdcdns", _("use of DNS to find Kerberos KDCs")),
- Option.Feature("krb5realmdns", _("use of DNS to find Kerberos realms")),
- Option.Feature("winbind", _("winbind for user information by default")),
- Option.Feature("winbindauth", _("winbind for authentication by default")),
- Option.Valued("winbindjoin", _("<Administrator>"), _("join the winbind domain or ads realm now as this administrator")),
- Option.Feature("winbindkrb5", _("Kerberos 5 for authenticate with winbind")),
- Option.Valued("smbworkgroup", _("<workgroup>"), _("workgroup authentication servers are in")),
- Option.Feature("sssd", _("SSSD for user information by default with manually managed configuration")),
- Option.Feature("sssdauth", _("SSSD for authentication by default with manually managed configuration")),
- Option.Feature("cachecreds", _("caching of user credentials in SSSD by default")),
- Option.Feature("pamaccess", _("check of access.conf during account authorization")),
- Option.Feature("mkhomedir", _("creation of home directories for users on their first login")),
- Option.Feature("faillock", _("account locking in case of too many consecutive authentication failures")),
- Option.Valued("passminlen", _("<number>"), _("minimum length of a password")),
- Option.Valued("passminclass", _("<number>"), _("minimum number of character classes in a password")),
- Option.Valued("passmaxrepeat", _("<number>"), _("maximum number of same consecutive characters in a password")),
- Option.Valued("passmaxclassrepeat", _("<number>"), _("maximum number of consecutive characters of same class in a password")),
- Option.Feature("reqlower", _("require at least one lowercase character in a password")),
- Option.Feature("requpper", _("require at least one uppercase character in a password")),
- Option.Feature("reqdigit", _("require at least one digit in a password")),
- Option.Feature("reqother", _("require at least one other character in a password")),
-
- # Program options
- Option.Switch("nostart", _("do not start/stop services")),
- Option.Switch("updateall", _("update all configuration files")),
- Option.Switch("update", _("the same as --updateall")),
- Option.Switch("kickstart", _("the same as --updateall")),
-
- # Hidden compat tool option, useful for testing. No changes to the
- # system will be done, they will be printed.
- Option.Switch("test-call", argparse.SUPPRESS),
-
- # Unsupported program options but we have to react somehow when set
- Option.UnsupportedSwitch("test"),
- Option.UnsupportedSwitch("probe"),
- Option.UnsupportedValued("savebackup", _("<name>")),
- Option.UnsupportedValued("restorebackup", _("<name>")),
- Option.UnsupportedSwitch("restorelastbackup"),
-
- # These options are no longer supported in authconfig compatibility
- # layers and will produce warning when used. They will not affect
- # the system.
- Option.UnsupportedFeature("cache"),
- Option.UnsupportedFeature("shadow"),
- Option.UnsupportedSwitch("useshadow"),
- Option.UnsupportedFeature("md5"),
- Option.UnsupportedSwitch("usemd5"),
- Option.UnsupportedValued("passalgo", _("<descrypt|bigcrypt|md5|sha256|sha512|yescrypt>")),
- Option.UnsupportedValued("ldaploadcacert", _("<URL>")),
- Option.UnsupportedValued("smartcardmodule", _("<module>")),
- Option.UnsupportedValued("smbsecurity", _("<user|server|domain|ads>")),
- Option.UnsupportedValued("smbrealm", _("<realm>")),
- Option.UnsupportedValued("smbservers", _("<servers>")),
- Option.UnsupportedValued("smbidmaprange", _("<lowest-highest>")),
- Option.UnsupportedValued("smbidmapuid", _("<lowest-highest>")),
- Option.UnsupportedValued("smbidmapgid", _("<lowest-highest>")),
- Option.UnsupportedValued("winbindseparator", _("<\\>")),
- Option.UnsupportedValued("winbindtemplatehomedir", _("</home/%D/%U>")),
- Option.UnsupportedValued("winbindtemplateshell", _("</bin/false>")),
- Option.UnsupportedFeature("winbindusedefaultdomain"),
- Option.UnsupportedFeature("winbindoffline"),
- Option.UnsupportedFeature("preferdns"),
- Option.UnsupportedFeature("forcelegacy"),
- Option.UnsupportedFeature("locauthorize"),
- Option.UnsupportedFeature("sysnetauth"),
- Option.UnsupportedValued("faillockargs", _("<options>")),
- ]
-
- Map = {
- # These options were use with autodetection of pam_cracklib
- # and pam_passwdqc. However, authselect supports only pam_pwquality.
- # "USEPWQUALITY" : "",
- # "USEPASSWDQC" : "",
- "USEFAILLOCK": "faillock",
- "FAILLOCKARGS": "faillockargs",
- "USELDAP": "ldap",
- "USENIS": "nis",
- "USEECRYPTFS": "ecryptfs",
- "USEWINBIND": "winbind",
- "WINBINDKRB5": "winbindkrb5",
- "USESSSD": "sssd",
- "USEKERBEROS": "krb5",
- "USELDAPAUTH": "ldapauth",
- "USESMARTCARD": "smartcard",
- "FORCESMARTCARD": "requiresmartcard",
- "USEFPRINTD": "fingerprint",
- "PASSWDALGORITHM": "passalgo",
- "USEMD5": "md5",
- "USESHADOW": "shadow",
- "USEWINBINDAUTH": "winbindauth",
- "USESSSDAUTH": "sssdauth",
- "USELOCAUTHORIZE": "locauthorize",
- "USEPAMACCESS": "pamaccess",
- "USEMKHOMEDIR": "mkhomedir",
- "USESYSNETAUTH": "sysnetauth",
- "FORCELEGACY": "forcelegacy",
- "CACHECREDENTIALS": "cachecreds",
- }
-
- def __init__(self):
- self.options = {}
-
- for option in self.List:
- self.options[option.name] = option
-
- def parse(self):
- parser = argparse.ArgumentParser(description='Authconfig Compatibility Tool.')
-
- parsers = {
- 'supported': parser.add_argument_group(_('These options have a compatibility layer')),
- 'unsupported': parser.add_argument_group(_('These options are no longer supported and have no effect'))
- }
-
- for option in self.List:
- group = 'supported' if option.supported else 'unsupported'
- self.add_option(parsers[group], option)
-
- cmdline = parser.parse_args()
-
- for name, option in self.options.items():
- value = getattr(cmdline, name)
- option.set(value)
-
- # usemd5 and useshadow are equivalent to enablemd5 and enableshadow
- if not self.isset('md5') and self.isset('usemd5'):
- self.set('md5', self.get('usemd5'))
-
- if not self.isset('shadow') and self.isset('useshadow'):
- self.set('shadow', self.get('useshadow'))
-
- # ldapstarttls is equivalent to ldaptls
- if self.isset('ldapstarttls') and not self.isset('ldaptls'):
- self.set('ldaptls', self.get('ldapstarttls'))
-
- def applysysconfig(self, sysconfig):
- for name, option in self.Map.items():
- if not self.isset(option):
- self.options[option].set_from_sysconfig(sysconfig.get(name))
-
- def updatesysconfig(self, sysconfig):
- for name, option in self.Map.items():
- if self.isset(option):
- sysconfig.set(name, self.get(option))
-
- def get(self, name):
- return self.options[name].value
-
- def set(self, name, value):
- self.options[name].set(value)
-
- def isset(self, name):
- return self.options[name].isset()
-
- def getBool(self, name):
- value = self.get(name)
- if value is None or not value:
- return False
- return True
-
- def getTrueOrNone(self, name):
- value = self.get(name)
- if value is None or not value:
- return None
- return True
-
- def getSetButUnsupported(self):
- options = []
- for option in Options.List:
- if option.supported:
- continue
-
- if not option.isset():
- continue
-
- if option.from_sysconfig:
- continue
-
- name = option.name
- if option.feature:
- name = "enable" + name if option.value else "disable" + name
-
- options.append(name)
-
- return options
-
- def add_option(self, parser, option):
- if option.metavar is not None:
- self.add_valued(parser, option)
- elif option.feature:
- self.add_feature(parser, option)
- else:
- self.add_switch(parser, option)
-
- def add_valued(self, parser, option):
- parser.add_argument("--" + option.name,
- action='store',
- help=option.help,
- dest=option.name,
- metavar=option.metavar)
-
- def add_switch(self, parser, option):
- parser.add_argument("--" + option.name,
- action='store_const',
- const=True,
- help=option.help,
- dest=option.name)
-
- def add_feature(self, parser, option):
- help_enable = None
- help_disable = None
-
- if option.help is not None:
- help_enable = _("enable") + " " + option.help
- help_disable = _("disable") + " " + option.help
-
- parser.add_argument("--enable" + option.name,
- action='store_const',
- const=True,
- help=help_enable,
- dest=option.name)
-
- parser.add_argument("--disable" + option.name,
- action='store_const',
- const=False,
- help=help_disable,
- dest=option.name)
diff --git a/src/compat/snippets/authconfig-krb.conf b/src/compat/snippets/authconfig-krb.conf
deleted file mode 100644
index e5ace8626321795c009ed9c0050cd35cab6a8ee0..0000000000000000000000000000000000000000
--- a/src/compat/snippets/authconfig-krb.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-[libdefaults]
- dns_lookup_kdc = ${kdc-srv}
- dns_lookup_realm = ${realm-srv}
- default_realm = ${realm}
-
-[realms]
- ${realm} = {
- kdc = ${kdc}
- admin_server = ${adminserver}
- ${?realm}}
-
-[domain_realm]
- ${domain} = ${realm}
- .${domain} = ${realm}
diff --git a/src/compat/snippets/authconfig-sssd.conf b/src/compat/snippets/authconfig-sssd.conf
deleted file mode 100644
index 13bd1dcb84c0b4a983d19dc00d8a73e4c7c2cee4..0000000000000000000000000000000000000000
--- a/src/compat/snippets/authconfig-sssd.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-[sssd]
-domains = default
-
-[domain/default]
-id_provider = ldap
-auth_provider${?krb5} = krb5
-ldap_uri = ${ldap-uri}
-ldap_search_base = ${ldap-basedn}
-ldap_id_use_start_tls = ${ldap-tls}
-ldap_schema = ${ldap-schema}
-krb5_server${?krb5} = ${kdc-uri}
-krb5_kpasswd${?krb5} = ${kpasswd-uri}
-krb5_realm${?krb5} = ${realm}
-krb5_store_password_if_offline${?krb5} = ${cache-credentials}
-cache_credentials = ${cache-credentials}
-
-[pam]${?cert-auth}
-pam_cert_auth = ${cert-auth}
diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
index ae8fa0274e038e98115d000717487dbdbc04df4c..8dafd94cf57398ce1c654d83289d210ac730d14d 100644
--- a/src/conf_macros.m4
+++ b/src/conf_macros.m4
@@ -81,15 +81,6 @@ AS_IF([test "x$enable_debug_template_regex" = "xyes"],
)
)
-AC_ARG_WITH([compat],
- [AC_HELP_STRING([--with-compat], [Build with compatibility tool [no]])],
- [], with_compat=no
-)
-if test x"$with_compat" = xyes; then
- AM_PATH_PYTHON([3])
-fi
-AM_CONDITIONAL([BUILD_COMPAT], [test x$with_compat = xyes])
-
AC_ARG_WITH([nis-profile],
[AC_HELP_STRING([--with-nis-profile], [Install NIS profile [no]])],
[], with_nis_profile=no
--
2.42.0