2828#include <stdio.h>
2929#include <stdbool.h>
3030
31+ #include "libssh/libssh.h"
3132#include "libssh/priv.h"
3233#include "libssh/buffer.h"
3334#include "libssh/dh.h"
@@ -374,14 +375,19 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
374375 (void )type ;
375376 (void )user ;
376377
378+ SSH_LOG (SSH_LOG_TRACE , "KEXINIT received" );
379+
377380 if (session -> session_state == SSH_SESSION_STATE_AUTHENTICATED ) {
378381 if (session -> dh_handshake_state == DH_STATE_FINISHED ) {
379382 SSH_LOG (SSH_LOG_DEBUG , "Peer initiated key re-exchange" );
380383 /* Reset the sent flag if the re-kex was initiated by the peer */
381384 session -> flags &= ~SSH_SESSION_FLAG_KEXINIT_SENT ;
382- } else if (session -> dh_handshake_state == DH_STATE_INIT_SENT ) {
383- SSH_LOG (SSH_LOG_DEBUG , "Receeved peer kexinit answer" );
384- } else {
385+ } else if (session -> flags & SSH_SESSION_FLAG_KEXINIT_SENT &&
386+ session -> dh_handshake_state == DH_STATE_INIT_SENT ) {
387+ /* This happens only when we are sending our-guessed first kex
388+ * packet right after our KEXINIT packet. */
389+ SSH_LOG (SSH_LOG_DEBUG , "Received peer kexinit answer." );
390+ } else if (session -> session_state != SSH_SESSION_STATE_INITIAL_KEX ) {
385391 ssh_set_error (session , SSH_FATAL ,
386392 "SSH_KEXINIT received in wrong state" );
387393 goto error ;
@@ -495,16 +501,19 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
495501 /*
496502 * Remember whether 'first_kex_packet_follows' was set and the client
497503 * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
498- * must be ignored.
504+ * must be ignored on the server side.
505+ * Client needs to start the Key exchange over with the correct method
499506 */
500- if (first_kex_packet_follows ) {
507+ if (first_kex_packet_follows || session -> send_first_kex_follows ) {
501508 char * * client_methods = crypto -> client_kex .methods ;
502509 char * * server_methods = crypto -> server_kex .methods ;
503510 session -> first_kex_follows_guess_wrong =
504511 cmp_first_kex_algo (client_methods [SSH_KEX ],
505512 server_methods [SSH_KEX ]) ||
506513 cmp_first_kex_algo (client_methods [SSH_HOSTKEYS ],
507514 server_methods [SSH_HOSTKEYS ]);
515+ SSH_LOG (SSH_LOG_DEBUG , "The initial guess was %s." ,
516+ session -> first_kex_follows_guess_wrong ? "wrong" : "right" );
508517 }
509518
510519 if (server_kex ) {
@@ -583,7 +592,12 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit)
583592
584593 /* Note, that his overwrites authenticated state in case of rekeying */
585594 session -> session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED ;
586- session -> dh_handshake_state = DH_STATE_INIT ;
595+ /* if we already sent our initial key exchange packet, do not reset the
596+ * DH state. We will know if we were right with our guess only in
597+ * dh_handshake_state() */
598+ if (session -> send_first_kex_follows == false) {
599+ session -> dh_handshake_state = DH_STATE_INIT ;
600+ }
587601 session -> ssh_connection_callback (session );
588602 return SSH_PACKET_USED ;
589603
@@ -892,8 +906,9 @@ int ssh_kex_select_methods (ssh_session session)
892906 struct ssh_crypto_struct * crypto = session -> next_crypto ;
893907 struct ssh_kex_struct * server = & crypto -> server_kex ;
894908 struct ssh_kex_struct * client = & crypto -> client_kex ;
895- char * ext_start = NULL , * kex ;
909+ char * ext_start = NULL ;
896910 const char * aead_hmac = NULL ;
911+ enum ssh_key_exchange_e kex_type ;
897912 int i ;
898913
899914 /* Here we should drop the ext-info-c from the list so we avoid matching.
@@ -925,8 +940,18 @@ int ssh_kex_select_methods (ssh_session session)
925940 crypto -> kex_methods [i ] = strdup ("" );
926941 }
927942 }
928- kex = crypto -> kex_methods [SSH_KEX ];
929- crypto -> kex_type = kex_select_kex_type (kex );
943+
944+ /* We can not set this value directly as the old value is needed to revert
945+ * callbacks if we are client */
946+ kex_type = kex_select_kex_type (crypto -> kex_methods [SSH_KEX ]);
947+ if (session -> client && session -> first_kex_follows_guess_wrong ) {
948+ SSH_LOG (SSH_LOG_DEBUG , "Our guess was wrong. Restarting the KEX" );
949+ /* We need to remove the wrong callbacks and start kex again */
950+ revert_kex_callbacks (session );
951+ session -> dh_handshake_state = DH_STATE_INIT ;
952+ session -> first_kex_follows_guess_wrong = false;
953+ }
954+ crypto -> kex_type = kex_type ;
930955
931956 SSH_LOG (SSH_LOG_INFO , "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s" ,
932957 session -> next_crypto -> kex_methods [SSH_KEX ],
@@ -953,6 +978,19 @@ int ssh_send_kex(ssh_session session)
953978 ssh_string str = NULL ;
954979 int i ;
955980 int rc ;
981+ int first_kex_packet_follows = 0 ;
982+
983+ /* Only client can initiate the handshake methods we implement. If we
984+ * already received the peer mechanisms, there is no point in guessing */
985+ if (session -> client &&
986+ session -> session_state != SSH_SESSION_STATE_KEXINIT_RECEIVED &&
987+ session -> send_first_kex_follows ) {
988+ first_kex_packet_follows = 1 ;
989+ }
990+
991+ SSH_LOG (SSH_LOG_TRACE ,
992+ "Sending KEXINIT packet, first_kex_packet_follows = %d" ,
993+ first_kex_packet_follows );
956994
957995 rc = ssh_buffer_pack (session -> out_buffer ,
958996 "bP" ,
@@ -987,14 +1025,14 @@ int ssh_send_kex(ssh_session session)
9871025
9881026 rc = ssh_buffer_pack (session -> out_buffer ,
9891027 "bd" ,
990- 0 ,
1028+ first_kex_packet_follows ,
9911029 0 );
9921030 if (rc != SSH_OK ) {
9931031 goto error ;
9941032 }
9951033
9961034 /* Prepare also the first_kex_packet_follows and reserved to 0 */
997- rc = ssh_buffer_add_u8 (session -> out_hashbuf , 0 );
1035+ rc = ssh_buffer_add_u8 (session -> out_hashbuf , first_kex_packet_follows );
9981036 if (rc < 0 ) {
9991037 goto error ;
10001038 }
@@ -1010,6 +1048,30 @@ int ssh_send_kex(ssh_session session)
10101048
10111049 session -> flags |= SSH_SESSION_FLAG_KEXINIT_SENT ;
10121050 SSH_LOG (SSH_LOG_PACKET , "SSH_MSG_KEXINIT sent" );
1051+
1052+ /* If we indicated that we are sending the guessed key exchange packet,
1053+ * do it now. The packet is simple, but we need to do some preparations */
1054+ if (first_kex_packet_follows ) {
1055+ char * list = kex -> methods [SSH_KEX ];
1056+ char * colon = strchr (list , ',' );
1057+ size_t kex_name_len = colon ? (size_t )(colon - list ) : strlen (list );
1058+ char * kex_name = calloc (kex_name_len + 1 , 1 );
1059+ if (kex_name == NULL ) {
1060+ ssh_set_error_oom (session );
1061+ goto error ;
1062+ }
1063+ snprintf (kex_name , kex_name_len + 1 , "%.*s" , (int )kex_name_len , list );
1064+ SSH_LOG (SSH_LOG_TRACE , "Sending the first kex packet for %s" , kex_name );
1065+
1066+ session -> next_crypto -> kex_type = kex_select_kex_type (kex_name );
1067+ free (kex_name );
1068+
1069+ /* run the first step of the DH handshake */
1070+ session -> dh_handshake_state = DH_STATE_INIT ;
1071+ if (dh_handshake (session ) == SSH_ERROR ) {
1072+ goto error ;
1073+ }
1074+ }
10131075 return 0 ;
10141076
10151077error :
0 commit comments