aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnderson Toshiyuki Sasaki <ansasaki@redhat.com>2019-05-15 11:48:49 +0200
committerAndreas Schneider <asn@cryptomilk.org>2019-06-12 10:17:54 +0200
commitf4363f56551509e1c43a20115448af269525285f (patch)
tree564dfc6e40351d2e8083bdba6df82d28ba8664a6 /src
parentbc95a517101cc2a124e35040e042ed5349696e2a (diff)
downloadlibssh-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.c25
-rw-r--r--src/messages.c27
-rw-r--r--src/options.c22
-rw-r--r--src/server.c13
4 files changed, 77 insertions, 10 deletions
diff --git a/src/bind.c b/src/bind.c
index a1f25de2..d5193f77 100644
--- a/src/bind.c
+++ b/src/bind.c
@@ -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,