diff --git a/src/yunohost/data_migrations/0006_manage_sshd_config.py b/src/yunohost/data_migrations/0006_manage_sshd_config.py new file mode 100644 index 000000000..413c3fefe --- /dev/null +++ b/src/yunohost/data_migrations/0006_manage_sshd_config.py @@ -0,0 +1,56 @@ +import subprocess +import os + +from shutil import copyfile + +from moulinette import m18n +from moulinette.core import MoulinetteError +from moulinette.utils.log import getActionLogger + +from yunohost.tools import Migration +from yunohost.service import service_regen_conf, _get_conf_hashes, + _calculate_hash + +logger = getActionLogger('yunohost.migration') + + +class MyMigration(Migration): + """ + Ensure SSH conf is managed by YunoHost, reapply initial change and setup an + extension dir + """ + + def migrate(self): + + # 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') + + # Manage SSHd in all case + if os.path.exists('/etc/yunohost/from_script'): + rm('/etc/yunohost/from_script') + copyfile('/etc/ssh/sshd_config', '/etc/ssh/sshd_config.restore') + service_regen_conf(names=['ssh'], force=True) + os.rename('/etc/ssh/sshd_config.restore', '/etc/ssh/sshd_config') + + # If custom conf, add 'Include' instruction + ynh_hash = _get_conf_hashes('ssh')['/etc/ssh/sshd_config'] + current_hash = _calculate_hash('/etc/ssh/sshd_config') + if ynh_hash == current_hash: + return + + 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: + add_include = True + break + + if add_include: + with open("/etc/ssh/sshd_config", "a") as conf: + conf.write('Include sshd_config.d/*') + + 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 new file mode 100644 index 000000000..701b60e3c --- /dev/null +++ b/src/yunohost/data_migrations/0007_reset_sshd_config.py @@ -0,0 +1,77 @@ +import subprocess +import os + +from shutil import copyfile + +from moulinette import m18n +from moulinette.core import MoulinetteError +from moulinette.utils.log import getActionLogger + +from yunohost.tools import Migration +from yunohost.service import service_regen_conf + +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) + + def backward(self): + + raise MoulinetteError(m18n.n("migration_0007_backward_impossible")) + + @property + def disclaimer(self): + + # Avoid having a super long disclaimer + ynh_hash = _get_conf_hashes('ssh')['/etc/ssh/sshd_config'] + current_hash = _calculate_hash('/etc/ssh/sshd_config') + if ynh_hash == current_hash: + return None + + # Detect major risk to migrate to the new configuration + dsa = False + port_rgx = r'^[ \t]*Port[ \t]+(\d+)[ \t]*(?:#.*)?$' + root_rgx = r'^[ \t]*PermitRootLogin[ \t]([\w-]*)[ \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) + + root_login = re.match(root_rgx, line) + if root_login is not None: + root_login = root_login.group(1) + + if not dsa and re.match(dsa_rgx, line): + dsa = True + + if len(ports) == 0: + ports = ['22'] + + port = ports != ['22'] + + root_user = root_login in ['yes'] + + # Build message + message = m18n.n("migration_0007_general_warning") + + if port: + message += "\n\n" + m18n.n("migration_0007_port") + + if root_user: + message += "\n\n" + m18n.n("migration_0007_root") + + if dsa: + message += "\n\n" + m18n.n("migration_0007_dsa") + + if port or root_user or dsa: + message += "\n\n" + m18n.n("migration_0007_risk") + else: + message += "\n\n" + m18n.n("migration_0007_no_risk") + + return message