1 /* $OpenBSD: kex.c,v 1.193 2026/03/05 05:40:35 djm Exp $ */
2 /*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "includes.h"
27
28 #include <sys/types.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36
37 #ifdef WITH_OPENSSL
38 #include <openssl/crypto.h>
39 #include <openssl/dh.h>
40 #endif
41
42 #include "ssh.h"
43 #include "ssh2.h"
44 #include "atomicio.h"
45 #include "version.h"
46 #include "packet.h"
47 #include "compat.h"
48 #include "cipher.h"
49 #include "sshkey.h"
50 #include "kex.h"
51 #include "log.h"
52 #include "mac.h"
53 #include "match.h"
54 #include "misc.h"
55 #include "dispatch.h"
56 #include "myproposal.h"
57
58 #include "ssherr.h"
59 #include "sshbuf.h"
60 #include "digest.h"
61 #include "xmalloc.h"
62
63 /* prototype */
64 static int kex_choose_conf(struct ssh *, uint32_t seq);
65 static int kex_input_newkeys(int, uint32_t, struct ssh *);
66
67 static const char * const proposal_names[PROPOSAL_MAX] = {
68 "KEX algorithms",
69 "host key algorithms",
70 "ciphers ctos",
71 "ciphers stoc",
72 "MACs ctos",
73 "MACs stoc",
74 "compression ctos",
75 "compression stoc",
76 "languages ctos",
77 "languages stoc",
78 };
79
80 /*
81 * Fill out a proposal array with dynamically allocated values, which may
82 * be modified as required for compatibility reasons.
83 * Any of the options may be NULL, in which case the default is used.
84 * Array contents must be freed by calling kex_proposal_free_entries.
85 */
86 void
kex_proposal_populate_entries(struct ssh * ssh,char * prop[PROPOSAL_MAX],const char * kexalgos,const char * ciphers,const char * macs,const char * comp,const char * hkalgs)87 kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
88 const char *kexalgos, const char *ciphers, const char *macs,
89 const char *comp, const char *hkalgs)
90 {
91 const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
92 const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
93 const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
94 u_int i;
95 char *cp;
96
97 if (prop == NULL)
98 fatal_f("proposal missing");
99
100 /* Append EXT_INFO signalling to KexAlgorithms */
101 if (kexalgos == NULL)
102 kexalgos = defprop[PROPOSAL_KEX_ALGS];
103 if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
104 "ext-info-s,kex-strict-s-v00@openssh.com" :
105 "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
106 fatal_f("kex_names_cat");
107
108 for (i = 0; i < PROPOSAL_MAX; i++) {
109 switch(i) {
110 case PROPOSAL_KEX_ALGS:
111 prop[i] = compat_kex_proposal(ssh, cp);
112 break;
113 case PROPOSAL_ENC_ALGS_CTOS:
114 case PROPOSAL_ENC_ALGS_STOC:
115 prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
116 break;
117 case PROPOSAL_MAC_ALGS_CTOS:
118 case PROPOSAL_MAC_ALGS_STOC:
119 prop[i] = xstrdup(macs ? macs : defprop[i]);
120 break;
121 case PROPOSAL_COMP_ALGS_CTOS:
122 case PROPOSAL_COMP_ALGS_STOC:
123 prop[i] = xstrdup(comp ? comp : defprop[i]);
124 break;
125 case PROPOSAL_SERVER_HOST_KEY_ALGS:
126 prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
127 break;
128 default:
129 prop[i] = xstrdup(defprop[i]);
130 }
131 }
132 free(cp);
133 }
134
135 void
kex_proposal_free_entries(char * prop[PROPOSAL_MAX])136 kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
137 {
138 u_int i;
139
140 for (i = 0; i < PROPOSAL_MAX; i++)
141 free(prop[i]);
142 }
143
144 /* put algorithm proposal into buffer */
145 int
kex_prop2buf(struct sshbuf * b,char * proposal[PROPOSAL_MAX])146 kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
147 {
148 u_int i;
149 int r;
150
151 sshbuf_reset(b);
152
153 /*
154 * add a dummy cookie, the cookie will be overwritten by
155 * kex_send_kexinit(), each time a kexinit is set
156 */
157 for (i = 0; i < KEX_COOKIE_LEN; i++) {
158 if ((r = sshbuf_put_u8(b, 0)) != 0)
159 return r;
160 }
161 for (i = 0; i < PROPOSAL_MAX; i++) {
162 if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
163 return r;
164 }
165 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
166 (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */
167 return r;
168 return 0;
169 }
170
171 /* parse buffer and return algorithm proposal */
172 int
kex_buf2prop(struct sshbuf * raw,int * first_kex_follows,char *** propp)173 kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
174 {
175 struct sshbuf *b = NULL;
176 u_char v;
177 u_int i;
178 char **proposal = NULL;
179 int r;
180
181 *propp = NULL;
182 if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
183 return SSH_ERR_ALLOC_FAIL;
184 if ((b = sshbuf_fromb(raw)) == NULL) {
185 r = SSH_ERR_ALLOC_FAIL;
186 goto out;
187 }
188 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */
189 error_fr(r, "consume cookie");
190 goto out;
191 }
192 /* extract kex init proposal strings */
193 for (i = 0; i < PROPOSAL_MAX; i++) {
194 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
195 error_fr(r, "parse proposal %u", i);
196 goto out;
197 }
198 debug2("%s: %s", proposal_names[i], proposal[i]);
199 }
200 /* first kex follows / reserved */
201 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
202 (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
203 error_fr(r, "parse");
204 goto out;
205 }
206 if (first_kex_follows != NULL)
207 *first_kex_follows = v;
208 debug2("first_kex_follows %d ", v);
209 debug2("reserved %u ", i);
210 r = 0;
211 *propp = proposal;
212 out:
213 if (r != 0 && proposal != NULL)
214 kex_prop_free(proposal);
215 sshbuf_free(b);
216 return r;
217 }
218
219 void
kex_prop_free(char ** proposal)220 kex_prop_free(char **proposal)
221 {
222 u_int i;
223
224 if (proposal == NULL)
225 return;
226 for (i = 0; i < PROPOSAL_MAX; i++)
227 free(proposal[i]);
228 free(proposal);
229 }
230
231 int
kex_protocol_error(int type,uint32_t seq,struct ssh * ssh)232 kex_protocol_error(int type, uint32_t seq, struct ssh *ssh)
233 {
234 int r;
235
236 /* If in strict mode, any unexpected message is an error */
237 if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
238 ssh_packet_disconnect(ssh, "strict KEX violation: "
239 "unexpected packet type %u (seqnr %u)", type, seq);
240 }
241 error_f("type %u seq %u", type, seq);
242 if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
243 (r = sshpkt_put_u32(ssh, seq)) != 0 ||
244 (r = sshpkt_send(ssh)) != 0)
245 return r;
246 return 0;
247 }
248
249 static void
kex_reset_dispatch(struct ssh * ssh)250 kex_reset_dispatch(struct ssh *ssh)
251 {
252 ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
253 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
254 }
255
256 void
kex_set_server_sig_algs(struct ssh * ssh,const char * allowed_algs)257 kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs)
258 {
259 char *alg, *oalgs, *algs, *sigalgs;
260 const char *sigalg;
261
262 /*
263 * NB. allowed algorithms may contain certificate algorithms that
264 * map to a specific plain signature type, e.g.
265 * rsa-sha2-512-cert-v01@openssh.com => rsa-sha2-512
266 * We need to be careful here to match these, retain the mapping
267 * and only add each signature algorithm once.
268 */
269 if ((sigalgs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
270 fatal_f("sshkey_alg_list failed");
271 oalgs = algs = xstrdup(allowed_algs);
272 free(ssh->kex->server_sig_algs);
273 ssh->kex->server_sig_algs = NULL;
274 for ((alg = strsep(&algs, ",")); alg != NULL && *alg != '\0';
275 (alg = strsep(&algs, ","))) {
276 if ((sigalg = sshkey_sigalg_by_name(alg)) == NULL)
277 continue;
278 if (!kex_has_any_alg(sigalg, sigalgs))
279 continue;
280 /* Don't add an algorithm twice. */
281 if (ssh->kex->server_sig_algs != NULL &&
282 kex_has_any_alg(sigalg, ssh->kex->server_sig_algs))
283 continue;
284 xextendf(&ssh->kex->server_sig_algs, ",", "%s", sigalg);
285 }
286 free(oalgs);
287 free(sigalgs);
288 if (ssh->kex->server_sig_algs == NULL)
289 ssh->kex->server_sig_algs = xstrdup("");
290 }
291
292 static int
kex_compose_ext_info_server(struct ssh * ssh,struct sshbuf * m)293 kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m)
294 {
295 int r;
296
297 if (ssh->kex->server_sig_algs == NULL &&
298 (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
299 return SSH_ERR_ALLOC_FAIL;
300 if ((r = sshbuf_put_u32(m, 4)) != 0 ||
301 (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 ||
302 (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 ||
303 (r = sshbuf_put_cstring(m,
304 "publickey-hostbound@openssh.com")) != 0 ||
305 (r = sshbuf_put_cstring(m, "0")) != 0 ||
306 (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 ||
307 (r = sshbuf_put_cstring(m, "0")) != 0 ||
308 (r = sshbuf_put_cstring(m, "agent-forward")) != 0 ||
309 (r = sshbuf_put_cstring(m, "0")) != 0) {
310 error_fr(r, "compose");
311 return r;
312 }
313 return 0;
314 }
315
316 static int
kex_compose_ext_info_client(struct ssh * ssh,struct sshbuf * m)317 kex_compose_ext_info_client(struct ssh *ssh, struct sshbuf *m)
318 {
319 int r;
320
321 if ((r = sshbuf_put_u32(m, 1)) != 0 ||
322 (r = sshbuf_put_cstring(m, "ext-info-in-auth@openssh.com")) != 0 ||
323 (r = sshbuf_put_cstring(m, "0")) != 0) {
324 error_fr(r, "compose");
325 goto out;
326 }
327 /* success */
328 r = 0;
329 out:
330 return r;
331 }
332
333 static int
kex_maybe_send_ext_info(struct ssh * ssh)334 kex_maybe_send_ext_info(struct ssh *ssh)
335 {
336 int r;
337 struct sshbuf *m = NULL;
338
339 if ((ssh->kex->flags & KEX_INITIAL) == 0)
340 return 0;
341 if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s)
342 return 0;
343
344 /* Compose EXT_INFO packet. */
345 if ((m = sshbuf_new()) == NULL)
346 fatal_f("sshbuf_new failed");
347 if (ssh->kex->ext_info_c &&
348 (r = kex_compose_ext_info_server(ssh, m)) != 0)
349 goto fail;
350 if (ssh->kex->ext_info_s &&
351 (r = kex_compose_ext_info_client(ssh, m)) != 0)
352 goto fail;
353
354 /* Send the actual KEX_INFO packet */
355 debug("Sending SSH2_MSG_EXT_INFO");
356 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
357 (r = sshpkt_putb(ssh, m)) != 0 ||
358 (r = sshpkt_send(ssh)) != 0) {
359 error_f("send EXT_INFO");
360 goto fail;
361 }
362
363 r = 0;
364
365 fail:
366 sshbuf_free(m);
367 return r;
368 }
369
370 int
kex_server_update_ext_info(struct ssh * ssh)371 kex_server_update_ext_info(struct ssh *ssh)
372 {
373 int r;
374
375 if ((ssh->kex->flags & KEX_HAS_EXT_INFO_IN_AUTH) == 0)
376 return 0;
377
378 debug_f("Sending SSH2_MSG_EXT_INFO");
379 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
380 (r = sshpkt_put_u32(ssh, 1)) != 0 ||
381 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
382 (r = sshpkt_put_cstring(ssh, ssh->kex->server_sig_algs)) != 0 ||
383 (r = sshpkt_send(ssh)) != 0) {
384 error_f("send EXT_INFO");
385 return r;
386 }
387 return 0;
388 }
389
390 int
kex_send_newkeys(struct ssh * ssh)391 kex_send_newkeys(struct ssh *ssh)
392 {
393 int r;
394
395 kex_reset_dispatch(ssh);
396 if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
397 (r = sshpkt_send(ssh)) != 0)
398 return r;
399 debug("SSH2_MSG_NEWKEYS sent");
400 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
401 if ((r = kex_maybe_send_ext_info(ssh)) != 0)
402 return r;
403 debug("expecting SSH2_MSG_NEWKEYS");
404 return 0;
405 }
406
407 /* Check whether an ext_info value contains the expected version string */
408 static int
kex_ext_info_check_ver(struct kex * kex,const char * name,const u_char * val,size_t len,const char * want_ver,u_int flag)409 kex_ext_info_check_ver(struct kex *kex, const char *name,
410 const u_char *val, size_t len, const char *want_ver, u_int flag)
411 {
412 if (memchr(val, '\0', len) != NULL) {
413 error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name);
414 return SSH_ERR_INVALID_FORMAT;
415 }
416 debug_f("%s=<%s>", name, val);
417 if (strcmp(val, want_ver) == 0)
418 kex->flags |= flag;
419 else
420 debug_f("unsupported version of %s extension", name);
421 return 0;
422 }
423
424 static int
kex_ext_info_client_parse(struct ssh * ssh,const char * name,const u_char * value,size_t vlen)425 kex_ext_info_client_parse(struct ssh *ssh, const char *name,
426 const u_char *value, size_t vlen)
427 {
428 int r;
429
430 /* NB. some messages are only accepted in the initial EXT_INFO */
431 if (strcmp(name, "server-sig-algs") == 0) {
432 /* Ensure no \0 lurking in value */
433 if (memchr(value, '\0', vlen) != NULL) {
434 error_f("nul byte in %s", name);
435 return SSH_ERR_INVALID_FORMAT;
436 }
437 debug_f("%s=<%s>", name, value);
438 free(ssh->kex->server_sig_algs);
439 ssh->kex->server_sig_algs = xstrdup((const char *)value);
440 } else if (ssh->kex->ext_info_received == 1 &&
441 strcmp(name, "publickey-hostbound@openssh.com") == 0) {
442 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
443 "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) {
444 return r;
445 }
446 } else if (ssh->kex->ext_info_received == 1 &&
447 strcmp(name, "ping@openssh.com") == 0) {
448 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
449 "0", KEX_HAS_PING)) != 0) {
450 return r;
451 }
452 } else if (ssh->kex->ext_info_received == 1 &&
453 strcmp(name, "agent-forward") == 0) {
454 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
455 "0", KEX_HAS_NEWAGENT)) != 0) {
456 return r;
457 }
458 } else
459 debug_f("%s (unrecognised)", name);
460
461 return 0;
462 }
463
464 static int
kex_ext_info_server_parse(struct ssh * ssh,const char * name,const u_char * value,size_t vlen)465 kex_ext_info_server_parse(struct ssh *ssh, const char *name,
466 const u_char *value, size_t vlen)
467 {
468 int r;
469
470 if (strcmp(name, "ext-info-in-auth@openssh.com") == 0) {
471 if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
472 "0", KEX_HAS_EXT_INFO_IN_AUTH)) != 0) {
473 return r;
474 }
475 } else
476 debug_f("%s (unrecognised)", name);
477 return 0;
478 }
479
480 int
kex_input_ext_info(int type,uint32_t seq,struct ssh * ssh)481 kex_input_ext_info(int type, uint32_t seq, struct ssh *ssh)
482 {
483 struct kex *kex = ssh->kex;
484 const int max_ext_info = kex->server ? 1 : 2;
485 uint32_t i, ninfo;
486 char *name;
487 u_char *val;
488 size_t vlen;
489 int r;
490
491 debug("SSH2_MSG_EXT_INFO received");
492 if (++kex->ext_info_received > max_ext_info) {
493 error("too many SSH2_MSG_EXT_INFO messages sent by peer");
494 return dispatch_protocol_error(type, seq, ssh);
495 }
496 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
497 if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
498 return r;
499 if (ninfo >= 1024) {
500 error("SSH2_MSG_EXT_INFO with too many entries, expected "
501 "<=1024, received %u", ninfo);
502 return dispatch_protocol_error(type, seq, ssh);
503 }
504 for (i = 0; i < ninfo; i++) {
505 if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
506 return r;
507 if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
508 free(name);
509 return r;
510 }
511 debug3_f("extension %s", name);
512 if (kex->server) {
513 if ((r = kex_ext_info_server_parse(ssh, name,
514 val, vlen)) != 0)
515 return r;
516 } else {
517 if ((r = kex_ext_info_client_parse(ssh, name,
518 val, vlen)) != 0)
519 return r;
520 }
521 free(name);
522 free(val);
523 }
524 return sshpkt_get_end(ssh);
525 }
526
527 static int
kex_input_newkeys(int type,uint32_t seq,struct ssh * ssh)528 kex_input_newkeys(int type, uint32_t seq, struct ssh *ssh)
529 {
530 struct kex *kex = ssh->kex;
531 int r, initial = (kex->flags & KEX_INITIAL) != 0;
532 char *cp, **prop;
533
534 debug("SSH2_MSG_NEWKEYS received");
535 if (kex->ext_info_c && initial)
536 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info);
537 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
538 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
539 if ((r = sshpkt_get_end(ssh)) != 0)
540 return r;
541 if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
542 return r;
543 if (initial) {
544 /* Remove initial KEX signalling from proposal for rekeying */
545 if ((r = kex_buf2prop(kex->my, NULL, &prop)) != 0)
546 return r;
547 if ((cp = match_filter_denylist(prop[PROPOSAL_KEX_ALGS],
548 kex->server ?
549 "ext-info-s,kex-strict-s-v00@openssh.com" :
550 "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) {
551 error_f("match_filter_denylist failed");
552 goto fail;
553 }
554 free(prop[PROPOSAL_KEX_ALGS]);
555 prop[PROPOSAL_KEX_ALGS] = cp;
556 if ((r = kex_prop2buf(ssh->kex->my, prop)) != 0) {
557 error_f("kex_prop2buf failed");
558 fail:
559 kex_proposal_free_entries(prop);
560 free(prop);
561 return SSH_ERR_INTERNAL_ERROR;
562 }
563 kex_proposal_free_entries(prop);
564 free(prop);
565 }
566 kex->done = 1;
567 kex->flags &= ~KEX_INITIAL;
568 sshbuf_reset(kex->peer);
569 kex->flags &= ~KEX_INIT_SENT;
570 return 0;
571 }
572
573 int
kex_send_kexinit(struct ssh * ssh)574 kex_send_kexinit(struct ssh *ssh)
575 {
576 u_char *cookie;
577 struct kex *kex = ssh->kex;
578 int r;
579
580 if (kex == NULL) {
581 error_f("no kex");
582 return SSH_ERR_INTERNAL_ERROR;
583 }
584 if (kex->flags & KEX_INIT_SENT)
585 return 0;
586 kex->done = 0;
587
588 /* generate a random cookie */
589 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) {
590 error_f("bad kex length: %zu < %d",
591 sshbuf_len(kex->my), KEX_COOKIE_LEN);
592 return SSH_ERR_INVALID_FORMAT;
593 }
594 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
595 error_f("buffer error");
596 return SSH_ERR_INTERNAL_ERROR;
597 }
598 arc4random_buf(cookie, KEX_COOKIE_LEN);
599
600 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
601 (r = sshpkt_putb(ssh, kex->my)) != 0 ||
602 (r = sshpkt_send(ssh)) != 0) {
603 error_fr(r, "compose reply");
604 return r;
605 }
606 debug("SSH2_MSG_KEXINIT sent");
607 kex->flags |= KEX_INIT_SENT;
608 return 0;
609 }
610
611 int
kex_input_kexinit(int type,uint32_t seq,struct ssh * ssh)612 kex_input_kexinit(int type, uint32_t seq, struct ssh *ssh)
613 {
614 struct kex *kex = ssh->kex;
615 const u_char *ptr;
616 u_int i;
617 size_t dlen;
618 int r;
619
620 debug("SSH2_MSG_KEXINIT received");
621 if (kex == NULL) {
622 error_f("no kex");
623 return SSH_ERR_INTERNAL_ERROR;
624 }
625 free(kex->name);
626 kex->name = NULL;
627 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
628 ptr = sshpkt_ptr(ssh, &dlen);
629 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
630 return r;
631
632 /* discard packet */
633 for (i = 0; i < KEX_COOKIE_LEN; i++) {
634 if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
635 error_fr(r, "discard cookie");
636 return r;
637 }
638 }
639 for (i = 0; i < PROPOSAL_MAX; i++) {
640 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
641 error_fr(r, "discard proposal");
642 return r;
643 }
644 }
645 /*
646 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
647 * KEX method has the server move first, but a server might be using
648 * a custom method or one that we otherwise don't support. We should
649 * be prepared to remember first_kex_follows here so we can eat a
650 * packet later.
651 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
652 * for cases where the server *doesn't* go first. I guess we should
653 * ignore it when it is set for these cases, which is what we do now.
654 */
655 if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
656 (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
657 (r = sshpkt_get_end(ssh)) != 0)
658 return r;
659
660 if (!(kex->flags & KEX_INIT_SENT))
661 if ((r = kex_send_kexinit(ssh)) != 0)
662 return r;
663 if ((r = kex_choose_conf(ssh, seq)) != 0)
664 return r;
665
666 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
667 return (kex->kex[kex->kex_type])(ssh);
668
669 error_f("unknown kex type %u", kex->kex_type);
670 return SSH_ERR_INTERNAL_ERROR;
671 }
672
673 struct kex *
kex_new(void)674 kex_new(void)
675 {
676 struct kex *kex;
677
678 if ((kex = calloc(1, sizeof(*kex))) == NULL ||
679 (kex->peer = sshbuf_new()) == NULL ||
680 (kex->my = sshbuf_new()) == NULL ||
681 (kex->client_version = sshbuf_new()) == NULL ||
682 (kex->server_version = sshbuf_new()) == NULL ||
683 (kex->session_id = sshbuf_new()) == NULL) {
684 kex_free(kex);
685 return NULL;
686 }
687 return kex;
688 }
689
690 void
kex_free_newkeys(struct newkeys * newkeys)691 kex_free_newkeys(struct newkeys *newkeys)
692 {
693 if (newkeys == NULL)
694 return;
695 if (newkeys->enc.key) {
696 explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
697 free(newkeys->enc.key);
698 newkeys->enc.key = NULL;
699 }
700 if (newkeys->enc.iv) {
701 explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
702 free(newkeys->enc.iv);
703 newkeys->enc.iv = NULL;
704 }
705 free(newkeys->enc.name);
706 explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
707 free(newkeys->comp.name);
708 explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
709 mac_clear(&newkeys->mac);
710 if (newkeys->mac.key) {
711 explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
712 free(newkeys->mac.key);
713 newkeys->mac.key = NULL;
714 }
715 free(newkeys->mac.name);
716 explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
717 freezero(newkeys, sizeof(*newkeys));
718 }
719
720 void
kex_free(struct kex * kex)721 kex_free(struct kex *kex)
722 {
723 u_int mode;
724
725 if (kex == NULL)
726 return;
727
728 #ifdef WITH_OPENSSL
729 DH_free(kex->dh);
730 #ifdef OPENSSL_HAS_ECC
731 EC_KEY_free(kex->ec_client_key);
732 #endif /* OPENSSL_HAS_ECC */
733 #endif /* WITH_OPENSSL */
734 for (mode = 0; mode < MODE_MAX; mode++) {
735 kex_free_newkeys(kex->newkeys[mode]);
736 kex->newkeys[mode] = NULL;
737 }
738 sshbuf_free(kex->peer);
739 sshbuf_free(kex->my);
740 sshbuf_free(kex->client_version);
741 sshbuf_free(kex->server_version);
742 sshbuf_free(kex->client_pub);
743 sshbuf_free(kex->session_id);
744 sshbuf_free(kex->initial_sig);
745 sshkey_free(kex->initial_hostkey);
746 free(kex->failed_choice);
747 free(kex->hostkey_alg);
748 free(kex->name);
749 free(kex->server_sig_algs);
750 free(kex);
751 }
752
753 int
kex_ready(struct ssh * ssh,char * proposal[PROPOSAL_MAX])754 kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
755 {
756 int r;
757
758 if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
759 return r;
760 ssh->kex->flags = KEX_INITIAL;
761 kex_reset_dispatch(ssh);
762 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
763 return 0;
764 }
765
766 int
kex_setup(struct ssh * ssh,char * proposal[PROPOSAL_MAX])767 kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
768 {
769 int r;
770
771 if ((r = kex_ready(ssh, proposal)) != 0)
772 return r;
773 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
774 kex_free(ssh->kex);
775 ssh->kex = NULL;
776 return r;
777 }
778 return 0;
779 }
780
781 /*
782 * Request key re-exchange, returns 0 on success or a ssherr.h error
783 * code otherwise. Must not be called if KEX is incomplete or in-progress.
784 */
785 int
kex_start_rekex(struct ssh * ssh)786 kex_start_rekex(struct ssh *ssh)
787 {
788 if (ssh->kex == NULL) {
789 error_f("no kex");
790 return SSH_ERR_INTERNAL_ERROR;
791 }
792 if (ssh->kex->done == 0) {
793 error_f("requested twice");
794 return SSH_ERR_INTERNAL_ERROR;
795 }
796 ssh->kex->done = 0;
797 return kex_send_kexinit(ssh);
798 }
799
800 static int
choose_enc(struct sshenc * enc,char * client,char * server)801 choose_enc(struct sshenc *enc, char *client, char *server)
802 {
803 char *name = match_list(client, server, NULL);
804
805 if (name == NULL)
806 return SSH_ERR_NO_CIPHER_ALG_MATCH;
807 if ((enc->cipher = cipher_by_name(name)) == NULL) {
808 error_f("unsupported cipher %s", name);
809 free(name);
810 return SSH_ERR_INTERNAL_ERROR;
811 }
812 enc->name = name;
813 enc->enabled = 0;
814 enc->iv = NULL;
815 enc->iv_len = cipher_ivlen(enc->cipher);
816 enc->key = NULL;
817 enc->key_len = cipher_keylen(enc->cipher);
818 enc->block_size = cipher_blocksize(enc->cipher);
819 return 0;
820 }
821
822 static int
choose_mac(struct ssh * ssh,struct sshmac * mac,char * client,char * server)823 choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
824 {
825 char *name = match_list(client, server, NULL);
826
827 if (name == NULL)
828 return SSH_ERR_NO_MAC_ALG_MATCH;
829 if (mac_setup(mac, name) < 0) {
830 error_f("unsupported MAC %s", name);
831 free(name);
832 return SSH_ERR_INTERNAL_ERROR;
833 }
834 mac->name = name;
835 mac->key = NULL;
836 mac->enabled = 0;
837 return 0;
838 }
839
840 static int
choose_comp(struct sshcomp * comp,char * client,char * server)841 choose_comp(struct sshcomp *comp, char *client, char *server)
842 {
843 char *name = match_list(client, server, NULL);
844
845 if (name == NULL)
846 return SSH_ERR_NO_COMPRESS_ALG_MATCH;
847 #ifdef WITH_ZLIB
848 if (strcmp(name, "zlib@openssh.com") == 0) {
849 comp->type = COMP_DELAYED;
850 } else
851 #endif /* WITH_ZLIB */
852 if (strcmp(name, "none") == 0) {
853 comp->type = COMP_NONE;
854 } else {
855 error_f("unsupported compression scheme %s", name);
856 free(name);
857 return SSH_ERR_INTERNAL_ERROR;
858 }
859 comp->name = name;
860 return 0;
861 }
862
863 static int
choose_kex(struct kex * k,char * client,char * server)864 choose_kex(struct kex *k, char *client, char *server)
865 {
866 k->name = match_list(client, server, NULL);
867
868 debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
869 if (k->name == NULL)
870 return SSH_ERR_NO_KEX_ALG_MATCH;
871 if (!kex_name_valid(k->name)) {
872 error_f("unsupported KEX method %s", k->name);
873 return SSH_ERR_INTERNAL_ERROR;
874 }
875 k->kex_type = kex_type_from_name(k->name);
876 k->hash_alg = kex_hash_from_name(k->name);
877 k->ec_nid = kex_nid_from_name(k->name);
878 return 0;
879 }
880
881 static int
choose_hostkeyalg(struct kex * k,char * client,char * server)882 choose_hostkeyalg(struct kex *k, char *client, char *server)
883 {
884 free(k->hostkey_alg);
885 k->hostkey_alg = match_list(client, server, NULL);
886
887 debug("kex: host key algorithm: %s",
888 k->hostkey_alg ? k->hostkey_alg : "(no match)");
889 if (k->hostkey_alg == NULL)
890 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
891 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
892 if (k->hostkey_type == KEY_UNSPEC) {
893 error_f("unsupported hostkey algorithm %s", k->hostkey_alg);
894 return SSH_ERR_INTERNAL_ERROR;
895 }
896 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
897 return 0;
898 }
899
900 static int
proposals_match(char * my[PROPOSAL_MAX],char * peer[PROPOSAL_MAX])901 proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
902 {
903 static int check[] = {
904 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
905 };
906 int *idx;
907 char *p;
908
909 for (idx = &check[0]; *idx != -1; idx++) {
910 if ((p = strchr(my[*idx], ',')) != NULL)
911 *p = '\0';
912 if ((p = strchr(peer[*idx], ',')) != NULL)
913 *p = '\0';
914 if (strcmp(my[*idx], peer[*idx]) != 0) {
915 debug2("proposal mismatch: my %s peer %s",
916 my[*idx], peer[*idx]);
917 return (0);
918 }
919 }
920 debug2("proposals match");
921 return (1);
922 }
923
924 static int
kexalgs_contains(char ** peer,const char * ext)925 kexalgs_contains(char **peer, const char *ext)
926 {
927 return kex_has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
928 }
929
930 static int
kex_choose_conf(struct ssh * ssh,uint32_t seq)931 kex_choose_conf(struct ssh *ssh, uint32_t seq)
932 {
933 struct kex *kex = ssh->kex;
934 struct newkeys *newkeys;
935 char **my = NULL, **peer = NULL;
936 char **cprop, **sprop;
937 int nenc, nmac, ncomp;
938 u_int mode, ctos, need, dh_need, authlen;
939 int r, first_kex_follows;
940
941 debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
942 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
943 goto out;
944 debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
945 if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
946 goto out;
947
948 if (kex->server) {
949 cprop=peer;
950 sprop=my;
951 } else {
952 cprop=my;
953 sprop=peer;
954 }
955
956 /* Check whether peer supports ext_info/kex_strict */
957 if ((kex->flags & KEX_INITIAL) != 0) {
958 if (kex->server) {
959 kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
960 kex->kex_strict = kexalgs_contains(peer,
961 "kex-strict-c-v00@openssh.com");
962 } else {
963 kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
964 kex->kex_strict = kexalgs_contains(peer,
965 "kex-strict-s-v00@openssh.com");
966 }
967 if (kex->kex_strict) {
968 debug3_f("will use strict KEX ordering");
969 if (seq != 0)
970 ssh_packet_disconnect(ssh,
971 "strict KEX violation: "
972 "KEXINIT was not the first packet");
973 }
974 }
975
976 /* Check whether client supports rsa-sha2 algorithms */
977 if (kex->server && (kex->flags & KEX_INITIAL)) {
978 if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
979 "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
980 kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
981 if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
982 "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
983 kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
984 }
985
986 /* Algorithm Negotiation */
987 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
988 sprop[PROPOSAL_KEX_ALGS])) != 0) {
989 kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
990 peer[PROPOSAL_KEX_ALGS] = NULL;
991 goto out;
992 }
993 if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
994 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
995 kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
996 peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
997 goto out;
998 }
999 for (mode = 0; mode < MODE_MAX; mode++) {
1000 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
1001 r = SSH_ERR_ALLOC_FAIL;
1002 goto out;
1003 }
1004 kex->newkeys[mode] = newkeys;
1005 ctos = (!kex->server && mode == MODE_OUT) ||
1006 (kex->server && mode == MODE_IN);
1007 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
1008 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
1009 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
1010 if ((r = choose_enc(&newkeys->enc, cprop[nenc],
1011 sprop[nenc])) != 0) {
1012 kex->failed_choice = peer[nenc];
1013 peer[nenc] = NULL;
1014 goto out;
1015 }
1016 authlen = cipher_authlen(newkeys->enc.cipher);
1017 /* ignore mac for authenticated encryption */
1018 if (authlen == 0 &&
1019 (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
1020 sprop[nmac])) != 0) {
1021 kex->failed_choice = peer[nmac];
1022 peer[nmac] = NULL;
1023 goto out;
1024 }
1025 if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
1026 sprop[ncomp])) != 0) {
1027 kex->failed_choice = peer[ncomp];
1028 peer[ncomp] = NULL;
1029 goto out;
1030 }
1031 debug("kex: %s cipher: %s MAC: %s compression: %s",
1032 ctos ? "client->server" : "server->client",
1033 newkeys->enc.name,
1034 authlen == 0 ? newkeys->mac.name : "<implicit>",
1035 newkeys->comp.name);
1036 }
1037 need = dh_need = 0;
1038 for (mode = 0; mode < MODE_MAX; mode++) {
1039 newkeys = kex->newkeys[mode];
1040 need = MAXIMUM(need, newkeys->enc.key_len);
1041 need = MAXIMUM(need, newkeys->enc.block_size);
1042 need = MAXIMUM(need, newkeys->enc.iv_len);
1043 need = MAXIMUM(need, newkeys->mac.key_len);
1044 dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
1045 dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
1046 dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
1047 dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
1048 }
1049 /* XXX need runden? */
1050 kex->we_need = need;
1051 kex->dh_need = dh_need;
1052
1053 /* ignore the next message if the proposals do not match */
1054 if (first_kex_follows && !proposals_match(my, peer))
1055 ssh->dispatch_skip_packets = 1;
1056 r = 0;
1057 out:
1058 kex_prop_free(my);
1059 kex_prop_free(peer);
1060 return r;
1061 }
1062
1063 static int
derive_key(struct ssh * ssh,int id,u_int need,u_char * hash,u_int hashlen,const struct sshbuf * shared_secret,u_char ** keyp)1064 derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
1065 const struct sshbuf *shared_secret, u_char **keyp)
1066 {
1067 struct kex *kex = ssh->kex;
1068 struct ssh_digest_ctx *hashctx = NULL;
1069 char c = id;
1070 u_int have;
1071 size_t mdsz;
1072 u_char *digest;
1073 int r;
1074
1075 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
1076 return SSH_ERR_INVALID_ARGUMENT;
1077 if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
1078 r = SSH_ERR_ALLOC_FAIL;
1079 goto out;
1080 }
1081
1082 /* K1 = HASH(K || H || "A" || session_id) */
1083 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1084 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1085 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1086 ssh_digest_update(hashctx, &c, 1) != 0 ||
1087 ssh_digest_update_buffer(hashctx, kex->session_id) != 0 ||
1088 ssh_digest_final(hashctx, digest, mdsz) != 0) {
1089 r = SSH_ERR_LIBCRYPTO_ERROR;
1090 error_f("KEX hash failed");
1091 goto out;
1092 }
1093 ssh_digest_free(hashctx);
1094 hashctx = NULL;
1095
1096 /*
1097 * expand key:
1098 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
1099 * Key = K1 || K2 || ... || Kn
1100 */
1101 for (have = mdsz; need > have; have += mdsz) {
1102 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1103 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1104 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1105 ssh_digest_update(hashctx, digest, have) != 0 ||
1106 ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
1107 error_f("KDF failed");
1108 r = SSH_ERR_LIBCRYPTO_ERROR;
1109 goto out;
1110 }
1111 ssh_digest_free(hashctx);
1112 hashctx = NULL;
1113 }
1114 #ifdef DEBUG_KEX
1115 fprintf(stderr, "key '%c'== ", c);
1116 dump_digest("key", digest, need);
1117 #endif
1118 *keyp = digest;
1119 digest = NULL;
1120 r = 0;
1121 out:
1122 free(digest);
1123 ssh_digest_free(hashctx);
1124 return r;
1125 }
1126
1127 #define NKEYS 6
1128 int
kex_derive_keys(struct ssh * ssh,u_char * hash,u_int hashlen,const struct sshbuf * shared_secret)1129 kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
1130 const struct sshbuf *shared_secret)
1131 {
1132 struct kex *kex = ssh->kex;
1133 u_char *keys[NKEYS];
1134 u_int i, j, mode, ctos;
1135 int r;
1136
1137 /* save initial hash as session id */
1138 if ((kex->flags & KEX_INITIAL) != 0) {
1139 if (sshbuf_len(kex->session_id) != 0) {
1140 error_f("already have session ID at kex");
1141 return SSH_ERR_INTERNAL_ERROR;
1142 }
1143 if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0)
1144 return r;
1145 } else if (sshbuf_len(kex->session_id) == 0) {
1146 error_f("no session ID in rekex");
1147 return SSH_ERR_INTERNAL_ERROR;
1148 }
1149 for (i = 0; i < NKEYS; i++) {
1150 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
1151 shared_secret, &keys[i])) != 0) {
1152 for (j = 0; j < i; j++)
1153 free(keys[j]);
1154 return r;
1155 }
1156 }
1157 for (mode = 0; mode < MODE_MAX; mode++) {
1158 ctos = (!kex->server && mode == MODE_OUT) ||
1159 (kex->server && mode == MODE_IN);
1160 kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1];
1161 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
1162 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
1163 }
1164 return 0;
1165 }
1166
1167 int
kex_load_hostkey(struct ssh * ssh,struct sshkey ** prvp,struct sshkey ** pubp)1168 kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1169 {
1170 struct kex *kex = ssh->kex;
1171
1172 *pubp = NULL;
1173 *prvp = NULL;
1174 if (kex->load_host_public_key == NULL ||
1175 kex->load_host_private_key == NULL) {
1176 error_f("missing hostkey loader");
1177 return SSH_ERR_INVALID_ARGUMENT;
1178 }
1179 *pubp = kex->load_host_public_key(kex->hostkey_type,
1180 kex->hostkey_nid, ssh);
1181 *prvp = kex->load_host_private_key(kex->hostkey_type,
1182 kex->hostkey_nid, ssh);
1183 if (*pubp == NULL)
1184 return SSH_ERR_NO_HOSTKEY_LOADED;
1185 return 0;
1186 }
1187
1188 int
kex_verify_host_key(struct ssh * ssh,struct sshkey * server_host_key)1189 kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1190 {
1191 struct kex *kex = ssh->kex;
1192
1193 if (kex->verify_host_key == NULL) {
1194 error_f("missing hostkey verifier");
1195 return SSH_ERR_INVALID_ARGUMENT;
1196 }
1197 if (server_host_key->type != kex->hostkey_type ||
1198 (kex->hostkey_type == KEY_ECDSA &&
1199 server_host_key->ecdsa_nid != kex->hostkey_nid))
1200 return SSH_ERR_KEY_TYPE_MISMATCH;
1201 if (kex->verify_host_key(server_host_key, ssh) == -1)
1202 return SSH_ERR_SIGNATURE_INVALID;
1203 return 0;
1204 }
1205
1206 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
1207 void
dump_digest(const char * msg,const u_char * digest,int len)1208 dump_digest(const char *msg, const u_char *digest, int len)
1209 {
1210 fprintf(stderr, "%s\n", msg);
1211 sshbuf_dump_data(digest, len, stderr);
1212 }
1213 #endif
1214
1215 /*
1216 * Send a plaintext error message to the peer, suffixed by \r\n.
1217 * Only used during banner exchange, and there only for the server.
1218 */
1219 static void
send_error(struct ssh * ssh,char * msg)1220 send_error(struct ssh *ssh, char *msg)
1221 {
1222 char *crnl = "\r\n";
1223
1224 if (!ssh->kex->server)
1225 return;
1226
1227 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1228 msg, strlen(msg)) != strlen(msg) ||
1229 atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1230 crnl, strlen(crnl)) != strlen(crnl))
1231 error_f("write: %.100s", strerror(errno));
1232 }
1233
1234 /*
1235 * Sends our identification string and waits for the peer's. Will block for
1236 * up to timeout_ms (or indefinitely if timeout_ms <= 0).
1237 * Returns on 0 success or a ssherr.h code on failure.
1238 */
1239 int
kex_exchange_identification(struct ssh * ssh,int timeout_ms,const char * version_addendum)1240 kex_exchange_identification(struct ssh *ssh, int timeout_ms,
1241 const char *version_addendum)
1242 {
1243 int remote_major, remote_minor, mismatch, oerrno = 0;
1244 size_t len, n;
1245 int r, expect_nl;
1246 u_char c;
1247 struct sshbuf *our_version = ssh->kex->server ?
1248 ssh->kex->server_version : ssh->kex->client_version;
1249 struct sshbuf *peer_version = ssh->kex->server ?
1250 ssh->kex->client_version : ssh->kex->server_version;
1251 char *our_version_string = NULL, *peer_version_string = NULL;
1252 char *cp, *remote_version = NULL;
1253
1254 /* Prepare and send our banner */
1255 sshbuf_reset(our_version);
1256 if (version_addendum != NULL && *version_addendum == '\0')
1257 version_addendum = NULL;
1258 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n",
1259 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
1260 version_addendum == NULL ? "" : " ",
1261 version_addendum == NULL ? "" : version_addendum)) != 0) {
1262 oerrno = errno;
1263 error_fr(r, "sshbuf_putf");
1264 goto out;
1265 }
1266
1267 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1268 sshbuf_mutable_ptr(our_version),
1269 sshbuf_len(our_version)) != sshbuf_len(our_version)) {
1270 oerrno = errno;
1271 debug_f("write: %.100s", strerror(errno));
1272 r = SSH_ERR_SYSTEM_ERROR;
1273 goto out;
1274 }
1275 if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
1276 oerrno = errno;
1277 error_fr(r, "sshbuf_consume_end");
1278 goto out;
1279 }
1280 our_version_string = sshbuf_dup_string(our_version);
1281 if (our_version_string == NULL) {
1282 error_f("sshbuf_dup_string failed");
1283 r = SSH_ERR_ALLOC_FAIL;
1284 goto out;
1285 }
1286 debug("Local version string %.100s", our_version_string);
1287
1288 /* Read other side's version identification. */
1289 for (n = 0; ; n++) {
1290 if (n >= SSH_MAX_PRE_BANNER_LINES) {
1291 send_error(ssh, "No SSH identification string "
1292 "received.");
1293 error_f("No SSH version received in first %u lines "
1294 "from server", SSH_MAX_PRE_BANNER_LINES);
1295 r = SSH_ERR_INVALID_FORMAT;
1296 goto out;
1297 }
1298 sshbuf_reset(peer_version);
1299 expect_nl = 0;
1300 for (;;) {
1301 if (timeout_ms > 0) {
1302 r = waitrfd(ssh_packet_get_connection_in(ssh),
1303 &timeout_ms, NULL);
1304 if (r == -1 && errno == ETIMEDOUT) {
1305 send_error(ssh, "Timed out waiting "
1306 "for SSH identification string.");
1307 error("Connection timed out during "
1308 "banner exchange");
1309 r = SSH_ERR_CONN_TIMEOUT;
1310 goto out;
1311 } else if (r == -1) {
1312 oerrno = errno;
1313 error_f("%s", strerror(errno));
1314 r = SSH_ERR_SYSTEM_ERROR;
1315 goto out;
1316 }
1317 }
1318
1319 len = atomicio(read, ssh_packet_get_connection_in(ssh),
1320 &c, 1);
1321 if (len != 1 && errno == EPIPE) {
1322 verbose_f("Connection closed by remote host");
1323 r = SSH_ERR_CONN_CLOSED;
1324 goto out;
1325 } else if (len != 1) {
1326 oerrno = errno;
1327 error_f("read: %.100s", strerror(errno));
1328 r = SSH_ERR_SYSTEM_ERROR;
1329 goto out;
1330 }
1331 if (c == '\r') {
1332 expect_nl = 1;
1333 continue;
1334 }
1335 if (c == '\n')
1336 break;
1337 if (c == '\0' || expect_nl) {
1338 verbose_f("banner line contains invalid "
1339 "characters");
1340 goto invalid;
1341 }
1342 if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
1343 oerrno = errno;
1344 error_fr(r, "sshbuf_put");
1345 goto out;
1346 }
1347 if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
1348 verbose_f("banner line too long");
1349 goto invalid;
1350 }
1351 }
1352 /* Is this an actual protocol banner? */
1353 if (sshbuf_len(peer_version) > 4 &&
1354 memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
1355 break;
1356 /* If not, then just log the line and continue */
1357 if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
1358 error_f("sshbuf_dup_string failed");
1359 r = SSH_ERR_ALLOC_FAIL;
1360 goto out;
1361 }
1362 /* Do not accept lines before the SSH ident from a client */
1363 if (ssh->kex->server) {
1364 verbose_f("client sent invalid protocol identifier "
1365 "\"%.256s\"", cp);
1366 free(cp);
1367 goto invalid;
1368 }
1369 debug_f("banner line %zu: %s", n, cp);
1370 free(cp);
1371 }
1372 peer_version_string = sshbuf_dup_string(peer_version);
1373 if (peer_version_string == NULL)
1374 fatal_f("sshbuf_dup_string failed");
1375 /* XXX must be same size for sscanf */
1376 if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
1377 error_f("calloc failed");
1378 r = SSH_ERR_ALLOC_FAIL;
1379 goto out;
1380 }
1381
1382 /*
1383 * Check that the versions match. In future this might accept
1384 * several versions and set appropriate flags to handle them.
1385 */
1386 if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
1387 &remote_major, &remote_minor, remote_version) != 3) {
1388 error("Bad remote protocol version identification: '%.100s'",
1389 peer_version_string);
1390 invalid:
1391 send_error(ssh, "Invalid SSH identification string.");
1392 r = SSH_ERR_INVALID_FORMAT;
1393 goto out;
1394 }
1395 debug("Remote protocol version %d.%d, remote software version %.100s",
1396 remote_major, remote_minor, remote_version);
1397 compat_banner(ssh, remote_version);
1398
1399 mismatch = 0;
1400 switch (remote_major) {
1401 case 2:
1402 break;
1403 case 1:
1404 if (remote_minor != 99)
1405 mismatch = 1;
1406 break;
1407 default:
1408 mismatch = 1;
1409 break;
1410 }
1411 if (mismatch) {
1412 error("Protocol major versions differ: %d vs. %d",
1413 PROTOCOL_MAJOR_2, remote_major);
1414 send_error(ssh, "Protocol major versions differ.");
1415 r = SSH_ERR_NO_PROTOCOL_VERSION;
1416 goto out;
1417 }
1418
1419 if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
1420 logit("probed from %s port %d with %s. Don't panic.",
1421 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1422 peer_version_string);
1423 r = SSH_ERR_CONN_CLOSED; /* XXX */
1424 goto out;
1425 }
1426 if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
1427 logit("scanned from %s port %d with %s. Don't panic.",
1428 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1429 peer_version_string);
1430 r = SSH_ERR_CONN_CLOSED; /* XXX */
1431 goto out;
1432 }
1433 /* success */
1434 r = 0;
1435 out:
1436 free(our_version_string);
1437 free(peer_version_string);
1438 free(remote_version);
1439 if (r == SSH_ERR_SYSTEM_ERROR)
1440 errno = oerrno;
1441 return r;
1442 }
1443
1444