From 761225712a28d70adea7a2b872c265bc98a83511 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 6 Aug 2018 11:51:26 +0200 Subject: [PATCH] client: Handle the MSG_EXT_INFO packet signalling supported extensions RFC 8308: The extension negotiation in Secure Shell (SSH) Protocol RFC 8332: Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- include/libssh/packet.h | 1 + include/libssh/session.h | 8 +++++++ include/libssh/ssh2.h | 1 + src/packet.c | 5 ++-- src/packet_cb.c | 52 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/include/libssh/packet.h b/include/libssh/packet.h index 1a9283d8..a3bcb9a8 100644 --- a/include/libssh/packet.h +++ b/include/libssh/packet.h @@ -51,6 +51,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback); SSH_PACKET_CALLBACK(ssh_packet_dh_reply); SSH_PACKET_CALLBACK(ssh_packet_newkeys); SSH_PACKET_CALLBACK(ssh_packet_service_accept); +SSH_PACKET_CALLBACK(ssh_packet_ext_info); #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_kexdh_init); diff --git a/include/libssh/session.h b/include/libssh/session.h index 6cb79628..00717652 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -86,6 +86,11 @@ enum ssh_pending_call_e { #define SSH_OPT_FLAG_KBDINT_AUTH 0x4 #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 +/* extensions flags */ +/* server-sig-algs extension */ +#define SSH_EXT_SIG_RSA_SHA256 0x01 +#define SSH_EXT_SIG_RSA_SHA512 0x02 + /* members that are common to ssh_session and ssh_bind */ struct ssh_common_struct { struct error_struct error; @@ -114,6 +119,9 @@ struct ssh_session_struct { /* session flags (SSH_SESSION_FLAG_*) */ int flags; + /* Extensions negotiated using RFC 8308 */ + uint32_t extensions; + ssh_string banner; /* that's the issue banner from the server */ char *discon_msg; /* disconnect message from diff --git a/include/libssh/ssh2.h b/include/libssh/ssh2.h index 8b39b9a6..35214330 100644 --- a/include/libssh/ssh2.h +++ b/include/libssh/ssh2.h @@ -7,6 +7,7 @@ #define SSH2_MSG_DEBUG 4 #define SSH2_MSG_SERVICE_REQUEST 5 #define SSH2_MSG_SERVICE_ACCEPT 6 +#define SSH2_MSG_EXT_INFO 7 #define SSH2_MSG_KEXINIT 20 #define SSH2_MSG_NEWKEYS 21 diff --git a/src/packet.c b/src/packet.c index 16f96149..5b9252f5 100644 --- a/src/packet.c +++ b/src/packet.c @@ -59,8 +59,9 @@ static ssh_packet_callback default_packet_handlers[]= { NULL, #endif ssh_packet_service_accept, // SSH2_MSG_SERVICE_ACCEPT 6 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, // 7-19 + ssh_packet_ext_info, // SSH2_MSG_EXT_INFO 7 + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, // 8-19 ssh_packet_kexinit, // SSH2_MSG_KEXINIT 20 ssh_packet_newkeys, // SSH2_MSG_NEWKEYS 21 NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/packet_cb.c b/src/packet_cb.c index ecf327ef..c3a1997f 100644 --- a/src/packet_cb.c +++ b/src/packet_cb.c @@ -270,3 +270,55 @@ SSH_PACKET_CALLBACK(ssh_packet_service_accept){ return SSH_PACKET_USED; } + +/** + * @internal + * @brief handles a SSH2_MSG_EXT_INFO packet defined in RFC 8308 + * + */ +SSH_PACKET_CALLBACK(ssh_packet_ext_info) +{ + int rc; + uint32_t nr_extensions = 0; + uint32_t i; + (void)type; + (void)user; + + SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_EXT_INFO"); + + rc = ssh_buffer_get_u32(packet, &nr_extensions); + if (rc == 0) { + SSH_LOG(SSH_LOG_PACKET, "Failed to read number of extensions"); + return SSH_PACKET_USED; + } + nr_extensions = ntohl(nr_extensions); + SSH_LOG(SSH_LOG_PACKET, "Follows %u extensions", nr_extensions); + + for (i = 0; i < nr_extensions; i++) { + char *name = NULL; + char *value = NULL; + int cmp; + + rc = ssh_buffer_unpack(packet, "ss", &name, &value); + if (rc != SSH_OK) { + SSH_LOG(SSH_LOG_PACKET, "Error reading extension name-value pair"); + return SSH_PACKET_USED; + } + + cmp = strcmp(name, "server-sig-algs"); + if (cmp == 0) { + /* TODO check for NULL bytes */ + SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value); + if (ssh_match_group(value, "rsa-sha2-512")) { + session->extensions |= SSH_EXT_SIG_RSA_SHA512; + } + if (ssh_match_group(value, "rsa-sha2-256")) { + session->extensions |= SSH_EXT_SIG_RSA_SHA256; + } + } + free(name); + free(value); + } + + return SSH_PACKET_USED; +}