1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-12-14 04:18:54 +03:00

CVE-2023-1667:kex: Correctly handle last fields of KEXINIT also in the client side

Previously, the last two fields of KEXINIT were considered as always zero for
the key exchange. This was true for the sending side, but might have not been
true for the received KEXINIT from the peer.

This moves the construction of these two fields closer to their reading or
writing, instead of hardcoding them on the last possible moment before they go
as input to the hashing function.

This also allows accepting the first_kex_packet_follows on the client side, even
though there is no kex algorithm now that would allow this.

It also avoid memory leaks in case the server_set_kex() or ssh_set_client_kex()
gets called multiple times, ensuring the algorithms will not change under our
hands.

It also makes use of a new flag to track if we sent KEXINIT.

Previously, this was tracked only implicitly by the content of the
session->next_crypto->{server,client}_kex (local kex). If it was not set, we
considered it was not send. But given that we need to check the local kex even
before sending it when we receive first_kex_packet_follows flag in the KEXINIT,
this can no longer be used.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Norbert Pocs <npocs@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2023-03-10 12:59:48 +01:00
committed by Andreas Schneider
parent cd0aa0bd91
commit 8dbe055328
4 changed files with 80 additions and 61 deletions

View File

@@ -92,7 +92,11 @@ int server_set_kex(ssh_session session)
size_t len;
int ok;
ZERO_STRUCTP(server);
/* Skip if already set, for example for the rekey or when we do the guessing
* it could have been already used to make some protocol decisions. */
if (server->methods[0] != NULL) {
return SSH_OK;
}
ok = ssh_get_random(server->cookie, 16, 0);
if (!ok) {
@@ -366,7 +370,7 @@ static void ssh_server_connection_callback(ssh_session session)
break;
case SSH_SESSION_STATE_KEXINIT_RECEIVED:
set_status(session, 0.6f);
if (session->next_crypto->server_kex.methods[0] == NULL) {
if ((session->flags & SSH_SESSION_FLAG_KEXINIT_SENT) == 0) {
rc = server_set_kex(session);
if (rc == SSH_ERROR) {
goto error;