ssh: Option for disabling password authentication

Closes: #572

[sunil: Reload instead of restart, fix i18n strings]
[sunil: Load augeas minimally, minor cosmetic fixes]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
Nektarios Katakis 2019-10-24 16:52:03 +01:00 committed by Sunil Mohan Adapa
parent caa336babc
commit ddb95752a8
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
4 changed files with 117 additions and 1 deletions

View File

@ -15,7 +15,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Configuration helper for SSH server.
"""
@ -28,6 +27,8 @@ import stat
import subprocess
import sys
import augeas
from plinth import action_utils
@ -47,6 +48,13 @@ def parse_arguments():
set_keys.add_argument('--username')
set_keys.add_argument('--keys')
subparsers.add_parser('get-password-config',
help='Get SSH password auth configuration')
set_password_config = subparsers.add_parser(
'set-password-config', help='Set SSH password auth configuration')
set_password_config.add_argument('--value')
subparsers.required = True
return parser.parse_args()
@ -107,6 +115,33 @@ def subcommand_set_keys(arguments):
os.chmod(key_file_path, stat.S_IRUSR | stat.S_IWUSR)
def _load_augeas():
"""Initialize augeas for this app's configuration file."""
aug = augeas.Augeas(
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Sshd/lens', 'Sshd.lns')
aug.set('/augeas/load/Sshd/incl[last() + 1]', '/etc/ssh/sshd_config')
aug.load()
return aug
def subcommand_get_password_config(_):
"""Retrieve value of password authentication from sshd configuration."""
aug = _load_augeas()
field_path = '/files/etc/ssh/sshd_config/PasswordAuthentication'
get_value = aug.get(field_path)
print(get_value or 'yes')
def subcommand_set_password_config(arguments):
"""Set value of password authentication in sshd configuration."""
aug = _load_augeas()
aug.set('/files/etc/ssh/sshd_config/PasswordAuthentication',
arguments.value)
aug.save()
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()

View File

@ -105,3 +105,9 @@ def get_host_keys():
host_keys.append(match.groupdict())
return host_keys
def is_password_authentication_disabled():
"""Return if ssh password authentication is enabled."""
return actions.superuser_run('ssh',
['get-password-config']).strip() == 'no'

View File

@ -0,0 +1,35 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
"""
FreedomBox configuration form for OpenSSH server.
"""
from django import forms
from django.utils.translation import ugettext_lazy as _
from plinth.forms import AppForm
class SSHServerForm(AppForm):
"""SSH server configuration form."""
password_auth_disabled = forms.BooleanField(
label=_('Disable password authentication'),
help_text=_('Improves security by preventing password guessing. '
'Ensure that you have setup SSH keys in your '
'administrator user account before enabling this option.'),
required=False,
)

View File

@ -17,10 +17,16 @@
"""
Views for the SSH module
"""
from django.contrib import messages
from django.utils.translation import ugettext_lazy as _
from plinth import action_utils, actions
from plinth.modules import ssh
from plinth.views import AppView
from . import is_password_authentication_disabled
from .forms import SSHServerForm
class SshAppView(AppView):
app_id = 'ssh'
@ -28,9 +34,43 @@ class SshAppView(AppView):
description = ssh.description
port_forwarding_info = ssh.port_forwarding_info
template_name = 'ssh.html'
form_class = SSHServerForm
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
context['host_keys'] = ssh.get_host_keys()
return context
def get_initial(self):
"""Initial form value"""
initial = super().get_initial()
initial.update({
'password_auth_disabled': is_password_authentication_disabled(),
})
return initial
def form_valid(self, form):
"""Apply changes from the form"""
old_config = self.get_initial()
new_config = form.cleaned_data
def is_field_changed(field):
return old_config[field] != new_config[field]
passwd_auth_changed = is_field_changed('password_auth_disabled')
if passwd_auth_changed:
if new_config['password_auth_disabled']:
passwd_auth = 'no'
message = _('SSH authentication with password disabled.')
else:
passwd_auth = 'yes'
message = _('SSH authentication with password enabled.')
actions.superuser_run(
'ssh', ['set-password-config', '--value', passwd_auth])
actions.superuser_run('service', ['reload', 'ssh'])
messages.success(self.request, message)
return super().form_valid(form)