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