From 40de5b7ffcfa4543f87cfff3f4e10b67515f3fdb Mon Sep 17 00:00:00 2001 From: Birger Schacht Date: Wed, 9 Oct 2019 17:46:47 +0200 Subject: [PATCH] ssh: Show server fingerprints in SSH page - Add a function to the ssh module that returns information about the SSH host keys as dict. - Move SSHAppView to a new ssh/views.py. - Add the ssh host key information to the SSHAppView context. - Create a template for the SSH module. - Display the sshkeys context information in the template below the status area. Closes: #1650 Signed-off-by: Birger Schacht [sunil@medhas.org Minor styling updates for variable names, isort, yapf] [sunil@medhas.org Styling updates on the HTML output for consistency] Signed-off-by: Sunil Mohan Adapa Reviewed-by: Sunil Mohan Adapa --- plinth/modules/ssh/__init__.py | 30 ++++++++++++---- plinth/modules/ssh/templates/ssh.html | 51 +++++++++++++++++++++++++++ plinth/modules/ssh/urls.py | 2 +- plinth/modules/ssh/views.py | 36 +++++++++++++++++++ 4 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 plinth/modules/ssh/templates/ssh.html create mode 100644 plinth/modules/ssh/views.py diff --git a/plinth/modules/ssh/__init__.py b/plinth/modules/ssh/__init__.py index 7d3911cbd..2169ab7a2 100644 --- a/plinth/modules/ssh/__init__.py +++ b/plinth/modules/ssh/__init__.py @@ -18,6 +18,10 @@ FreedomBox app for OpenSSH server. """ +import pathlib +import re +import subprocess + from django.utils.translation import ugettext_lazy as _ from plinth import actions @@ -25,9 +29,8 @@ from plinth import app as app_module from plinth import menu from plinth.daemon import Daemon from plinth.modules.firewall.components import Firewall -from plinth.views import AppView -from .manifest import backup # noqa, pylint: disable=unused-import +from .manifest import backup # noqa, pylint: disable=unused-import version = 1 @@ -84,8 +87,21 @@ def setup(helper, old_version=None): actions.superuser_run('ssh', ['setup']) -class SshAppView(AppView): - app_id = 'ssh' - name = name - description = description - port_forwarding_info = port_forwarding_info +def get_host_keys(): + """Return Host keys of the system.""" + etc_ssh = pathlib.Path('/etc/ssh/') + host_keys = [] + pattern = re.compile(r'^(?P\d+) (?P[\S]+) ' + r'.+ \((?P\w+)\)$') + + for public_key in etc_ssh.glob('*.pub'): + process = subprocess.run(['ssh-keygen', '-l', '-f', + str(public_key)], stdout=subprocess.PIPE, + check=True) + output = process.stdout.decode().strip() + if output: + match = re.match(pattern, output) + if match: + host_keys.append(match.groupdict()) + + return host_keys diff --git a/plinth/modules/ssh/templates/ssh.html b/plinth/modules/ssh/templates/ssh.html new file mode 100644 index 000000000..e9589476c --- /dev/null +++ b/plinth/modules/ssh/templates/ssh.html @@ -0,0 +1,51 @@ +{% extends "app.html" %} +{% comment %} +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +{% endcomment %} +{% load bootstrap %} +{% load i18n %} + +{% block status %} + {{ block.super }} + +

{% trans "Server Fingerprints" %}

+ +

+ {% blocktrans trimmed %} + When connecting to the server, ensure that the fingerprint shown by the + SSH client matches one of these fingerprints. + {% endblocktrans %} +

+ + + + + + + + + + {% for host_key in host_keys %} + + + + + {% endfor %} + +
{% trans "Algorithm" %}{% trans "Fingerprint" %}
{{ host_key.algorithm }}{{ host_key.fingerprint }}
+{% endblock %} diff --git a/plinth/modules/ssh/urls.py b/plinth/modules/ssh/urls.py index e8b1264d3..66d4701c9 100644 --- a/plinth/modules/ssh/urls.py +++ b/plinth/modules/ssh/urls.py @@ -20,7 +20,7 @@ URLs for the Secure Shell Server module. from django.conf.urls import url -from plinth.modules.ssh import SshAppView +from plinth.modules.ssh.views import SshAppView urlpatterns = [ url(r'^sys/ssh/$', SshAppView.as_view(), name='index'), diff --git a/plinth/modules/ssh/views.py b/plinth/modules/ssh/views.py new file mode 100644 index 000000000..83ce5b5f0 --- /dev/null +++ b/plinth/modules/ssh/views.py @@ -0,0 +1,36 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Views for the SSH module +""" + +from plinth.modules import ssh +from plinth.views import AppView + + +class SshAppView(AppView): + app_id = 'ssh' + name = ssh.name + description = ssh.description + port_forwarding_info = ssh.port_forwarding_info + template_name = 'ssh.html' + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(**kwargs) + context['host_keys'] = ssh.get_host_keys() + + return context