We now build libssh2 in Xcode and it's a much better UB/10.4 citizen
[printdrop.git] / Vendor / libssh2 / Source / kex.c
1 /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 *
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 */
37
38 #include "libssh2_priv.h"
39
40 /* TODO: Switch this to an inline and handle alloc() failures */
41 /* Helper macro called from libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange */
42 #define LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(value, reqlen, version) \
43 { \
44 libssh2_sha1_ctx hash; \
45 unsigned long len = 0; \
46 if (!(value)) { \
47 value = LIBSSH2_ALLOC(session, reqlen + SHA_DIGEST_LENGTH); \
48 } \
49 if (value) \
50 while (len < (unsigned long)reqlen) { \
51 libssh2_sha1_init(&hash); \
52 libssh2_sha1_update(hash, exchange_state->k_value, \
53 exchange_state->k_value_len); \
54 libssh2_sha1_update(hash, exchange_state->h_sig_comp, \
55 SHA_DIGEST_LENGTH); \
56 if (len > 0) { \
57 libssh2_sha1_update(hash, value, len); \
58 } else { \
59 libssh2_sha1_update(hash, (version), 1); \
60 libssh2_sha1_update(hash, session->session_id, \
61 session->session_id_len); \
62 } \
63 libssh2_sha1_final(hash, (value) + len); \
64 len += SHA_DIGEST_LENGTH; \
65 } \
66 }
67
68 /* {{{ libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
69 * Diffie Hellman Key Exchange, Group Agnostic
70 */
71 static int
72 libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_SESSION *
73 session,
74 _libssh2_bn * g,
75 _libssh2_bn * p,
76 int group_order,
77 unsigned char
78 packet_type_init,
79 unsigned char
80 packet_type_reply,
81 unsigned char
82 *midhash,
83 unsigned long
84 midhash_len,
85 kmdhgGPsha1kex_state_t
86 * exchange_state)
87 {
88 int ret = 0;
89 int rc;
90
91 if (exchange_state->state == libssh2_NB_state_idle) {
92 /* Setup initial values */
93 exchange_state->e_packet = NULL;
94 exchange_state->s_packet = NULL;
95 exchange_state->k_value = NULL;
96 exchange_state->ctx = _libssh2_bn_ctx_new();
97 exchange_state->x = _libssh2_bn_init(); /* Random from client */
98 exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
99 exchange_state->f = _libssh2_bn_init(); /* g^(Random from server) mod p */
100 exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod p */
101
102 /* Zero the whole thing out */
103 memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
104
105 /* Generate x and e */
106 _libssh2_bn_rand(exchange_state->x, group_order, 0, -1);
107 _libssh2_bn_mod_exp(exchange_state->e, g, exchange_state->x, p,
108 exchange_state->ctx);
109
110 /* Send KEX init */
111 /* packet_type(1) + String Length(4) + leading 0(1) */
112 exchange_state->e_packet_len =
113 _libssh2_bn_bytes(exchange_state->e) + 6;
114 if (_libssh2_bn_bits(exchange_state->e) % 8) {
115 /* Leading 00 not needed */
116 exchange_state->e_packet_len--;
117 }
118
119 exchange_state->e_packet =
120 LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
121 if (!exchange_state->e_packet) {
122 libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Out of memory error",
123 0);
124 ret = -1;
125 goto clean_exit;
126 }
127 exchange_state->e_packet[0] = packet_type_init;
128 libssh2_htonu32(exchange_state->e_packet + 1,
129 exchange_state->e_packet_len - 5);
130 if (_libssh2_bn_bits(exchange_state->e) % 8) {
131 _libssh2_bn_to_bin(exchange_state->e,
132 exchange_state->e_packet + 5);
133 } else {
134 exchange_state->e_packet[5] = 0;
135 _libssh2_bn_to_bin(exchange_state->e,
136 exchange_state->e_packet + 6);
137 }
138
139 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending KEX packet %d",
140 (int) packet_type_init);
141 exchange_state->state = libssh2_NB_state_created;
142 }
143
144 if (exchange_state->state == libssh2_NB_state_created) {
145 rc = libssh2_packet_write(session, exchange_state->e_packet,
146 exchange_state->e_packet_len);
147 if (rc == PACKET_EAGAIN) {
148 return PACKET_EAGAIN;
149 } else if (rc) {
150 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
151 "Unable to send KEX init message", 0);
152 ret = -1;
153 goto clean_exit;
154 }
155 exchange_state->state = libssh2_NB_state_sent;
156 }
157
158 if (exchange_state->state == libssh2_NB_state_sent) {
159 if (session->burn_optimistic_kexinit) {
160 /* The first KEX packet to come along will be the guess initially
161 * sent by the server. That guess turned out to be wrong so we
162 * need to silently ignore it */
163 int burn_type;
164
165 _libssh2_debug(session, LIBSSH2_DBG_KEX,
166 "Waiting for badly guessed KEX packet (to be ignored)");
167 burn_type =
168 libssh2_packet_burn(session, &exchange_state->burn_state);
169 if (burn_type == PACKET_EAGAIN) {
170 return PACKET_EAGAIN;
171 } else if (burn_type <= 0) {
172 /* Failed to receive a packet */
173 ret = -1;
174 goto clean_exit;
175 }
176 session->burn_optimistic_kexinit = 0;
177
178 _libssh2_debug(session, LIBSSH2_DBG_KEX,
179 "Burnt packet of type: %02x",
180 (unsigned int) burn_type);
181 }
182
183 exchange_state->state = libssh2_NB_state_sent1;
184 }
185
186 if (exchange_state->state == libssh2_NB_state_sent1) {
187 /* Wait for KEX reply */
188 rc = libssh2_packet_require_ex(session, packet_type_reply,
189 &exchange_state->s_packet,
190 &exchange_state->s_packet_len, 0, NULL,
191 0, &exchange_state->req_state);
192 if (rc == PACKET_EAGAIN) {
193 return PACKET_EAGAIN;
194 }
195 if (rc) {
196 libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
197 "Timed out waiting for KEX reply", 0);
198 ret = -1;
199 goto clean_exit;
200 }
201
202 /* Parse KEXDH_REPLY */
203 exchange_state->s = exchange_state->s_packet + 1;
204
205 session->server_hostkey_len = libssh2_ntohu32(exchange_state->s);
206 exchange_state->s += 4;
207 session->server_hostkey =
208 LIBSSH2_ALLOC(session, session->server_hostkey_len);
209 if (!session->server_hostkey) {
210 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
211 "Unable to allocate memory for a copy of the host key",
212 0);
213 ret = -1;
214 goto clean_exit;
215 }
216 memcpy(session->server_hostkey, exchange_state->s,
217 session->server_hostkey_len);
218 exchange_state->s += session->server_hostkey_len;
219
220 #if LIBSSH2_MD5
221 {
222 libssh2_md5_ctx fingerprint_ctx;
223
224 libssh2_md5_init(&fingerprint_ctx);
225 libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
226 session->server_hostkey_len);
227 libssh2_md5_final(fingerprint_ctx, session->server_hostkey_md5);
228 }
229 #ifdef LIBSSH2DEBUG
230 {
231 char fingerprint[50], *fprint = fingerprint;
232 int i;
233 for(i = 0; i < 16; i++, fprint += 3) {
234 snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
235 }
236 *(--fprint) = '\0';
237 _libssh2_debug(session, LIBSSH2_DBG_KEX,
238 "Server's MD5 Fingerprint: %s", fingerprint);
239 }
240 #endif /* LIBSSH2DEBUG */
241 #endif /* ! LIBSSH2_MD5 */
242
243 {
244 libssh2_sha1_ctx fingerprint_ctx;
245
246 libssh2_sha1_init(&fingerprint_ctx);
247 libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
248 session->server_hostkey_len);
249 libssh2_sha1_final(fingerprint_ctx, session->server_hostkey_sha1);
250 }
251 #ifdef LIBSSH2DEBUG
252 {
253 char fingerprint[64], *fprint = fingerprint;
254 int i;
255
256 for(i = 0; i < 20; i++, fprint += 3) {
257 snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
258 }
259 *(--fprint) = '\0';
260 _libssh2_debug(session, LIBSSH2_DBG_KEX,
261 "Server's SHA1 Fingerprint: %s", fingerprint);
262 }
263 #endif /* LIBSSH2DEBUG */
264
265 if (session->hostkey->
266 init(session, session->server_hostkey, session->server_hostkey_len,
267 &session->server_hostkey_abstract)) {
268 libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
269 "Unable to initialize hostkey importer", 0);
270 ret = -1;
271 goto clean_exit;
272 }
273
274 exchange_state->f_value_len = libssh2_ntohu32(exchange_state->s);
275 exchange_state->s += 4;
276 exchange_state->f_value = exchange_state->s;
277 exchange_state->s += exchange_state->f_value_len;
278 _libssh2_bn_from_bin(exchange_state->f, exchange_state->f_value_len,
279 exchange_state->f_value);
280
281 exchange_state->h_sig_len = libssh2_ntohu32(exchange_state->s);
282 exchange_state->s += 4;
283 exchange_state->h_sig = exchange_state->s;
284
285 /* Compute the shared secret */
286 _libssh2_bn_mod_exp(exchange_state->k, exchange_state->f,
287 exchange_state->x, p, exchange_state->ctx);
288 exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
289 if (_libssh2_bn_bits(exchange_state->k) % 8) {
290 /* don't need leading 00 */
291 exchange_state->k_value_len--;
292 }
293 exchange_state->k_value =
294 LIBSSH2_ALLOC(session, exchange_state->k_value_len);
295 if (!exchange_state->k_value) {
296 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
297 "Unable to allocate buffer for K", 0);
298 ret = -1;
299 goto clean_exit;
300 }
301 libssh2_htonu32(exchange_state->k_value,
302 exchange_state->k_value_len - 4);
303 if (_libssh2_bn_bits(exchange_state->k) % 8) {
304 _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 4);
305 } else {
306 exchange_state->k_value[4] = 0;
307 _libssh2_bn_to_bin(exchange_state->k, exchange_state->k_value + 5);
308 }
309
310 libssh2_sha1_init(&exchange_state->exchange_hash);
311 if (session->local.banner) {
312 libssh2_htonu32(exchange_state->h_sig_comp,
313 strlen((char *) session->local.banner) - 2);
314 libssh2_sha1_update(exchange_state->exchange_hash,
315 exchange_state->h_sig_comp, 4);
316 libssh2_sha1_update(exchange_state->exchange_hash,
317 (char *) session->local.banner,
318 strlen((char *) session->local.banner) - 2);
319 } else {
320 libssh2_htonu32(exchange_state->h_sig_comp,
321 sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
322 libssh2_sha1_update(exchange_state->exchange_hash,
323 exchange_state->h_sig_comp, 4);
324 libssh2_sha1_update(exchange_state->exchange_hash,
325 LIBSSH2_SSH_DEFAULT_BANNER,
326 sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
327 }
328
329 libssh2_htonu32(exchange_state->h_sig_comp,
330 strlen((char *) session->remote.banner));
331 libssh2_sha1_update(exchange_state->exchange_hash,
332 exchange_state->h_sig_comp, 4);
333 libssh2_sha1_update(exchange_state->exchange_hash,
334 session->remote.banner,
335 strlen((char *) session->remote.banner));
336
337 libssh2_htonu32(exchange_state->h_sig_comp,
338 session->local.kexinit_len);
339 libssh2_sha1_update(exchange_state->exchange_hash,
340 exchange_state->h_sig_comp, 4);
341 libssh2_sha1_update(exchange_state->exchange_hash,
342 session->local.kexinit,
343 session->local.kexinit_len);
344
345 libssh2_htonu32(exchange_state->h_sig_comp,
346 session->remote.kexinit_len);
347 libssh2_sha1_update(exchange_state->exchange_hash,
348 exchange_state->h_sig_comp, 4);
349 libssh2_sha1_update(exchange_state->exchange_hash,
350 session->remote.kexinit,
351 session->remote.kexinit_len);
352
353 libssh2_htonu32(exchange_state->h_sig_comp,
354 session->server_hostkey_len);
355 libssh2_sha1_update(exchange_state->exchange_hash,
356 exchange_state->h_sig_comp, 4);
357 libssh2_sha1_update(exchange_state->exchange_hash,
358 session->server_hostkey,
359 session->server_hostkey_len);
360
361 if (packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
362 /* diffie-hellman-group-exchange hashes additional fields */
363 #ifdef LIBSSH2_DH_GEX_NEW
364 libssh2_htonu32(exchange_state->h_sig_comp,
365 LIBSSH2_DH_GEX_MINGROUP);
366 libssh2_htonu32(exchange_state->h_sig_comp + 4,
367 LIBSSH2_DH_GEX_OPTGROUP);
368 libssh2_htonu32(exchange_state->h_sig_comp + 8,
369 LIBSSH2_DH_GEX_MAXGROUP);
370 libssh2_sha1_update(exchange_state->exchange_hash,
371 exchange_state->h_sig_comp, 12);
372 #else
373 libssh2_htonu32(exchange_state->h_sig_comp,
374 LIBSSH2_DH_GEX_OPTGROUP);
375 libssh2_sha1_update(exchange_state->exchange_hash,
376 exchange_state->h_sig_comp, 4);
377 #endif
378 }
379
380 if (midhash) {
381 libssh2_sha1_update(exchange_state->exchange_hash, midhash,
382 midhash_len);
383 }
384
385 libssh2_sha1_update(exchange_state->exchange_hash,
386 exchange_state->e_packet + 1,
387 exchange_state->e_packet_len - 1);
388
389 libssh2_htonu32(exchange_state->h_sig_comp,
390 exchange_state->f_value_len);
391 libssh2_sha1_update(exchange_state->exchange_hash,
392 exchange_state->h_sig_comp, 4);
393 libssh2_sha1_update(exchange_state->exchange_hash,
394 exchange_state->f_value,
395 exchange_state->f_value_len);
396
397 libssh2_sha1_update(exchange_state->exchange_hash,
398 exchange_state->k_value,
399 exchange_state->k_value_len);
400
401 libssh2_sha1_final(exchange_state->exchange_hash,
402 exchange_state->h_sig_comp);
403
404 if (session->hostkey->
405 sig_verify(session, exchange_state->h_sig,
406 exchange_state->h_sig_len, exchange_state->h_sig_comp,
407 20, &session->server_hostkey_abstract)) {
408 libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
409 "Unable to verify hostkey signature", 0);
410 ret = -1;
411 goto clean_exit;
412 }
413
414 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sending NEWKEYS message");
415 exchange_state->c = SSH_MSG_NEWKEYS;
416
417 exchange_state->state = libssh2_NB_state_sent2;
418 }
419
420 if (exchange_state->state == libssh2_NB_state_sent2) {
421 rc = libssh2_packet_write(session, &exchange_state->c, 1);
422 if (rc == PACKET_EAGAIN) {
423 return PACKET_EAGAIN;
424 } else if (rc) {
425 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
426 "Unable to send NEWKEYS message", 0);
427 ret = -1;
428 goto clean_exit;
429 }
430
431 exchange_state->state = libssh2_NB_state_sent3;
432 }
433
434 if (exchange_state->state == libssh2_NB_state_sent3) {
435 rc = libssh2_packet_require_ex(session, SSH_MSG_NEWKEYS,
436 &exchange_state->tmp,
437 &exchange_state->tmp_len, 0, NULL, 0,
438 &exchange_state->req_state);
439 if (rc == PACKET_EAGAIN) {
440 return PACKET_EAGAIN;
441 } else if (rc) {
442 libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
443 "Timed out waiting for NEWKEYS", 0);
444 ret = -1;
445 goto clean_exit;
446 }
447 /* The first key exchange has been performed,
448 switch to active crypt/comp/mac mode */
449 session->state |= LIBSSH2_STATE_NEWKEYS;
450 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Received NEWKEYS message");
451
452 /* This will actually end up being just packet_type(1)
453 for this packet type anyway */
454 LIBSSH2_FREE(session, exchange_state->tmp);
455
456 if (!session->session_id) {
457 session->session_id = LIBSSH2_ALLOC(session, SHA_DIGEST_LENGTH);
458 if (!session->session_id) {
459 ret = -1;
460 goto clean_exit;
461 }
462 memcpy(session->session_id, exchange_state->h_sig_comp,
463 SHA_DIGEST_LENGTH);
464 session->session_id_len = SHA_DIGEST_LENGTH;
465 _libssh2_debug(session, LIBSSH2_DBG_KEX, "session_id calculated");
466 }
467
468 /* Cleanup any existing cipher */
469 if (session->local.crypt->dtor) {
470 session->local.crypt->dtor(session,
471 &session->local.crypt_abstract);
472 }
473
474 /* Calculate IV/Secret/Key for each direction */
475 if (session->local.crypt->init) {
476 unsigned char *iv = NULL, *secret = NULL;
477 int free_iv = 0, free_secret = 0;
478
479 LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
480 session->local.crypt->
481 iv_len, "A");
482 if (!iv) {
483 ret = -1;
484 goto clean_exit;
485 }
486 LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
487 session->local.crypt->
488 secret_len, "C");
489 if (!secret) {
490 LIBSSH2_FREE(session, iv);
491 ret = -1;
492 goto clean_exit;
493 }
494 if (session->local.crypt->
495 init(session, session->local.crypt, iv, &free_iv, secret,
496 &free_secret, 1, &session->local.crypt_abstract)) {
497 LIBSSH2_FREE(session, iv);
498 LIBSSH2_FREE(session, secret);
499 ret = -1;
500 goto clean_exit;
501 }
502
503 if (free_iv) {
504 memset(iv, 0, session->local.crypt->iv_len);
505 LIBSSH2_FREE(session, iv);
506 }
507
508 if (free_secret) {
509 memset(secret, 0, session->local.crypt->secret_len);
510 LIBSSH2_FREE(session, secret);
511 }
512 }
513 _libssh2_debug(session, LIBSSH2_DBG_KEX,
514 "Client to Server IV and Key calculated");
515
516 if (session->remote.crypt->dtor) {
517 /* Cleanup any existing cipher */
518 session->remote.crypt->dtor(session,
519 &session->remote.crypt_abstract);
520 }
521
522 if (session->remote.crypt->init) {
523 unsigned char *iv = NULL, *secret = NULL;
524 int free_iv = 0, free_secret = 0;
525
526 LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv,
527 session->remote.crypt->
528 iv_len, "B");
529 if (!iv) {
530 ret = -1;
531 goto clean_exit;
532 }
533 LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret,
534 session->remote.crypt->
535 secret_len, "D");
536 if (!secret) {
537 LIBSSH2_FREE(session, iv);
538 ret = -1;
539 goto clean_exit;
540 }
541 if (session->remote.crypt->
542 init(session, session->remote.crypt, iv, &free_iv, secret,
543 &free_secret, 0, &session->remote.crypt_abstract)) {
544 LIBSSH2_FREE(session, iv);
545 LIBSSH2_FREE(session, secret);
546 ret = -1;
547 goto clean_exit;
548 }
549
550 if (free_iv) {
551 memset(iv, 0, session->remote.crypt->iv_len);
552 LIBSSH2_FREE(session, iv);
553 }
554
555 if (free_secret) {
556 memset(secret, 0, session->remote.crypt->secret_len);
557 LIBSSH2_FREE(session, secret);
558 }
559 }
560 _libssh2_debug(session, LIBSSH2_DBG_KEX,
561 "Server to Client IV and Key calculated");
562
563 if (session->local.mac->dtor) {
564 session->local.mac->dtor(session, &session->local.mac_abstract);
565 }
566
567 if (session->local.mac->init) {
568 unsigned char *key = NULL;
569 int free_key = 0;
570
571 LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
572 session->local.mac->
573 key_len, "E");
574 if (!key) {
575 ret = -1;
576 goto clean_exit;
577 }
578 session->local.mac->init(session, key, &free_key,
579 &session->local.mac_abstract);
580
581 if (free_key) {
582 memset(key, 0, session->local.mac->key_len);
583 LIBSSH2_FREE(session, key);
584 }
585 }
586 _libssh2_debug(session, LIBSSH2_DBG_KEX,
587 "Client to Server HMAC Key calculated");
588
589 if (session->remote.mac->dtor) {
590 session->remote.mac->dtor(session, &session->remote.mac_abstract);
591 }
592
593 if (session->remote.mac->init) {
594 unsigned char *key = NULL;
595 int free_key = 0;
596
597 LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(key,
598 session->remote.mac->
599 key_len, "F");
600 if (!key) {
601 ret = -1;
602 goto clean_exit;
603 }
604 session->remote.mac->init(session, key, &free_key,
605 &session->remote.mac_abstract);
606
607 if (free_key) {
608 memset(key, 0, session->remote.mac->key_len);
609 LIBSSH2_FREE(session, key);
610 }
611 }
612 _libssh2_debug(session, LIBSSH2_DBG_KEX,
613 "Server to Client HMAC Key calculated");
614 }
615
616 clean_exit:
617 _libssh2_bn_free(exchange_state->x);
618 exchange_state->x = NULL;
619 _libssh2_bn_free(exchange_state->e);
620 exchange_state->e = NULL;
621 _libssh2_bn_free(exchange_state->f);
622 exchange_state->f = NULL;
623 _libssh2_bn_free(exchange_state->k);
624 exchange_state->k = NULL;
625 _libssh2_bn_ctx_free(exchange_state->ctx);
626 exchange_state->ctx = NULL;
627
628 if (exchange_state->e_packet) {
629 LIBSSH2_FREE(session, exchange_state->e_packet);
630 exchange_state->e_packet = NULL;
631 }
632
633 if (exchange_state->s_packet) {
634 LIBSSH2_FREE(session, exchange_state->s_packet);
635 exchange_state->s_packet = NULL;
636 }
637
638 if (exchange_state->k_value) {
639 LIBSSH2_FREE(session, exchange_state->k_value);
640 exchange_state->k_value = NULL;
641 }
642
643 if (session->server_hostkey) {
644 LIBSSH2_FREE(session, session->server_hostkey);
645 session->server_hostkey = NULL;
646 }
647
648 exchange_state->state = libssh2_NB_state_idle;
649
650 return ret;
651 }
652
653 /* }}} */
654
655 /* {{{ libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange
656 * Diffie-Hellman Group1 (Actually Group2) Key Exchange using SHA1
657 */
658 static int
659 libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *
660 session,
661 key_exchange_state_low_t
662 * key_state)
663 {
664 static const unsigned char p_value[128] = {
665 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
666 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
667 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
668 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
669 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
670 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
671 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
672 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
673 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
674 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
675 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
676 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
677 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
678 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
679 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
680 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
681 };
682
683 int ret;
684
685 if (key_state->state == libssh2_NB_state_idle) {
686 /* g == 2 */
687 key_state->p = _libssh2_bn_init(); /* SSH2 defined value (p_value) */
688 key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
689
690 /* Initialize P and G */
691 _libssh2_bn_set_word(key_state->g, 2);
692 _libssh2_bn_from_bin(key_state->p, 128, p_value);
693
694 _libssh2_debug(session, LIBSSH2_DBG_KEX,
695 "Initiating Diffie-Hellman Group1 Key Exchange");
696
697 key_state->state = libssh2_NB_state_created;
698 }
699
700 ret =
701 libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session,
702 key_state->
703 g,
704 key_state->
705 p, 128,
706 SSH_MSG_KEXDH_INIT,
707 SSH_MSG_KEXDH_REPLY,
708 NULL, 0,
709 &key_state->
710 exchange_state);
711 if (ret == PACKET_EAGAIN) {
712 return PACKET_EAGAIN;
713 }
714
715 _libssh2_bn_free(key_state->p);
716 key_state->p = NULL;
717 _libssh2_bn_free(key_state->g);
718 key_state->g = NULL;
719 key_state->state = libssh2_NB_state_idle;
720
721 return ret;
722 }
723
724 /* }}} */
725
726 /* {{{ libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange
727 * Diffie-Hellman Group14 Key Exchange using SHA1
728 */
729 static int
730 libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *
731 session,
732 key_exchange_state_low_t
733 * key_state)
734 {
735 static const unsigned char p_value[256] = {
736 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
737 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
738 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
739 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
740 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
741 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
742 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
743 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
744 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
745 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
746 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
747 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
748 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
749 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
750 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
751 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
752 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
753 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
754 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
755 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
756 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
757 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
758 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
759 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
760 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
761 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
762 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
763 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
764 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
765 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
766 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
767 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
768 };
769 int ret;
770
771 if (key_state->state == libssh2_NB_state_idle) {
772 key_state->p = _libssh2_bn_init(); /* SSH2 defined value (p_value) */
773 key_state->g = _libssh2_bn_init(); /* SSH2 defined value (2) */
774
775 /* g == 2 */
776 /* Initialize P and G */
777 _libssh2_bn_set_word(key_state->g, 2);
778 _libssh2_bn_from_bin(key_state->p, 256, p_value);
779
780 _libssh2_debug(session, LIBSSH2_DBG_KEX,
781 "Initiating Diffie-Hellman Group14 Key Exchange");
782
783 key_state->state = libssh2_NB_state_created;
784 }
785 ret =
786 libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(session,
787 key_state->
788 g,
789 key_state->
790 p, 256,
791 SSH_MSG_KEXDH_INIT,
792 SSH_MSG_KEXDH_REPLY,
793 NULL, 0,
794 &key_state->
795 exchange_state);
796 if (ret == PACKET_EAGAIN) {
797 return PACKET_EAGAIN;
798 }
799
800 key_state->state = libssh2_NB_state_idle;
801 _libssh2_bn_free(key_state->p);
802 key_state->p = NULL;
803 _libssh2_bn_free(key_state->g);
804 key_state->g = NULL;
805
806 return ret;
807 }
808
809 /* }}} */
810
811 /* {{{ libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange
812 * Diffie-Hellman Group Exchange Key Exchange using SHA1
813 * Negotiates random(ish) group for secret derivation
814 */
815 static int
816 libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange
817 (LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
818 {
819 unsigned char *s;
820 unsigned long p_len, g_len;
821 int ret;
822 int rc;
823
824 if (key_state->state == libssh2_NB_state_idle) {
825 key_state->p = _libssh2_bn_init();
826 key_state->g = _libssh2_bn_init();
827 /* Ask for a P and G pair */
828 #ifdef LIBSSH2_DH_GEX_NEW
829 key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST;
830 libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP);
831 libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
832 libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
833 key_state->request_len = 13;
834 _libssh2_debug(session, LIBSSH2_DBG_KEX,
835 "Initiating Diffie-Hellman Group-Exchange (New Method)");
836 #else
837 key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST_OLD;
838 libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_OPTGROUP);
839 key_state->request_len = 5;
840 _libssh2_debug(session, LIBSSH2_DBG_KEX,
841 "Initiating Diffie-Hellman Group-Exchange (Old Method)");
842 #endif
843
844 key_state->state = libssh2_NB_state_created;
845 }
846
847 if (key_state->state == libssh2_NB_state_created) {
848 rc = libssh2_packet_write(session, key_state->request,
849 key_state->request_len);
850 if (rc == PACKET_EAGAIN) {
851 return PACKET_EAGAIN;
852 } else if (rc) {
853 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
854 "Unable to send Group Exchange Request", 0);
855 ret = -1;
856 goto dh_gex_clean_exit;
857 }
858
859 key_state->state = libssh2_NB_state_sent;
860 }
861
862 if (key_state->state == libssh2_NB_state_sent) {
863 rc = libssh2_packet_require_ex(session, SSH_MSG_KEX_DH_GEX_GROUP,
864 &key_state->data, &key_state->data_len,
865 0, NULL, 0, &key_state->req_state);
866 if (rc == PACKET_EAGAIN) {
867 return PACKET_EAGAIN;
868 } else if (rc) {
869 libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
870 "Timeout waiting for GEX_GROUP reply", 0);
871 ret = -1;
872 goto dh_gex_clean_exit;
873 }
874
875 key_state->state = libssh2_NB_state_sent1;
876 }
877
878 if (key_state->state == libssh2_NB_state_sent1) {
879 s = key_state->data + 1;
880 p_len = libssh2_ntohu32(s);
881 s += 4;
882 _libssh2_bn_from_bin(key_state->p, p_len, s);
883 s += p_len;
884
885 g_len = libssh2_ntohu32(s);
886 s += 4;
887 _libssh2_bn_from_bin(key_state->g, g_len, s);
888 s += g_len;
889
890 ret =
891 libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange
892 (session, key_state->g, key_state->p, p_len,
893 SSH_MSG_KEX_DH_GEX_INIT, SSH_MSG_KEX_DH_GEX_REPLY,
894 key_state->data + 1, key_state->data_len - 1,
895 &key_state->exchange_state);
896 if (ret == PACKET_EAGAIN) {
897 return PACKET_EAGAIN;
898 }
899
900 LIBSSH2_FREE(session, key_state->data);
901 }
902
903 dh_gex_clean_exit:
904 key_state->state = libssh2_NB_state_idle;
905 _libssh2_bn_free(key_state->g);
906 key_state->g = NULL;
907 _libssh2_bn_free(key_state->p);
908 key_state->p = NULL;
909
910 return ret;
911 }
912
913 /* }}} */
914
915 #define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY 0x0001
916 #define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY 0x0002
917
918 static const LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group1_sha1 = {
919 "diffie-hellman-group1-sha1",
920 libssh2_kex_method_diffie_hellman_group1_sha1_key_exchange,
921 LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
922 };
923
924 static const LIBSSH2_KEX_METHOD libssh2_kex_method_diffie_helman_group14_sha1 = {
925 "diffie-hellman-group14-sha1",
926 libssh2_kex_method_diffie_hellman_group14_sha1_key_exchange,
927 LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
928 };
929
930 static const LIBSSH2_KEX_METHOD
931 libssh2_kex_method_diffie_helman_group_exchange_sha1 = {
932 "diffie-hellman-group-exchange-sha1",
933 libssh2_kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
934 LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
935 };
936
937 static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
938 &libssh2_kex_method_diffie_helman_group14_sha1,
939 &libssh2_kex_method_diffie_helman_group_exchange_sha1,
940 &libssh2_kex_method_diffie_helman_group1_sha1,
941 NULL
942 };
943
944 typedef struct _LIBSSH2_COMMON_METHOD
945 {
946 const char *name;
947 } LIBSSH2_COMMON_METHOD;
948
949 /* {{{ libssh2_kex_method_strlen
950 * Calculate the length of a particular method list's resulting string
951 * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1 (because the last coma isn't used)
952 * Another sign of bad coding practices gone mad. Pretend you don't see this.
953 */
954 static size_t
955 libssh2_kex_method_strlen(LIBSSH2_COMMON_METHOD ** method)
956 {
957 size_t len = 0;
958
959 if (!method || !*method) {
960 return 0;
961 }
962
963 while (*method && (*method)->name) {
964 len += strlen((*method)->name) + 1;
965 method++;
966 }
967
968 return len - 1;
969 }
970
971 /* }}} */
972
973 /* {{{ libssh2_kex_method_list
974 * Generate formatted preference list in buf
975 */
976 static size_t
977 libssh2_kex_method_list(unsigned char *buf, size_t list_strlen,
978 LIBSSH2_COMMON_METHOD ** method)
979 {
980 libssh2_htonu32(buf, list_strlen);
981 buf += 4;
982
983 if (!method || !*method) {
984 return 4;
985 }
986
987 while (*method && (*method)->name) {
988 int mlen = strlen((*method)->name);
989 memcpy(buf, (*method)->name, mlen);
990 buf += mlen;
991 *(buf++) = ',';
992 method++;
993 }
994
995 return list_strlen + 4;
996 }
997
998 /* }}} */
999
1000 #define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar) ((prefvar) ? strlen(prefvar) : libssh2_kex_method_strlen((LIBSSH2_COMMON_METHOD**)(defaultvar)))
1001 #define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar) \
1002 if (prefvar) { \
1003 libssh2_htonu32((buf), (prefvarlen)); \
1004 buf += 4; \
1005 memcpy((buf), (prefvar), (prefvarlen)); \
1006 buf += (prefvarlen); \
1007 } else { \
1008 buf += libssh2_kex_method_list((buf), (prefvarlen), (LIBSSH2_COMMON_METHOD**)(defaultvar)); \
1009 }
1010
1011 /* {{{ libssh2_kexinit
1012 * Send SSH_MSG_KEXINIT packet
1013 */
1014 static int
1015 libssh2_kexinit(LIBSSH2_SESSION * session)
1016 {
1017 /* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) +
1018 reserved(4) + length longs(40) */
1019 size_t data_len = 62;
1020 size_t kex_len, hostkey_len = 0;
1021 size_t crypt_cs_len, crypt_sc_len;
1022 size_t comp_cs_len, comp_sc_len;
1023 size_t mac_cs_len, mac_sc_len;
1024 size_t lang_cs_len, lang_sc_len;
1025 unsigned char *data, *s;
1026 int rc;
1027
1028 if (session->kexinit_state == libssh2_NB_state_idle) {
1029 kex_len =
1030 LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
1031 hostkey_len =
1032 LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs,
1033 libssh2_hostkey_methods());
1034 crypt_cs_len =
1035 LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs,
1036 libssh2_crypt_methods());
1037 crypt_sc_len =
1038 LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs,
1039 libssh2_crypt_methods());
1040 mac_cs_len =
1041 LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs,
1042 libssh2_mac_methods());
1043 mac_sc_len =
1044 LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs,
1045 libssh2_mac_methods());
1046 comp_cs_len =
1047 LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs,
1048 libssh2_comp_methods());
1049 comp_sc_len =
1050 LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs,
1051 libssh2_comp_methods());
1052 lang_cs_len =
1053 LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
1054 lang_sc_len =
1055 LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL);
1056
1057 data_len += kex_len + hostkey_len + crypt_cs_len + crypt_sc_len +
1058 comp_cs_len + comp_sc_len + mac_cs_len + mac_sc_len +
1059 lang_cs_len + lang_sc_len;
1060
1061 s = data = LIBSSH2_ALLOC(session, data_len);
1062 if (!data) {
1063 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1064 "Unable to allocate memory", 0);
1065 return -1;
1066 }
1067
1068 *(s++) = SSH_MSG_KEXINIT;
1069
1070 libssh2_random(s, 16);
1071 s += 16;
1072
1073 /* Ennumerating through these lists twice is probably (certainly?)
1074 inefficient from a CPU standpoint, but it saves multiple
1075 malloc/realloc calls */
1076 LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs,
1077 libssh2_kex_methods);
1078 LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs,
1079 libssh2_hostkey_methods());
1080 LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs,
1081 libssh2_crypt_methods());
1082 LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs,
1083 libssh2_crypt_methods());
1084 LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs,
1085 libssh2_mac_methods());
1086 LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs,
1087 libssh2_mac_methods());
1088 LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs,
1089 libssh2_comp_methods());
1090 LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs,
1091 libssh2_comp_methods());
1092 LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs,
1093 NULL);
1094 LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs,
1095 NULL);
1096
1097 /* No optimistic KEX packet follows */
1098 /* Deal with optimistic packets
1099 * session->flags |= KEXINIT_OPTIMISTIC
1100 * session->flags |= KEXINIT_METHODSMATCH
1101 */
1102 *(s++) = 0;
1103
1104 /* Reserved == 0 */
1105 *(s++) = 0;
1106 *(s++) = 0;
1107 *(s++) = 0;
1108 *(s++) = 0;
1109
1110 #ifdef LIBSSH2DEBUG
1111 {
1112 /* Funnily enough, they'll all "appear" to be '\0' terminated */
1113 unsigned char *p = data + 21; /* type(1) + cookie(16) + len(4) */
1114
1115 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent KEX: %s", p);
1116 p += kex_len + 4;
1117 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent HOSTKEY: %s", p);
1118 p += hostkey_len + 4;
1119 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_CS: %s", p);
1120 p += crypt_cs_len + 4;
1121 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent CRYPT_SC: %s", p);
1122 p += crypt_sc_len + 4;
1123 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_CS: %s", p);
1124 p += mac_cs_len + 4;
1125 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent MAC_SC: %s", p);
1126 p += mac_sc_len + 4;
1127 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_CS: %s", p);
1128 p += comp_cs_len + 4;
1129 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent COMP_SC: %s", p);
1130 p += comp_sc_len + 4;
1131 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_CS: %s", p);
1132 p += lang_cs_len + 4;
1133 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Sent LANG_SC: %s", p);
1134 p += lang_sc_len + 4;
1135 }
1136 #endif /* LIBSSH2DEBUG */
1137
1138 session->kexinit_state = libssh2_NB_state_created;
1139 } else {
1140 data = session->kexinit_data;
1141 data_len = session->kexinit_data_len;
1142 }
1143
1144 if ((rc = libssh2_packet_write(session, data, data_len)) == PACKET_EAGAIN) {
1145 session->kexinit_data = data;
1146 session->kexinit_data_len = data_len;
1147 return PACKET_EAGAIN;
1148 } else if (rc) {
1149 LIBSSH2_FREE(session, data);
1150 libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
1151 "Unable to send KEXINIT packet to remote host", 0);
1152 session->kexinit_state = libssh2_NB_state_idle;
1153 return -1;
1154 }
1155
1156 if (session->local.kexinit) {
1157 LIBSSH2_FREE(session, session->local.kexinit);
1158 }
1159
1160 session->local.kexinit = data;
1161 session->local.kexinit_len = data_len;
1162
1163 session->kexinit_state = libssh2_NB_state_idle;
1164
1165 return 0;
1166 }
1167
1168 /* }}} */
1169
1170 /* {{{ libssh2_kex_agree_instr
1171 * Kex specific variant of strstr()
1172 * Needle must be preceed by BOL or ',', and followed by ',' or EOL
1173 */
1174 static unsigned char *
1175 libssh2_kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
1176 const unsigned char *needle, unsigned long needle_len)
1177 {
1178 unsigned char *s;
1179
1180 /* Haystack too short to bother trying */
1181 if (haystack_len < needle_len) {
1182 return NULL;
1183 }
1184
1185 /* Needle at start of haystack */
1186 if ((strncmp((char *) haystack, (char *) needle, needle_len) == 0) &&
1187 (needle_len == haystack_len || haystack[needle_len] == ',')) {
1188 return haystack;
1189 }
1190
1191 s = haystack;
1192 /* Search until we run out of comas or we run out of haystack,
1193 whichever comes first */
1194 while ((s = (unsigned char *) strchr((char *) s, ','))
1195 && ((haystack_len - (s - haystack)) > needle_len)) {
1196 s++;
1197 /* Needle at X position */
1198 if ((strncmp((char *) s, (char *) needle, needle_len) == 0) &&
1199 (((s - haystack) + needle_len) == haystack_len
1200 || s[needle_len] == ',')) {
1201 return s;
1202 }
1203 }
1204
1205 return NULL;
1206 }
1207
1208 /* }}} */
1209
1210 /* {{{ libssh2_get_method_by_name
1211 */
1212 static const LIBSSH2_COMMON_METHOD *
1213 libssh2_get_method_by_name(const char *name, int name_len,
1214 const LIBSSH2_COMMON_METHOD ** methodlist)
1215 {
1216 while (*methodlist) {
1217 if ((strlen((*methodlist)->name) == name_len) &&
1218 (strncmp((*methodlist)->name, name, name_len) == 0)) {
1219 return *methodlist;
1220 }
1221 methodlist++;
1222 }
1223 return NULL;
1224 }
1225
1226 /* }}} */
1227
1228 /* {{{ libssh2_kex_agree_hostkey
1229 * Agree on a Hostkey which works with this kex
1230 */
1231 static int
1232 libssh2_kex_agree_hostkey(LIBSSH2_SESSION * session, unsigned long kex_flags,
1233 unsigned char *hostkey, unsigned long hostkey_len)
1234 {
1235 const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
1236 unsigned char *s;
1237
1238 if (session->hostkey_prefs) {
1239 s = (unsigned char *) session->hostkey_prefs;
1240
1241 while (s && *s) {
1242 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
1243 int method_len = (p ? (p - s) : strlen((char *) s));
1244 if (libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
1245 const LIBSSH2_HOSTKEY_METHOD *method =
1246 (const LIBSSH2_HOSTKEY_METHOD *)
1247 libssh2_get_method_by_name((char *) s, method_len,
1248 (const LIBSSH2_COMMON_METHOD **)
1249 hostkeyp);
1250
1251 if (!method) {
1252 /* Invalid method -- Should never be reached */
1253 return -1;
1254 }
1255
1256 /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
1257 if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
1258 0) || (method->encrypt)) {
1259 /* Either this hostkey can do encryption or this kex just doesn't require it */
1260 if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
1261 == 0) || (method->sig_verify)) {
1262 /* Either this hostkey can do signing or this kex just doesn't require it */
1263 session->hostkey = method;
1264 return 0;
1265 }
1266 }
1267 }
1268
1269 s = p ? p + 1 : NULL;
1270 }
1271 return -1;
1272 }
1273
1274 while (hostkeyp && (*hostkeyp)->name) {
1275 s = libssh2_kex_agree_instr(hostkey, hostkey_len,
1276 (unsigned char *) (*hostkeyp)->name,
1277 strlen((*hostkeyp)->name));
1278 if (s) {
1279 /* So far so good, but does it suit our purposes? (Encrypting vs Signing) */
1280 if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
1281 ((*hostkeyp)->encrypt)) {
1282 /* Either this hostkey can do encryption or this kex just doesn't require it */
1283 if (((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
1284 0) || ((*hostkeyp)->sig_verify)) {
1285 /* Either this hostkey can do signing or this kex just doesn't require it */
1286 session->hostkey = *hostkeyp;
1287 return 0;
1288 }
1289 }
1290 }
1291 hostkeyp++;
1292 }
1293
1294 return -1;
1295 }
1296
1297 /* }}} */
1298
1299 /* {{{ libssh2_kex_agree_kex_hostkey
1300 * Agree on a Key Exchange method and a hostkey encoding type
1301 */
1302 static int
1303 libssh2_kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
1304 unsigned long kex_len, unsigned char *hostkey,
1305 unsigned long hostkey_len)
1306 {
1307 const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
1308 unsigned char *s;
1309
1310 if (session->kex_prefs) {
1311 s = (unsigned char *) session->kex_prefs;
1312
1313 while (s && *s) {
1314 unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
1315 int method_len = (p ? (p - s) : strlen((char *) s));
1316 if ((q = libssh2_kex_agree_instr(kex, kex_len, s, method_len))) {
1317 const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
1318 libssh2_get_method_by_name((char *) s, method_len,
1319 (const LIBSSH2_COMMON_METHOD **)
1320 kexp);
1321
1322 if (!method) {
1323 /* Invalid method -- Should never be reached */
1324 return -1;
1325 }
1326
1327 /* We've agreed on a key exchange method,
1328 * Can we agree on a hostkey that works with this kex?
1329 */
1330 if (libssh2_kex_agree_hostkey
1331 (session, method->flags, hostkey, hostkey_len) == 0) {
1332 session->kex = method;
1333 if (session->burn_optimistic_kexinit && (kex == q)) {
1334 /* Server sent an optimistic packet,
1335 * and client agrees with preference
1336 * cancel burning the first KEX_INIT packet that comes in */
1337 session->burn_optimistic_kexinit = 0;
1338 }
1339 return 0;
1340 }
1341 }
1342
1343 s = p ? p + 1 : NULL;
1344 }
1345 return -1;
1346 }
1347
1348 while (*kexp && (*kexp)->name) {
1349 s = libssh2_kex_agree_instr(kex, kex_len,
1350 (unsigned char *) (*kexp)->name,
1351 strlen((*kexp)->name));
1352 if (s) {
1353 /* We've agreed on a key exchange method,
1354 * Can we agree on a hostkey that works with this kex?
1355 */
1356 if (libssh2_kex_agree_hostkey
1357 (session, (*kexp)->flags, hostkey, hostkey_len) == 0) {
1358 session->kex = *kexp;
1359 if (session->burn_optimistic_kexinit && (kex == s)) {
1360 /* Server sent an optimistic packet,
1361 * and client agrees with preference
1362 * cancel burning the first KEX_INIT packet that comes in */
1363 session->burn_optimistic_kexinit = 0;
1364 }
1365 return 0;
1366 }
1367 }
1368 kexp++;
1369 }
1370 return -1;
1371 }
1372
1373 /* }}} */
1374
1375 /* {{{ libssh2_kex_agree_crypt
1376 * Agree on a cipher algo
1377 */
1378 static int
1379 libssh2_kex_agree_crypt(LIBSSH2_SESSION * session,
1380 libssh2_endpoint_data * endpoint, unsigned char *crypt,
1381 unsigned long crypt_len)
1382 {
1383 const LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods();
1384 unsigned char *s;
1385
1386 (void) session;
1387
1388 if (endpoint->crypt_prefs) {
1389 s = (unsigned char *) endpoint->crypt_prefs;
1390
1391 while (s && *s) {
1392 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
1393 int method_len = (p ? (p - s) : strlen((char *) s));
1394
1395 if (libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
1396 const LIBSSH2_CRYPT_METHOD *method =
1397 (const LIBSSH2_CRYPT_METHOD *)
1398 libssh2_get_method_by_name((char *) s, method_len,
1399 (const LIBSSH2_COMMON_METHOD **)
1400 cryptp);
1401
1402 if (!method) {
1403 /* Invalid method -- Should never be reached */
1404 return -1;
1405 }
1406
1407 endpoint->crypt = method;
1408 return 0;
1409 }
1410
1411 s = p ? p + 1 : NULL;
1412 }
1413 return -1;
1414 }
1415
1416 while (*cryptp && (*cryptp)->name) {
1417 s = libssh2_kex_agree_instr(crypt, crypt_len,
1418 (unsigned char *) (*cryptp)->name,
1419 strlen((*cryptp)->name));
1420 if (s) {
1421 endpoint->crypt = *cryptp;
1422 return 0;
1423 }
1424 cryptp++;
1425 }
1426
1427 return -1;
1428 }
1429
1430 /* }}} */
1431
1432 /* {{{ libssh2_kex_agree_mac
1433 * Agree on a message authentication hash
1434 */
1435 static int
1436 libssh2_kex_agree_mac(LIBSSH2_SESSION * session,
1437 libssh2_endpoint_data * endpoint, unsigned char *mac,
1438 unsigned long mac_len)
1439 {
1440 const LIBSSH2_MAC_METHOD **macp = libssh2_mac_methods();
1441 unsigned char *s;
1442 (void) session;
1443
1444 if (endpoint->mac_prefs) {
1445 s = (unsigned char *) endpoint->mac_prefs;
1446
1447 while (s && *s) {
1448 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
1449 int method_len = (p ? (p - s) : strlen((char *) s));
1450
1451 if (libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
1452 const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
1453 libssh2_get_method_by_name((char *) s, method_len,
1454 (const LIBSSH2_COMMON_METHOD **)
1455 macp);
1456
1457 if (!method) {
1458 /* Invalid method -- Should never be reached */
1459 return -1;
1460 }
1461
1462 endpoint->mac = method;
1463 return 0;
1464 }
1465
1466 s = p ? p + 1 : NULL;
1467 }
1468 return -1;
1469 }
1470
1471 while (*macp && (*macp)->name) {
1472 s = libssh2_kex_agree_instr(mac, mac_len,
1473 (unsigned char *) (*macp)->name,
1474 strlen((*macp)->name));
1475 if (s) {
1476 endpoint->mac = *macp;
1477 return 0;
1478 }
1479 macp++;
1480 }
1481
1482 return -1;
1483 }
1484
1485 /* }}} */
1486
1487 /* {{{ libssh2_kex_agree_comp
1488 * Agree on a compression scheme
1489 */
1490 static int
1491 libssh2_kex_agree_comp(LIBSSH2_SESSION * session,
1492 libssh2_endpoint_data * endpoint, unsigned char *comp,
1493 unsigned long comp_len)
1494 {
1495 const LIBSSH2_COMP_METHOD **compp = libssh2_comp_methods();
1496 unsigned char *s;
1497 (void) session;
1498
1499 if (endpoint->comp_prefs) {
1500 s = (unsigned char *) endpoint->comp_prefs;
1501
1502 while (s && *s) {
1503 unsigned char *p = (unsigned char *) strchr((char *) s, ',');
1504 int method_len = (p ? (p - s) : strlen((char *) s));
1505
1506 if (libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
1507 const LIBSSH2_COMP_METHOD *method =
1508 (const LIBSSH2_COMP_METHOD *)
1509 libssh2_get_method_by_name((char *) s, method_len,
1510 (const LIBSSH2_COMMON_METHOD **)
1511 compp);
1512
1513 if (!method) {
1514 /* Invalid method -- Should never be reached */
1515 return -1;
1516 }
1517
1518 endpoint->comp = method;
1519 return 0;
1520 }
1521
1522 s = p ? p + 1 : NULL;
1523 }
1524 return -1;
1525 }
1526
1527 while (*compp && (*compp)->name) {
1528 s = libssh2_kex_agree_instr(comp, comp_len,
1529 (unsigned char *) (*compp)->name,
1530 strlen((*compp)->name));
1531 if (s) {
1532 endpoint->comp = *compp;
1533 return 0;
1534 }
1535 compp++;
1536 }
1537
1538 return -1;
1539 }
1540
1541 /* }}} */
1542
1543 /* TODO: When in server mode we need to turn this logic on its head
1544 * The Client gets to make the final call on "agreed methods"
1545 */
1546
1547 /* {{{ libssh2_kex_agree_methods
1548 * Decide which specific method to use of the methods offered by each party
1549 */
1550 static int
1551 libssh2_kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
1552 unsigned data_len)
1553 {
1554 unsigned char *kex, *hostkey, *crypt_cs, *crypt_sc, *comp_cs, *comp_sc,
1555 *mac_cs, *mac_sc, *lang_cs, *lang_sc;
1556 size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
1557 size_t comp_sc_len, mac_cs_len, mac_sc_len, lang_cs_len, lang_sc_len;
1558 unsigned char *s = data;
1559
1560 /* Skip packet_type, we know it already */
1561 s++;
1562
1563 /* Skip cookie, don't worry, it's preserved in the kexinit field */
1564 s += 16;
1565
1566 /* Locate each string */
1567 kex_len = libssh2_ntohu32(s);
1568 kex = s + 4;
1569 s += 4 + kex_len;
1570 hostkey_len = libssh2_ntohu32(s);
1571 hostkey = s + 4;
1572 s += 4 + hostkey_len;
1573 crypt_cs_len = libssh2_ntohu32(s);
1574 crypt_cs = s + 4;
1575 s += 4 + crypt_cs_len;
1576 crypt_sc_len = libssh2_ntohu32(s);
1577 crypt_sc = s + 4;
1578 s += 4 + crypt_sc_len;
1579 mac_cs_len = libssh2_ntohu32(s);
1580 mac_cs = s + 4;
1581 s += 4 + mac_cs_len;
1582 mac_sc_len = libssh2_ntohu32(s);
1583 mac_sc = s + 4;
1584 s += 4 + mac_sc_len;
1585 comp_cs_len = libssh2_ntohu32(s);
1586 comp_cs = s + 4;
1587 s += 4 + comp_cs_len;
1588 comp_sc_len = libssh2_ntohu32(s);
1589 comp_sc = s + 4;
1590 s += 4 + comp_sc_len;
1591 lang_cs_len = libssh2_ntohu32(s);
1592 lang_cs = s + 4;
1593 s += 4 + lang_cs_len;
1594 lang_sc_len = libssh2_ntohu32(s);
1595 lang_sc = s + 4;
1596 s += 4 + lang_sc_len;
1597
1598 /* If the server sent an optimistic packet, assume that it guessed wrong.
1599 * If the guess is determined to be right (by libssh2_kex_agree_kex_hostkey)
1600 * This flag will be reset to zero so that it's not ignored */
1601 session->burn_optimistic_kexinit = *(s++);
1602 /* Next uint32 in packet is all zeros (reserved) */
1603
1604 if (data_len < (unsigned) (s - data))
1605 return -1; /* short packet */
1606
1607 if (libssh2_kex_agree_kex_hostkey
1608 (session, kex, kex_len, hostkey, hostkey_len)) {
1609 return -1;
1610 }
1611
1612 if (libssh2_kex_agree_crypt
1613 (session, &session->local, crypt_cs, crypt_cs_len)
1614 || libssh2_kex_agree_crypt(session, &session->remote, crypt_sc,
1615 crypt_sc_len)) {
1616 return -1;
1617 }
1618
1619 if (libssh2_kex_agree_mac(session, &session->local, mac_cs, mac_cs_len) ||
1620 libssh2_kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) {
1621 return -1;
1622 }
1623
1624 if (libssh2_kex_agree_comp(session, &session->local, comp_cs, comp_cs_len)
1625 || libssh2_kex_agree_comp(session, &session->remote, comp_sc,
1626 comp_sc_len)) {
1627 return -1;
1628 }
1629
1630 if (libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
1631 || libssh2_kex_agree_lang(session, &session->remote, lang_sc,
1632 lang_sc_len)) {
1633 return -1;
1634 }
1635
1636 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on KEX method: %s",
1637 session->kex->name);
1638 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on HOSTKEY method: %s",
1639 session->hostkey->name);
1640 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_CS method: %s",
1641 session->local.crypt->name);
1642 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on CRYPT_SC method: %s",
1643 session->remote.crypt->name);
1644 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_CS method: %s",
1645 session->local.mac->name);
1646 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on MAC_SC method: %s",
1647 session->remote.mac->name);
1648 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_CS method: %s",
1649 session->local.comp->name);
1650 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on COMP_SC method: %s",
1651 session->remote.comp->name);
1652 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_CS method:"); /* None yet */
1653 _libssh2_debug(session, LIBSSH2_DBG_KEX, "Agreed on LANG_SC method:"); /* None yet */
1654
1655 /* Initialize compression layer */
1656 if (session->local.comp && session->local.comp->init &&
1657 session->local.comp->init(session, 1, &session->local.comp_abstract)) {
1658 return -1;
1659 }
1660
1661 if (session->remote.comp && session->remote.comp->init &&
1662 session->remote.comp->init(session, 0,
1663 &session->remote.comp_abstract)) {
1664 return -1;
1665 }
1666
1667 return 0;
1668 }
1669
1670 /* }}} */
1671
1672 /* {{{ libssh2_kex_exchange
1673 * Exchange keys
1674 * Returns 0 on success, non-zero on failure
1675 */
1676 int
1677 libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange, /* session->flags |= SERVER */
1678 key_exchange_state_t * key_state)
1679 {
1680 int rc = 0;
1681 int retcode;
1682
1683 if (key_state->state == libssh2_NB_state_idle) {
1684 /* Prevent loop in packet_add() */
1685 session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
1686
1687 if (reexchange) {
1688 session->kex = NULL;
1689
1690 if (session->hostkey && session->hostkey->dtor) {
1691 session->hostkey->dtor(session,
1692 &session->server_hostkey_abstract);
1693 }
1694 session->hostkey = NULL;
1695 }
1696
1697 key_state->state = libssh2_NB_state_created;
1698 }
1699
1700 if (!session->kex || !session->hostkey) {
1701 if (key_state->state == libssh2_NB_state_created) {
1702 /* Preserve in case of failure */
1703 key_state->oldlocal = session->local.kexinit;
1704 key_state->oldlocal_len = session->local.kexinit_len;
1705
1706 session->local.kexinit = NULL;
1707
1708 key_state->state = libssh2_NB_state_sent;
1709 }
1710
1711 if (key_state->state == libssh2_NB_state_sent) {
1712 retcode = libssh2_kexinit(session);
1713 if (retcode == PACKET_EAGAIN) {
1714 return PACKET_EAGAIN;
1715 } else if (retcode) {
1716 session->local.kexinit = key_state->oldlocal;
1717 session->local.kexinit_len = key_state->oldlocal_len;
1718 key_state->state = libssh2_NB_state_idle;
1719 return -1;
1720 }
1721
1722 key_state->state = libssh2_NB_state_sent1;
1723 }
1724
1725 if (key_state->state == libssh2_NB_state_sent1) {
1726 retcode =
1727 libssh2_packet_require_ex(session, SSH_MSG_KEXINIT,
1728 &key_state->data,
1729 &key_state->data_len, 0, NULL, 0,
1730 &key_state->req_state);
1731 if (retcode == PACKET_EAGAIN) {
1732 return PACKET_EAGAIN;
1733 } else if (retcode) {
1734 if (session->local.kexinit) {
1735 LIBSSH2_FREE(session, session->local.kexinit);
1736 }
1737 session->local.kexinit = key_state->oldlocal;
1738 session->local.kexinit_len = key_state->oldlocal_len;
1739 key_state->state = libssh2_NB_state_idle;
1740 return -1;
1741 }
1742
1743 if (session->remote.kexinit) {
1744 LIBSSH2_FREE(session, session->remote.kexinit);
1745 }
1746 session->remote.kexinit = key_state->data;
1747 session->remote.kexinit_len = key_state->data_len;
1748
1749 if (libssh2_kex_agree_methods
1750 (session, key_state->data, key_state->data_len)) {
1751 rc = -1;
1752 }
1753
1754 key_state->state = libssh2_NB_state_sent2;
1755 }
1756 } else {
1757 key_state->state = libssh2_NB_state_sent2;
1758 }
1759
1760 if (rc == 0) {
1761 if (key_state->state == libssh2_NB_state_sent2) {
1762 retcode =
1763 session->kex->exchange_keys(session,
1764 &key_state->key_state_low);
1765 if (retcode == PACKET_EAGAIN) {
1766 return PACKET_EAGAIN;
1767 } else if (retcode) {
1768 libssh2_error(session, LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
1769 "Unrecoverable error exchanging keys", 0);
1770 rc = -1;
1771 }
1772 }
1773 }
1774
1775 /* Done with kexinit buffers */
1776 if (session->local.kexinit) {
1777 LIBSSH2_FREE(session, session->local.kexinit);
1778 session->local.kexinit = NULL;
1779 }
1780 if (session->remote.kexinit) {
1781 LIBSSH2_FREE(session, session->remote.kexinit);
1782 session->remote.kexinit = NULL;
1783 }
1784
1785 session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
1786
1787 key_state->state = libssh2_NB_state_idle;
1788
1789 return rc;
1790 }
1791
1792 /* }}} */
1793
1794 /* {{{ libssh2_session_method_pref
1795 * Set preferred method
1796 */
1797 LIBSSH2_API int
1798 libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
1799 const char *prefs)
1800 {
1801 char **prefvar, *s, *newprefs;
1802 int prefs_len = strlen(prefs);
1803 const LIBSSH2_COMMON_METHOD **mlist;
1804
1805 switch (method_type) {
1806 case LIBSSH2_METHOD_KEX:
1807 prefvar = &session->kex_prefs;
1808 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_kex_methods;
1809 break;
1810
1811 case LIBSSH2_METHOD_HOSTKEY:
1812 prefvar = &session->hostkey_prefs;
1813 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_hostkey_methods();
1814 break;
1815
1816 case LIBSSH2_METHOD_CRYPT_CS:
1817 prefvar = &session->local.crypt_prefs;
1818 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
1819 break;
1820
1821 case LIBSSH2_METHOD_CRYPT_SC:
1822 prefvar = &session->remote.crypt_prefs;
1823 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_crypt_methods();
1824 break;
1825
1826 case LIBSSH2_METHOD_MAC_CS:
1827 prefvar = &session->local.mac_prefs;
1828 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_mac_methods();
1829 break;
1830
1831 case LIBSSH2_METHOD_MAC_SC:
1832 prefvar = &session->remote.mac_prefs;
1833 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_mac_methods();
1834 break;
1835
1836 case LIBSSH2_METHOD_COMP_CS:
1837 prefvar = &session->local.comp_prefs;
1838 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_comp_methods();
1839 break;
1840
1841 case LIBSSH2_METHOD_COMP_SC:
1842 prefvar = &session->remote.comp_prefs;
1843 mlist = (const LIBSSH2_COMMON_METHOD **) libssh2_comp_methods();
1844 break;
1845
1846 case LIBSSH2_METHOD_LANG_CS:
1847 prefvar = &session->local.lang_prefs;
1848 mlist = NULL;
1849 break;
1850
1851 case LIBSSH2_METHOD_LANG_SC:
1852 prefvar = &session->remote.lang_prefs;
1853 mlist = NULL;
1854 break;
1855
1856 default:
1857 libssh2_error(session, LIBSSH2_ERROR_INVAL,
1858 "Invalid parameter specified for method_type", 0);
1859 return -1;
1860 }
1861
1862 s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
1863 if (!newprefs) {
1864 libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1865 "Error allocated space for method preferences", 0);
1866 return -1;
1867 }
1868 memcpy(s, prefs, prefs_len + 1);
1869
1870 while (s && *s) {
1871 char *p = strchr(s, ',');
1872 int method_len = p ? (p - s) : (int) strlen(s);
1873
1874 if (!libssh2_get_method_by_name(s, method_len, mlist)) {
1875 /* Strip out unsupported method */
1876 if (p) {
1877 memcpy(s, p + 1, strlen(s) - method_len);
1878 } else {
1879 if (s > newprefs) {
1880 *(--s) = '\0';
1881 } else {
1882 *s = '\0';
1883 }
1884 }
1885 }
1886
1887 s = p ? (p + 1) : NULL;
1888 }
1889
1890 if (strlen(newprefs) == 0) {
1891 libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
1892 "The requested method(s) are not currently supported",
1893 0);
1894 LIBSSH2_FREE(session, newprefs);
1895 return -1;
1896 }
1897
1898 if (*prefvar) {
1899 LIBSSH2_FREE(session, *prefvar);
1900 }
1901 *prefvar = newprefs;
1902
1903 return 0;
1904 }
1905
1906 /* }}} */