diff options
author | Anderson Toshiyuki Sasaki <ansasaki@redhat.com> | 2019-05-15 11:48:49 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2019-06-12 10:17:54 +0200 |
commit | f4363f56551509e1c43a20115448af269525285f (patch) | |
tree | 564dfc6e40351d2e8083bdba6df82d28ba8664a6 /src | |
parent | bc95a517101cc2a124e35040e042ed5349696e2a (diff) | |
download | libssh-f4363f56551509e1c43a20115448af269525285f.tar.gz libssh-f4363f56551509e1c43a20115448af269525285f.tar.xz libssh-f4363f56551509e1c43a20115448af269525285f.zip |
options: Add option to set server accepted pubkey types
The added option SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES allows
restricting the allowed public key types accepted by the server for
authentication.
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/bind.c | 25 | ||||
-rw-r--r-- | src/messages.c | 27 | ||||
-rw-r--r-- | src/options.c | 22 | ||||
-rw-r--r-- | src/server.c | 13 |
4 files changed, 77 insertions, 10 deletions
@@ -38,6 +38,7 @@ #include "libssh/buffer.h" #include "libssh/socket.h" #include "libssh/session.h" +#include "libssh/token.h" /** * @addtogroup libssh_server @@ -402,6 +403,7 @@ void ssh_bind_free(ssh_bind sshbind){ SAFE_FREE(sshbind->banner); SAFE_FREE(sshbind->bindaddr); SAFE_FREE(sshbind->config_dir); + SAFE_FREE(sshbind->pubkey_accepted_key_types); SAFE_FREE(sshbind->dsakey); SAFE_FREE(sshbind->rsakey); @@ -456,6 +458,29 @@ int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ } } + if (sshbind->pubkey_accepted_key_types != NULL) { + if (session->opts.pubkey_accepted_types == NULL) { + session->opts.pubkey_accepted_types = strdup(sshbind->pubkey_accepted_key_types); + if (session->opts.pubkey_accepted_types == NULL) { + ssh_set_error_oom(sshbind); + return SSH_ERROR; + } + } else { + char *p; + /* If something was set to the session prior to calling this + * function, keep only what is allowed by the options set in + * sshbind */ + p = ssh_find_all_matching(sshbind->pubkey_accepted_key_types, + session->opts.pubkey_accepted_types); + if (p == NULL) { + return SSH_ERROR; + } + + SAFE_FREE(session->opts.pubkey_accepted_types); + session->opts.pubkey_accepted_types = p; + } + } + session->common.log_verbosity = sshbind->common.log_verbosity; if(sshbind->banner != NULL) session->opts.custombanner = strdup(sshbind->banner); diff --git a/src/messages.c b/src/messages.c index f65a484c..f0c6d781 100644 --- a/src/messages.c +++ b/src/messages.c @@ -868,11 +868,28 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){ msg->auth_request.pubkey, &sig); if (rc == SSH_OK) { - rc = ssh_pki_signature_verify(session, - sig, - msg->auth_request.pubkey, - ssh_buffer_get(digest), - ssh_buffer_get_len(digest)); + /* Check if the signature from client matches server preferences */ + if (session->opts.pubkey_accepted_types) { + if (!ssh_match_group(session->opts.pubkey_accepted_types, + sig->type_c)) + { + ssh_set_error(session, + SSH_FATAL, + "Public key from client (%s) doesn't match server " + "preference (%s)", + sig->type_c, + session->opts.pubkey_accepted_types); + rc = SSH_ERROR; + } + } + + if (rc == SSH_OK) { + rc = ssh_pki_signature_verify(session, + sig, + msg->auth_request.pubkey, + ssh_buffer_get(digest), + ssh_buffer_get_len(digest)); + } } ssh_string_free(sig_blob); ssh_buffer_free(digest); diff --git a/src/options.c b/src/options.c index e9d8a721..244f3edf 100644 --- a/src/options.c +++ b/src/options.c @@ -1608,6 +1608,10 @@ static int ssh_bind_set_algo(ssh_bind sshbind, * paths of configuration files to * ssh_bind_options_parse_config(). * + * - SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES: + * Set the public key algorithm accepted by the server + * (const char *, comma-separated list). + * * @param value The value to set. This is a generic pointer and the * datatype which should be used is described at the * corresponding value of type above. @@ -1912,6 +1916,24 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, } } break; + case SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES: + v = value; + if (v == NULL || v[0] == '\0') { + ssh_set_error_invalid(sshbind); + return -1; + } else { + p = ssh_keep_known_algos(SSH_HOSTKEYS, v); + if (p == NULL) { + ssh_set_error(sshbind, SSH_REQUEST_DENIED, + "Setting method: no known public key algorithm (%s)", + v); + return -1; + } + + SAFE_FREE(sshbind->pubkey_accepted_key_types); + sshbind->pubkey_accepted_key_types = p; + } + break; default: ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); return -1; diff --git a/src/server.c b/src/server.c index b2c81b60..2937d0f5 100644 --- a/src/server.c +++ b/src/server.c @@ -180,11 +180,14 @@ static int ssh_server_send_extensions(ssh_session session) { const char *hostkey_algorithms; SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO"); - /* - * We can list here all the default hostkey methods, since - * they already contain the SHA2 extension algorithms - */ - hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS); + + if (session->opts.pubkey_accepted_types) { + hostkey_algorithms = session->opts.pubkey_accepted_types; + } else { + /* There are no restrictions to the accepted public keys */ + hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS); + } + rc = ssh_buffer_pack(session->out_buffer, "bdss", SSH2_MSG_EXT_INFO, |