forked from pool/openssh
426 lines
16 KiB
Diff
426 lines
16 KiB
Diff
|
# HG changeset patch
|
||
|
# Parent 681914438b1a02c1940d19204138e9b8eacfda7b
|
||
|
|
||
|
Raise minimal size of DH group parameters to 2048 bits like upstream did in
|
||
|
7.2. 1024b values are believed to be in breaking range for state adversaries
|
||
|
and the default moduli shipped with openssh have been around long enough to
|
||
|
make it more likely for them to be broken.
|
||
|
|
||
|
Also provide an option that allows the client to accept shorter (RFC4419
|
||
|
compliant) parameters.
|
||
|
|
||
|
CVE-2015-4000 (LOGJAM)
|
||
|
bsc#932483
|
||
|
|
||
|
Index: openssh-7.8p1/dh.c
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/dh.c
|
||
|
+++ openssh-7.8p1/dh.c
|
||
|
@@ -43,6 +43,8 @@
|
||
|
#include "misc.h"
|
||
|
#include "ssherr.h"
|
||
|
|
||
|
+int dh_grp_min = DH_GRP_MIN;
|
||
|
+
|
||
|
static int
|
||
|
parse_prime(int linenum, char *line, struct dhgroup *dhg)
|
||
|
{
|
||
|
Index: openssh-7.8p1/dh.h
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/dh.h
|
||
|
+++ openssh-7.8p1/dh.h
|
||
|
@@ -50,6 +50,7 @@ u_int dh_estimate(int);
|
||
|
* Max value from RFC4419.
|
||
|
* Miniumum increased in light of DH precomputation attacks.
|
||
|
*/
|
||
|
+#define DH_GRP_MIN_RFC 1024
|
||
|
#define DH_GRP_MIN 2048
|
||
|
#define DH_GRP_MAX 8192
|
||
|
|
||
|
Index: openssh-7.8p1/kexgexc.c
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/kexgexc.c
|
||
|
+++ openssh-7.8p1/kexgexc.c
|
||
|
@@ -51,6 +51,9 @@
|
||
|
#include "sshbuf.h"
|
||
|
#include "misc.h"
|
||
|
|
||
|
+/* import from dh.c */
|
||
|
+extern int dh_grp_min;
|
||
|
+
|
||
|
static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *);
|
||
|
static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *);
|
||
|
|
||
|
@@ -63,7 +66,7 @@ kexgex_client(struct ssh *ssh)
|
||
|
|
||
|
nbits = dh_estimate(kex->dh_need * 8);
|
||
|
|
||
|
- kex->min = DH_GRP_MIN;
|
||
|
+ kex->min = dh_grp_min;
|
||
|
kex->max = DH_GRP_MAX;
|
||
|
kex->nbits = nbits;
|
||
|
if (datafellows & SSH_BUG_DHGEX_LARGE)
|
||
|
@@ -108,6 +111,12 @@ input_kex_dh_gex_group(int type, u_int32
|
||
|
goto out;
|
||
|
if ((bits = BN_num_bits(p)) < 0 ||
|
||
|
(u_int)bits < kex->min || (u_int)bits > kex->max) {
|
||
|
+ if ((u_int)bits < kex->min && (u_int)bits >= DH_GRP_MIN_RFC)
|
||
|
+ logit("DH parameter offered by the server (%d bits) "
|
||
|
+ "is considered insecure. "
|
||
|
+ "You can lower the accepted the minimum "
|
||
|
+ "via the KexDHMin option.",
|
||
|
+ bits);
|
||
|
r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
|
||
|
goto out;
|
||
|
}
|
||
|
Index: openssh-7.8p1/kexgexs.c
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/kexgexs.c
|
||
|
+++ openssh-7.8p1/kexgexs.c
|
||
|
@@ -54,6 +54,9 @@
|
||
|
#include "sshbuf.h"
|
||
|
#include "misc.h"
|
||
|
|
||
|
+/* import from dh.c */
|
||
|
+extern int dh_grp_min;
|
||
|
+
|
||
|
static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *);
|
||
|
static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *);
|
||
|
|
||
|
@@ -82,13 +85,19 @@ input_kex_dh_gex_request(int type, u_int
|
||
|
kex->nbits = nbits;
|
||
|
kex->min = min;
|
||
|
kex->max = max;
|
||
|
- min = MAXIMUM(DH_GRP_MIN, min);
|
||
|
+ min = MAXIMUM(dh_grp_min, min);
|
||
|
max = MINIMUM(DH_GRP_MAX, max);
|
||
|
- nbits = MAXIMUM(DH_GRP_MIN, nbits);
|
||
|
+ nbits = MAXIMUM(dh_grp_min, nbits);
|
||
|
nbits = MINIMUM(DH_GRP_MAX, nbits);
|
||
|
|
||
|
if (kex->max < kex->min || kex->nbits < kex->min ||
|
||
|
kex->max < kex->nbits || kex->max < DH_GRP_MIN) {
|
||
|
+ if (kex->nbits < kex->min && kex->nbits >= DH_GRP_MIN_RFC)
|
||
|
+ logit("DH parameter requested by the client (%d bits) "
|
||
|
+ "is considered insecure. "
|
||
|
+ "You can lower the accepted minimum "
|
||
|
+ "via the KexDHMin option.",
|
||
|
+ kex->nbits);
|
||
|
r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
|
||
|
goto out;
|
||
|
}
|
||
|
Index: openssh-7.8p1/readconf.c
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/readconf.c
|
||
|
+++ openssh-7.8p1/readconf.c
|
||
|
@@ -67,6 +67,7 @@
|
||
|
#include "uidswap.h"
|
||
|
#include "myproposal.h"
|
||
|
#include "digest.h"
|
||
|
+#include "dh.h"
|
||
|
|
||
|
/* Format of the configuration file:
|
||
|
|
||
|
@@ -167,7 +168,7 @@ typedef enum {
|
||
|
oTunnel, oTunnelDevice,
|
||
|
oLocalCommand, oPermitLocalCommand, oRemoteCommand,
|
||
|
oVisualHostKey,
|
||
|
- oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
|
||
|
+ oKexAlgorithms, oKexDHMin, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
|
||
|
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
||
|
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
||
|
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
|
||
|
@@ -291,6 +292,7 @@ static struct {
|
||
|
{ "remotecommand", oRemoteCommand },
|
||
|
{ "visualhostkey", oVisualHostKey },
|
||
|
{ "kexalgorithms", oKexAlgorithms },
|
||
|
+ { "kexdhmin", oKexDHMin },
|
||
|
{ "ipqos", oIPQoS },
|
||
|
{ "requesttty", oRequestTTY },
|
||
|
{ "proxyusefdpass", oProxyUseFdpass },
|
||
|
@@ -312,6 +314,9 @@ static struct {
|
||
|
{ NULL, oBadOption }
|
||
|
};
|
||
|
|
||
|
+/* import from dh.c */
|
||
|
+extern int dh_grp_min;
|
||
|
+
|
||
|
/*
|
||
|
* Adds a local TCP/IP port forward to options. Never returns if there is an
|
||
|
* error.
|
||
|
@@ -1206,6 +1211,10 @@ parse_int:
|
||
|
options->kex_algorithms = xstrdup(arg);
|
||
|
break;
|
||
|
|
||
|
+ case oKexDHMin:
|
||
|
+ intptr = &options->kex_dhmin;
|
||
|
+ goto parse_int;
|
||
|
+
|
||
|
case oHostKeyAlgorithms:
|
||
|
charptr = &options->hostkeyalgorithms;
|
||
|
parse_keytypes:
|
||
|
@@ -1835,6 +1844,7 @@ initialize_options(Options * options)
|
||
|
options->ciphers = NULL;
|
||
|
options->macs = NULL;
|
||
|
options->kex_algorithms = NULL;
|
||
|
+ options->kex_dhmin = -1;
|
||
|
options->hostkeyalgorithms = NULL;
|
||
|
options->num_identity_files = 0;
|
||
|
options->num_certificate_files = 0;
|
||
|
@@ -1988,6 +1998,13 @@ fill_default_options(Options * options)
|
||
|
options->connection_attempts = 1;
|
||
|
if (options->number_of_password_prompts == -1)
|
||
|
options->number_of_password_prompts = 3;
|
||
|
+ if (options->kex_dhmin == -1)
|
||
|
+ options->kex_dhmin = DH_GRP_MIN;
|
||
|
+ else {
|
||
|
+ options->kex_dhmin = MAXIMUM(options->kex_dhmin, DH_GRP_MIN_RFC);
|
||
|
+ options->kex_dhmin = MINIMUM(options->kex_dhmin, DH_GRP_MAX);
|
||
|
+ }
|
||
|
+ dh_grp_min = options->kex_dhmin;
|
||
|
/* options->hostkeyalgorithms, default set in myproposals.h */
|
||
|
if (options->add_keys_to_agent == -1)
|
||
|
options->add_keys_to_agent = 0;
|
||
|
Index: openssh-7.8p1/readconf.h
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/readconf.h
|
||
|
+++ openssh-7.8p1/readconf.h
|
||
|
@@ -67,6 +67,7 @@ typedef struct {
|
||
|
char *macs; /* SSH2 macs in order of preference. */
|
||
|
char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */
|
||
|
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
|
||
|
+ int kex_dhmin; /* minimum bit length of the DH group parameter */
|
||
|
char *hostname; /* Real host to connect. */
|
||
|
char *host_key_alias; /* hostname alias for .ssh/known_hosts */
|
||
|
char *proxy_command; /* Proxy command for connecting the host. */
|
||
|
Index: openssh-7.8p1/servconf.c
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/servconf.c
|
||
|
+++ openssh-7.8p1/servconf.c
|
||
|
@@ -64,6 +64,10 @@
|
||
|
#include "auth.h"
|
||
|
#include "myproposal.h"
|
||
|
#include "digest.h"
|
||
|
+#include "dh.h"
|
||
|
+
|
||
|
+/* import from dh.c */
|
||
|
+extern int dh_grp_min;
|
||
|
|
||
|
static void add_listen_addr(ServerOptions *, const char *,
|
||
|
const char *, int);
|
||
|
@@ -146,6 +150,7 @@ initialize_server_options(ServerOptions
|
||
|
options->ciphers = NULL;
|
||
|
options->macs = NULL;
|
||
|
options->kex_algorithms = NULL;
|
||
|
+ options->kex_dhmin = -1;
|
||
|
options->fwd_opts.gateway_ports = -1;
|
||
|
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
|
||
|
options->fwd_opts.streamlocal_bind_unlink = -1;
|
||
|
@@ -263,6 +268,14 @@ fill_default_server_options(ServerOption
|
||
|
if (options->use_pam_check_locks == -1)
|
||
|
options->use_pam_check_locks = 0;
|
||
|
|
||
|
+ if (options->kex_dhmin == -1)
|
||
|
+ options->kex_dhmin = DH_GRP_MIN;
|
||
|
+ else {
|
||
|
+ options->kex_dhmin = MAXIMUM(options->kex_dhmin, DH_GRP_MIN_RFC);
|
||
|
+ options->kex_dhmin = MINIMUM(options->kex_dhmin, DH_GRP_MAX);
|
||
|
+ }
|
||
|
+ dh_grp_min = options->kex_dhmin;
|
||
|
+
|
||
|
/* Standard Options */
|
||
|
if (options->num_host_key_files == 0) {
|
||
|
/* fill default hostkeys for protocols */
|
||
|
@@ -490,7 +503,7 @@ typedef enum {
|
||
|
sHostCertificate,
|
||
|
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
|
||
|
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
|
||
|
- sKexAlgorithms, sIPQoS, sVersionAddendum,
|
||
|
+ sKexAlgorithms, sKexDHMin, sIPQoS, sVersionAddendum,
|
||
|
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
|
||
|
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
||
|
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
||
|
@@ -631,6 +644,7 @@ static struct {
|
||
|
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
|
||
|
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
|
||
|
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
|
||
|
+ { "kexdhmin", sKexDHMin },
|
||
|
{ "ipqos", sIPQoS, SSHCFG_ALL },
|
||
|
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
|
||
|
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||
|
@@ -1726,6 +1740,10 @@ process_server_config_line(ServerOptions
|
||
|
options->kex_algorithms = xstrdup(arg);
|
||
|
break;
|
||
|
|
||
|
+ case sKexDHMin:
|
||
|
+ intptr = &options->kex_dhmin;
|
||
|
+ goto parse_int;
|
||
|
+
|
||
|
case sSubsystem:
|
||
|
if (options->num_subsystems >= MAX_SUBSYSTEMS) {
|
||
|
fatal("%s line %d: too many subsystems defined.",
|
||
|
@@ -2540,6 +2558,7 @@ dump_config(ServerOptions *o)
|
||
|
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
|
||
|
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
|
||
|
dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
|
||
|
+ dump_cfg_int(sKexDHMin, o->kex_dhmin);
|
||
|
|
||
|
/* formatted integer arguments */
|
||
|
dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
|
||
|
Index: openssh-7.8p1/servconf.h
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/servconf.h
|
||
|
+++ openssh-7.8p1/servconf.h
|
||
|
@@ -103,6 +103,7 @@ typedef struct {
|
||
|
char *ciphers; /* Supported SSH2 ciphers. */
|
||
|
char *macs; /* Supported SSH2 macs. */
|
||
|
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
|
||
|
+ int kex_dhmin; /* minimum bit length of the DH group parameter */
|
||
|
struct ForwardOptions fwd_opts; /* forwarding options */
|
||
|
SyslogFacility log_facility; /* Facility for system logging. */
|
||
|
LogLevel log_level; /* Level for system logging. */
|
||
|
Index: openssh-7.8p1/ssh_config
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/ssh_config
|
||
|
+++ openssh-7.8p1/ssh_config
|
||
|
@@ -17,6 +17,11 @@
|
||
|
# list of available options, their meanings and defaults, please see the
|
||
|
# ssh_config(5) man page.
|
||
|
|
||
|
+# Minimum accepted size of the DH parameter p. By default this is set to 1024
|
||
|
+# to maintain compatibility with RFC4419, but should be set higher.
|
||
|
+# Upstream default is identical to setting this to 2048.
|
||
|
+#KexDHMin 1024
|
||
|
+
|
||
|
Host *
|
||
|
# ForwardAgent no
|
||
|
# ForwardX11 no
|
||
|
Index: openssh-7.8p1/ssh_config.0
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/ssh_config.0
|
||
|
+++ openssh-7.8p1/ssh_config.0
|
||
|
@@ -595,6 +595,23 @@ DESCRIPTION
|
||
|
The list of available key exchange algorithms may also be
|
||
|
obtained using "ssh -Q kex".
|
||
|
|
||
|
+ KexDHMin
|
||
|
+ Specifies the minimum accepted bit length of the DH group
|
||
|
+ parameter p.
|
||
|
+
|
||
|
+ As per RFC4419, this is 1024 bits, however this has increasingly
|
||
|
+ been seen as insecure, which prompted the change to 2048 bits.
|
||
|
+ Setting this option allows the client to accept parameters shorter
|
||
|
+ than the current minimum, down to the RFC specified 1024 bits.
|
||
|
+ Using this option may be needed when connecting to servers that
|
||
|
+ only know short DH group parameters.
|
||
|
+
|
||
|
+ Note, that while by default this option is set to 1024 to maintain
|
||
|
+ maximum backward compatibility, using it can severly impact
|
||
|
+ security and thus should be viewed as a temporary fix of last
|
||
|
+ resort and all efforts should be made to fix the (broken)
|
||
|
+ counterparty.
|
||
|
+
|
||
|
LocalCommand
|
||
|
Specifies a command to execute on the local machine after
|
||
|
successfully connecting to the server. The command string
|
||
|
Index: openssh-7.8p1/ssh_config.5
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/ssh_config.5
|
||
|
+++ openssh-7.8p1/ssh_config.5
|
||
|
@@ -1025,6 +1025,22 @@ diffie-hellman-group14-sha1
|
||
|
.Pp
|
||
|
The list of available key exchange algorithms may also be obtained using
|
||
|
.Qq ssh -Q kex .
|
||
|
+.It Cm KexDHMin
|
||
|
+Specifies the minimum accepted bit length of the DH group
|
||
|
+parameter p.
|
||
|
+.Pp
|
||
|
+As per RFC4419, this is 1024 bits, however this has increasingly
|
||
|
+been seen as insecure, which prompted the change to 2048 bits.
|
||
|
+Setting this option allows the client to accept parameters shorter
|
||
|
+than the current minimum, down to the RFC specified 1024 bits.
|
||
|
+Using this option may be needed when connecting to servers that
|
||
|
+only know short DH group parameters.
|
||
|
+.Pp
|
||
|
+Note, that while by default this option is set to 1024 to maintain
|
||
|
+maximum backward compatibility, using it can severly impact
|
||
|
+security and thus should be viewed as a temporary fix of last
|
||
|
+resort and all efforts should be made to fix the (broken)
|
||
|
+counterparty.
|
||
|
.It Cm LocalCommand
|
||
|
Specifies a command to execute on the local machine after successfully
|
||
|
connecting to the server.
|
||
|
Index: openssh-7.8p1/sshd_config
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/sshd_config
|
||
|
+++ openssh-7.8p1/sshd_config
|
||
|
@@ -19,6 +19,13 @@
|
||
|
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||
|
#HostKey /etc/ssh/ssh_host_ed25519_key
|
||
|
|
||
|
+# Minimum accepted size of the DH parameter p. The default, which replicates
|
||
|
+# upstream behaviour, is 2048. To maintain compatibility with RFC4419 it should
|
||
|
+# be set to 1024.
|
||
|
+# You will also need to add a HostKey directive to load a DSA key (typically
|
||
|
+# located in /etc/ssh/ssh_host_dsa_key), which is not loaded by default.
|
||
|
+#KexDHMin 2048
|
||
|
+
|
||
|
# Ciphers and keying
|
||
|
#RekeyLimit default none
|
||
|
|
||
|
Index: openssh-7.8p1/sshd_config.0
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/sshd_config.0
|
||
|
+++ openssh-7.8p1/sshd_config.0
|
||
|
@@ -545,6 +545,23 @@ DESCRIPTION
|
||
|
The list of available key exchange algorithms may also be
|
||
|
obtained using "ssh -Q kex".
|
||
|
|
||
|
+ KexDHMin
|
||
|
+ Specifies the minimum accepted bit length of the DH group
|
||
|
+ parameter p.
|
||
|
+
|
||
|
+ As per RFC4419, this is 1024 bits, however this has increasingly
|
||
|
+ been seen as insecure, which prompted the change to 2048 bits.
|
||
|
+ Setting this option allows the server to accept parameters shorter
|
||
|
+ than the current minimum, down to the RFC specified 1024 bits.
|
||
|
+ Using this option may be needed when some of the connectiong
|
||
|
+ clients only know short DH group parameters.
|
||
|
+
|
||
|
+ Note, that while by default this option is set to 1024 to maintain
|
||
|
+ maximum backward compatibility, using it can severly impact
|
||
|
+ security and thus should be viewed as a temporary fix of last
|
||
|
+ resort and all efforts should be made to fix the (broken)
|
||
|
+ counterparty.
|
||
|
+
|
||
|
ListenAddress
|
||
|
Specifies the local addresses sshd(8) should listen on. The
|
||
|
following forms may be used:
|
||
|
Index: openssh-7.8p1/sshd_config.5
|
||
|
===================================================================
|
||
|
--- openssh-7.8p1.orig/sshd_config.5
|
||
|
+++ openssh-7.8p1/sshd_config.5
|
||
|
@@ -912,6 +912,22 @@ diffie-hellman-group14-sha256,diffie-hel
|
||
|
.Pp
|
||
|
The list of available key exchange algorithms may also be obtained using
|
||
|
.Qq ssh -Q kex .
|
||
|
+.It Cm KexDHMin
|
||
|
+Specifies the minimum accepted bit length of the DH group
|
||
|
+parameter p.
|
||
|
+.Pp
|
||
|
+As per RFC4419, this is 1024 bits, however this has increasingly
|
||
|
+been seen as insecure, which prompted the change to 2048 bits.
|
||
|
+Setting this option allows the server to accept parameters shorter
|
||
|
+than the current minimum, down to the RFC specified 1024 bits.
|
||
|
+Using this option may be needed when some of the connectiong
|
||
|
+clients only know short DH group parameters.
|
||
|
+.Pp
|
||
|
+Note, that while by default this option is set to 1024 to maintain
|
||
|
+maximum backward compatibility, using it can severly impact
|
||
|
+security and thus should be viewed as a temporary fix of last
|
||
|
+resort and all efforts should be made to fix the (broken)
|
||
|
+counterparty.
|
||
|
.It Cm ListenAddress
|
||
|
Specifies the local addresses
|
||
|
.Xr sshd 8
|