1 /* $OpenBSD: kex.c,v 1.194 2026/05/31 04:44:38 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|KEX_INIT_RECVD);
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 if ((kex->flags & KEX_INIT_RECVD) != 0) {
628 ssh_packet_disconnect(ssh,
629 "multiple KEXINIT received from peer");
630 }
631 kex->flags |= KEX_INIT_RECVD;
632 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
633 ptr = sshpkt_ptr(ssh, &dlen);
634 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
635 return r;
636
637 /* discard packet */
638 for (i = 0; i < KEX_COOKIE_LEN; i++) {
639 if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
640 error_fr(r, "discard cookie");
641 return r;
642 }
643 }
644 for (i = 0; i < PROPOSAL_MAX; i++) {
645 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
646 error_fr(r, "discard proposal");
647 return r;
648 }
649 }
650 /*
651 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
652 * KEX method has the server move first, but a server might be using
653 * a custom method or one that we otherwise don't support. We should
654 * be prepared to remember first_kex_follows here so we can eat a
655 * packet later.
656 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
657 * for cases where the server *doesn't* go first. I guess we should
658 * ignore it when it is set for these cases, which is what we do now.
659 */
660 if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
661 (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
662 (r = sshpkt_get_end(ssh)) != 0)
663 return r;
664
665 if (!(kex->flags & KEX_INIT_SENT))
666 if ((r = kex_send_kexinit(ssh)) != 0)
667 return r;
668 if ((r = kex_choose_conf(ssh, seq)) != 0)
669 return r;
670
671 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
672 return (kex->kex[kex->kex_type])(ssh);
673
674 error_f("unknown kex type %u", kex->kex_type);
675 return SSH_ERR_INTERNAL_ERROR;
676 }
677
678 struct kex *
kex_new(void)679 kex_new(void)
680 {
681 struct kex *kex;
682
683 if ((kex = calloc(1, sizeof(*kex))) == NULL ||
684 (kex->peer = sshbuf_new()) == NULL ||
685 (kex->my = sshbuf_new()) == NULL ||
686 (kex->client_version = sshbuf_new()) == NULL ||
687 (kex->server_version = sshbuf_new()) == NULL ||
688 (kex->session_id = sshbuf_new()) == NULL) {
689 kex_free(kex);
690 return NULL;
691 }
692 return kex;
693 }
694
695 void
kex_free_newkeys(struct newkeys * newkeys)696 kex_free_newkeys(struct newkeys *newkeys)
697 {
698 if (newkeys == NULL)
699 return;
700 if (newkeys->enc.key) {
701 explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
702 free(newkeys->enc.key);
703 newkeys->enc.key = NULL;
704 }
705 if (newkeys->enc.iv) {
706 explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
707 free(newkeys->enc.iv);
708 newkeys->enc.iv = NULL;
709 }
710 free(newkeys->enc.name);
711 explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
712 free(newkeys->comp.name);
713 explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
714 mac_clear(&newkeys->mac);
715 if (newkeys->mac.key) {
716 explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
717 free(newkeys->mac.key);
718 newkeys->mac.key = NULL;
719 }
720 free(newkeys->mac.name);
721 explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
722 freezero(newkeys, sizeof(*newkeys));
723 }
724
725 void
kex_free(struct kex * kex)726 kex_free(struct kex *kex)
727 {
728 u_int mode;
729
730 if (kex == NULL)
731 return;
732
733 #ifdef WITH_OPENSSL
734 DH_free(kex->dh);
735 #ifdef OPENSSL_HAS_ECC
736 EC_KEY_free(kex->ec_client_key);
737 #endif /* OPENSSL_HAS_ECC */
738 #endif /* WITH_OPENSSL */
739 for (mode = 0; mode < MODE_MAX; mode++) {
740 kex_free_newkeys(kex->newkeys[mode]);
741 kex->newkeys[mode] = NULL;
742 }
743 sshbuf_free(kex->peer);
744 sshbuf_free(kex->my);
745 sshbuf_free(kex->client_version);
746 sshbuf_free(kex->server_version);
747 sshbuf_free(kex->client_pub);
748 sshbuf_free(kex->session_id);
749 sshbuf_free(kex->initial_sig);
750 sshkey_free(kex->initial_hostkey);
751 free(kex->failed_choice);
752 free(kex->hostkey_alg);
753 free(kex->name);
754 free(kex->server_sig_algs);
755 free(kex);
756 }
757
758 int
kex_ready(struct ssh * ssh,char * proposal[PROPOSAL_MAX])759 kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
760 {
761 int r;
762
763 if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
764 return r;
765 ssh->kex->flags = KEX_INITIAL;
766 kex_reset_dispatch(ssh);
767 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
768 return 0;
769 }
770
771 int
kex_setup(struct ssh * ssh,char * proposal[PROPOSAL_MAX])772 kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
773 {
774 int r;
775
776 if ((r = kex_ready(ssh, proposal)) != 0)
777 return r;
778 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
779 kex_free(ssh->kex);
780 ssh->kex = NULL;
781 return r;
782 }
783 return 0;
784 }
785
786 /*
787 * Request key re-exchange, returns 0 on success or a ssherr.h error
788 * code otherwise. Must not be called if KEX is incomplete or in-progress.
789 */
790 int
kex_start_rekex(struct ssh * ssh)791 kex_start_rekex(struct ssh *ssh)
792 {
793 if (ssh->kex == NULL) {
794 error_f("no kex");
795 return SSH_ERR_INTERNAL_ERROR;
796 }
797 if (ssh->kex->done == 0) {
798 error_f("requested twice");
799 return SSH_ERR_INTERNAL_ERROR;
800 }
801 ssh->kex->done = 0;
802 return kex_send_kexinit(ssh);
803 }
804
805 static int
choose_enc(struct sshenc * enc,char * client,char * server)806 choose_enc(struct sshenc *enc, char *client, char *server)
807 {
808 char *name = match_list(client, server, NULL);
809
810 if (name == NULL)
811 return SSH_ERR_NO_CIPHER_ALG_MATCH;
812 if ((enc->cipher = cipher_by_name(name)) == NULL) {
813 error_f("unsupported cipher %s", name);
814 free(name);
815 return SSH_ERR_INTERNAL_ERROR;
816 }
817 enc->name = name;
818 enc->enabled = 0;
819 enc->iv = NULL;
820 enc->iv_len = cipher_ivlen(enc->cipher);
821 enc->key = NULL;
822 enc->key_len = cipher_keylen(enc->cipher);
823 enc->block_size = cipher_blocksize(enc->cipher);
824 return 0;
825 }
826
827 static int
choose_mac(struct ssh * ssh,struct sshmac * mac,char * client,char * server)828 choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
829 {
830 char *name = match_list(client, server, NULL);
831
832 if (name == NULL)
833 return SSH_ERR_NO_MAC_ALG_MATCH;
834 if (mac_setup(mac, name) < 0) {
835 error_f("unsupported MAC %s", name);
836 free(name);
837 return SSH_ERR_INTERNAL_ERROR;
838 }
839 mac->name = name;
840 mac->key = NULL;
841 mac->enabled = 0;
842 return 0;
843 }
844
845 static int
choose_comp(struct sshcomp * comp,char * client,char * server)846 choose_comp(struct sshcomp *comp, char *client, char *server)
847 {
848 char *name = match_list(client, server, NULL);
849
850 if (name == NULL)
851 return SSH_ERR_NO_COMPRESS_ALG_MATCH;
852 #ifdef WITH_ZLIB
853 if (strcmp(name, "zlib@openssh.com") == 0) {
854 comp->type = COMP_DELAYED;
855 } else
856 #endif /* WITH_ZLIB */
857 if (strcmp(name, "none") == 0) {
858 comp->type = COMP_NONE;
859 } else {
860 error_f("unsupported compression scheme %s", name);
861 free(name);
862 return SSH_ERR_INTERNAL_ERROR;
863 }
864 comp->name = name;
865 return 0;
866 }
867
868 static int
choose_kex(struct kex * k,char * client,char * server)869 choose_kex(struct kex *k, char *client, char *server)
870 {
871 k->name = match_list(client, server, NULL);
872
873 debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
874 if (k->name == NULL)
875 return SSH_ERR_NO_KEX_ALG_MATCH;
876 if (!kex_name_valid(k->name)) {
877 error_f("unsupported KEX method %s", k->name);
878 return SSH_ERR_INTERNAL_ERROR;
879 }
880 k->kex_type = kex_type_from_name(k->name);
881 k->hash_alg = kex_hash_from_name(k->name);
882 k->ec_nid = kex_nid_from_name(k->name);
883 return 0;
884 }
885
886 static int
choose_hostkeyalg(struct kex * k,char * client,char * server)887 choose_hostkeyalg(struct kex *k, char *client, char *server)
888 {
889 free(k->hostkey_alg);
890 k->hostkey_alg = match_list(client, server, NULL);
891
892 debug("kex: host key algorithm: %s",
893 k->hostkey_alg ? k->hostkey_alg : "(no match)");
894 if (k->hostkey_alg == NULL)
895 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
896 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
897 if (k->hostkey_type == KEY_UNSPEC) {
898 error_f("unsupported hostkey algorithm %s", k->hostkey_alg);
899 return SSH_ERR_INTERNAL_ERROR;
900 }
901 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
902 return 0;
903 }
904
905 static int
proposals_match(char * my[PROPOSAL_MAX],char * peer[PROPOSAL_MAX])906 proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
907 {
908 static int check[] = {
909 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
910 };
911 int *idx;
912 char *p;
913
914 for (idx = &check[0]; *idx != -1; idx++) {
915 if ((p = strchr(my[*idx], ',')) != NULL)
916 *p = '\0';
917 if ((p = strchr(peer[*idx], ',')) != NULL)
918 *p = '\0';
919 if (strcmp(my[*idx], peer[*idx]) != 0) {
920 debug2("proposal mismatch: my %s peer %s",
921 my[*idx], peer[*idx]);
922 return (0);
923 }
924 }
925 debug2("proposals match");
926 return (1);
927 }
928
929 static int
kexalgs_contains(char ** peer,const char * ext)930 kexalgs_contains(char **peer, const char *ext)
931 {
932 return kex_has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
933 }
934
935 static int
kex_choose_conf(struct ssh * ssh,uint32_t seq)936 kex_choose_conf(struct ssh *ssh, uint32_t seq)
937 {
938 struct kex *kex = ssh->kex;
939 struct newkeys *newkeys;
940 char **my = NULL, **peer = NULL;
941 char **cprop, **sprop;
942 int nenc, nmac, ncomp;
943 u_int mode, ctos, need, dh_need, authlen;
944 int r, first_kex_follows;
945
946 debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
947 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
948 goto out;
949 debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
950 if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
951 goto out;
952
953 if (kex->server) {
954 cprop=peer;
955 sprop=my;
956 } else {
957 cprop=my;
958 sprop=peer;
959 }
960
961 /* Check whether peer supports ext_info/kex_strict */
962 if ((kex->flags & KEX_INITIAL) != 0) {
963 if (kex->server) {
964 kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
965 kex->kex_strict = kexalgs_contains(peer,
966 "kex-strict-c-v00@openssh.com");
967 } else {
968 kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
969 kex->kex_strict = kexalgs_contains(peer,
970 "kex-strict-s-v00@openssh.com");
971 }
972 if (kex->kex_strict) {
973 debug3_f("will use strict KEX ordering");
974 if (seq != 0)
975 ssh_packet_disconnect(ssh,
976 "strict KEX violation: "
977 "KEXINIT was not the first packet");
978 }
979 }
980
981 /* Check whether client supports rsa-sha2 algorithms */
982 if (kex->server && (kex->flags & KEX_INITIAL)) {
983 if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
984 "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
985 kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
986 if (kex_has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
987 "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
988 kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
989 }
990
991 /* Algorithm Negotiation */
992 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
993 sprop[PROPOSAL_KEX_ALGS])) != 0) {
994 kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
995 peer[PROPOSAL_KEX_ALGS] = NULL;
996 goto out;
997 }
998 if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
999 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
1000 kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
1001 peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
1002 goto out;
1003 }
1004 for (mode = 0; mode < MODE_MAX; mode++) {
1005 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
1006 r = SSH_ERR_ALLOC_FAIL;
1007 goto out;
1008 }
1009 kex->newkeys[mode] = newkeys;
1010 ctos = (!kex->server && mode == MODE_OUT) ||
1011 (kex->server && mode == MODE_IN);
1012 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
1013 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
1014 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
1015 if ((r = choose_enc(&newkeys->enc, cprop[nenc],
1016 sprop[nenc])) != 0) {
1017 kex->failed_choice = peer[nenc];
1018 peer[nenc] = NULL;
1019 goto out;
1020 }
1021 authlen = cipher_authlen(newkeys->enc.cipher);
1022 /* ignore mac for authenticated encryption */
1023 if (authlen == 0 &&
1024 (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
1025 sprop[nmac])) != 0) {
1026 kex->failed_choice = peer[nmac];
1027 peer[nmac] = NULL;
1028 goto out;
1029 }
1030 if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
1031 sprop[ncomp])) != 0) {
1032 kex->failed_choice = peer[ncomp];
1033 peer[ncomp] = NULL;
1034 goto out;
1035 }
1036 debug("kex: %s cipher: %s MAC: %s compression: %s",
1037 ctos ? "client->server" : "server->client",
1038 newkeys->enc.name,
1039 authlen == 0 ? newkeys->mac.name : "<implicit>",
1040 newkeys->comp.name);
1041 }
1042 need = dh_need = 0;
1043 for (mode = 0; mode < MODE_MAX; mode++) {
1044 newkeys = kex->newkeys[mode];
1045 need = MAXIMUM(need, newkeys->enc.key_len);
1046 need = MAXIMUM(need, newkeys->enc.block_size);
1047 need = MAXIMUM(need, newkeys->enc.iv_len);
1048 need = MAXIMUM(need, newkeys->mac.key_len);
1049 dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
1050 dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
1051 dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
1052 dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
1053 }
1054 /* XXX need runden? */
1055 kex->we_need = need;
1056 kex->dh_need = dh_need;
1057
1058 /* ignore the next message if the proposals do not match */
1059 if (first_kex_follows && !proposals_match(my, peer))
1060 ssh->dispatch_skip_packets = 1;
1061 r = 0;
1062 out:
1063 kex_prop_free(my);
1064 kex_prop_free(peer);
1065 return r;
1066 }
1067
1068 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)1069 derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
1070 const struct sshbuf *shared_secret, u_char **keyp)
1071 {
1072 struct kex *kex = ssh->kex;
1073 struct ssh_digest_ctx *hashctx = NULL;
1074 char c = id;
1075 u_int have;
1076 size_t mdsz;
1077 u_char *digest;
1078 int r;
1079
1080 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
1081 return SSH_ERR_INVALID_ARGUMENT;
1082 if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
1083 r = SSH_ERR_ALLOC_FAIL;
1084 goto out;
1085 }
1086
1087 /* K1 = HASH(K || H || "A" || session_id) */
1088 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1089 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1090 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1091 ssh_digest_update(hashctx, &c, 1) != 0 ||
1092 ssh_digest_update_buffer(hashctx, kex->session_id) != 0 ||
1093 ssh_digest_final(hashctx, digest, mdsz) != 0) {
1094 r = SSH_ERR_LIBCRYPTO_ERROR;
1095 error_f("KEX hash failed");
1096 goto out;
1097 }
1098 ssh_digest_free(hashctx);
1099 hashctx = NULL;
1100
1101 /*
1102 * expand key:
1103 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
1104 * Key = K1 || K2 || ... || Kn
1105 */
1106 for (have = mdsz; need > have; have += mdsz) {
1107 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1108 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1109 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1110 ssh_digest_update(hashctx, digest, have) != 0 ||
1111 ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
1112 error_f("KDF failed");
1113 r = SSH_ERR_LIBCRYPTO_ERROR;
1114 goto out;
1115 }
1116 ssh_digest_free(hashctx);
1117 hashctx = NULL;
1118 }
1119 #ifdef DEBUG_KEX
1120 fprintf(stderr, "key '%c'== ", c);
1121 dump_digest("key", digest, need);
1122 #endif
1123 *keyp = digest;
1124 digest = NULL;
1125 r = 0;
1126 out:
1127 free(digest);
1128 ssh_digest_free(hashctx);
1129 return r;
1130 }
1131
1132 #define NKEYS 6
1133 int
kex_derive_keys(struct ssh * ssh,u_char * hash,u_int hashlen,const struct sshbuf * shared_secret)1134 kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
1135 const struct sshbuf *shared_secret)
1136 {
1137 struct kex *kex = ssh->kex;
1138 u_char *keys[NKEYS];
1139 u_int i, j, mode, ctos;
1140 int r;
1141
1142 /* save initial hash as session id */
1143 if ((kex->flags & KEX_INITIAL) != 0) {
1144 if (sshbuf_len(kex->session_id) != 0) {
1145 error_f("already have session ID at kex");
1146 return SSH_ERR_INTERNAL_ERROR;
1147 }
1148 if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0)
1149 return r;
1150 } else if (sshbuf_len(kex->session_id) == 0) {
1151 error_f("no session ID in rekex");
1152 return SSH_ERR_INTERNAL_ERROR;
1153 }
1154 for (i = 0; i < NKEYS; i++) {
1155 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
1156 shared_secret, &keys[i])) != 0) {
1157 for (j = 0; j < i; j++)
1158 free(keys[j]);
1159 return r;
1160 }
1161 }
1162 for (mode = 0; mode < MODE_MAX; mode++) {
1163 ctos = (!kex->server && mode == MODE_OUT) ||
1164 (kex->server && mode == MODE_IN);
1165 kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1];
1166 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
1167 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
1168 }
1169 return 0;
1170 }
1171
1172 int
kex_load_hostkey(struct ssh * ssh,struct sshkey ** prvp,struct sshkey ** pubp)1173 kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1174 {
1175 struct kex *kex = ssh->kex;
1176
1177 *pubp = NULL;
1178 *prvp = NULL;
1179 if (kex->load_host_public_key == NULL ||
1180 kex->load_host_private_key == NULL) {
1181 error_f("missing hostkey loader");
1182 return SSH_ERR_INVALID_ARGUMENT;
1183 }
1184 *pubp = kex->load_host_public_key(kex->hostkey_type,
1185 kex->hostkey_nid, ssh);
1186 *prvp = kex->load_host_private_key(kex->hostkey_type,
1187 kex->hostkey_nid, ssh);
1188 if (*pubp == NULL)
1189 return SSH_ERR_NO_HOSTKEY_LOADED;
1190 return 0;
1191 }
1192
1193 int
kex_verify_host_key(struct ssh * ssh,struct sshkey * server_host_key)1194 kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1195 {
1196 struct kex *kex = ssh->kex;
1197
1198 if (kex->verify_host_key == NULL) {
1199 error_f("missing hostkey verifier");
1200 return SSH_ERR_INVALID_ARGUMENT;
1201 }
1202 if (server_host_key->type != kex->hostkey_type ||
1203 (kex->hostkey_type == KEY_ECDSA &&
1204 server_host_key->ecdsa_nid != kex->hostkey_nid))
1205 return SSH_ERR_KEY_TYPE_MISMATCH;
1206 if (kex->verify_host_key(server_host_key, ssh) == -1)
1207 return SSH_ERR_SIGNATURE_INVALID;
1208 return 0;
1209 }
1210
1211 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
1212 void
dump_digest(const char * msg,const u_char * digest,int len)1213 dump_digest(const char *msg, const u_char *digest, int len)
1214 {
1215 fprintf(stderr, "%s\n", msg);
1216 sshbuf_dump_data(digest, len, stderr);
1217 }
1218 #endif
1219
1220 /*
1221 * Send a plaintext error message to the peer, suffixed by \r\n.
1222 * Only used during banner exchange, and there only for the server.
1223 */
1224 static void
send_error(struct ssh * ssh,char * msg)1225 send_error(struct ssh *ssh, char *msg)
1226 {
1227 char *crnl = "\r\n";
1228
1229 if (!ssh->kex->server)
1230 return;
1231
1232 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1233 msg, strlen(msg)) != strlen(msg) ||
1234 atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1235 crnl, strlen(crnl)) != strlen(crnl))
1236 error_f("write: %.100s", strerror(errno));
1237 }
1238
1239 /*
1240 * Sends our identification string and waits for the peer's. Will block for
1241 * up to timeout_ms (or indefinitely if timeout_ms <= 0).
1242 * Returns on 0 success or a ssherr.h code on failure.
1243 */
1244 int
kex_exchange_identification(struct ssh * ssh,int timeout_ms,const char * version_addendum)1245 kex_exchange_identification(struct ssh *ssh, int timeout_ms,
1246 const char *version_addendum)
1247 {
1248 int remote_major, remote_minor, mismatch, oerrno = 0;
1249 size_t len, n;
1250 int r, expect_nl;
1251 u_char c;
1252 struct sshbuf *our_version = ssh->kex->server ?
1253 ssh->kex->server_version : ssh->kex->client_version;
1254 struct sshbuf *peer_version = ssh->kex->server ?
1255 ssh->kex->client_version : ssh->kex->server_version;
1256 char *our_version_string = NULL, *peer_version_string = NULL;
1257 char *cp, *remote_version = NULL;
1258
1259 /* Prepare and send our banner */
1260 sshbuf_reset(our_version);
1261 if (version_addendum != NULL && *version_addendum == '\0')
1262 version_addendum = NULL;
1263 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n",
1264 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
1265 version_addendum == NULL ? "" : " ",
1266 version_addendum == NULL ? "" : version_addendum)) != 0) {
1267 oerrno = errno;
1268 error_fr(r, "sshbuf_putf");
1269 goto out;
1270 }
1271
1272 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1273 sshbuf_mutable_ptr(our_version),
1274 sshbuf_len(our_version)) != sshbuf_len(our_version)) {
1275 oerrno = errno;
1276 debug_f("write: %.100s", strerror(errno));
1277 r = SSH_ERR_SYSTEM_ERROR;
1278 goto out;
1279 }
1280 if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
1281 oerrno = errno;
1282 error_fr(r, "sshbuf_consume_end");
1283 goto out;
1284 }
1285 our_version_string = sshbuf_dup_string(our_version);
1286 if (our_version_string == NULL) {
1287 error_f("sshbuf_dup_string failed");
1288 r = SSH_ERR_ALLOC_FAIL;
1289 goto out;
1290 }
1291 debug("Local version string %.100s", our_version_string);
1292
1293 /* Read other side's version identification. */
1294 for (n = 0; ; n++) {
1295 if (n >= SSH_MAX_PRE_BANNER_LINES) {
1296 send_error(ssh, "No SSH identification string "
1297 "received.");
1298 error_f("No SSH version received in first %u lines "
1299 "from server", SSH_MAX_PRE_BANNER_LINES);
1300 r = SSH_ERR_INVALID_FORMAT;
1301 goto out;
1302 }
1303 sshbuf_reset(peer_version);
1304 expect_nl = 0;
1305 for (;;) {
1306 if (timeout_ms > 0) {
1307 r = waitrfd(ssh_packet_get_connection_in(ssh),
1308 &timeout_ms, NULL);
1309 if (r == -1 && errno == ETIMEDOUT) {
1310 send_error(ssh, "Timed out waiting "
1311 "for SSH identification string.");
1312 error("Connection timed out during "
1313 "banner exchange");
1314 r = SSH_ERR_CONN_TIMEOUT;
1315 goto out;
1316 } else if (r == -1) {
1317 oerrno = errno;
1318 error_f("%s", strerror(errno));
1319 r = SSH_ERR_SYSTEM_ERROR;
1320 goto out;
1321 }
1322 }
1323
1324 len = atomicio(read, ssh_packet_get_connection_in(ssh),
1325 &c, 1);
1326 if (len != 1 && errno == EPIPE) {
1327 verbose_f("Connection closed by remote host");
1328 r = SSH_ERR_CONN_CLOSED;
1329 goto out;
1330 } else if (len != 1) {
1331 oerrno = errno;
1332 error_f("read: %.100s", strerror(errno));
1333 r = SSH_ERR_SYSTEM_ERROR;
1334 goto out;
1335 }
1336 if (c == '\r') {
1337 expect_nl = 1;
1338 continue;
1339 }
1340 if (c == '\n')
1341 break;
1342 if (c == '\0' || expect_nl) {
1343 verbose_f("banner line contains invalid "
1344 "characters");
1345 goto invalid;
1346 }
1347 if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
1348 oerrno = errno;
1349 error_fr(r, "sshbuf_put");
1350 goto out;
1351 }
1352 if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
1353 verbose_f("banner line too long");
1354 goto invalid;
1355 }
1356 }
1357 /* Is this an actual protocol banner? */
1358 if (sshbuf_len(peer_version) > 4 &&
1359 memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
1360 break;
1361 /* If not, then just log the line and continue */
1362 if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
1363 error_f("sshbuf_dup_string failed");
1364 r = SSH_ERR_ALLOC_FAIL;
1365 goto out;
1366 }
1367 /* Do not accept lines before the SSH ident from a client */
1368 if (ssh->kex->server) {
1369 verbose_f("client sent invalid protocol identifier "
1370 "\"%.256s\"", cp);
1371 free(cp);
1372 goto invalid;
1373 }
1374 debug_f("banner line %zu: %s", n, cp);
1375 free(cp);
1376 }
1377 peer_version_string = sshbuf_dup_string(peer_version);
1378 if (peer_version_string == NULL)
1379 fatal_f("sshbuf_dup_string failed");
1380 /* XXX must be same size for sscanf */
1381 if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
1382 error_f("calloc failed");
1383 r = SSH_ERR_ALLOC_FAIL;
1384 goto out;
1385 }
1386
1387 /*
1388 * Check that the versions match. In future this might accept
1389 * several versions and set appropriate flags to handle them.
1390 */
1391 if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
1392 &remote_major, &remote_minor, remote_version) != 3) {
1393 error("Bad remote protocol version identification: '%.100s'",
1394 peer_version_string);
1395 invalid:
1396 send_error(ssh, "Invalid SSH identification string.");
1397 r = SSH_ERR_INVALID_FORMAT;
1398 goto out;
1399 }
1400 debug("Remote protocol version %d.%d, remote software version %.100s",
1401 remote_major, remote_minor, remote_version);
1402 compat_banner(ssh, remote_version);
1403
1404 mismatch = 0;
1405 switch (remote_major) {
1406 case 2:
1407 break;
1408 case 1:
1409 if (remote_minor != 99)
1410 mismatch = 1;
1411 break;
1412 default:
1413 mismatch = 1;
1414 break;
1415 }
1416 if (mismatch) {
1417 error("Protocol major versions differ: %d vs. %d",
1418 PROTOCOL_MAJOR_2, remote_major);
1419 send_error(ssh, "Protocol major versions differ.");
1420 r = SSH_ERR_NO_PROTOCOL_VERSION;
1421 goto out;
1422 }
1423
1424 if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
1425 logit("probed from %s port %d with %s. Don't panic.",
1426 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1427 peer_version_string);
1428 r = SSH_ERR_CONN_CLOSED; /* XXX */
1429 goto out;
1430 }
1431 if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
1432 logit("scanned from %s port %d with %s. Don't panic.",
1433 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1434 peer_version_string);
1435 r = SSH_ERR_CONN_CLOSED; /* XXX */
1436 goto out;
1437 }
1438 /* success */
1439 r = 0;
1440 out:
1441 free(our_version_string);
1442 free(peer_version_string);
1443 free(remote_version);
1444 if (r == SSH_ERR_SYSTEM_ERROR)
1445 errno = oerrno;
1446 return r;
1447 }
1448
1449