system: generic rewrite of ssh advanced opts

o Batch the backend call calling from GUI once and
  only if needed from configuration.
o Turn the configuration into a generic loop.
o Move advanced options to the back of the configuration.
o Warning level for both log messages.
This commit is contained in:
Franco Fichtner 2022-01-18 16:39:18 +01:00
parent 7e1e676b53
commit 17b294b38e
4 changed files with 66 additions and 86 deletions

View File

@ -3,7 +3,7 @@
/*
* Copyright (C) 2004 Scott Ullrich <sullrich@gmail.com>
* Copyright (C) 2004 Fred Mol <fredmol@xs4all.nl>
* Copyright (C) 2015-2021 Franco Fichtner <franco@opnsense.org>
* Copyright (C) 2015-2022 Franco Fichtner <franco@opnsense.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -87,24 +87,6 @@ function openssh_stop()
mwexecf('/bin/pkill -af %s', '/usr/local/sbin/sshd', true);
}
function openssh_check_querylist($list, $config)
{
$supported = json_decode(configd_run("openssh query {$list}"));
$selected = [];
foreach (explode(',', $config) as $elem) {
if (in_array($elem, $supported)) {
$selected[] = $elem;
} else {
syslog(LOG_NOTICE, "OpenSSH: Configured value '{$elem}' of {$list} setting not suppored.");
}
}
if (count($selected) == 0) {
syslog(LOG_WARNING, "OpenSSH: No configured {$list} ({$config}) supported - using defaults.");
}
return implode(',', $selected);
}
function openssh_configure_do($verbose = false, $interface = '')
{
global $config;
@ -209,36 +191,6 @@ function openssh_configure_do($verbose = false, $interface = '')
$sshconf .= "ChallengeResponseAuthentication no\n";
$sshconf .= "PasswordAuthentication no\n";
}
if (!empty($sshcfg['kex'])) {
$kexs = openssh_check_querylist('kex', $sshcfg['kex']);
if (strlen($kexs) > 0) {
$sshconf .= "KexAlgorithms {$kexs}\n";
}
}
if (!empty($sshcfg['ciphers'])) {
$ciphers = openssh_check_querylist('cipher', $sshcfg['ciphers']);
if (strlen($ciphers) > 0) {
$sshconf .= "Ciphers {$ciphers}\n";
}
}
if (!empty($sshcfg['macs'])) {
$macs = openssh_check_querylist('mac', $sshcfg['macs']);
if (strlen($macs) > 0) {
$sshconf .= "MACs {$macs}\n";
}
}
if (!empty($sshcfg['keys'])) {
$keys = openssh_check_querylist('key', $sshcfg['keys']);
if (strlen($keys) > 0) {
$sshconf .= "HostKeyAlgorithms {$keys}\n";
}
}
if (!empty($sshcfg['keysig'])) {
$keysigs = openssh_check_querylist('key-sig', $sshcfg['keysig']);
if (strlen($keysigs) > 0) {
$sshconf .= "PubkeyAcceptedAlgorithms {$keysigs}\n";
}
}
foreach ($keys_all as $name) {
$file = "/conf/sshd/{$name}";
@ -272,6 +224,42 @@ function openssh_configure_do($verbose = false, $interface = '')
$sshconf .= "ListenAddress {$listener}\n";
}
$supported = null;
$advanced = [
[ 'config' => 'Ciphers', 'node' => 'ciphers', 'key' => 'cipher'],
[ 'config' => 'HostKeyAlgorithms', 'node' => 'keys', 'key' => 'key'],
[ 'config' => 'KexAlgorithms', 'node' => 'kex', 'key' => 'kex'],
[ 'config' => 'MACs', 'node' => 'macs', 'key' => 'mac'],
[ 'config' => 'PubkeyAcceptedAlgorithms', 'node' => 'keysig', 'key' => 'key-sig'],
];
foreach ($advanced as $adv) {
if (empty($sshcfg[$adv['node']])) {
continue;
}
if ($supported === null) {
/* cache return as it includes all probable values */
$supported = json_decode(configd_run('openssh query'), true);
}
$selected = [];
foreach (explode(',', $sshcfg[$adv['node']]) as $elem) {
if (in_array($elem, $supported[$adv['key']])) {
$selected[] = $elem;
} else {
syslog(LOG_WARNING, "OpenSSH: Configured {$adv['node']} value '{$elem}' is not supported.");
}
}
if (count($selected) == 0) {
syslog(LOG_WARNING, "OpenSSH: No configured {$adv['node']} value is supported - using defaults.");
} else {
$sshconf .= $adv['config'] . ' ' . implode(',', $selected) . PHP_EOL;
}
}
file_put_contents("/usr/local/etc/ssh/sshd_config", $sshconf);
if ($verbose) {

View File

@ -30,14 +30,18 @@ import subprocess
import ujson
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('option', help='query option', choices=['kex', 'mac', 'cipher' ,'key', 'key-sig'])
args = parser.parse_args()
opts = ['kex', 'mac', 'cipher' ,'key', 'key-sig']
if __name__ == '__main__':
result = dict()
for opt in opts:
partial = list()
for l in subprocess.run(['/usr/local/bin/ssh', '-Q', opt], capture_output=True).stdout.decode().split('\n'):
if len(l.strip()) > 1:
partial.append(l.strip())
sorted(partial)
result[opt] = partial
result = list()
for l in subprocess.run(['/usr/local/bin/ssh', '-Q', args.option], capture_output=True).stdout.decode().split('\n'):
if len(l.strip()) > 1:
result.append(l.strip())
sorted(result)
print(ujson.dumps(result))

View File

@ -2,23 +2,23 @@
command:/usr/local/etc/rc.sshd
parameters:
type:script
message:starting openssh
message:Starting OpenSSH
[restart]
command:/usr/local/etc/rc.sshd
parameters:
type:script
message:restarting openssh
message:Restarting OpenSSH
description:Restart OpenSSH service
[stop]
command:/bin/pkill -TERM sshd
parameters:
type:script
message:stopping openssh
message:Stopping OpenSSH
[query]
command:/usr/local/opnsense/scripts/openssh/ssh_query.py
parameters: %s
parameters:
type:script_output
message: query options %s
message:Query OpenSSH options

View File

@ -366,6 +366,8 @@ if (empty($pconfig['webguiproto']) || !$certs_available) {
$pconfig['webguiproto'] = "http";
}
$sshoptions = json_decode(configd_run('openssh query'), true);
legacy_html_escape_form_data($pconfig);
legacy_html_escape_form_data($a_group);
@ -770,21 +772,18 @@ $(document).ready(function() {
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?=gettext("Advanced");?></td>
<td>
<button id="show-advanced-cryptocryptobtn" class="btn btn-xs btn-default" value="yes"><?= gettext('Show cryptographic option') ?></button>
<button id="show-advanced-cryptocryptobtn" class="btn btn-xs btn-default" value="yes"><?= gettext('Show cryptographic overrides') ?></button>
</td>
</tr>
<tr class="show-advanced-crypto" style="display:none">
<td><a id="help_for_sshkex" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Key exchange algorithms"); ?></td>
<td>
<select name="ssh-kex[]" class="selectpicker advanced-crypto" multiple="multiple" data-live-search="true" title="<?=gettext("System defaults");?>">
<?php
$options = json_decode(configd_run("openssh query kex"), true);
foreach ($options = empty($options) ? array() : $options as $option):?>
<?php foreach ($options = empty($sshoptions['kex']) ? [] : $sshoptions['kex'] as $option): ?>
<option value="<?=$option;?>" <?= !empty($pconfig['ssh-kex']) && in_array($option, $pconfig['ssh-kex']) ? 'selected="selected"' : '' ?>>
<?=$option;?>
</option>
<?php
endforeach;?>
<?php endforeach ?>
</select>
<div class="hidden" data-for="help_for_sshkex">
<?=gettext("The key exchange methods that are used to generate per-connection keys");?>
@ -795,14 +794,11 @@ $(document).ready(function() {
<td><a id="help_for_sshciphers" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Ciphers"); ?></td>
<td>
<select name="ssh-ciphers[]" class="selectpicker advanced-crypto" multiple="multiple" data-live-search="true" title="<?=gettext("System defaults");?>">
<?php
$options = json_decode(configd_run("openssh query cipher"), true);
foreach ($options = empty($options) ? array() : $options as $option):?>
<?php foreach ($options = empty($sshoptions['cipher']) ? [] : $sshoptions['cipher'] as $option): ?>
<option value="<?=$option;?>" <?= !empty($pconfig['ssh-ciphers']) && in_array($option, $pconfig['ssh-ciphers']) ? 'selected="selected"' : '' ?>>
<?=$option;?>
</option>
<?php
endforeach;?>
<?php endforeach ?>
</select>
<div class="hidden" data-for="help_for_sshciphers">
<?=gettext("The ciphers to encrypt the connection");?>
@ -813,9 +809,7 @@ $(document).ready(function() {
<td><a id="help_for_sshmacs" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("MACs"); ?></td>
<td>
<select name="ssh-macs[]" class="selectpicker advanced-crypto" multiple="multiple" data-live-search="true" title="<?=gettext("System defaults");?>">
<?php
$options = json_decode(configd_run("openssh query mac"), true);
foreach ($options = empty($options) ? array() : $options as $option):?>
<?php foreach ($options = empty($sshoptions['mac']) ? [] : $sshoptions['mac'] as $option): ?>
<option value="<?=$option;?>" <?= !empty($pconfig['ssh-macs']) && in_array($option, $pconfig['ssh-macs']) ? 'selected="selected"' : '' ?>>
<?=$option;?>
</option>
@ -831,14 +825,11 @@ $(document).ready(function() {
<td><a id="help_for_sshkeys" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Host key algorithms"); ?></td>
<td>
<select name="ssh-keys[]" class="selectpicker advanced-crypto" multiple="multiple" data-live-search="true" title="<?=gettext("System defaults");?>">
<?php
$options = json_decode(configd_run("openssh query key"), true);
foreach ($options = empty($options) ? array() : $options as $option):?>
<?php foreach ($options = empty($sshoptions['key']) ? [] : $sshoptions['key'] as $option): ?>
<option value="<?=$option;?>" <?= !empty($pconfig['ssh-keys']) && in_array($option, $pconfig['ssh-keys']) ? 'selected="selected"' : '' ?>>
<?=$option;?>
</option>
<?php
endforeach;?>
<?php endforeach ?>
</select>
<div class="hidden" data-for="help_for_sshkeys">
<?=gettext("Specifies the host key algorithms that the server offers");?>
@ -849,14 +840,11 @@ $(document).ready(function() {
<td><a id="help_for_sshkeysig" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Public key signature algorithms"); ?></td>
<td>
<select name="ssh-keysig[]" class="selectpicker advanced-crypto" multiple="multiple" data-live-search="true" title="<?=gettext("System defaults");?>">
<?php
$options = json_decode(configd_run("openssh query key-sig"), true);
foreach ($options = empty($options) ? array() : $options as $option):?>
<?php foreach ($options = empty($sshoptions['key-sig']) ? [] : $sshoptions['key-sig'] as $option): ?>
<option value="<?=$option;?>" <?= !empty($pconfig['ssh-keysig']) && in_array($option, $pconfig['ssh-keysig']) ? 'selected="selected"' : '' ?>>
<?=$option;?>
</option>
<?php
endforeach;?>
<?php endforeach ?>
</select>
<div class="hidden" data-for="help_for_sshkeysig">
<?=gettext("The signature algorithms that are used for public key authentication");?>