import openssh-8.7p1-28.el9

This commit is contained in:
CentOS Sources 2023-03-28 09:20:54 +00:00 committed by Stepan Oksanichenko
parent 044f5935ef
commit 7f53c0e133
6 changed files with 378 additions and 124 deletions

View File

@ -1,6 +1,14 @@
diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c
--- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200
+++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200
@@ -36,6 +36,7 @@
#include <openssl/bn.h>
#include <openssl/dh.h>
+#include <openssl/fips.h>
#include "dh.h"
#include "pathnames.h"
@@ -164,6 +164,12 @@ choose_dh(int min, int wantbits, int max
int best, bestcount, which, linenum;
struct dhgroup dhg;
@ -67,6 +75,14 @@ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h
diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c
--- openssh-8.6p1/kex.c.fips 2021-05-06 12:08:36.489926807 +0200
+++ openssh-8.6p1/kex.c 2021-05-06 12:08:36.498926877 +0200
@@ -39,6 +39,7 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include <openssl/dh.h>
# ifdef HAVE_EVP_KDF_CTX_NEW_ID
# include <openssl/kdf.h>
@@ -203,7 +203,10 @@ kex_names_valid(const char *names)
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
@ -86,7 +102,7 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c
#ifdef WITH_OPENSSL
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include <sys/types.h>
#include <openssl/dh.h>
@ -154,6 +170,14 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h
diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c
--- openssh-8.6p1/readconf.c.fips 2021-05-06 12:08:36.428926336 +0200
+++ openssh-8.6p1/readconf.c 2021-05-06 12:08:36.499926885 +0200
@@ -39,6 +39,7 @@
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
+#include <openssl/fips.h>
#ifdef USE_SYSTEM_GLOB
# include <glob.h>
#else
@@ -2538,11 +2538,16 @@ fill_default_options(Options * options)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
@ -192,6 +216,14 @@ diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-secco
diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c
--- openssh-8.6p1/servconf.c.fips 2021-05-06 12:08:36.455926545 +0200
+++ openssh-8.6p1/servconf.c 2021-05-06 12:08:36.500926893 +0200
@@ -38,6 +38,7 @@
#include <limits.h>
#include <stdarg.h>
#include <errno.h>
+#include <openssl/fips.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
@@ -226,11 +226,16 @@ assemble_algorithms(ServerOptions *o)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
@ -221,7 +253,7 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@ -243,7 +275,7 @@ diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c
#include <vis.h>
#endif
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
+
#include "openbsd-compat/sys-queue.h"
@ -332,7 +364,7 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include "openbsd-compat/openssl-compat.h"
#endif
@ -395,7 +427,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
#endif
#include "crypto_api.h"
@ -482,6 +514,14 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
--- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200
+++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200
@@ -20,6 +20,7 @@
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
+#include <openssl/fips.h>
#include <openssl/pem.h>
#include "openbsd-compat/openssl-compat.h"
#endif
@@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na
#endif
}
@ -521,7 +561,7 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
#include <stdio.h>
#include <string.h>
#include <signal.h>
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include "sshkey.h"
#include "kex.h"
@ -607,7 +647,7 @@ diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c
#include <string.h>
#include <stdarg.h>
+#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include "log.h"
#include "sshbuf.h"

View File

@ -1,184 +1,188 @@
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 2ab222ed6..4e9437912 100644
index 36b9d2f5..6b517db4 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -118,6 +118,10 @@ userauth_hostbased(struct ssh *ssh, const char *method)
@@ -119,6 +119,11 @@ userauth_hostbased(struct ssh *ssh, const char *method)
"(null)" : key->cert->signature_type);
goto done;
}
+ if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) {
+ logit("refusing %s key", sshkey_type(key));
+ if ((r = sshkey_check_rsa_length(key,
+ options.required_rsa_size)) != 0) {
+ logit_r(r, "refusing %s key", sshkey_type(key));
+ goto done;
+ }
if (!authctxt->valid || authctxt->user == NULL) {
debug2_f("disabled because of invalid user");
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index daa756a01..68e7dea1f 100644
index 962fd342..5d59febc 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -172,6 +172,10 @@ userauth_pubkey(struct ssh *ssh, const char *method)
@@ -175,6 +175,11 @@ userauth_pubkey(struct ssh *ssh, const char *method)
"(null)" : key->cert->signature_type);
goto done;
}
+ if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) {
+ logit("refusing %s key", sshkey_type(key));
+ if ((r = sshkey_check_rsa_length(key,
+ options.required_rsa_size)) != 0) {
+ logit_r(r, "refusing %s key", sshkey_type(key));
+ goto done;
+ }
key_s = format_key(key);
if (sshkey_is_cert(key))
ca_s = format_key(key->cert->signature_key);
diff --git a/readconf.c b/readconf.c
index 5b5afa8e3..5e17abd41 100644
index 7f26c680..42be690b 100644
--- a/readconf.c
+++ b/readconf.c
@@ -160,7 +160,7 @@ typedef enum {
@@ -174,7 +174,7 @@ typedef enum {
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
- oSecurityKeyProvider, oKnownHostsCommand,
+ oSecurityKeyProvider, oKnownHostsCommand, oRSAMinSize,
+ oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@@ -306,6 +306,7 @@ static struct {
@@ -320,6 +320,8 @@ static struct {
{ "proxyjump", oProxyJump },
{ "securitykeyprovider", oSecurityKeyProvider },
{ "knownhostscommand", oKnownHostsCommand },
+ { "rsaminsize", oRSAMinSize },
+ { "requiredrsasize", oRequiredRSASize },
+ { "rsaminsize", oRequiredRSASize }, /* alias */
{ NULL, oBadOption }
};
@@ -2162,6 +2163,10 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
@@ -2176,6 +2177,10 @@ parse_pubkey_algos:
*charptr = xstrdup(arg);
break;
+ case oRSAMinSize:
+ intptr = &options->rsa_min_size;
+ case oRequiredRSASize:
+ intptr = &options->required_rsa_size;
+ goto parse_int;
+
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@@ -2409,6 +2414,7 @@ initialize_options(Options * options)
@@ -2423,6 +2428,7 @@ initialize_options(Options * options)
options->hostbased_accepted_algos = NULL;
options->pubkey_accepted_algos = NULL;
options->known_hosts_command = NULL;
+ options->rsa_min_size = -1;
+ options->required_rsa_size = -1;
}
/*
@@ -2598,6 +2604,8 @@ fill_default_options(Options * options)
@@ -2619,6 +2625,8 @@ fill_default_options(Options * options)
if (options->sk_provider == NULL)
options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
#endif
+ if (options->rsa_min_size == -1)
+ options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
+ if (options->required_rsa_size == -1)
+ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
/* Expand KEX name lists */
all_cipher = cipher_alg_list(',', 0);
@@ -3287,6 +3295,7 @@ dump_client_config(Options *o, const char *host)
@@ -3308,6 +3316,7 @@ dump_client_config(Options *o, const char *host)
dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
+ dump_cfg_int(oRSAMinSize, o->rsa_min_size);
+ dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
/* String options */
dump_cfg_string(oBindAddress, o->bind_address);
diff --git a/readconf.h b/readconf.h
index f647bd42a..29db353ab 100644
index f647bd42..ffb5ec4f 100644
--- a/readconf.h
+++ b/readconf.h
@@ -176,6 +176,8 @@ typedef struct {
char *known_hosts_command;
+ int rsa_min_size; /* minimum size of RSA keys */
+ int required_rsa_size; /* minimum size of RSA keys */
+
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
diff --git a/servconf.c b/servconf.c
index f7317a5cb..362ff5b67 100644
index 29df0463..423772b1 100644
--- a/servconf.c
+++ b/servconf.c
@@ -177,6 +177,7 @@ initialize_server_options(ServerOptions *options)
@@ -195,6 +195,7 @@ initialize_server_options(ServerOptions *options)
options->fingerprint_hash = -1;
options->disable_forwarding = -1;
options->expose_userauth_info = -1;
+ options->rsa_min_size = -1;
+ options->required_rsa_size = -1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -416,6 +417,8 @@ fill_default_server_options(ServerOptions *options)
@@ -441,6 +442,8 @@ fill_default_server_options(ServerOptions *options)
options->expose_userauth_info = 0;
if (options->sk_provider == NULL)
options->sk_provider = xstrdup("internal");
+ if (options->rsa_min_size == -1)
+ options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
+ if (options->required_rsa_size == -1)
+ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
assemble_algorithms(options);
@@ -489,6 +492,7 @@ typedef enum {
@@ -517,6 +520,7 @@ typedef enum {
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
+ sRSAMinSize,
+ sRequiredRSASize,
sDeprecated, sIgnore, sUnsupported
} ServerOpCodes;
@@ -632,6 +636,7 @@ static struct {
@@ -676,6 +680,8 @@ static struct {
{ "rdomain", sRDomain, SSHCFG_ALL },
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
+ { "rsaminsize", sRSAMinSize, SSHCFG_ALL },
+ { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
+ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */
{ NULL, sBadOption, 0 }
};
@@ -2377,6 +2382,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
@@ -2438,6 +2443,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
*charptr = xstrdup(arg);
break;
+ case sRSAMinSize:
+ intptr = &options->rsa_min_size;
+ case sRequiredRSASize:
+ intptr = &options->required_rsa_size;
+ goto parse_int;
+
case sDeprecated:
case sIgnore:
case sUnsupported:
@@ -2549,6 +2558,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
@@ -2610,6 +2619,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
M_CP_INTOPT(log_level);
+ M_CP_INTOPT(rsa_min_size);
+ M_CP_INTOPT(required_rsa_size);
/*
* The bind_mask is a mode_t that may be unsigned, so we can't use
@@ -2810,6 +2820,7 @@ dump_config(ServerOptions *o)
@@ -2874,6 +2884,7 @@ dump_config(ServerOptions *o)
dump_cfg_int(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
+ dump_cfg_int(sRSAMinSize, o->rsa_min_size);
+ dump_cfg_int(sRequiredRSASize, o->required_rsa_size);
dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
/* formatted integer arguments */
diff --git a/servconf.h b/servconf.h
index 115db1e79..2e3486906 100644
index 8a04463e..9346155c 100644
--- a/servconf.h
+++ b/servconf.h
@@ -227,6 +227,7 @@ typedef struct {
@@ -229,6 +229,7 @@ typedef struct {
int expose_userauth_info;
u_int64_t timing_secret;
char *sk_provider;
+ int rsa_min_size; /* minimum size of RSA keys */
+ int required_rsa_size; /* minimum size of RSA keys */
} ServerOptions;
/* Information about the incoming connection as used by Match */
diff --git a/ssh.c b/ssh.c
index a926cc007..cd13fb879 100644
index 559bf2af..25be53d5 100644
--- a/ssh.c
+++ b/ssh.c
@@ -500,14 +500,22 @@ resolve_canonicalize(char **hostp, int port)
@@ -516,14 +516,22 @@ resolve_canonicalize(char **hostp, int port)
}
/*
@ -196,7 +200,7 @@ index a926cc007..cd13fb879 100644
+ /* Check RSA keys size and discard if undersized */
+ if (k != NULL && *k != NULL &&
+ (r = sshkey_check_rsa_length(*k,
+ options.rsa_min_size)) != 0) {
+ options.required_rsa_size)) != 0) {
+ error_r(r, "load %s \"%s\"", message, path);
+ free(*k);
+ *k = NULL;
@ -204,13 +208,16 @@ index a926cc007..cd13fb879 100644
break;
case SSH_ERR_INTERNAL_ERROR:
case SSH_ERR_ALLOC_FAIL:
@@ -1557,12 +1565,13 @@ main(int ac, char **av)
@@ -1578,7 +1586,7 @@ main(int ac, char **av)
if ((o) >= sensitive_data.nkeys) \
fatal_f("pubkey out of array bounds"); \
check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
- p, "pubkey"); \
+ &(sensitive_data.keys[o]), p, "pubkey"); \
} while (0)
#define L_CERT(p,o) do { \
if ((o) >= sensitive_data.nkeys) \
@@ -1586,7 +1594,8 @@ main(int ac, char **av)
#define L_CERT(p,o) do { \
if ((o) >= sensitive_data.nkeys) \
fatal_f("cert out of array bounds"); \
@ -229,7 +236,7 @@ index a926cc007..cd13fb879 100644
debug("identity file %s type %d", filename,
public ? public->type : -1);
free(options.identity_files[i]);
@@ -2263,7 +2272,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
@@ -2284,7 +2293,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
continue;
xasprintf(&cp, "%s-cert", filename);
check_load(sshkey_load_public(cp, &public, NULL),
@ -238,7 +245,7 @@ index a926cc007..cd13fb879 100644
debug("identity file %s type %d", cp,
public ? public->type : -1);
if (public == NULL) {
@@ -2294,7 +2303,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
@@ -2315,7 +2324,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
free(cp);
check_load(sshkey_load_public(filename, &public, NULL),
@ -248,25 +255,27 @@ index a926cc007..cd13fb879 100644
public ? public->type : -1);
free(options.certificate_files[i]);
diff --git a/sshconnect2.c b/sshconnect2.c
index 67f8e0309..d050c1656 100644
index f9bd19ea..58fe98db 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -91,6 +91,10 @@ static const struct ssh_conn_info *xxx_conn_info;
@@ -96,6 +96,11 @@ static const struct ssh_conn_info *xxx_conn_info;
static int
verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
{
+ int r;
+
+ if ((r = sshkey_check_rsa_length(hostkey, options.rsa_min_size)) != 0)
+ if ((r = sshkey_check_rsa_length(hostkey,
+ options.required_rsa_size)) != 0)
+ fatal_r(r, "Bad server host key");
if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
xxx_conn_info) == -1)
fatal("Host key verification failed.");
@@ -1762,6 +1762,12 @@ load_identity_file(Identity *id)
@@ -1606,6 +1611,13 @@ load_identity_file(Identity *id)
private = NULL;
quit = 1;
}
+ if (r = sshkey_check_rsa_length(private, options.rsa_min_size) != 0) {
+ if (!quit && (r = sshkey_check_rsa_length(private,
+ options.required_rsa_size)) != 0) {
+ debug_fr(r, "Skipping key %s", id->filename);
+ sshkey_free(private);
+ private = NULL;
@ -275,12 +284,12 @@ index 67f8e0309..d050c1656 100644
if (!quit && private != NULL && id->agent_fd == -1 &&
!(id->key && id->isprivate))
maybe_add_key_to_agent(id->filename, private, comment,
@@ -1747,6 +1751,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
@@ -1752,6 +1764,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
close(agent_fd);
} else {
for (j = 0; j < idlist->nkeys; j++) {
+ if ((r = sshkey_check_rsa_length(idlist->keys[j],
+ options.rsa_min_size)) != 0) {
+ options.required_rsa_size)) != 0) {
+ debug_fr(r, "ignoring %s agent key",
+ sshkey_ssh_name(idlist->keys[j]));
+ continue;
@ -289,15 +298,15 @@ index 67f8e0309..d050c1656 100644
TAILQ_FOREACH(id, &files, next) {
/*
diff --git a/sshd.c b/sshd.c
index d26eb86ae..5f36905a1 100644
index 17eee9d8..395ef493 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1746,6 +1746,13 @@ main(int ac, char **av)
@@ -1870,6 +1870,13 @@ main(int ac, char **av)
fatal_r(r, "Could not demote key: \"%s\"",
options.host_key_files[i]);
}
+ if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey,
+ options.rsa_min_size)) != 0) {
+ options.required_rsa_size)) != 0) {
+ error_fr(r, "Host key %s", options.host_key_files[i]);
+ sshkey_free(pubkey);
+ sshkey_free(key);
@ -307,10 +316,10 @@ index d26eb86ae..5f36905a1 100644
sensitive_data.host_pubkeys[i] = pubkey;
diff --git a/sshkey.c b/sshkey.c
index 47864e6d8..8bad6bd99 100644
index ed2b5dff..77093235 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -2319,18 +2319,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
@@ -2365,18 +2365,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
return ret;
}
@ -341,7 +350,7 @@ index 47864e6d8..8bad6bd99 100644
static int
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
@@ -2391,7 +2397,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
@@ -2439,7 +2445,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
goto out;
}
rsa_n = rsa_e = NULL; /* transferred */
@ -350,7 +359,7 @@ index 47864e6d8..8bad6bd99 100644
goto out;
#ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8);
@@ -3580,7 +3586,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
@@ -3642,7 +3648,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
goto out;
}
rsa_p = rsa_q = NULL; /* transferred */
@ -359,7 +368,7 @@ index 47864e6d8..8bad6bd99 100644
goto out;
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
goto out;
@@ -4566,7 +4572,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
@@ -4644,7 +4650,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@ -369,10 +378,10 @@ index 47864e6d8..8bad6bd99 100644
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) {
diff --git a/sshkey.h b/sshkey.h
index 125cadb64..52e879456 100644
index 094815e0..be254e6b 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -267,6 +267,7 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
@@ -273,6 +273,7 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
int type, struct sshkey **pubkeyp);
@ -381,57 +390,57 @@ index 125cadb64..52e879456 100644
int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
diff --git a/ssh.1 b/ssh.1
index b4956aec..b1a40ebd 100644
index b4956aec..e255b9b9 100644
--- a/ssh.1
+++ b/ssh.1
@@ -554,6 +554,7 @@ For full details of the options listed below, and their possible values, see
.It LogLevel
.It MACs
.It Match
+.It RSAMinSize
.It NoHostAuthenticationForLocalhost
.It NumberOfPasswordPrompts
.It PasswordAuthentication
@@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see
.It RemoteCommand
.It RemoteForward
.It RequestTTY
+.It RequiredRSASize
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
diff --git a/ssh_config.5 b/ssh_config.5
index 24a46460..68771e4b 100644
index 24a46460..d1ede18e 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -1322,6 +1322,10 @@ The argument to this keyword must be
or
.Cm no
(the default).
+.It Cm RSAMinSize
+Provides a minimal bits requirement for RSA keys when used for signature and
+verification but not for the key generation. The default value is 1024 and
+can't be reduced.
.It Cm NumberOfPasswordPrompts
Specifies the number of password prompts before giving up.
The argument to this keyword must be an integer.
@@ -1634,6 +1634,17 @@ and
.Fl T
flags for
.Xr ssh 1 .
+.It Cm RequiredRSASize
+Specifies the minimum RSA key size (in bits) that
+.Xr ssh 1
+will accept.
+User authentication keys smaller than this limit will be ignored.
+Servers that present host keys smaller than this limit will cause the
+connection to be terminated.
+The default is
+.Cm 1024
+bits.
+Note that this limit may only be raised from the default.
.It Cm RevokedHostKeys
Specifies revoked host public keys.
Keys listed in this file will be refused for host authentication.
diff --git a/sshd_config.5 b/sshd_config.5
index 867a747d..e08811ca 100644
index 867a747d..f5a06637 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1266,6 +1266,10 @@ will refuse connection attempts with a probability of rate/100 (30%)
if there are currently start (10) unauthenticated connections.
The probability increases linearly and all connection attempts
are refused if the number of unauthenticated connections reaches full (60).
+.It Cm RSAMinSize
+Provides a minimal bits requirement for RSA keys when used for signature and
+verification but not for the key generation. The default value is 1024 and
+can't be reduced.
.It Cm ModuliFile
Specifies the
.Xr moduli 5
diff --git a/sshkey.h b/sshkey.h
index 094815e0..2bb8cb90 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -286,6 +286,8 @@ int sshkey_private_serialize_maxsign(struct sshkey *key,
void sshkey_sig_details_free(struct sshkey_sig_details *);
+int ssh_set_rsa_min_bits(int minbits);
+
#ifdef SSHKEY_INTERNAL
int ssh_rsa_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
@@ -1596,6 +1596,16 @@ is
.Cm default none ,
which means that rekeying is performed after the cipher's default amount
of data has been sent or received and no time based rekeying is done.
+.It Cm RequiredRSASize
+Specifies the minimum RSA key size (in bits) that
+.Xr sshd 8
+will accept.
+User and host-based authentication keys smaller than this limit will be
+refused.
+The default is
+.Cm 1024
+bits.
+Note that this limit may only be raised from the default.
.It Cm RevokedKeys
Specifies revoked public keys file, or
.Cm none

View File

@ -0,0 +1,100 @@
diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c
--- openssh-8.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100
+++ openssh-8.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100
@@ -43,6 +43,7 @@ void
compat_banner(struct ssh *ssh, const char *version)
{
int i;
+ int forbid_ssh_rsa = 0;
static struct {
char *pat;
int bugs;
@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha
};
/* process table, return first match */
+ forbid_ssh_rsa = (ssh->compat & SSH_RH_RSASIGSHA);
ssh->compat = 0;
for (i = 0; check[i].pat; i++) {
if (match_pattern_list(version, check[i].pat, 0) == 1) {
debug_f("match: %s pat %s compat 0x%08x",
version, check[i].pat, check[i].bugs);
ssh->compat = check[i].bugs;
+ if (forbid_ssh_rsa)
+ ssh->compat |= SSH_RH_RSASIGSHA;
return;
}
}
debug_f("no match: %s", version);
+ if (forbid_ssh_rsa)
+ ssh->compat |= SSH_RH_RSASIGSHA;
}
/* Always returns pointer to allocated memory, caller must free. */
diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h
--- openssh-8.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100
@@ -30,7 +30,7 @@
#define SSH_BUG_UTF8TTYMODE 0x00000001
#define SSH_BUG_SIGTYPE 0x00000002
#define SSH_BUG_SIGTYPE74 0x00000004
-/* #define unused 0x00000008 */
+#define SSH_RH_RSASIGSHA 0x00000008
#define SSH_OLD_SESSIONID 0x00000010
/* #define unused 0x00000020 */
#define SSH_BUG_DEBUG 0x00000040
diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c
--- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100
+++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100
@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh *
else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED)
sigalg = "rsa-sha2-256";
}
+ if (ssh->compat & SSH_RH_RSASIGSHA && sigalg == NULL) {
+ sigalg = "rsa-sha2-512";
+ debug3_f("SHA1 signature is not supported, falling back to %s", sigalg);
+ }
debug3_f("sign %s key (index %d) using sigalg %s",
sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
if ((r = sshbuf_put_cstring(sigbuf,
diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c
--- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100
+++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100
@@ -1640,6 +1651,7 @@ main(int ac, char **av)
int keytype;
Authctxt *authctxt;
struct connection_info *connection_info = NULL;
+ int forbid_ssh_rsa = 0;
#ifdef HAVE_SECUREWARE
(void)set_auth_parameters(ac, av);
@@ -1938,6 +1950,19 @@ main(int ac, char **av)
key = NULL;
continue;
}
+ if (key && (sshkey_type_plain(key->type) == KEY_RSA || sshkey_type_plain(key->type) == KEY_RSA_CERT)) {
+ size_t sign_size = 0;
+ u_char *tmp = NULL;
+ u_char data[] = "Test SHA1 vector";
+ int res;
+
+ res = ssh_rsa_sign(key, &tmp, &sign_size, data, sizeof(data), NULL);
+ free(tmp);
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
+ logit_f("sshd: ssh-rsa algorithm is disabled");
+ forbid_ssh_rsa = 1;
+ }
+ }
if (sshkey_is_sk(key) &&
key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
debug("host key %s requires user presence, ignoring",
@@ -2275,6 +2306,9 @@ main(int ac, char **av)
check_ip_options(ssh);
+ if (forbid_ssh_rsa)
+ ssh->compat |= SSH_RH_RSASIGSHA;
+
/* Prepare the channels layer */
channel_init_channels(ssh);
channel_set_af(ssh, options.address_family);

View File

@ -33,16 +33,16 @@ diff --color -ru a/ssh.1 b/ssh.1
+.It LogVerbose
.It MACs
.It Match
.It RSAMinSize
.It NoHostAuthenticationForLocalhost
@@ -566,6 +571,8 @@
.It RemoteCommand
.It RemoteForward
.It RequestTTY
+.It RevokedHostKeys
+.It SecurityKeyProvider
.It RequiredRSASize
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
@@ -575,6 +582,7 @@
.It StreamLocalBindMask
.It StreamLocalBindUnlink

View File

@ -0,0 +1,57 @@
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index d29a03b4..d7283136 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -490,6 +490,15 @@ congreet(int s)
return;
}
+ /*
+ * Read the server banner as per RFC4253 section 4.2. The "SSH-"
+ * protocol identification string may be preceeded by an arbitarily
+ * large banner which we must read and ignore. Loop while reading
+ * newline-terminated lines until we have one starting with "SSH-".
+ * The ID string cannot be longer than 255 characters although the
+ * preceeding banner lines may (in which case they'll be discarded
+ * in multiple iterations of the outer loop).
+ */
for (;;) {
memset(buf, '\0', sizeof(buf));
bufsiz = sizeof(buf);
@@ -517,6 +526,11 @@ congreet(int s)
conrecycle(s);
return;
}
+ if (cp >= buf + sizeof(buf)) {
+ error("%s: greeting exceeds allowable length", c->c_name);
+ confree(s);
+ return;
+ }
if (*cp != '\n' && *cp != '\r') {
error("%s: bad greeting", c->c_name);
confree(s);
diff --git a/sshsig.c b/sshsig.c
index 1e3b6398..eb2a931e 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -491,7 +491,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
{
char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH];
ssize_t n, total = 0;
- struct ssh_digest_ctx *ctx;
+ struct ssh_digest_ctx *ctx = NULL;
int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
@@ -549,9 +548,11 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
/* success */
r = 0;
out:
+ oerrno = errno;
sshbuf_free(b);
ssh_digest_free(ctx);
explicit_bzero(hash, sizeof(hash));
+ errno = oerrno;
return r;
}

View File

@ -51,7 +51,7 @@
# Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1
%global openssh_ver 8.7p1
%global openssh_rel 22
%global openssh_rel 28
%global pam_ssh_agent_ver 0.10.4
%global pam_ssh_agent_rel 5
@ -221,6 +221,8 @@ Patch983: openssh-8.7p1-evpgenkey.patch
# downstream only, IBMCA tentative fix
# From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14
Patch984: openssh-8.7p1-ibmca.patch
# Upstream ff89b1bed80721295555bd083b173247a9c0484e, 5062ad48814b06162511c4f5924a33d97b6b2566
Patch986: openssh-9.1p1-sshbanner.patch
# Minimize the use of SHA1 as a proof of possession for RSA key (#2031868)
# upstream commits:
@ -257,6 +259,8 @@ Patch1005: openssh-8.7p1-host-based-auth.patch
# upstream MR:
# https://github.com/openssh/openssh-portable/pull/323
Patch1006: openssh-8.7p1-negotiate-supported-algs.patch
#
Patch1007: openssh-8.7p1-nohostsha1proof.patch
License: BSD
Requires: /sbin/nologin
@ -324,6 +328,10 @@ Requires: openssh = %{version}-%{release}
Summary: A passphrase dialog for OpenSSH and X
Requires: openssh = %{version}-%{release}
%package sk-dummy
Summary: OpenSSH SK driver for test purposes
Requires: openssh = %{version}-%{release}
%package -n pam_ssh_agent_auth
Summary: PAM module for authentication with ssh-agent
Version: %{pam_ssh_agent_ver}
@ -364,6 +372,9 @@ OpenSSH is a free version of SSH (Secure SHell), a program for logging
into and executing commands on a remote machine. This package contains
an X11 passphrase dialog for OpenSSH.
%description sk-dummy
This package contains a test SK driver used for OpenSSH test purposes
%description -n pam_ssh_agent_auth
This package contains a PAM module which can be used to authenticate
users using ssh keys stored in a ssh-agent. Through the use of the
@ -442,6 +453,7 @@ popd
%patch982 -p1 -b .minrsabits
%patch983 -p1 -b .evpgenrsa
%patch984 -p1 -b .ibmca
%patch986 -p1 -b .91cleanup
%patch200 -p1 -b .audit
%patch201 -p1 -b .audit-race
@ -457,6 +469,8 @@ popd
%patch100 -p1 -b .coverity
%patch1007 -p1 -b .sshrsacheck
autoreconf
pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}
autoreconf
@ -532,6 +546,7 @@ perl -pi -e "s|-lcrypto|%{_libdir}/libcrypto.a|g" Makefile
%endif
%make_build
make regress/misc/sk-dummy/sk-dummy.so
# Define a variable to toggle gnome1/gtk2 building. This is necessary
# because RPM doesn't handle nested %%if statements.
@ -623,6 +638,10 @@ pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}
%make_install
popd
%endif
install -m 755 -d $RPM_BUILD_ROOT%{_libdir}/sshtest/
install -m 755 regress/misc/sk-dummy/sk-dummy.so $RPM_BUILD_ROOT%{_libdir}/sshtest
%pre
getent group ssh_keys >/dev/null || groupadd -r ssh_keys || :
@ -726,6 +745,9 @@ test -f %{sysconfig_anaconda} && \
%attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass
%endif
%files sk-dummy
%attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so
%if %{pam_ssh_agent}
%files -n pam_ssh_agent_auth
%license pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE
@ -734,6 +756,32 @@ test -f %{sysconfig_anaconda} && \
%endif
%changelog
* Thu Jan 12 2023 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-28
- Do not try to use SHA1 for host key ownership proof when we don't support it server-side
Resolves: rhbz#2088750
* Thu Jan 12 2023 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-27
- Add sk-dummy subpackage for test purposes
Resolves: rhbz#2092780
* Fri Jan 06 2023 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-26
- Fix one-byte overflow in SSH banner processing
Resolves: rhbz#2138345
- Fix double free() in error path
Resolves: rhbz#2138347
* Fri Dec 16 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-25
- Build fix after OpenSSL rebase
Resolves: rhbz#2153626
* Fri Sep 23 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-24
- Set minimal value of RSA key length via configuration option - support both names
Resolves: rhbz#2128352
* Thu Sep 22 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-23
- Set minimal value of RSA key length via configuration option
Resolves: rhbz#2128352
* Tue Aug 16 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-22
- Avoid spirous message on connecting to the machine with ssh-rsa keys
Related: rhbz#2115246