Skip to content

Commit 54b333d

Browse files
committed
upstream: add a RequiredRSASize for checking RSA key length in
ssh(1). User authentication keys that fall beneath this limit will be ignored. If a host presents a host key beneath this limit then the connection will be terminated (unfortunately there are no fallbacks in the protocol for host authentication). feedback deraadt, Dmitry Belyavskiy; ok markus@ OpenBSD-Commit-ID: 430e339b2a79fa9ecc63f2837b06fdd88a7da13a
1 parent 07d8771 commit 54b333d

File tree

6 files changed

+67
-17
lines changed

6 files changed

+67
-17
lines changed

readconf.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: readconf.c,v 1.368 2022/06/03 04:30:47 djm Exp $ */
1+
/* $OpenBSD: readconf.c,v 1.369 2022/09/17 10:33:18 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -174,7 +174,7 @@ typedef enum {
174174
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
175175
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
176176
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
177-
oSecurityKeyProvider, oKnownHostsCommand,
177+
oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
178178
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
179179
} OpCodes;
180180

@@ -320,6 +320,7 @@ static struct {
320320
{ "proxyjump", oProxyJump },
321321
{ "securitykeyprovider", oSecurityKeyProvider },
322322
{ "knownhostscommand", oKnownHostsCommand },
323+
{ "requiredrsasize", oRequiredRSASize },
323324

324325
{ NULL, oBadOption }
325326
};
@@ -2176,6 +2177,10 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
21762177
*charptr = xstrdup(arg);
21772178
break;
21782179

2180+
case oRequiredRSASize:
2181+
intptr = &options->required_rsa_size;
2182+
goto parse_int;
2183+
21792184
case oDeprecated:
21802185
debug("%s line %d: Deprecated option \"%s\"",
21812186
filename, linenum, keyword);
@@ -2423,6 +2428,7 @@ initialize_options(Options * options)
24232428
options->hostbased_accepted_algos = NULL;
24242429
options->pubkey_accepted_algos = NULL;
24252430
options->known_hosts_command = NULL;
2431+
options->required_rsa_size = -1;
24262432
}
24272433

24282434
/*
@@ -2619,6 +2625,8 @@ fill_default_options(Options * options)
26192625
if (options->sk_provider == NULL)
26202626
options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
26212627
#endif
2628+
if (options->required_rsa_size == -1)
2629+
options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
26222630

26232631
/* Expand KEX name lists */
26242632
all_cipher = cipher_alg_list(',', 0);
@@ -3308,6 +3316,7 @@ dump_client_config(Options *o, const char *host)
33083316
dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
33093317
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
33103318
dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3319+
dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
33113320

33123321
/* String options */
33133322
dump_cfg_string(oBindAddress, o->bind_address);

readconf.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: readconf.h,v 1.147 2022/06/03 04:30:47 djm Exp $ */
1+
/* $OpenBSD: readconf.h,v 1.148 2022/09/17 10:33:18 djm Exp $ */
22

33
/*
44
* Author: Tatu Ylonen <[email protected]>
@@ -176,6 +176,8 @@ typedef struct {
176176

177177
char *known_hosts_command;
178178

179+
int required_rsa_size; /* minimum size of RSA keys */
180+
179181
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
180182
} Options;
181183

ssh.1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3434
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535
.\"
36-
.\" $OpenBSD: ssh.1,v 1.431 2022/05/28 05:57:56 jmc Exp $
37-
.Dd $Mdocdate: May 28 2022 $
36+
.\" $OpenBSD: ssh.1,v 1.432 2022/09/17 10:33:18 djm Exp $
37+
.Dd $Mdocdate: September 17 2022 $
3838
.Dt SSH 1
3939
.Os
4040
.Sh NAME
@@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see
571571
.It RemoteCommand
572572
.It RemoteForward
573573
.It RequestTTY
574+
.It RequiredRSASize
574575
.It SendEnv
575576
.It ServerAliveInterval
576577
.It ServerAliveCountMax

ssh.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ssh.c,v 1.575 2022/07/01 00:36:30 djm Exp $ */
1+
/* $OpenBSD: ssh.c,v 1.576 2022/09/17 10:33:18 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -516,14 +516,22 @@ resolve_canonicalize(char **hostp, int port)
516516
}
517517

518518
/*
519-
* Check the result of hostkey loading, ignoring some errors and
520-
* fatal()ing for others.
519+
* Check the result of hostkey loading, ignoring some errors and either
520+
* discarding the key or fatal()ing for others.
521521
*/
522522
static void
523-
check_load(int r, const char *path, const char *message)
523+
check_load(int r, struct sshkey **k, const char *path, const char *message)
524524
{
525525
switch (r) {
526526
case 0:
527+
/* Check RSA keys size and discard if undersized */
528+
if (k != NULL && *k != NULL &&
529+
(r = sshkey_check_rsa_length(*k,
530+
options.required_rsa_size)) != 0) {
531+
error_r(r, "load %s \"%s\"", message, path);
532+
free(*k);
533+
*k = NULL;
534+
}
527535
break;
528536
case SSH_ERR_INTERNAL_ERROR:
529537
case SSH_ERR_ALLOC_FAIL:
@@ -1578,15 +1586,16 @@ main(int ac, char **av)
15781586
if ((o) >= sensitive_data.nkeys) \
15791587
fatal_f("pubkey out of array bounds"); \
15801588
check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
1581-
p, "pubkey"); \
1589+
&(sensitive_data.keys[o]), p, "pubkey"); \
15821590
if (sensitive_data.keys[o] != NULL) \
15831591
debug2("hostbased key %d: %s key from \"%s\"", o, \
15841592
sshkey_ssh_name(sensitive_data.keys[o]), p); \
15851593
} while (0)
15861594
#define L_CERT(p,o) do { \
15871595
if ((o) >= sensitive_data.nkeys) \
15881596
fatal_f("cert out of array bounds"); \
1589-
check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
1597+
check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \
1598+
&(sensitive_data.keys[o]), p, "cert"); \
15901599
if (sensitive_data.keys[o] != NULL) \
15911600
debug2("hostbased key %d: %s cert from \"%s\"", o, \
15921601
sshkey_ssh_name(sensitive_data.keys[o]), p); \
@@ -2265,7 +2274,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
22652274
filename = default_client_percent_dollar_expand(cp, cinfo);
22662275
free(cp);
22672276
check_load(sshkey_load_public(filename, &public, NULL),
2268-
filename, "pubkey");
2277+
&public, filename, "pubkey");
22692278
debug("identity file %s type %d", filename,
22702279
public ? public->type : -1);
22712280
free(options.identity_files[i]);
@@ -2284,7 +2293,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
22842293
continue;
22852294
xasprintf(&cp, "%s-cert", filename);
22862295
check_load(sshkey_load_public(cp, &public, NULL),
2287-
filename, "pubkey");
2296+
&public, filename, "pubkey");
22882297
debug("identity file %s type %d", cp,
22892298
public ? public->type : -1);
22902299
if (public == NULL) {
@@ -2315,7 +2324,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
23152324
free(cp);
23162325

23172326
check_load(sshkey_load_public(filename, &public, NULL),
2318-
filename, "certificate");
2327+
&public, filename, "certificate");
23192328
debug("certificate file %s type %d", filename,
23202329
public ? public->type : -1);
23212330
free(options.certificate_files[i]);

ssh_config.5

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3434
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535
.\"
36-
.\" $OpenBSD: ssh_config.5,v 1.373 2022/06/24 04:27:14 djm Exp $
37-
.Dd $Mdocdate: June 24 2022 $
36+
.\" $OpenBSD: ssh_config.5,v 1.374 2022/09/17 10:33:18 djm Exp $
37+
.Dd $Mdocdate: September 17 2022 $
3838
.Dt SSH_CONFIG 5
3939
.Os
4040
.Sh NAME
@@ -1634,6 +1634,17 @@ and
16341634
.Fl T
16351635
flags for
16361636
.Xr ssh 1 .
1637+
.It Cm RequiredRSASize
1638+
Specifies the minimum RSA key size (in bits) that
1639+
.Xr ssh 1
1640+
will accept.
1641+
User authentication keys smaller than this limit will be ignored.
1642+
Servers that present host keys smaller than this limit will cause the
1643+
connection to be terminated.
1644+
The default is
1645+
.Cm 1024
1646+
bits.
1647+
Note that this limit may only be raised from the default.
16371648
.It Cm RevokedHostKeys
16381649
Specifies revoked host public keys.
16391650
Keys listed in this file will be refused for host authentication.

sshconnect2.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: sshconnect2.c,v 1.360 2022/08/19 06:07:47 djm Exp $ */
1+
/* $OpenBSD: sshconnect2.c,v 1.361 2022/09/17 10:33:18 djm Exp $ */
22
/*
33
* Copyright (c) 2000 Markus Friedl. All rights reserved.
44
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -96,6 +96,11 @@ static const struct ssh_conn_info *xxx_conn_info;
9696
static int
9797
verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
9898
{
99+
int r;
100+
101+
if ((r = sshkey_check_rsa_length(hostkey,
102+
options.required_rsa_size)) != 0)
103+
fatal_r(r, "Bad server host key");
99104
if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
100105
xxx_conn_info) == -1)
101106
fatal("Host key verification failed.");
@@ -1606,6 +1611,13 @@ load_identity_file(Identity *id)
16061611
private = NULL;
16071612
quit = 1;
16081613
}
1614+
if (!quit && (r = sshkey_check_rsa_length(private,
1615+
options.required_rsa_size)) != 0) {
1616+
debug_fr(r, "Skipping key %s", id->filename);
1617+
sshkey_free(private);
1618+
private = NULL;
1619+
quit = 1;
1620+
}
16091621
if (!quit && private != NULL && id->agent_fd == -1 &&
16101622
!(id->key && id->isprivate))
16111623
maybe_add_key_to_agent(id->filename, private, comment,
@@ -1752,6 +1764,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
17521764
/* list of keys supported by the agent */
17531765
if ((r = get_agent_identities(ssh, &agent_fd, &idlist)) == 0) {
17541766
for (j = 0; j < idlist->nkeys; j++) {
1767+
if ((r = sshkey_check_rsa_length(idlist->keys[j],
1768+
options.required_rsa_size)) != 0) {
1769+
debug_fr(r, "ignoring %s agent key",
1770+
sshkey_ssh_name(idlist->keys[j]));
1771+
continue;
1772+
}
17551773
found = 0;
17561774
TAILQ_FOREACH(id, &files, next) {
17571775
/*

0 commit comments

Comments
 (0)