diff --git a/0002-backup-remove-non-existing-files-when-restoring-non-.patch b/0002-backup-remove-non-existing-files-when-restoring-non-.patch new file mode 100644 index 0000000..9859284 --- /dev/null +++ b/0002-backup-remove-non-existing-files-when-restoring-non-.patch @@ -0,0 +1,49 @@ +From 348dda6eb3da39748c43d89caf5e7bb4eb284b70 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 12 Feb 2020 12:35:30 +0100 +Subject: [PATCH 1/4] backup: remove non-existing files when restoring + non-authselect configuration + +Configuration that was not previously generated by authselect may not contain all +the files (usually dconf configuration). This should not be treated as error +but rather the files should be unlinked from the file system. + +Resolves: +https://github.com/pbrezina/authselect/issues/197 +--- + src/lib/util/selinux.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/lib/util/selinux.c b/src/lib/util/selinux.c +index aed0b475703959447cb37da3711e5f412d80dc50..468634dcc8993dca1cd715a5c39a2d91659c0f6b 100644 +--- a/src/lib/util/selinux.c ++++ b/src/lib/util/selinux.c +@@ -369,6 +369,12 @@ selinux_copy_files_safely(struct selinux_safe_copy *table, + /* First, write content into temporary files, so we can safely fail + * on error without overwriting destination files. */ + for (i = 0; table[i].source != NULL; i++) { ++ if (file_exists(table[i].source) == ENOENT) { ++ INFO("File [%s] does not exist", table[i].source); ++ tmpfiles[i] = NULL; ++ continue; ++ } ++ + INFO("Writing temporary file for [%s]", table[i].destination); + ret = selinux_mkstemp_copy(table[i].source, dirs[i], names[i], + dir_mode, &tmpfiles[i]); +@@ -385,6 +391,12 @@ selinux_copy_files_safely(struct selinux_safe_copy *table, + * even recover from it. + */ + for (i = 0; table[i].source != NULL; i++) { ++ if (tmpfiles[i] == NULL) { ++ INFO("Removing [%s]", table[i].destination); ++ unlink(table[i].destination); ++ continue; ++ } ++ + INFO("Renaming [%s] to [%s]", tmpfiles[i], table[i].destination); + ret = rename(tmpfiles[i], table[i].destination); + if (ret != 0) { +-- +2.24.1 + diff --git a/0003-backup-remove-authselect.conf-when-restoring-non-aut.patch b/0003-backup-remove-authselect.conf-when-restoring-non-aut.patch new file mode 100644 index 0000000..307ead3 --- /dev/null +++ b/0003-backup-remove-authselect.conf-when-restoring-non-aut.patch @@ -0,0 +1,27 @@ +From 3327fb6346f076c67897e51598b7576e1be4110a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 12 Feb 2020 12:36:11 +0100 +Subject: [PATCH 2/4] backup: remove authselect.conf when restoring + non-authselect configuration + +Non-authselect configuration does not contain authselect.conf so this file +should be of course removed. +--- + src/lib/authselect_backup.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lib/authselect_backup.c b/src/lib/authselect_backup.c +index 68fca2721c64f7bbb3f04d69800b2d29f49ad1f6..58529626da9adb112a64a662c6bcc60b036a9a2d 100644 +--- a/src/lib/authselect_backup.c ++++ b/src/lib/authselect_backup.c +@@ -236,6 +236,7 @@ static errno_t + authselect_restore_system_configuration(const char *path) + { + struct selinux_safe_copy table[] = { ++ {FILE_CONFIG, PATH_CONFIG_FILE}, + {FILE_SYSTEM, PATH_SYMLINK_SYSTEM}, + {FILE_PASSWORD, PATH_SYMLINK_PASSWORD}, + {FILE_FINGERPRINT, PATH_SYMLINK_FINGERPRINT}, +-- +2.24.1 + diff --git a/0004-backup-do-not-unlink-dangerous-missing-files.patch b/0004-backup-do-not-unlink-dangerous-missing-files.patch new file mode 100644 index 0000000..c86f754 --- /dev/null +++ b/0004-backup-do-not-unlink-dangerous-missing-files.patch @@ -0,0 +1,108 @@ +From 3b4ad2849ba29c80f83cad9c0224bd8a744a7089 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 12 Feb 2020 12:42:28 +0100 +Subject: [PATCH 3/4] backup: do not unlink dangerous missing files + +/etc/pam.d/system-auth and /etc/pam.d/postlogin should always exist +so the user is able to login at least through terminal. If by any +chance the backup files are missing, we must not remove these two, +otherwise we would effectively lock out the system. +--- + src/lib/authselect_backup.c | 40 ++++++++++++++++++------------------- + src/lib/util/selinux.c | 7 +++++++ + src/lib/util/selinux.h | 3 +++ + 3 files changed, 30 insertions(+), 20 deletions(-) + +diff --git a/src/lib/authselect_backup.c b/src/lib/authselect_backup.c +index 58529626da9adb112a64a662c6bcc60b036a9a2d..e9bb9af35d70e058010acb7b469b8c03b9d7a049 100644 +--- a/src/lib/authselect_backup.c ++++ b/src/lib/authselect_backup.c +@@ -236,16 +236,16 @@ static errno_t + authselect_restore_system_configuration(const char *path) + { + struct selinux_safe_copy table[] = { +- {FILE_CONFIG, PATH_CONFIG_FILE}, +- {FILE_SYSTEM, PATH_SYMLINK_SYSTEM}, +- {FILE_PASSWORD, PATH_SYMLINK_PASSWORD}, +- {FILE_FINGERPRINT, PATH_SYMLINK_FINGERPRINT}, +- {FILE_SMARTCARD, PATH_SYMLINK_SMARTCARD}, +- {FILE_POSTLOGIN, PATH_SYMLINK_POSTLOGIN}, +- {FILE_NSSWITCH, PATH_SYMLINK_NSSWITCH}, +- {FILE_DCONF_DB, PATH_SYMLINK_DCONF_DB}, +- {FILE_DCONF_LOCK, PATH_SYMLINK_DCONF_LOCK}, +- {NULL, NULL}, ++ {FILE_CONFIG, PATH_CONFIG_FILE, true}, ++ {FILE_SYSTEM, PATH_SYMLINK_SYSTEM, false}, ++ {FILE_PASSWORD, PATH_SYMLINK_PASSWORD, true}, ++ {FILE_FINGERPRINT, PATH_SYMLINK_FINGERPRINT, true}, ++ {FILE_SMARTCARD, PATH_SYMLINK_SMARTCARD, true}, ++ {FILE_POSTLOGIN, PATH_SYMLINK_POSTLOGIN, false}, ++ {FILE_NSSWITCH, PATH_SYMLINK_NSSWITCH, true}, ++ {FILE_DCONF_DB, PATH_SYMLINK_DCONF_DB, true}, ++ {FILE_DCONF_LOCK, PATH_SYMLINK_DCONF_LOCK, true}, ++ {NULL, NULL, false}, + }; + errno_t ret; + int i; +@@ -274,16 +274,16 @@ static errno_t + authselect_restore_authselect_configuration(const char *path) + { + struct selinux_safe_copy table[] = { +- {FILE_CONFIG, PATH_CONFIG_FILE}, +- {FILE_SYSTEM, PATH_SYSTEM}, +- {FILE_PASSWORD, PATH_PASSWORD}, +- {FILE_FINGERPRINT, PATH_FINGERPRINT}, +- {FILE_SMARTCARD, PATH_SMARTCARD}, +- {FILE_POSTLOGIN, PATH_POSTLOGIN}, +- {FILE_NSSWITCH, PATH_NSSWITCH}, +- {FILE_DCONF_DB, PATH_DCONF_DB}, +- {FILE_DCONF_LOCK, PATH_DCONF_LOCK}, +- {NULL, NULL}, ++ {FILE_CONFIG, PATH_CONFIG_FILE, false}, ++ {FILE_SYSTEM, PATH_SYSTEM, false}, ++ {FILE_PASSWORD, PATH_PASSWORD, false}, ++ {FILE_FINGERPRINT, PATH_FINGERPRINT, false}, ++ {FILE_SMARTCARD, PATH_SMARTCARD, false}, ++ {FILE_POSTLOGIN, PATH_POSTLOGIN, false}, ++ {FILE_NSSWITCH, PATH_NSSWITCH, false}, ++ {FILE_DCONF_DB, PATH_DCONF_DB, false}, ++ {FILE_DCONF_LOCK, PATH_DCONF_LOCK, false}, ++ {NULL, NULL, false}, + }; + errno_t ret; + int i; +diff --git a/src/lib/util/selinux.c b/src/lib/util/selinux.c +index 468634dcc8993dca1cd715a5c39a2d91659c0f6b..899512710a71b3b111e17623e35a4dd2fe3d992c 100644 +--- a/src/lib/util/selinux.c ++++ b/src/lib/util/selinux.c +@@ -370,6 +370,13 @@ selinux_copy_files_safely(struct selinux_safe_copy *table, + * on error without overwriting destination files. */ + for (i = 0; table[i].source != NULL; i++) { + if (file_exists(table[i].source) == ENOENT) { ++ if (!table[i].can_unlink) { ++ ERROR("File [%s] should exist but is missing. It is not safe to " ++ "delete [%s]. Aborting.", table[i].source, ++ table[i].destination); ++ ret = EPERM; ++ goto done; ++ } + INFO("File [%s] does not exist", table[i].source); + tmpfiles[i] = NULL; + continue; +diff --git a/src/lib/util/selinux.h b/src/lib/util/selinux.h +index f9cf070d05675f181f33eb5ac718ef9378954e14..76fcce7e3d71e036108ff6cd7f1d47e9c54e3fb9 100644 +--- a/src/lib/util/selinux.h ++++ b/src/lib/util/selinux.h +@@ -82,6 +82,9 @@ struct selinux_safe_copy { + + /* Destination file name. */ + const char *destination; ++ ++ /* Unlink destination if source file does not exist. */ ++ bool can_unlink; + }; + + /** +-- +2.24.1 + diff --git a/0005-backup-list-return-empty-array-if-directory-does-not.patch b/0005-backup-list-return-empty-array-if-directory-does-not.patch new file mode 100644 index 0000000..05bb63d --- /dev/null +++ b/0005-backup-list-return-empty-array-if-directory-does-not.patch @@ -0,0 +1,29 @@ +From be2c69f4a47bd754299c2b4212fcd796b94098a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 12 Feb 2020 13:44:28 +0100 +Subject: [PATCH 4/4] backup-list: return empty array if directory does not + exist + +--- + src/lib/authselect_backup.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/lib/authselect_backup.c b/src/lib/authselect_backup.c +index e9bb9af35d70e058010acb7b469b8c03b9d7a049..07c609861b0ef97e8041dd82c96feb6bec527e6a 100644 +--- a/src/lib/authselect_backup.c ++++ b/src/lib/authselect_backup.c +@@ -201,7 +201,10 @@ authselect_backup_list(void) + ret = dir_list(AUTHSELECT_BACKUP_DIR, + DIR_LIST_DIRS | DIR_LIST_SORT_BY_CTIME, + &names, NULL); +- if (ret != EOK) { ++ if (ret == ENOENT) { ++ INFO(AUTHSELECT_BACKUP_DIR " does not exist."); ++ return string_array_create(0); ++ } else if (ret != EOK) { + ERROR("Unable to list directory [%s] [%d]: %s", + AUTHSELECT_BACKUP_DIR, ret, strerror(ret)); + return NULL; +-- +2.24.1 + diff --git a/authselect.spec b/authselect.spec index 832c91b..3984fa0 100644 --- a/authselect.spec +++ b/authselect.spec @@ -3,7 +3,7 @@ Name: authselect Version: 1.1 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Configures authentication and identity sources from supported profiles URL: https://github.com/pbrezina/authselect @@ -14,6 +14,10 @@ Source1: translations.tar.gz %endif Patch0001: 0001-cli-fix-auto-backup-when-force-is-set.patch +Patch0002: 0002-backup-remove-non-existing-files-when-restoring-non-.patch +Patch0003: 0003-backup-remove-authselect.conf-when-restoring-non-aut.patch +Patch0004: 0004-backup-do-not-unlink-dangerous-missing-files.patch +Patch0005: 0005-backup-list-return-empty-array-if-directory-does-not.patch %global makedir %{_builddir}/%{name}-%{version} @@ -267,6 +271,9 @@ exit 0 exit 0 %changelog +* Mon Feb 17 2020 Pavel Březina - 1.1-7 +- fix restoring non-authselect configuration from backup + * Wed Jan 29 2020 Pavel Březina - 1.1-6 - cli: fix auto backup when --force is set