diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config index 8c5a7fb95..b79ffd3bf 100644 --- a/data/templates/ssh/sshd_config +++ b/data/templates/ssh/sshd_config @@ -94,3 +94,5 @@ Match User sftpusers AllowTcpForwarding no GatewayPorts no X11Forwarding no + +Include sshd_config.d/* diff --git a/locales/en.json b/locales/en.json index d63fc4a69..94e8a6384 100644 --- a/locales/en.json +++ b/locales/en.json @@ -274,6 +274,8 @@ "migration_description_0004_php5_to_php7_pools": "Reconfigure the PHP pools to use PHP 7 instead of 5", "migration_description_0005_postgresql_9p4_to_9p6": "Migrate databases from postgresql 9.4 to 9.6", "migration_description_0006_sync_admin_and_root_passwords": "Synchronize admin and root passwords", + "migration_description_0006_manage_sshd_config": "Manage SSH conf in a better way", + "migration_description_0007_reset_sshd_config": "Reset SSH conf to the YunoHost default conf", "migration_0003_backward_impossible": "The stretch migration cannot be reverted.", "migration_0003_start": "Starting migration to Stretch. The logs will be available in {logfile}.", "migration_0003_patching_sources_list": "Patching the sources.lists ...", diff --git a/src/yunohost/data_migrations/0006_manage_sshd_config.py b/src/yunohost/data_migrations/0006_manage_sshd_config.py index 413c3fefe..d4740192e 100644 --- a/src/yunohost/data_migrations/0006_manage_sshd_config.py +++ b/src/yunohost/data_migrations/0006_manage_sshd_config.py @@ -1,15 +1,17 @@ import subprocess import os +import re from shutil import copyfile from moulinette import m18n from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger +from moulinette.utils.filesystem import mkdir, rm from yunohost.tools import Migration -from yunohost.service import service_regen_conf, _get_conf_hashes, - _calculate_hash +from yunohost.service import service_regen_conf, _get_conf_hashes, \ + _calculate_hash, _run_service_command logger = getActionLogger('yunohost.migration') @@ -24,7 +26,7 @@ class MyMigration(Migration): # Create sshd_config.d dir if not os.path.exists('/etc/ssh/sshd_config.d'): - mkdir('/etc/ssh/sshd_config.d', '0755', uid='root', gid='root') + mkdir('/etc/ssh/sshd_config.d', 0755, uid='root', gid='root') # Manage SSHd in all case if os.path.exists('/etc/yunohost/from_script'): @@ -42,7 +44,7 @@ class MyMigration(Migration): add_include = False include_rgx = r'^[ \t]*Include[ \t]+sshd_config\.d/\*[ \t]*(?:#.*)?$' for line in open('/etc/ssh/sshd_config'): - if re.match(root_rgx, line) is not None: + if re.match(include_rgx, line) is not None: add_include = True break @@ -50,6 +52,9 @@ class MyMigration(Migration): with open("/etc/ssh/sshd_config", "a") as conf: conf.write('Include sshd_config.d/*') + if not _run_service_command('restart', 'ssh'): + self.backward() + def backward(self): raise MoulinetteError(m18n.n("migration_0006_backward_impossible")) diff --git a/src/yunohost/data_migrations/0007_reset_sshd_config.py b/src/yunohost/data_migrations/0007_reset_sshd_config.py index 701b60e3c..a9fb9fa14 100644 --- a/src/yunohost/data_migrations/0007_reset_sshd_config.py +++ b/src/yunohost/data_migrations/0007_reset_sshd_config.py @@ -1,5 +1,6 @@ import subprocess import os +import re from shutil import copyfile @@ -8,7 +9,7 @@ from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger from yunohost.tools import Migration -from yunohost.service import service_regen_conf +from yunohost.service import service_regen_conf, _get_conf_hashes, _calculate_hash logger = getActionLogger('yunohost.migration') @@ -16,8 +17,6 @@ logger = getActionLogger('yunohost.migration') class MyMigration(Migration): "Reset SSH conf to the YunoHost one" - mode = "manual" - def migrate(self): service_regen_conf(names=['ssh'], force=True) @@ -26,26 +25,37 @@ class MyMigration(Migration): raise MoulinetteError(m18n.n("migration_0007_backward_impossible")) @property - def disclaimer(self): + def mode(self): # Avoid having a super long disclaimer - ynh_hash = _get_conf_hashes('ssh')['/etc/ssh/sshd_config'] + ynh_hash = _get_conf_hashes('ssh') + if '/etc/ssh/sshd_config' in ynh_hash: + ynh_hash = ynh_hash['/etc/ssh/sshd_config'] current_hash = _calculate_hash('/etc/ssh/sshd_config') if ynh_hash == current_hash: + return "auto" + + return "manual" + + + @property + def disclaimer(self): + + if self.mode == "auto": return None # Detect major risk to migrate to the new configuration dsa = False + ports = [] + root_login = [] port_rgx = r'^[ \t]*Port[ \t]+(\d+)[ \t]*(?:#.*)?$' - root_rgx = r'^[ \t]*PermitRootLogin[ \t]([\w-]*)[ \t]*(?:#.*)?$' + root_rgx = r'^[ \t]*PermitRootLogin[ \t]([^# \t]*)[ \t]*(?:#.*)?$' dsa_rgx = r'^[ \t]*HostKey[ \t]+/etc/ssh/ssh_host_dsa_key[ \t]*(?:#.*)?$' for line in open('/etc/ssh/sshd_config'): - ports = re.findall(port_rgx, line) + ports = ports + re.findall(port_rgx, line) - root_login = re.match(root_rgx, line) - if root_login is not None: - root_login = root_login.group(1) + root_login = root_login + re.findall(root_rgx, line) if not dsa and re.match(dsa_rgx, line): dsa = True @@ -55,7 +65,7 @@ class MyMigration(Migration): port = ports != ['22'] - root_user = root_login in ['yes'] + root_user = root_login and root_login[-1] != 'no' # Build message message = m18n.n("migration_0007_general_warning")