1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-29 01:03:57 +03:00

server: Support for extension negotiation

This includes intercepting the  ext-info-c  string from
the client kex proposal, configuring the server to allow using
this extension and sending the SSH_MSG_EXT_INFO packet back
to the client after the new keys are in use.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2018-07-03 16:16:25 +02:00
committed by Andreas Schneider
parent 60ad7ee15d
commit 6fa5e8adb0
3 changed files with 58 additions and 2 deletions

View File

@@ -90,6 +90,7 @@ enum ssh_pending_call_e {
/* server-sig-algs extension */ /* server-sig-algs extension */
#define SSH_EXT_SIG_RSA_SHA256 0x01 #define SSH_EXT_SIG_RSA_SHA256 0x01
#define SSH_EXT_SIG_RSA_SHA512 0x02 #define SSH_EXT_SIG_RSA_SHA512 0x02
#define SSH_EXT_ALL SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512
/* members that are common to ssh_session and ssh_bind */ /* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct { struct ssh_common_struct {

View File

@@ -415,7 +415,7 @@ out:
} }
SSH_PACKET_CALLBACK(ssh_packet_kexinit){ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
int i; int i, ok;
int server_kex=session->server; int server_kex=session->server;
ssh_string str = NULL; ssh_string str = NULL;
char *strings[KEX_METHODS_SIZE]; char *strings[KEX_METHODS_SIZE];
@@ -519,6 +519,22 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
goto error; goto error;
} }
/*
* If client sent a ext-info-c message in the kex list, it supports
* RFC 8308 extension negotiation.
*/
ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX],
KEX_EXTENSION_CLIENT);
if (ok) {
/*
* Enable all the supported extensions and when the time comes
* (after NEWKEYS) send them to the client.
*/
SSH_LOG(SSH_LOG_DEBUG, "The client supports extension "
"negotiation: enabling all extensions");
session->extensions = SSH_EXT_ALL;
}
/* /*
* Remember whether 'first_kex_packet_follows' was set and the client * Remember whether 'first_kex_packet_follows' was set and the client
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message

View File

@@ -67,7 +67,6 @@
static int dh_handshake_server(ssh_session session); static int dh_handshake_server(ssh_session session);
/** /**
* @addtogroup libssh_server * @addtogroup libssh_server
* *
@@ -194,6 +193,37 @@ static int ssh_server_kexdh_init(ssh_session session, ssh_buffer packet){
return SSH_OK; return SSH_OK;
} }
static int ssh_server_send_extensions(ssh_session session) {
int rc;
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);
rc = ssh_buffer_pack(session->out_buffer,
"bdss",
SSH2_MSG_EXT_INFO,
1, /* nr. of extensions */
"server-sig-algs",
hostkey_algorithms);
if (rc != SSH_OK) {
goto error;
}
if (ssh_packet_send(session) == SSH_ERROR) {
goto error;
}
return 0;
error:
ssh_buffer_reinit(session->out_buffer);
return -1;
}
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){ SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){
int rc = SSH_ERROR; int rc = SSH_ERROR;
(void)type; (void)type;
@@ -486,6 +516,15 @@ static void ssh_server_connection_callback(ssh_session session){
session->session_state=SSH_SESSION_STATE_AUTHENTICATING; session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
session->session_state = SSH_SESSION_STATE_AUTHENTICATED; session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
/*
* If the client supports extension negotiation, we will send
* our supported extensions now. This is the first message after
* sending NEWKEYS message and after turning on crypto.
*/
if (session->extensions) {
ssh_server_send_extensions(session);
}
} }
break; break;
case SSH_SESSION_STATE_AUTHENTICATING: case SSH_SESSION_STATE_AUTHENTICATING: