mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-29 01:03:57 +03:00
Allow limiting RSA Key size also for server
Thanks to Harry Sintonen from WithSecure for pointing this out. Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
@@ -51,6 +51,7 @@ struct ssh_bind_struct {
|
|||||||
char *config_dir;
|
char *config_dir;
|
||||||
char *pubkey_accepted_key_types;
|
char *pubkey_accepted_key_types;
|
||||||
char* moduli_file;
|
char* moduli_file;
|
||||||
|
unsigned int rsa_min_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct
|
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ enum ssh_bind_options_e {
|
|||||||
SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS,
|
SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS,
|
||||||
SSH_BIND_OPTIONS_PROCESS_CONFIG,
|
SSH_BIND_OPTIONS_PROCESS_CONFIG,
|
||||||
SSH_BIND_OPTIONS_MODULI,
|
SSH_BIND_OPTIONS_MODULI,
|
||||||
|
SSH_BIND_OPTIONS_RSA_MIN_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ssh_bind_struct* ssh_bind;
|
typedef struct ssh_bind_struct* ssh_bind;
|
||||||
|
|||||||
@@ -503,6 +503,8 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session->opts.rsa_min_size = sshbind->rsa_min_size;
|
||||||
|
|
||||||
ssh_socket_free(session->socket);
|
ssh_socket_free(session->socket);
|
||||||
session->socket = ssh_socket_new(session);
|
session->socket = ssh_socket_new(session);
|
||||||
if (session->socket == NULL) {
|
if (session->socket == NULL) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include "libssh/pki_priv.h"
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
@@ -1524,6 +1525,20 @@ int ssh_options_apply(ssh_session session) {
|
|||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
|
static bool ssh_bind_key_size_allowed(ssh_bind sshbind, ssh_key key)
|
||||||
|
{
|
||||||
|
int min_size = 0;
|
||||||
|
|
||||||
|
switch (ssh_key_type(key)) {
|
||||||
|
case SSH_KEYTYPE_RSA:
|
||||||
|
case SSH_KEYTYPE_RSA_CERT01:
|
||||||
|
min_size = sshbind->rsa_min_size;
|
||||||
|
return ssh_key_size_allowed_rsa(min_size, key);
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup libssh_server
|
* @addtogroup libssh_server
|
||||||
* @{
|
* @{
|
||||||
@@ -1683,6 +1698,17 @@ static int ssh_bind_set_algo(ssh_bind sshbind,
|
|||||||
* Set the path to the moduli file. Defaults to
|
* Set the path to the moduli file. Defaults to
|
||||||
* /etc/ssh/moduli if not specified (const char *).
|
* /etc/ssh/moduli if not specified (const char *).
|
||||||
*
|
*
|
||||||
|
* - SSH_BIND_OPTIONS_RSA_MIN_SIZE
|
||||||
|
* Set the minimum RSA key size in bits to be accepted by
|
||||||
|
* the server for both authentication and hostkey
|
||||||
|
* operations. The values under 768 bits are not accepted
|
||||||
|
* even with this configuration option as they are
|
||||||
|
* considered completely broken. Setting 0 will revert
|
||||||
|
* the value to defaults.
|
||||||
|
* Default is 1024 bits or 2048 bits in FIPS mode.
|
||||||
|
* (unsigned int)
|
||||||
|
*
|
||||||
|
*
|
||||||
* @param value The value to set. This is a generic pointer and the
|
* @param value The value to set. This is a generic pointer and the
|
||||||
* datatype which should be used is described at the
|
* datatype which should be used is described at the
|
||||||
* corresponding value of type above.
|
* corresponding value of type above.
|
||||||
@@ -1692,6 +1718,7 @@ static int ssh_bind_set_algo(ssh_bind sshbind,
|
|||||||
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
||||||
const void *value)
|
const void *value)
|
||||||
{
|
{
|
||||||
|
bool allowed;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
const char *v;
|
const char *v;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
@@ -1715,6 +1742,16 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
allowed = ssh_bind_key_size_allowed(sshbind, key);
|
||||||
|
if (!allowed) {
|
||||||
|
ssh_set_error(sshbind,
|
||||||
|
SSH_FATAL,
|
||||||
|
"The host key size %d is too small.",
|
||||||
|
ssh_key_size(key));
|
||||||
|
ssh_key_free(key);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
key_type = ssh_key_type(key);
|
key_type = ssh_key_type(key);
|
||||||
switch (key_type) {
|
switch (key_type) {
|
||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
@@ -1780,6 +1817,15 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|||||||
ssh_key *bind_key_loc = NULL;
|
ssh_key *bind_key_loc = NULL;
|
||||||
ssh_key key = (ssh_key)value;
|
ssh_key key = (ssh_key)value;
|
||||||
|
|
||||||
|
allowed = ssh_bind_key_size_allowed(sshbind, key);
|
||||||
|
if (!allowed) {
|
||||||
|
ssh_set_error(sshbind,
|
||||||
|
SSH_FATAL,
|
||||||
|
"The host key size %d is too small.",
|
||||||
|
ssh_key_size(key));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
key_type = ssh_key_type(key);
|
key_type = ssh_key_type(key);
|
||||||
switch (key_type) {
|
switch (key_type) {
|
||||||
case SSH_KEYTYPE_DSS:
|
case SSH_KEYTYPE_DSS:
|
||||||
@@ -2043,6 +2089,21 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SSH_BIND_OPTIONS_RSA_MIN_SIZE:
|
||||||
|
if (value == NULL) {
|
||||||
|
ssh_set_error_invalid(sshbind);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
unsigned int *x = (unsigned int *)value;
|
||||||
|
if (*x > 0 && *x < 768) {
|
||||||
|
ssh_set_error(sshbind, SSH_REQUEST_DENIED,
|
||||||
|
"The provided value (%u) for minimal RSA key "
|
||||||
|
"size is too small. Use at least 768 bits.", *x);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sshbind->rsa_min_size = *x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
|
ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
37
src/pki.c
37
src/pki.c
@@ -404,6 +404,20 @@ int ssh_key_algorithm_allowed(ssh_session session, const char *type)
|
|||||||
return ssh_match_group(allowed_list, type);
|
return ssh_match_group(allowed_list, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ssh_key_size_allowed_rsa(int min_size, ssh_key key)
|
||||||
|
{
|
||||||
|
int key_size = ssh_key_size(key);
|
||||||
|
|
||||||
|
if (min_size < 768) {
|
||||||
|
if (ssh_fips_mode()) {
|
||||||
|
min_size = 2048;
|
||||||
|
} else {
|
||||||
|
min_size = 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (key_size >= min_size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check the given key is acceptable in regards to the key size policy
|
* @brief Check the given key is acceptable in regards to the key size policy
|
||||||
* specified by the configuration
|
* specified by the configuration
|
||||||
@@ -414,24 +428,13 @@ int ssh_key_algorithm_allowed(ssh_session session, const char *type)
|
|||||||
*/
|
*/
|
||||||
bool ssh_key_size_allowed(ssh_session session, ssh_key key)
|
bool ssh_key_size_allowed(ssh_session session, ssh_key key)
|
||||||
{
|
{
|
||||||
int key_size = ssh_key_size(key);
|
|
||||||
int min_size = 0;
|
int min_size = 0;
|
||||||
|
|
||||||
switch (key->type) {
|
switch (ssh_key_type(key)) {
|
||||||
case SSH_KEYTYPE_RSA:
|
case SSH_KEYTYPE_RSA:
|
||||||
case SSH_KEYTYPE_RSA_CERT01:
|
case SSH_KEYTYPE_RSA_CERT01:
|
||||||
min_size = session->opts.rsa_min_size;
|
min_size = session->opts.rsa_min_size;
|
||||||
if (min_size < 768) {
|
return ssh_key_size_allowed_rsa(min_size, key);
|
||||||
if (ssh_fips_mode()) {
|
|
||||||
min_size = 2048;
|
|
||||||
} else {
|
|
||||||
min_size = 1024;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (key_size < min_size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2704,7 +2707,7 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
|||||||
const enum ssh_digest_e digest)
|
const enum ssh_digest_e digest)
|
||||||
{
|
{
|
||||||
struct ssh_crypto_struct *crypto = NULL;
|
struct ssh_crypto_struct *crypto = NULL;
|
||||||
|
bool allowed;
|
||||||
ssh_signature sig = NULL;
|
ssh_signature sig = NULL;
|
||||||
ssh_string sig_blob = NULL;
|
ssh_string sig_blob = NULL;
|
||||||
|
|
||||||
@@ -2716,6 +2719,12 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allowed = ssh_key_size_allowed(session, privkey);
|
||||||
|
if (!allowed) {
|
||||||
|
ssh_set_error(session, SSH_FATAL, "The hostkey size too small");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
crypto = session->next_crypto ? session->next_crypto :
|
crypto = session->next_crypto ? session->next_crypto :
|
||||||
session->current_crypto;
|
session->current_crypto;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user