[openssh-commits] [openssh] 05/14: upstream: Add WarnWeakCrypto to sshd
git+noreply at mindrot.org
git+noreply at mindrot.org
Wed Sep 16 11:15:59 AEST 2026
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit 813f670ccc086aeb48ca6bf701e6a73c098a65bb
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Wed Sep 16 00:29:44 2026 +0000
upstream: Add WarnWeakCrypto to sshd
This option was previously available for the client only. This adds it to
sshd, so allow logging of non-PQ key exchanges.
ok markus, deraadt
OpenBSD-Commit-ID: 524564b82a7a20a4ff984c948fb75aa2b0f9b707
---
kex.c | 37 ++++++++++++++++++++++++++++++++++++-
kex.h | 7 ++++++-
monitor_wrap.c | 3 ++-
packet.c | 12 +++++++++---
servconf.c | 17 ++++++++++++++++-
servconf.h | 5 +++--
sshconnect.c | 8 ++++++--
sshd-auth.c | 3 ++-
sshd_config.5 | 16 +++++++++++++++-
9 files changed, 95 insertions(+), 13 deletions(-)
diff --git a/kex.c b/kex.c
index b2c3d9720..af9108b7b 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.194 2026/05/31 04:44:38 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.195 2026/09/16 00:29:44 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -289,6 +289,40 @@ kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs)
ssh->kex->server_sig_algs = xstrdup("");
}
+void
+kex_set_warn_weak_crypto(struct ssh *ssh, int warn_weak_crypto)
+{
+ if (ssh != NULL && ssh->kex != NULL)
+ ssh->kex->warn_weak_crypto = warn_weak_crypto != 0;
+}
+
+void
+kex_check_warn_weak_crypto(struct ssh *ssh)
+{
+ char remote_id[512];
+ int rekeyed = 0;
+
+ if (ssh == NULL || ssh->kex == NULL || ssh->kex->name == NULL ||
+ !ssh->kex->warn_weak_crypto || ssh->kex->non_pq_kex_warned)
+ return;
+ if (kex_is_pq_from_name(ssh->kex->name)) {
+ ssh->kex->pq_kex_negotiated = 1;
+ return;
+ }
+
+ if (ssh->kex->pq_kex_negotiated)
+ rekeyed = 1;
+ if (!rekeyed && !ssh->kex->server)
+ return; /* client logs initial KEX warning separately */
+
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
+ logit("WARNING: %sconnection%s%s is not using a post-quantum "
+ "key exchange algorithm: \"%s\"", rekeyed ? "rekeyed " : "",
+ ssh->kex->server ? " from " : "",
+ ssh->kex->server ? remote_id : "", ssh->kex->name);
+ ssh->kex->non_pq_kex_warned = 1;
+}
+
static int
kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m)
{
@@ -567,6 +601,7 @@ kex_input_newkeys(int type, uint32_t seq, struct ssh *ssh)
kex->flags &= ~KEX_INITIAL;
sshbuf_reset(kex->peer);
kex->flags &= ~(KEX_INIT_SENT|KEX_INIT_RECVD);
+ kex_check_warn_weak_crypto(ssh);
return 0;
}
diff --git a/kex.h b/kex.h
index 9816b1d83..4cd6e0b83 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.134 2026/08/08 07:27:54 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.135 2026/09/16 00:29:44 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -164,6 +164,9 @@ struct kex {
struct sshkey *initial_hostkey;
sig_atomic_t done;
u_int flags;
+ u_int warn_weak_crypto;
+ u_int pq_kex_negotiated;
+ u_int non_pq_kex_warned;
int hash_alg;
int ec_nid;
char *failed_choice;
@@ -223,6 +226,8 @@ int kex_send_newkeys(struct ssh *);
int kex_start_rekex(struct ssh *);
int kex_server_update_ext_info(struct ssh *);
void kex_set_server_sig_algs(struct ssh *, const char *);
+void kex_set_warn_weak_crypto(struct ssh *, int);
+void kex_check_warn_weak_crypto(struct ssh *);
int kexgex_client(struct ssh *);
int kexgex_server(struct ssh *);
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 859e10f72..3d68f804f 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.149 2026/09/16 00:13:58 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.150 2026/09/16 00:29:44 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos at citi.umich.edu>
* Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -386,6 +386,7 @@ out:
channel_set_tcp_keepalives(ssh,
options.tcp_keep_alive == SSH_KEEPALIVES_ALL);
kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
+ kex_set_warn_weak_crypto(ssh, options.warn_weak_crypto);
ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
options.rekey_interval);
sshbuf_free(m);
diff --git a/packet.c b/packet.c
index 1909a6670..fe78097d2 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.342 2026/09/14 02:40:27 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.343 2026/09/16 00:29:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -2432,7 +2432,10 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
(r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
(r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
(r = sshbuf_put_stringb(m, kex->session_id)) != 0 ||
- (r = sshbuf_put_u32(m, kex->flags)) != 0)
+ (r = sshbuf_put_u32(m, kex->flags)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->warn_weak_crypto)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->pq_kex_negotiated)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->non_pq_kex_warned)) != 0)
return r;
return 0;
}
@@ -2606,7 +2609,10 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
(r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
(r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
(r = sshbuf_get_stringb(m, kex->session_id)) != 0 ||
- (r = sshbuf_get_u32(m, &kex->flags)) != 0)
+ (r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->warn_weak_crypto)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->pq_kex_negotiated)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->non_pq_kex_warned)) != 0)
goto out;
if (kex->we_need > 1024) {
r = SSH_ERR_INVALID_FORMAT;
diff --git a/servconf.c b/servconf.c
index becf72b81..e7826958f 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.455 2026/09/16 00:25:50 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.456 2026/09/16 00:29:44 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -1107,6 +1107,13 @@ static const struct multistate multistate_keepalives[] = {
{ "no", SSH_KEEPALIVES_OFF },
{ "transport", SSH_KEEPALIVES_TRANSPORT },
{ "all", SSH_KEEPALIVES_ALL },
+};
+static const struct multistate multistate_warnweakcrypto[] = {
+ { "true", 1 },
+ { "false", 0 },
+ { "yes", 1 },
+ { "no", 0 },
+ { "no-pq-kex", 0 },
{ NULL, -1 }
};
@@ -2606,6 +2613,11 @@ process_server_config_line_depth(ServerOptions *options, char *line,
multistate_ptr = multistate_flag;
goto parse_multistate;
+ case sWarnWeakCrypto:
+ intptr = &options->warn_weak_crypto;
+ multistate_ptr = multistate_warnweakcrypto;
+ goto parse_multistate;
+
case sDeprecated:
case sIgnore:
case sUnsupported:
@@ -4140,6 +4152,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_ignore_rhosts);
case sTCPKeepAlive:
return fmt_multistate_int(val, multistate_keepalives);
+ case sWarnWeakCrypto:
+ return fmt_multistate_int(val, multistate_warnweakcrypto);
case sFingerprintHash:
return ssh_digest_alg_name(val);
default:
@@ -4334,6 +4348,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
+ dump_cfg_fmtint(sWarnWeakCrypto, o->warn_weak_crypto);
dump_cfg_fmtint(sRefuseConnection, o->refuse_connection);
/* string arguments */
diff --git a/servconf.h b/servconf.h
index e54e56c62..f31668549 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.182 2026/09/16 00:25:50 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.183 2026/09/16 00:29:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -241,7 +241,8 @@ SSHCONF_INT(unused_connection_timeout, UnusedConnectionTimeout, SSHCFG_ALL, NULL
SSHCONF_STRING(sshd_session_path, SshdSessionPath, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \
SSHCONF_STRING(sshd_auth_path, SshdAuthPath, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \
SSHCONF_INTFLAG(refuse_connection, RefuseConnection, SSHCFG_ALL, 0, SSHCFG_COPY_MATCH) \
-SSHCONF_STRING(agent_socket_path, AgentSocketPath, SSHCFG_ALL, SSHCFG_COPY_MATCH)
+SSHCONF_STRING(agent_socket_path, AgentSocketPath, SSHCFG_ALL, SSHCFG_COPY_MATCH) \
+SSHCONF_INT(warn_weak_crypto, WarnWeakCrypto, SSHCFG_GLOBAL, multistate_warnweakcrypto, 1, SSHCFG_COPY_NONE)
#define SSHD_CONFIG_ENTRIES_LEGACY \
SSHCONF_DEPRECATE(ServerKeyBits, SSHCFG_GLOBAL, SSHCONF_DEPRECATED) \
diff --git a/sshconnect.c b/sshconnect.c
index c8f8e24e1..3349d8e39 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.385 2026/09/16 00:13:58 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.386 2026/09/16 00:29:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -1657,10 +1657,14 @@ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
/* authenticate user */
debug("Authenticating to %s:%d as '%s'", host, port, server_user);
ssh_kex2(ssh, host, hostaddr, port, cinfo);
+ kex_set_warn_weak_crypto(ssh, options.warn_weak_crypto &&
+ !options.kex_algorithms_set);
if (!options.kex_algorithms_set && ssh->kex != NULL &&
ssh->kex->name != NULL && options.warn_weak_crypto &&
- !kex_is_pq_from_name(ssh->kex->name))
+ !kex_is_pq_from_name(ssh->kex->name)) {
warn_nonpq_kex();
+ ssh->kex->non_pq_kex_warned = 1;
+ }
ssh_userauth2(ssh, local_user, server_user, host, sensitive);
free(local_user);
free(host);
diff --git a/sshd-auth.c b/sshd-auth.c
index f1ff432be..3adf1a41e 100644
--- a/sshd-auth.c
+++ b/sshd-auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd-auth.c,v 1.19 2026/09/16 00:13:58 djm Exp $ */
+/* $OpenBSD: sshd-auth.c,v 1.20 2026/09/16 00:29:44 djm Exp $ */
/*
* SSH2 implementation:
* Privilege Separation:
@@ -798,6 +798,7 @@ do_ssh2_kex(struct ssh *ssh)
if ((r = kex_setup(ssh, myproposal)) != 0)
fatal_r(r, "kex_setup");
kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos);
+ kex_set_warn_weak_crypto(ssh, options.warn_weak_crypto);
kex = ssh->kex;
#ifdef WITH_OPENSSL
diff --git a/sshd_config.5 b/sshd_config.5
index bfd208901..f446f094e 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,7 +33,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: sshd_config.5,v 1.406 2026/09/16 00:25:50 djm Exp $
+.\" $OpenBSD: sshd_config.5,v 1.407 2026/09/16 00:29:44 djm Exp $
.Dd $Mdocdate: September 16 2026 $
.Dt SSHD_CONFIG 5
.Os
@@ -2147,6 +2147,20 @@ Optionally specifies additional text to append to the SSH protocol banner
sent by the server upon connection.
The default is
.Cm none .
+.It Cm WarnWeakCrypto
+Controls whether warnings are logged when the cryptographic algorithms
+negotiated for the connection are weak or otherwise recommended against.
+Warnings may be disabled by turning off a specific warning or by disabling
+all warnings.
+Warnings about connections that don't use a post-quantum key exchange
+may be disabled using the
+.Cm no-pq-kex
+flag.
+.Cm no
+will disable all warnings.
+The default, equivalent to
+.Cm yes ,
+is to enable all warnings.
.It Cm X11DisplayOffset
Specifies the first display number available for
.Xr sshd 8 Ns 's
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list