Set minimal value of RSA key length via configuration option

Resolves: rhbz#2128352
This commit is contained in:
Dmitry Belyavskiy 2022-09-22 14:48:29 +02:00
parent d925600c40
commit d4ff0b8809
3 changed files with 128 additions and 117 deletions

View File

@ -1,184 +1,186 @@
diff --git a/auth2-hostbased.c b/auth2-hostbased.c diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 2ab222ed6..4e9437912 100644 index 36b9d2f5..6b517db4 100644
--- a/auth2-hostbased.c --- a/auth2-hostbased.c
+++ b/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); "(null)" : key->cert->signature_type);
goto done; goto done;
} }
+ if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) { + if ((r = sshkey_check_rsa_length(key,
+ logit("refusing %s key", sshkey_type(key)); + options.required_rsa_size)) != 0) {
+ logit_r(r, "refusing %s key", sshkey_type(key));
+ goto done; + goto done;
+ } + }
if (!authctxt->valid || authctxt->user == NULL) { if (!authctxt->valid || authctxt->user == NULL) {
debug2_f("disabled because of invalid user"); debug2_f("disabled because of invalid user");
diff --git a/auth2-pubkey.c b/auth2-pubkey.c diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index daa756a01..68e7dea1f 100644 index 962fd342..5d59febc 100644
--- a/auth2-pubkey.c --- a/auth2-pubkey.c
+++ b/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); "(null)" : key->cert->signature_type);
goto done; goto done;
} }
+ if ((r = sshkey_check_rsa_length(key, options.rsa_min_size)) != 0) { + if ((r = sshkey_check_rsa_length(key,
+ logit("refusing %s key", sshkey_type(key)); + options.required_rsa_size)) != 0) {
+ logit_r(r, "refusing %s key", sshkey_type(key));
+ goto done; + goto done;
+ } + }
key_s = format_key(key); key_s = format_key(key);
if (sshkey_is_cert(key)) if (sshkey_is_cert(key))
ca_s = format_key(key->cert->signature_key); ca_s = format_key(key->cert->signature_key);
diff --git a/readconf.c b/readconf.c diff --git a/readconf.c b/readconf.c
index 5b5afa8e3..5e17abd41 100644 index 7f26c680..42be690b 100644
--- a/readconf.c --- a/readconf.c
+++ b/readconf.c +++ b/readconf.c
@@ -160,7 +160,7 @@ typedef enum { @@ -174,7 +174,7 @@ typedef enum {
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
- oSecurityKeyProvider, oKnownHostsCommand, - oSecurityKeyProvider, oKnownHostsCommand,
+ oSecurityKeyProvider, oKnownHostsCommand, oRSAMinSize, + oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes; } OpCodes;
@@ -306,6 +306,7 @@ static struct { @@ -320,6 +320,7 @@ static struct {
{ "proxyjump", oProxyJump }, { "proxyjump", oProxyJump },
{ "securitykeyprovider", oSecurityKeyProvider }, { "securitykeyprovider", oSecurityKeyProvider },
{ "knownhostscommand", oKnownHostsCommand }, { "knownhostscommand", oKnownHostsCommand },
+ { "rsaminsize", oRSAMinSize }, + { "requiredrsasize", oRequiredRSASize },
{ NULL, oBadOption } { 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); *charptr = xstrdup(arg);
break; break;
+ case oRSAMinSize: + case oRequiredRSASize:
+ intptr = &options->rsa_min_size; + intptr = &options->required_rsa_size;
+ goto parse_int; + goto parse_int;
+ +
case oDeprecated: case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"", debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword); 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->hostbased_accepted_algos = NULL;
options->pubkey_accepted_algos = NULL; options->pubkey_accepted_algos = NULL;
options->known_hosts_command = 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) if (options->sk_provider == NULL)
options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
#endif #endif
+ if (options->rsa_min_size == -1) + if (options->required_rsa_size == -1)
+ options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
/* Expand KEX name lists */ /* Expand KEX name lists */
all_cipher = cipher_alg_list(',', 0); 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(oNumberOfPasswordPrompts, o->number_of_password_prompts);
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
dump_cfg_int(oServerAliveInterval, o->server_alive_interval); 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 */ /* String options */
dump_cfg_string(oBindAddress, o->bind_address); dump_cfg_string(oBindAddress, o->bind_address);
diff --git a/readconf.h b/readconf.h diff --git a/readconf.h b/readconf.h
index f647bd42a..29db353ab 100644 index f647bd42..ffb5ec4f 100644
--- a/readconf.h --- a/readconf.h
+++ b/readconf.h +++ b/readconf.h
@@ -176,6 +176,8 @@ typedef struct { @@ -176,6 +176,8 @@ typedef struct {
char *known_hosts_command; 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 */ char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options; } Options;
diff --git a/servconf.c b/servconf.c diff --git a/servconf.c b/servconf.c
index f7317a5cb..362ff5b67 100644 index 29df0463..423772b1 100644
--- a/servconf.c --- a/servconf.c
+++ b/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->fingerprint_hash = -1;
options->disable_forwarding = -1; options->disable_forwarding = -1;
options->expose_userauth_info = -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. */ /* 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; options->expose_userauth_info = 0;
if (options->sk_provider == NULL) if (options->sk_provider == NULL)
options->sk_provider = xstrdup("internal"); options->sk_provider = xstrdup("internal");
+ if (options->rsa_min_size == -1) + if (options->required_rsa_size == -1)
+ options->rsa_min_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
assemble_algorithms(options); assemble_algorithms(options);
@@ -489,6 +492,7 @@ typedef enum { @@ -517,6 +520,7 @@ typedef enum {
sStreamLocalBindMask, sStreamLocalBindUnlink, sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
+ sRSAMinSize, + sRequiredRSASize,
sDeprecated, sIgnore, sUnsupported sDeprecated, sIgnore, sUnsupported
} ServerOpCodes; } ServerOpCodes;
@@ -632,6 +636,7 @@ static struct { @@ -676,6 +680,7 @@ static struct {
{ "rdomain", sRDomain, SSHCFG_ALL }, { "rdomain", sRDomain, SSHCFG_ALL },
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
+ { "rsaminsize", sRSAMinSize, SSHCFG_ALL }, + { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
{ NULL, sBadOption, 0 } { 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); *charptr = xstrdup(arg);
break; break;
+ case sRSAMinSize: + case sRequiredRSASize:
+ intptr = &options->rsa_min_size; + intptr = &options->required_rsa_size;
+ goto parse_int; + goto parse_int;
+ +
case sDeprecated: case sDeprecated:
case sIgnore: case sIgnore:
case sUnsupported: 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_limit);
M_CP_INTOPT(rekey_interval); M_CP_INTOPT(rekey_interval);
M_CP_INTOPT(log_level); 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 * 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(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval); dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); 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); dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
/* formatted integer arguments */ /* formatted integer arguments */
diff --git a/servconf.h b/servconf.h diff --git a/servconf.h b/servconf.h
index 115db1e79..2e3486906 100644 index 8a04463e..9346155c 100644
--- a/servconf.h --- a/servconf.h
+++ b/servconf.h +++ b/servconf.h
@@ -227,6 +227,7 @@ typedef struct { @@ -229,6 +229,7 @@ typedef struct {
int expose_userauth_info; int expose_userauth_info;
u_int64_t timing_secret; u_int64_t timing_secret;
char *sk_provider; char *sk_provider;
+ int rsa_min_size; /* minimum size of RSA keys */ + int required_rsa_size; /* minimum size of RSA keys */
} ServerOptions; } ServerOptions;
/* Information about the incoming connection as used by Match */ /* Information about the incoming connection as used by Match */
diff --git a/ssh.c b/ssh.c diff --git a/ssh.c b/ssh.c
index a926cc007..cd13fb879 100644 index 559bf2af..25be53d5 100644
--- a/ssh.c --- a/ssh.c
+++ b/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 +198,7 @@ index a926cc007..cd13fb879 100644
+ /* Check RSA keys size and discard if undersized */ + /* Check RSA keys size and discard if undersized */
+ if (k != NULL && *k != NULL && + if (k != NULL && *k != NULL &&
+ (r = sshkey_check_rsa_length(*k, + (r = sshkey_check_rsa_length(*k,
+ options.rsa_min_size)) != 0) { + options.required_rsa_size)) != 0) {
+ error_r(r, "load %s \"%s\"", message, path); + error_r(r, "load %s \"%s\"", message, path);
+ free(*k); + free(*k);
+ *k = NULL; + *k = NULL;
@ -204,13 +206,16 @@ index a926cc007..cd13fb879 100644
break; break;
case SSH_ERR_INTERNAL_ERROR: case SSH_ERR_INTERNAL_ERROR:
case SSH_ERR_ALLOC_FAIL: 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) \ if ((o) >= sensitive_data.nkeys) \
fatal_f("pubkey out of array bounds"); \ fatal_f("pubkey out of array bounds"); \
check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
- p, "pubkey"); \ - p, "pubkey"); \
+ &(sensitive_data.keys[o]), p, "pubkey"); \ + &(sensitive_data.keys[o]), p, "pubkey"); \
} while (0) } 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 { \ #define L_CERT(p,o) do { \
if ((o) >= sensitive_data.nkeys) \ if ((o) >= sensitive_data.nkeys) \
fatal_f("cert out of array bounds"); \ fatal_f("cert out of array bounds"); \
@ -229,7 +234,7 @@ index a926cc007..cd13fb879 100644
debug("identity file %s type %d", filename, debug("identity file %s type %d", filename,
public ? public->type : -1); public ? public->type : -1);
free(options.identity_files[i]); 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; continue;
xasprintf(&cp, "%s-cert", filename); xasprintf(&cp, "%s-cert", filename);
check_load(sshkey_load_public(cp, &public, NULL), check_load(sshkey_load_public(cp, &public, NULL),
@ -238,7 +243,7 @@ index a926cc007..cd13fb879 100644
debug("identity file %s type %d", cp, debug("identity file %s type %d", cp,
public ? public->type : -1); public ? public->type : -1);
if (public == NULL) { 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); free(cp);
check_load(sshkey_load_public(filename, &public, NULL), check_load(sshkey_load_public(filename, &public, NULL),
@ -248,25 +253,27 @@ index a926cc007..cd13fb879 100644
public ? public->type : -1); public ? public->type : -1);
free(options.certificate_files[i]); free(options.certificate_files[i]);
diff --git a/sshconnect2.c b/sshconnect2.c diff --git a/sshconnect2.c b/sshconnect2.c
index 67f8e0309..d050c1656 100644 index f9bd19ea..58fe98db 100644
--- a/sshconnect2.c --- a/sshconnect2.c
+++ b/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 static int
verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
{ {
+ int r; + 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"); + fatal_r(r, "Bad server host key");
if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
xxx_conn_info) == -1) xxx_conn_info) == -1)
fatal("Host key verification failed."); 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; private = NULL;
quit = 1; 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); + debug_fr(r, "Skipping key %s", id->filename);
+ sshkey_free(private); + sshkey_free(private);
+ private = NULL; + private = NULL;
@ -275,12 +282,12 @@ index 67f8e0309..d050c1656 100644
if (!quit && private != NULL && id->agent_fd == -1 && if (!quit && private != NULL && id->agent_fd == -1 &&
!(id->key && id->isprivate)) !(id->key && id->isprivate))
maybe_add_key_to_agent(id->filename, private, comment, 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); close(agent_fd);
} else { } else {
for (j = 0; j < idlist->nkeys; j++) { for (j = 0; j < idlist->nkeys; j++) {
+ if ((r = sshkey_check_rsa_length(idlist->keys[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", + debug_fr(r, "ignoring %s agent key",
+ sshkey_ssh_name(idlist->keys[j])); + sshkey_ssh_name(idlist->keys[j]));
+ continue; + continue;
@ -289,15 +296,15 @@ index 67f8e0309..d050c1656 100644
TAILQ_FOREACH(id, &files, next) { TAILQ_FOREACH(id, &files, next) {
/* /*
diff --git a/sshd.c b/sshd.c diff --git a/sshd.c b/sshd.c
index d26eb86ae..5f36905a1 100644 index 17eee9d8..395ef493 100644
--- a/sshd.c --- a/sshd.c
+++ b/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\"", fatal_r(r, "Could not demote key: \"%s\"",
options.host_key_files[i]); options.host_key_files[i]);
} }
+ if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey, + 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]); + error_fr(r, "Host key %s", options.host_key_files[i]);
+ sshkey_free(pubkey); + sshkey_free(pubkey);
+ sshkey_free(key); + sshkey_free(key);
@ -307,10 +314,10 @@ index d26eb86ae..5f36905a1 100644
sensitive_data.host_pubkeys[i] = pubkey; sensitive_data.host_pubkeys[i] = pubkey;
diff --git a/sshkey.c b/sshkey.c diff --git a/sshkey.c b/sshkey.c
index 47864e6d8..8bad6bd99 100644 index ed2b5dff..77093235 100644
--- a/sshkey.c --- a/sshkey.c
+++ b/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; return ret;
} }
@ -341,7 +348,7 @@ index 47864e6d8..8bad6bd99 100644
static int static int
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, 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; goto out;
} }
rsa_n = rsa_e = NULL; /* transferred */ rsa_n = rsa_e = NULL; /* transferred */
@ -350,7 +357,7 @@ index 47864e6d8..8bad6bd99 100644
goto out; goto out;
#ifdef DEBUG_PK #ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8); 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; goto out;
} }
rsa_p = rsa_q = NULL; /* transferred */ rsa_p = rsa_q = NULL; /* transferred */
@ -359,7 +366,7 @@ index 47864e6d8..8bad6bd99 100644
goto out; goto out;
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
goto out; 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; r = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
} }
@ -369,10 +376,10 @@ index 47864e6d8..8bad6bd99 100644
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) { (type == KEY_UNSPEC || type == KEY_DSA)) {
diff --git a/sshkey.h b/sshkey.h diff --git a/sshkey.h b/sshkey.h
index 125cadb64..52e879456 100644 index 094815e0..be254e6b 100644
--- a/sshkey.h --- a/sshkey.h
+++ b/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 sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
int type, struct sshkey **pubkeyp); int type, struct sshkey **pubkeyp);
@ -381,57 +388,57 @@ index 125cadb64..52e879456 100644
int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *); int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
diff --git a/ssh.1 b/ssh.1 diff --git a/ssh.1 b/ssh.1
index b4956aec..b1a40ebd 100644 index b4956aec..e255b9b9 100644
--- a/ssh.1 --- a/ssh.1
+++ b/ssh.1 +++ b/ssh.1
@@ -554,6 +554,7 @@ For full details of the options listed below, and their possible values, see @@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see
.It LogLevel .It RemoteCommand
.It MACs .It RemoteForward
.It Match .It RequestTTY
+.It RSAMinSize +.It RequiredRSASize
.It NoHostAuthenticationForLocalhost .It SendEnv
.It NumberOfPasswordPrompts .It ServerAliveInterval
.It PasswordAuthentication .It ServerAliveCountMax
diff --git a/ssh_config.5 b/ssh_config.5 diff --git a/ssh_config.5 b/ssh_config.5
index 24a46460..68771e4b 100644 index 24a46460..d1ede18e 100644
--- a/ssh_config.5 --- a/ssh_config.5
+++ b/ssh_config.5 +++ b/ssh_config.5
@@ -1322,6 +1322,10 @@ The argument to this keyword must be @@ -1634,6 +1634,17 @@ and
or .Fl T
.Cm no flags for
(the default). .Xr ssh 1 .
+.It Cm RSAMinSize +.It Cm RequiredRSASize
+Provides a minimal bits requirement for RSA keys when used for signature and +Specifies the minimum RSA key size (in bits) that
+verification but not for the key generation. The default value is 1024 and +.Xr ssh 1
+can't be reduced. +will accept.
.It Cm NumberOfPasswordPrompts +User authentication keys smaller than this limit will be ignored.
Specifies the number of password prompts before giving up. +Servers that present host keys smaller than this limit will cause the
The argument to this keyword must be an integer. +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 diff --git a/sshd_config.5 b/sshd_config.5
index 867a747d..e08811ca 100644 index 867a747d..f5a06637 100644
--- a/sshd_config.5 --- a/sshd_config.5
+++ b/sshd_config.5 +++ b/sshd_config.5
@@ -1266,6 +1266,10 @@ will refuse connection attempts with a probability of rate/100 (30%) @@ -1596,6 +1596,16 @@ is
if there are currently start (10) unauthenticated connections. .Cm default none ,
The probability increases linearly and all connection attempts which means that rekeying is performed after the cipher's default amount
are refused if the number of unauthenticated connections reaches full (60). of data has been sent or received and no time based rekeying is done.
+.It Cm RSAMinSize +.It Cm RequiredRSASize
+Provides a minimal bits requirement for RSA keys when used for signature and +Specifies the minimum RSA key size (in bits) that
+verification but not for the key generation. The default value is 1024 and +.Xr sshd 8
+can't be reduced. +will accept.
.It Cm ModuliFile +User and host-based authentication keys smaller than this limit will be
Specifies the +refused.
.Xr moduli 5 +The default is
diff --git a/sshkey.h b/sshkey.h +.Cm 1024
index 094815e0..2bb8cb90 100644 +bits.
--- a/sshkey.h +Note that this limit may only be raised from the default.
+++ b/sshkey.h .It Cm RevokedKeys
@@ -286,6 +286,8 @@ int sshkey_private_serialize_maxsign(struct sshkey *key, Specifies revoked public keys file, or
.Cm none
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,

View File

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

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 # 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_ver 8.7p1
%global openssh_rel 22 %global openssh_rel 23
%global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_ver 0.10.4
%global pam_ssh_agent_rel 5 %global pam_ssh_agent_rel 5
@ -734,6 +734,10 @@ test -f %{sysconfig_anaconda} && \
%endif %endif
%changelog %changelog
* 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 * Tue Aug 16 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-22
- Avoid spirous message on connecting to the machine with ssh-rsa keys - Avoid spirous message on connecting to the machine with ssh-rsa keys
Related: rhbz#2115246 Related: rhbz#2115246