aboutsummaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
authorAnderson Toshiyuki Sasaki <ansasaki@redhat.com>2019-05-17 11:38:43 +0200
committerAndreas Schneider <asn@cryptomilk.org>2019-06-12 10:17:54 +0200
commit250a0be0f9fa371b3dda5db594729fae862ee26d (patch)
tree2d8223046e46cf1953d6011d3a7186d120ed7f6b /src/server.c
parent8f6e6f774e4dc731bf5a6cd6f03290b9e6de826c (diff)
downloadlibssh-250a0be0f9fa371b3dda5db594729fae862ee26d.tar.gz
libssh-250a0be0f9fa371b3dda5db594729fae862ee26d.tar.xz
libssh-250a0be0f9fa371b3dda5db594729fae862ee26d.zip
options: Added an option to set server HostKey algorithms
The added option SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS allows restricting the signature algorithms to offer to the client for host authentication. The list set is used as a filter of allowed algorithms. First a list of possible signature algorithms to offer is created from the keys set and then such list is filtered against the allowed algorithms. Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c142
1 files changed, 80 insertions, 62 deletions
diff --git a/src/server.c b/src/server.c
index 2937d0f5..adb6ff7c 100644
--- a/src/server.c
+++ b/src/server.c
@@ -59,6 +59,7 @@
#include "libssh/messages.h"
#include "libssh/options.h"
#include "libssh/curve25519.h"
+#include "libssh/token.h"
#define set_status(session, status) do {\
if (session->common.callbacks && session->common.callbacks->connect_status_function) \
@@ -82,82 +83,99 @@
int server_set_kex(ssh_session session)
{
- struct ssh_kex_struct *server = &session->next_crypto->server_kex;
- int i, j, rc;
- const char *wanted;
- char hostkeys[128] = {0};
- enum ssh_keytypes_e keytype;
- size_t len;
- int ok;
-
- ZERO_STRUCTP(server);
-
- ok = ssh_get_random(server->cookie, 16, 0);
- if (!ok) {
- ssh_set_error(session, SSH_FATAL, "PRNG error");
- return -1;
- }
+ struct ssh_kex_struct *server = &session->next_crypto->server_kex;
+ int i, j, rc;
+ const char *wanted, *allowed;
+ char *kept;
+ char hostkeys[128] = {0};
+ enum ssh_keytypes_e keytype;
+ size_t len;
+ int ok;
+
+ ZERO_STRUCTP(server);
+
+ ok = ssh_get_random(server->cookie, 16, 0);
+ if (!ok) {
+ ssh_set_error(session, SSH_FATAL, "PRNG error");
+ return -1;
+ }
- if (session->srv.ed25519_key != NULL) {
- snprintf(hostkeys,
- sizeof(hostkeys),
- "%s",
- ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key)));
- }
+ if (session->srv.ed25519_key != NULL) {
+ snprintf(hostkeys,
+ sizeof(hostkeys),
+ "%s",
+ ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key)));
+ }
#ifdef HAVE_ECC
- if (session->srv.ecdsa_key != NULL) {
- len = strlen(hostkeys);
- snprintf(hostkeys + len, sizeof(hostkeys) - len,
- ",%s", session->srv.ecdsa_key->type_c);
- }
+ if (session->srv.ecdsa_key != NULL) {
+ len = strlen(hostkeys);
+ snprintf(hostkeys + len, sizeof(hostkeys) - len,
+ ",%s", session->srv.ecdsa_key->type_c);
+ }
#endif
#ifdef HAVE_DSA
- if (session->srv.dsa_key != NULL) {
- len = strlen(hostkeys);
- keytype = ssh_key_type(session->srv.dsa_key);
+ if (session->srv.dsa_key != NULL) {
+ len = strlen(hostkeys);
+ keytype = ssh_key_type(session->srv.dsa_key);
- snprintf(hostkeys + len, sizeof(hostkeys) - len,
- ",%s", ssh_key_type_to_char(keytype));
- }
+ snprintf(hostkeys + len, sizeof(hostkeys) - len,
+ ",%s", ssh_key_type_to_char(keytype));
+ }
#endif
- if (session->srv.rsa_key != NULL) {
- /* We support also the SHA2 variants */
- len = strlen(hostkeys);
- snprintf(hostkeys + len, sizeof(hostkeys) - len,
- ",rsa-sha2-512,rsa-sha2-256");
+ if (session->srv.rsa_key != NULL) {
+ /* We support also the SHA2 variants */
+ len = strlen(hostkeys);
+ snprintf(hostkeys + len, sizeof(hostkeys) - len,
+ ",rsa-sha2-512,rsa-sha2-256");
- len = strlen(hostkeys);
- keytype = ssh_key_type(session->srv.rsa_key);
+ len = strlen(hostkeys);
+ keytype = ssh_key_type(session->srv.rsa_key);
- snprintf(hostkeys + len, sizeof(hostkeys) - len,
- ",%s", ssh_key_type_to_char(keytype));
- }
+ snprintf(hostkeys + len, sizeof(hostkeys) - len,
+ ",%s", ssh_key_type_to_char(keytype));
+ }
- if (strlen(hostkeys) == 0) {
- return -1;
- }
+ if (strlen(hostkeys) == 0) {
+ return -1;
+ }
- rc = ssh_options_set_algo(session,
- SSH_HOSTKEYS,
- hostkeys[0] == ',' ? hostkeys + 1 : hostkeys);
- if (rc < 0) {
- return -1;
- }
+ if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
+ allowed = session->opts.wanted_methods[SSH_HOSTKEYS];
+ } else {
+ allowed = ssh_kex_get_supported_method(SSH_HOSTKEYS);
+ }
- for (i = 0; i < 10; i++) {
- if ((wanted = session->opts.wanted_methods[i]) == NULL) {
- wanted = ssh_kex_get_supported_method(i);
+ /* It is expected for the list of allowed hostkeys to be ordered by
+ * preference */
+ kept = ssh_find_all_matching(hostkeys[0] == ',' ? hostkeys + 1 : hostkeys,
+ allowed);
+ if (kept == NULL) {
+ /* Nothing was allowed */
+ return -1;
}
- server->methods[i] = strdup(wanted);
- if (server->methods[i] == NULL) {
- for (j = 0; j < i; j++) {
- SAFE_FREE(server->methods[j]);
- }
- return -1;
+
+ rc = ssh_options_set_algo(session,
+ SSH_HOSTKEYS,
+ kept);
+ SAFE_FREE(kept);
+ if (rc < 0) {
+ return -1;
}
- }
- return 0;
+ for (i = 0; i < 10; i++) {
+ if ((wanted = session->opts.wanted_methods[i]) == NULL) {
+ wanted = ssh_kex_get_supported_method(i);
+ }
+ server->methods[i] = strdup(wanted);
+ if (server->methods[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ SAFE_FREE(server->methods[j]);
+ }
+ return -1;
+ }
+ }
+
+ return 0;
}
int ssh_server_init_kex(ssh_session session) {