Coverage Report

Created: 2024-06-18 06:23

/src/hpn-ssh/kex.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: kex.c,v 1.185 2024/01/08 00:34:33 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
#ifdef HAVE_POLL_H
37
#include <poll.h>
38
#endif
39
40
#ifdef WITH_OPENSSL
41
#include <openssl/crypto.h>
42
#include <openssl/dh.h>
43
#endif
44
45
#include "ssh.h"
46
#include "ssh2.h"
47
#include "atomicio.h"
48
#include "version.h"
49
#include "packet.h"
50
#include "compat.h"
51
#include "cipher.h"
52
#include "sshkey.h"
53
#include "kex.h"
54
#include "log.h"
55
#include "mac.h"
56
#include "match.h"
57
#include "misc.h"
58
#include "dispatch.h"
59
#include "monitor.h"
60
#include "myproposal.h"
61
62
#include "ssherr.h"
63
#include "sshbuf.h"
64
#include "canohost.h"
65
#include "digest.h"
66
#include "xmalloc.h"
67
68
/* prototype */
69
static int kex_choose_conf(struct ssh *, uint32_t seq);
70
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
71
72
static const char * const proposal_names[PROPOSAL_MAX] = {
73
  "KEX algorithms",
74
  "host key algorithms",
75
  "ciphers ctos",
76
  "ciphers stoc",
77
  "MACs ctos",
78
  "MACs stoc",
79
  "compression ctos",
80
  "compression stoc",
81
  "languages ctos",
82
  "languages stoc",
83
};
84
85
struct kexalg {
86
  char *name;
87
  u_int type;
88
  int ec_nid;
89
  int hash_alg;
90
};
91
static const struct kexalg kexalgs[] = {
92
#ifdef WITH_OPENSSL
93
  { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
94
  { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
95
  { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
96
  { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
97
  { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
98
  { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
99
#ifdef HAVE_EVP_SHA256
100
  { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
101
#endif /* HAVE_EVP_SHA256 */
102
#ifdef OPENSSL_HAS_ECC
103
  { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
104
      NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
105
  { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1,
106
      SSH_DIGEST_SHA384 },
107
# ifdef OPENSSL_HAS_NISTP521
108
  { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
109
      SSH_DIGEST_SHA512 },
110
# endif /* OPENSSL_HAS_NISTP521 */
111
#endif /* OPENSSL_HAS_ECC */
112
#endif /* WITH_OPENSSL */
113
#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL)
114
  { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
115
  { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
116
#ifdef USE_SNTRUP761X25519
117
  { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0,
118
      SSH_DIGEST_SHA512 },
119
#endif
120
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
121
  { NULL, 0, -1, -1},
122
};
123
124
char *
125
kex_alg_list(char sep)
126
0
{
127
0
  char *ret = NULL, *tmp;
128
0
  size_t nlen, rlen = 0;
129
0
  const struct kexalg *k;
130
131
0
  for (k = kexalgs; k->name != NULL; k++) {
132
0
    if (ret != NULL)
133
0
      ret[rlen++] = sep;
134
0
    nlen = strlen(k->name);
135
0
    if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
136
0
      free(ret);
137
0
      return NULL;
138
0
    }
139
0
    ret = tmp;
140
0
    memcpy(ret + rlen, k->name, nlen + 1);
141
0
    rlen += nlen;
142
0
  }
143
0
  return ret;
144
0
}
145
146
static const struct kexalg *
147
kex_alg_by_name(const char *name)
148
504
{
149
504
  const struct kexalg *k;
150
151
4.61k
  for (k = kexalgs; k->name != NULL; k++) {
152
4.61k
    if (strcmp(k->name, name) == 0)
153
504
      return k;
154
4.61k
  }
155
0
  return NULL;
156
504
}
157
158
/* Validate KEX method name list */
159
int
160
kex_names_valid(const char *names)
161
0
{
162
0
  char *s, *cp, *p;
163
164
0
  if (names == NULL || strcmp(names, "") == 0)
165
0
    return 0;
166
0
  if ((s = cp = strdup(names)) == NULL)
167
0
    return 0;
168
0
  for ((p = strsep(&cp, ",")); p && *p != '\0';
169
0
      (p = strsep(&cp, ","))) {
170
0
    if (kex_alg_by_name(p) == NULL) {
171
0
      error("Unsupported KEX algorithm \"%.100s\"", p);
172
0
      free(s);
173
0
      return 0;
174
0
    }
175
0
  }
176
0
  debug3("kex names ok: [%s]", names);
177
0
  free(s);
178
0
  return 1;
179
0
}
180
181
/* returns non-zero if proposal contains any algorithm from algs */
182
static int
183
has_any_alg(const char *proposal, const char *algs)
184
149k
{
185
149k
  char *cp;
186
187
149k
  if ((cp = match_list(proposal, algs, NULL)) == NULL)
188
149k
    return 0;
189
0
  free(cp);
190
0
  return 1;
191
149k
}
192
193
/*
194
 * Concatenate algorithm names, avoiding duplicates in the process.
195
 * Caller must free returned string.
196
 */
197
char *
198
kex_names_cat(const char *a, const char *b)
199
70.0k
{
200
70.0k
  char *ret = NULL, *tmp = NULL, *cp, *p;
201
70.0k
  size_t len;
202
203
70.0k
  if (a == NULL || *a == '\0')
204
0
    return strdup(b);
205
70.0k
  if (b == NULL || *b == '\0')
206
0
    return strdup(a);
207
70.0k
  if (strlen(b) > 1024*1024)
208
0
    return NULL;
209
70.0k
  len = strlen(a) + strlen(b) + 2;
210
70.0k
  if ((tmp = cp = strdup(b)) == NULL ||
211
70.0k
      (ret = calloc(1, len)) == NULL) {
212
0
    free(tmp);
213
0
    return NULL;
214
0
  }
215
70.0k
  strlcpy(ret, a, len);
216
210k
  for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
217
140k
    if (has_any_alg(ret, p))
218
0
      continue; /* Algorithm already present */
219
140k
    if (strlcat(ret, ",", len) >= len ||
220
140k
        strlcat(ret, p, len) >= len) {
221
0
      free(tmp);
222
0
      free(ret);
223
0
      return NULL; /* Shouldn't happen */
224
0
    }
225
140k
  }
226
70.0k
  free(tmp);
227
70.0k
  return ret;
228
70.0k
}
229
230
/*
231
 * Assemble a list of algorithms from a default list and a string from a
232
 * configuration file. The user-provided string may begin with '+' to
233
 * indicate that it should be appended to the default, '-' that the
234
 * specified names should be removed, or '^' that they should be placed
235
 * at the head.
236
 */
237
int
238
kex_assemble_names(char **listp, const char *def, const char *all)
239
0
{
240
0
  char *cp, *tmp, *patterns;
241
0
  char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL;
242
0
  int r = SSH_ERR_INTERNAL_ERROR;
243
244
0
  if (listp == NULL || def == NULL || all == NULL)
245
0
    return SSH_ERR_INVALID_ARGUMENT;
246
247
0
  if (*listp == NULL || **listp == '\0') {
248
0
    if ((*listp = strdup(def)) == NULL)
249
0
      return SSH_ERR_ALLOC_FAIL;
250
0
    return 0;
251
0
  }
252
253
0
  list = *listp;
254
0
  *listp = NULL;
255
0
  if (*list == '+') {
256
    /* Append names to default list */
257
0
    if ((tmp = kex_names_cat(def, list + 1)) == NULL) {
258
0
      r = SSH_ERR_ALLOC_FAIL;
259
0
      goto fail;
260
0
    }
261
0
    free(list);
262
0
    list = tmp;
263
0
  } else if (*list == '-') {
264
    /* Remove names from default list */
265
0
    if ((*listp = match_filter_denylist(def, list + 1)) == NULL) {
266
0
      r = SSH_ERR_ALLOC_FAIL;
267
0
      goto fail;
268
0
    }
269
0
    free(list);
270
    /* filtering has already been done */
271
0
    return 0;
272
0
  } else if (*list == '^') {
273
    /* Place names at head of default list */
274
0
    if ((tmp = kex_names_cat(list + 1, def)) == NULL) {
275
0
      r = SSH_ERR_ALLOC_FAIL;
276
0
      goto fail;
277
0
    }
278
0
    free(list);
279
0
    list = tmp;
280
0
  } else {
281
    /* Explicit list, overrides default - just use "list" as is */
282
0
  }
283
284
  /*
285
   * The supplied names may be a pattern-list. For the -list case,
286
   * the patterns are applied above. For the +list and explicit list
287
   * cases we need to do it now.
288
   */
289
0
  ret = NULL;
290
0
  if ((patterns = opatterns = strdup(list)) == NULL) {
291
0
    r = SSH_ERR_ALLOC_FAIL;
292
0
    goto fail;
293
0
  }
294
  /* Apply positive (i.e. non-negated) patterns from the list */
295
0
  while ((cp = strsep(&patterns, ",")) != NULL) {
296
0
    if (*cp == '!') {
297
      /* negated matches are not supported here */
298
0
      r = SSH_ERR_INVALID_ARGUMENT;
299
0
      goto fail;
300
0
    }
301
0
    free(matching);
302
0
    if ((matching = match_filter_allowlist(all, cp)) == NULL) {
303
0
      r = SSH_ERR_ALLOC_FAIL;
304
0
      goto fail;
305
0
    }
306
0
    if ((tmp = kex_names_cat(ret, matching)) == NULL) {
307
0
      r = SSH_ERR_ALLOC_FAIL;
308
0
      goto fail;
309
0
    }
310
0
    free(ret);
311
0
    ret = tmp;
312
0
  }
313
0
  if (ret == NULL || *ret == '\0') {
314
    /* An empty name-list is an error */
315
    /* XXX better error code? */
316
0
    r = SSH_ERR_INVALID_ARGUMENT;
317
0
    goto fail;
318
0
  }
319
320
  /* success */
321
0
  *listp = ret;
322
0
  ret = NULL;
323
0
  r = 0;
324
325
0
 fail:
326
0
  free(matching);
327
0
  free(opatterns);
328
0
  free(list);
329
0
  free(ret);
330
0
  return r;
331
0
}
332
333
/*
334
 * Fill out a proposal array with dynamically allocated values, which may
335
 * be modified as required for compatibility reasons.
336
 * Any of the options may be NULL, in which case the default is used.
337
 * Array contents must be freed by calling kex_proposal_free_entries.
338
 */
339
void
340
kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
341
    const char *kexalgos, const char *ciphers, const char *macs,
342
    const char *comp, const char *hkalgs)
343
70.0k
{
344
70.0k
  const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
345
70.0k
  const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
346
70.0k
  const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
347
70.0k
  u_int i;
348
70.0k
  char *cp;
349
350
70.0k
  if (prop == NULL)
351
0
    fatal_f("proposal missing");
352
353
  /* Append EXT_INFO signalling to KexAlgorithms */
354
70.0k
  if (kexalgos == NULL)
355
0
    kexalgos = defprop[PROPOSAL_KEX_ALGS];
356
70.0k
  if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
357
35.0k
      "ext-info-s,kex-strict-s-v00@openssh.com" :
358
70.0k
      "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
359
0
    fatal_f("kex_names_cat");
360
361
770k
  for (i = 0; i < PROPOSAL_MAX; i++) {
362
700k
    switch(i) {
363
70.0k
    case PROPOSAL_KEX_ALGS:
364
70.0k
      prop[i] = compat_kex_proposal(ssh, cp);
365
70.0k
      break;
366
70.0k
    case PROPOSAL_ENC_ALGS_CTOS:
367
140k
    case PROPOSAL_ENC_ALGS_STOC:
368
140k
      prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
369
140k
      break;
370
70.0k
    case PROPOSAL_MAC_ALGS_CTOS:
371
140k
    case PROPOSAL_MAC_ALGS_STOC:
372
140k
      prop[i]  = xstrdup(macs ? macs : defprop[i]);
373
140k
      break;
374
70.0k
    case PROPOSAL_COMP_ALGS_CTOS:
375
140k
    case PROPOSAL_COMP_ALGS_STOC:
376
140k
      prop[i] = xstrdup(comp ? comp : defprop[i]);
377
140k
      break;
378
70.0k
    case PROPOSAL_SERVER_HOST_KEY_ALGS:
379
70.0k
      prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
380
70.0k
      break;
381
140k
    default:
382
140k
      prop[i] = xstrdup(defprop[i]);
383
700k
    }
384
700k
  }
385
70.0k
  free(cp);
386
70.0k
}
387
388
void
389
kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
390
70.0k
{
391
70.0k
  u_int i;
392
393
770k
  for (i = 0; i < PROPOSAL_MAX; i++)
394
700k
    free(prop[i]);
395
70.0k
}
396
397
/* put algorithm proposal into buffer */
398
int
399
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
400
90.1k
{
401
90.1k
  u_int i;
402
90.1k
  int r;
403
404
90.1k
  sshbuf_reset(b);
405
406
  /*
407
   * add a dummy cookie, the cookie will be overwritten by
408
   * kex_send_kexinit(), each time a kexinit is set
409
   */
410
1.53M
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
411
1.44M
    if ((r = sshbuf_put_u8(b, 0)) != 0)
412
0
      return r;
413
1.44M
  }
414
991k
  for (i = 0; i < PROPOSAL_MAX; i++) {
415
901k
    if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
416
0
      return r;
417
901k
  }
418
90.1k
  if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
419
90.1k
      (r = sshbuf_put_u32(b, 0)) != 0)  /* uint32 reserved */
420
0
    return r;
421
90.1k
  return 0;
422
90.1k
}
423
424
/* parse buffer and return algorithm proposal */
425
int
426
kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
427
27.2k
{
428
27.2k
  struct sshbuf *b = NULL;
429
27.2k
  u_char v;
430
27.2k
  u_int i;
431
27.2k
  char **proposal = NULL;
432
27.2k
  int r;
433
434
27.2k
  *propp = NULL;
435
27.2k
  if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
436
0
    return SSH_ERR_ALLOC_FAIL;
437
27.2k
  if ((b = sshbuf_fromb(raw)) == NULL) {
438
0
    r = SSH_ERR_ALLOC_FAIL;
439
0
    goto out;
440
0
  }
441
27.2k
  if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */
442
0
    error_fr(r, "consume cookie");
443
0
    goto out;
444
0
  }
445
  /* extract kex init proposal strings */
446
298k
  for (i = 0; i < PROPOSAL_MAX; i++) {
447
271k
    if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
448
260
      error_fr(r, "parse proposal %u", i);
449
260
      goto out;
450
260
    }
451
271k
    debug2("%s: %s", proposal_names[i], proposal[i]);
452
271k
  }
453
  /* first kex follows / reserved */
454
27.0k
  if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
455
27.0k
      (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
456
0
    error_fr(r, "parse");
457
0
    goto out;
458
0
  }
459
27.0k
  if (first_kex_follows != NULL)
460
3.34k
    *first_kex_follows = v;
461
27.0k
  debug2("first_kex_follows %d ", v);
462
27.0k
  debug2("reserved %u ", i);
463
27.0k
  r = 0;
464
27.0k
  *propp = proposal;
465
27.2k
 out:
466
27.2k
  if (r != 0 && proposal != NULL)
467
260
    kex_prop_free(proposal);
468
27.2k
  sshbuf_free(b);
469
27.2k
  return r;
470
27.0k
}
471
472
void
473
kex_prop_free(char **proposal)
474
27.5k
{
475
27.5k
  u_int i;
476
477
27.5k
  if (proposal == NULL)
478
260
    return;
479
299k
  for (i = 0; i < PROPOSAL_MAX; i++)
480
272k
    free(proposal[i]);
481
27.2k
  free(proposal);
482
27.2k
}
483
484
int
485
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
486
198k
{
487
198k
  int r;
488
489
  /* If in strict mode, any unexpected message is an error */
490
198k
  if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
491
0
    ssh_packet_disconnect(ssh, "strict KEX violation: "
492
0
        "unexpected packet type %u (seqnr %u)", type, seq);
493
0
  }
494
198k
  error_f("type %u seq %u", type, seq);
495
198k
  if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
496
198k
      (r = sshpkt_put_u32(ssh, seq)) != 0 ||
497
198k
      (r = sshpkt_send(ssh)) != 0)
498
0
    return r;
499
198k
  return 0;
500
198k
}
501
502
static void
503
kex_reset_dispatch(struct ssh *ssh)
504
70.0k
{
505
70.0k
  ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
506
70.0k
      SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
507
70.0k
}
508
509
void
510
kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs)
511
0
{
512
0
  char *alg, *oalgs, *algs, *sigalgs;
513
0
  const char *sigalg;
514
515
  /*
516
   * NB. allowed algorithms may contain certificate algorithms that
517
   * map to a specific plain signature type, e.g.
518
   * rsa-sha2-512-cert-v01@openssh.com => rsa-sha2-512
519
   * We need to be careful here to match these, retain the mapping
520
   * and only add each signature algorithm once.
521
   */
522
0
  if ((sigalgs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
523
0
    fatal_f("sshkey_alg_list failed");
524
0
  oalgs = algs = xstrdup(allowed_algs);
525
0
  free(ssh->kex->server_sig_algs);
526
0
  ssh->kex->server_sig_algs = NULL;
527
0
  for ((alg = strsep(&algs, ",")); alg != NULL && *alg != '\0';
528
0
      (alg = strsep(&algs, ","))) {
529
0
    if ((sigalg = sshkey_sigalg_by_name(alg)) == NULL)
530
0
      continue;
531
0
    if (!has_any_alg(sigalg, sigalgs))
532
0
      continue;
533
    /* Don't add an algorithm twice. */
534
0
    if (ssh->kex->server_sig_algs != NULL &&
535
0
        has_any_alg(sigalg, ssh->kex->server_sig_algs))
536
0
      continue;
537
0
    xextendf(&ssh->kex->server_sig_algs, ",", "%s", sigalg);
538
0
  }
539
0
  free(oalgs);
540
0
  free(sigalgs);
541
0
  if (ssh->kex->server_sig_algs == NULL)
542
0
    ssh->kex->server_sig_algs = xstrdup("");
543
0
}
544
545
static int
546
kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m)
547
0
{
548
0
  int r;
549
550
0
  if (ssh->kex->server_sig_algs == NULL &&
551
0
      (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
552
0
    return SSH_ERR_ALLOC_FAIL;
553
0
  if ((r = sshbuf_put_u32(m, 3)) != 0 ||
554
0
      (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 ||
555
0
      (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 ||
556
0
      (r = sshbuf_put_cstring(m,
557
0
      "publickey-hostbound@openssh.com")) != 0 ||
558
0
      (r = sshbuf_put_cstring(m, "0")) != 0 ||
559
0
      (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 ||
560
0
      (r = sshbuf_put_cstring(m, "0")) != 0) {
561
0
    error_fr(r, "compose");
562
0
    return r;
563
0
  }
564
0
  return 0;
565
0
}
566
567
static int
568
kex_compose_ext_info_client(struct ssh *ssh, struct sshbuf *m)
569
0
{
570
0
  int r;
571
572
0
  if ((r = sshbuf_put_u32(m, 1)) != 0 ||
573
0
      (r = sshbuf_put_cstring(m, "ext-info-in-auth@openssh.com")) != 0 ||
574
0
      (r = sshbuf_put_cstring(m, "0")) != 0) {
575
0
    error_fr(r, "compose");
576
0
    goto out;
577
0
  }
578
  /* success */
579
0
  r = 0;
580
0
 out:
581
0
  return r;
582
0
}
583
584
static int
585
kex_maybe_send_ext_info(struct ssh *ssh)
586
0
{
587
0
  int r;
588
0
  struct sshbuf *m = NULL;
589
590
0
  if ((ssh->kex->flags & KEX_INITIAL) == 0)
591
0
    return 0;
592
0
  if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s)
593
0
    return 0;
594
595
  /* Compose EXT_INFO packet. */
596
0
  if ((m = sshbuf_new()) == NULL)
597
0
    fatal_f("sshbuf_new failed");
598
0
  if (ssh->kex->ext_info_c &&
599
0
      (r = kex_compose_ext_info_server(ssh, m)) != 0)
600
0
    goto fail;
601
0
  if (ssh->kex->ext_info_s &&
602
0
      (r = kex_compose_ext_info_client(ssh, m)) != 0)
603
0
    goto fail;
604
605
  /* Send the actual KEX_INFO packet */
606
0
  debug("Sending SSH2_MSG_EXT_INFO");
607
0
  if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
608
0
      (r = sshpkt_putb(ssh, m)) != 0 ||
609
0
      (r = sshpkt_send(ssh)) != 0) {
610
0
    error_f("send EXT_INFO");
611
0
    goto fail;
612
0
  }
613
614
0
  r = 0;
615
616
0
 fail:
617
0
  sshbuf_free(m);
618
0
  return r;
619
0
}
620
621
int
622
kex_server_update_ext_info(struct ssh *ssh)
623
0
{
624
0
  int r;
625
626
0
  if ((ssh->kex->flags & KEX_HAS_EXT_INFO_IN_AUTH) == 0)
627
0
    return 0;
628
629
0
  debug_f("Sending SSH2_MSG_EXT_INFO");
630
0
  if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
631
0
      (r = sshpkt_put_u32(ssh, 1)) != 0 ||
632
0
      (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
633
0
      (r = sshpkt_put_cstring(ssh, ssh->kex->server_sig_algs)) != 0 ||
634
0
      (r = sshpkt_send(ssh)) != 0) {
635
0
    error_f("send EXT_INFO");
636
0
    return r;
637
0
  }
638
0
  return 0;
639
0
}
640
641
int
642
kex_send_newkeys(struct ssh *ssh)
643
0
{
644
0
  int r;
645
646
0
  kex_reset_dispatch(ssh);
647
0
  if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
648
0
      (r = sshpkt_send(ssh)) != 0)
649
0
    return r;
650
0
  debug("SSH2_MSG_NEWKEYS sent");
651
0
  ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
652
0
  if ((r = kex_maybe_send_ext_info(ssh)) != 0)
653
0
    return r;
654
0
  debug("expecting SSH2_MSG_NEWKEYS");
655
0
  return 0;
656
0
}
657
658
/* Check whether an ext_info value contains the expected version string */
659
static int
660
kex_ext_info_check_ver(struct kex *kex, const char *name,
661
    const u_char *val, size_t len, const char *want_ver, u_int flag)
662
0
{
663
0
  if (memchr(val, '\0', len) != NULL) {
664
0
    error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name);
665
0
    return SSH_ERR_INVALID_FORMAT;
666
0
  }
667
0
  debug_f("%s=<%s>", name, val);
668
0
  if (strcmp(val, want_ver) == 0)
669
0
    kex->flags |= flag;
670
0
  else
671
0
    debug_f("unsupported version of %s extension", name);
672
0
  return 0;
673
0
}
674
675
static int
676
kex_ext_info_client_parse(struct ssh *ssh, const char *name,
677
    const u_char *value, size_t vlen)
678
0
{
679
0
  int r;
680
681
  /* NB. some messages are only accepted in the initial EXT_INFO */
682
0
  if (strcmp(name, "server-sig-algs") == 0) {
683
    /* Ensure no \0 lurking in value */
684
0
    if (memchr(value, '\0', vlen) != NULL) {
685
0
      error_f("nul byte in %s", name);
686
0
      return SSH_ERR_INVALID_FORMAT;
687
0
    }
688
0
    debug_f("%s=<%s>", name, value);
689
0
    free(ssh->kex->server_sig_algs);
690
0
    ssh->kex->server_sig_algs = xstrdup((const char *)value);
691
0
  } else if (ssh->kex->ext_info_received == 1 &&
692
0
      strcmp(name, "publickey-hostbound@openssh.com") == 0) {
693
0
    if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
694
0
        "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) {
695
0
      return r;
696
0
    }
697
0
  } else if (ssh->kex->ext_info_received == 1 &&
698
0
      strcmp(name, "ping@openssh.com") == 0) {
699
0
    if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
700
0
        "0", KEX_HAS_PING)) != 0) {
701
0
      return r;
702
0
    }
703
0
  } else
704
0
    debug_f("%s (unrecognised)", name);
705
706
0
  return 0;
707
0
}
708
709
static int
710
kex_ext_info_server_parse(struct ssh *ssh, const char *name,
711
    const u_char *value, size_t vlen)
712
0
{
713
0
  int r;
714
715
0
  if (strcmp(name, "ext-info-in-auth@openssh.com") == 0) {
716
0
    if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen,
717
0
        "0", KEX_HAS_EXT_INFO_IN_AUTH)) != 0) {
718
0
      return r;
719
0
    }
720
0
  } else
721
0
    debug_f("%s (unrecognised)", name);
722
0
  return 0;
723
0
}
724
725
int
726
kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
727
0
{
728
0
  struct kex *kex = ssh->kex;
729
0
  const int max_ext_info = kex->server ? 1 : 2;
730
0
  u_int32_t i, ninfo;
731
0
  char *name;
732
0
  u_char *val;
733
0
  size_t vlen;
734
0
  int r;
735
736
0
  debug("SSH2_MSG_EXT_INFO received");
737
0
  if (++kex->ext_info_received > max_ext_info) {
738
0
    error("too many SSH2_MSG_EXT_INFO messages sent by peer");
739
0
    return dispatch_protocol_error(type, seq, ssh);
740
0
  }
741
0
  ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
742
0
  if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
743
0
    return r;
744
0
  if (ninfo >= 1024) {
745
0
    error("SSH2_MSG_EXT_INFO with too many entries, expected "
746
0
        "<=1024, received %u", ninfo);
747
0
    return dispatch_protocol_error(type, seq, ssh);
748
0
  }
749
0
  for (i = 0; i < ninfo; i++) {
750
0
    if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
751
0
      return r;
752
0
    if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
753
0
      free(name);
754
0
      return r;
755
0
    }
756
0
    debug3_f("extension %s", name);
757
0
    if (kex->server) {
758
0
      if ((r = kex_ext_info_server_parse(ssh, name,
759
0
          val, vlen)) != 0)
760
0
        return r;
761
0
    } else {
762
0
      if ((r = kex_ext_info_client_parse(ssh, name,
763
0
          val, vlen)) != 0)
764
0
        return r;
765
0
    }
766
0
    free(name);
767
0
    free(val);
768
0
  }
769
0
  return sshpkt_get_end(ssh);
770
0
}
771
772
static int
773
kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
774
0
{
775
0
  struct kex *kex = ssh->kex;
776
0
  int r, initial = (kex->flags & KEX_INITIAL) != 0;
777
0
  char *cp, **prop;
778
779
0
  debug("SSH2_MSG_NEWKEYS received");
780
0
  if (kex->ext_info_c && initial)
781
0
    ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info);
782
0
  ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
783
0
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
784
0
  if ((r = sshpkt_get_end(ssh)) != 0)
785
0
    return r;
786
0
  if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
787
0
    return r;
788
0
  if (initial) {
789
    /* Remove initial KEX signalling from proposal for rekeying */
790
0
    if ((r = kex_buf2prop(kex->my, NULL, &prop)) != 0)
791
0
      return r;
792
0
    if ((cp = match_filter_denylist(prop[PROPOSAL_KEX_ALGS],
793
0
        kex->server ?
794
0
        "ext-info-s,kex-strict-s-v00@openssh.com" :
795
0
        "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) {
796
0
      error_f("match_filter_denylist failed");
797
0
      goto fail;
798
0
    }
799
0
    free(prop[PROPOSAL_KEX_ALGS]);
800
0
    prop[PROPOSAL_KEX_ALGS] = cp;
801
0
    if ((r = kex_prop2buf(ssh->kex->my, prop)) != 0) {
802
0
      error_f("kex_prop2buf failed");
803
0
 fail:
804
0
      kex_proposal_free_entries(prop);
805
0
      free(prop);
806
0
      return SSH_ERR_INTERNAL_ERROR;
807
0
    }
808
0
    kex_proposal_free_entries(prop);
809
0
    free(prop);
810
0
  }
811
0
  kex->done = 1;
812
0
  kex->flags &= ~KEX_INITIAL;
813
0
  sshbuf_reset(kex->peer);
814
0
  kex->flags &= ~KEX_INIT_SENT;
815
0
  free(kex->name);
816
0
  kex->name = NULL;
817
0
  return 0;
818
0
}
819
820
int
821
kex_send_kexinit(struct ssh *ssh)
822
20.0k
{
823
20.0k
  u_char *cookie;
824
20.0k
  struct kex *kex = ssh->kex;
825
20.0k
  int r;
826
827
20.0k
  if (kex == NULL) {
828
0
    error_f("no kex");
829
0
    return SSH_ERR_INTERNAL_ERROR;
830
0
  }
831
20.0k
  if (kex->flags & KEX_INIT_SENT)
832
0
    return 0;
833
20.0k
  kex->done = 0;
834
835
  /* generate a random cookie */
836
20.0k
  if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) {
837
0
    error_f("bad kex length: %zu < %d",
838
0
        sshbuf_len(kex->my), KEX_COOKIE_LEN);
839
0
    return SSH_ERR_INVALID_FORMAT;
840
0
  }
841
20.0k
  if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
842
0
    error_f("buffer error");
843
0
    return SSH_ERR_INTERNAL_ERROR;
844
0
  }
845
20.0k
  arc4random_buf(cookie, KEX_COOKIE_LEN);
846
847
20.0k
  if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
848
20.0k
      (r = sshpkt_putb(ssh, kex->my)) != 0 ||
849
20.0k
      (r = sshpkt_send(ssh)) != 0) {
850
0
    error_fr(r, "compose reply");
851
0
    return r;
852
0
  }
853
20.0k
  debug("SSH2_MSG_KEXINIT sent");
854
20.0k
  kex->flags |= KEX_INIT_SENT;
855
20.0k
  return 0;
856
20.0k
}
857
858
int
859
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
860
9.34k
{
861
9.34k
  struct kex *kex = ssh->kex;
862
9.34k
  const u_char *ptr;
863
9.34k
  u_int i;
864
9.34k
  size_t dlen;
865
9.34k
  int r;
866
867
9.34k
  debug("SSH2_MSG_KEXINIT received");
868
9.34k
  if (kex == NULL) {
869
0
    error_f("no kex");
870
0
    return SSH_ERR_INTERNAL_ERROR;
871
0
  }
872
9.34k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
873
9.34k
  ptr = sshpkt_ptr(ssh, &dlen);
874
9.34k
  if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
875
0
    return r;
876
877
  /* discard packet */
878
149k
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
879
141k
    if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
880
940
      error_fr(r, "discard cookie");
881
940
      return r;
882
940
    }
883
141k
  }
884
55.2k
  for (i = 0; i < PROPOSAL_MAX; i++) {
885
51.1k
    if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
886
4.36k
      error_fr(r, "discard proposal");
887
4.36k
      return r;
888
4.36k
    }
889
51.1k
  }
890
  /*
891
   * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
892
   * KEX method has the server move first, but a server might be using
893
   * a custom method or one that we otherwise don't support. We should
894
   * be prepared to remember first_kex_follows here so we can eat a
895
   * packet later.
896
   * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
897
   * for cases where the server *doesn't* go first. I guess we should
898
   * ignore it when it is set for these cases, which is what we do now.
899
   */
900
4.04k
  if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
901
4.04k
      (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
902
4.04k
      (r = sshpkt_get_end(ssh)) != 0)
903
440
      return r;
904
905
3.60k
  if (!(kex->flags & KEX_INIT_SENT))
906
0
    if ((r = kex_send_kexinit(ssh)) != 0)
907
0
      return r;
908
3.60k
  if ((r = kex_choose_conf(ssh, seq)) != 0)
909
3.60k
    return r;
910
911
0
  if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
912
0
    return (kex->kex[kex->kex_type])(ssh);
913
914
0
  error_f("unknown kex type %u", kex->kex_type);
915
0
  return SSH_ERR_INTERNAL_ERROR;
916
0
}
917
918
struct kex *
919
kex_new(void)
920
70.0k
{
921
70.0k
  struct kex *kex;
922
923
70.0k
  if ((kex = calloc(1, sizeof(*kex))) == NULL ||
924
70.0k
      (kex->peer = sshbuf_new()) == NULL ||
925
70.0k
      (kex->my = sshbuf_new()) == NULL ||
926
70.0k
      (kex->client_version = sshbuf_new()) == NULL ||
927
70.0k
      (kex->server_version = sshbuf_new()) == NULL ||
928
70.0k
      (kex->session_id = sshbuf_new()) == NULL) {
929
0
    kex_free(kex);
930
0
    return NULL;
931
0
  }
932
70.0k
  return kex;
933
70.0k
}
934
935
void
936
kex_free_newkeys(struct newkeys *newkeys)
937
280k
{
938
280k
  if (newkeys == NULL)
939
280k
    return;
940
116
  if (newkeys->enc.key) {
941
0
    explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
942
0
    free(newkeys->enc.key);
943
0
    newkeys->enc.key = NULL;
944
0
  }
945
116
  if (newkeys->enc.iv) {
946
0
    explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
947
0
    free(newkeys->enc.iv);
948
0
    newkeys->enc.iv = NULL;
949
0
  }
950
116
  free(newkeys->enc.name);
951
116
  explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
952
116
  free(newkeys->comp.name);
953
116
  explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
954
116
  mac_clear(&newkeys->mac);
955
116
  if (newkeys->mac.key) {
956
0
    explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
957
0
    free(newkeys->mac.key);
958
0
    newkeys->mac.key = NULL;
959
0
  }
960
116
  free(newkeys->mac.name);
961
116
  explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
962
116
  freezero(newkeys, sizeof(*newkeys));
963
116
}
964
965
void
966
kex_free(struct kex *kex)
967
70.0k
{
968
70.0k
  u_int mode;
969
970
70.0k
  if (kex == NULL)
971
0
    return;
972
973
70.0k
#ifdef WITH_OPENSSL
974
70.0k
  DH_free(kex->dh);
975
70.0k
#ifdef OPENSSL_HAS_ECC
976
70.0k
  EC_KEY_free(kex->ec_client_key);
977
70.0k
#endif /* OPENSSL_HAS_ECC */
978
70.0k
#endif /* WITH_OPENSSL */
979
210k
  for (mode = 0; mode < MODE_MAX; mode++) {
980
140k
    kex_free_newkeys(kex->newkeys[mode]);
981
140k
    kex->newkeys[mode] = NULL;
982
140k
  }
983
70.0k
  sshbuf_free(kex->peer);
984
70.0k
  sshbuf_free(kex->my);
985
70.0k
  sshbuf_free(kex->client_version);
986
70.0k
  sshbuf_free(kex->server_version);
987
70.0k
  sshbuf_free(kex->client_pub);
988
70.0k
  sshbuf_free(kex->session_id);
989
70.0k
  sshbuf_free(kex->initial_sig);
990
70.0k
  sshkey_free(kex->initial_hostkey);
991
70.0k
  free(kex->failed_choice);
992
70.0k
  free(kex->hostkey_alg);
993
70.0k
  free(kex->name);
994
70.0k
  free(kex);
995
70.0k
}
996
997
/*
998
 * This function seeks through a comma-separated list and checks for instances
999
 * of the multithreaded CC20 cipher. If found, it then ensures that the serial
1000
 * CC20 cipher is also in the list, adding it if necessary.
1001
 */
1002
char *
1003
patch_list(char * orig)
1004
140k
{
1005
140k
  char * adj = xstrdup(orig);
1006
140k
  char * match;
1007
140k
  u_int next;
1008
1009
140k
  const char * ccpstr = "chacha20-poly1305@openssh.com";
1010
140k
  const char * ccpmtstr = "chacha20-poly1305-mt@hpnssh.org";
1011
1012
140k
  match = match_list(ccpmtstr, orig, &next);
1013
140k
  if (match != NULL) { /* CC20-MT found in the list */
1014
0
    free(match);
1015
0
    match = match_list(ccpstr, orig, NULL);
1016
0
    if (match == NULL) { /* CC20-Serial NOT found in the list */
1017
0
      adj = xreallocarray(adj,
1018
0
          strlen(adj) /* original string length */
1019
0
          + 1 /* for the original null-terminator */
1020
0
          + strlen(ccpstr) /* make room for ccpstr */
1021
0
          + 1 /* make room for the comma delimiter */
1022
0
          , sizeof(char));
1023
      /*
1024
       * adj[next] points to the character after the CC20-MT
1025
       * string. adj[next] might be ',' or '\0' at this point.
1026
       */
1027
0
      adj[next] = ',';
1028
      /* adj + next + 1 is the character after that comma */
1029
0
      memcpy(adj + next + 1, ccpstr, strlen(ccpstr));
1030
      /* rewrite the rest of the original list */
1031
0
      memcpy(adj + next + 1 + strlen(ccpstr), orig + next,
1032
0
          strlen(orig + next) + 1);
1033
0
    } else { /* CC20-Serial found in the list, nothing to do */
1034
0
      free(match);
1035
0
    }
1036
0
  }
1037
1038
140k
  return adj;
1039
140k
}
1040
1041
int
1042
kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
1043
70.0k
{
1044
70.0k
  int r = 0;
1045
1046
70.0k
#ifdef WITH_OPENSSL
1047
70.0k
  char * orig_ctos = proposal[PROPOSAL_ENC_ALGS_CTOS];
1048
70.0k
  char * orig_stoc = proposal[PROPOSAL_ENC_ALGS_STOC];
1049
70.0k
  proposal[PROPOSAL_ENC_ALGS_CTOS] =
1050
70.0k
      patch_list(proposal[PROPOSAL_ENC_ALGS_CTOS]);
1051
70.0k
  proposal[PROPOSAL_ENC_ALGS_STOC] =
1052
70.0k
      patch_list(proposal[PROPOSAL_ENC_ALGS_STOC]);
1053
1054
  /*
1055
   * TODO: Likely memory leak here. The original contents of
1056
   * proposal[PROPOSAL_ENC_ALGS_CTOS] are no longer accessible or
1057
   * freeable.
1058
   */
1059
70.0k
#endif
1060
1061
70.0k
  if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
1062
0
    goto restoreProposal;
1063
70.0k
  ssh->kex->flags = KEX_INITIAL;
1064
70.0k
  kex_reset_dispatch(ssh);
1065
70.0k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
1066
70.0k
 restoreProposal:
1067
70.0k
#ifdef WITH_OPENSSL
1068
70.0k
  free(proposal[PROPOSAL_ENC_ALGS_CTOS]);
1069
70.0k
  free(proposal[PROPOSAL_ENC_ALGS_STOC]);
1070
70.0k
  proposal[PROPOSAL_ENC_ALGS_CTOS] = orig_ctos;
1071
70.0k
  proposal[PROPOSAL_ENC_ALGS_STOC] = orig_stoc;
1072
70.0k
#endif
1073
70.0k
  return r;
1074
70.0k
}
1075
1076
int
1077
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
1078
0
{
1079
0
  int r;
1080
1081
0
  if ((r = kex_ready(ssh, proposal)) != 0)
1082
0
    return r;
1083
0
  if ((r = kex_send_kexinit(ssh)) != 0) {   /* we start */
1084
0
    kex_free(ssh->kex);
1085
0
    ssh->kex = NULL;
1086
0
    return r;
1087
0
  }
1088
0
  return 0;
1089
0
}
1090
1091
/*
1092
 * Request key re-exchange, returns 0 on success or a ssherr.h error
1093
 * code otherwise. Must not be called if KEX is incomplete or in-progress.
1094
 */
1095
int
1096
kex_start_rekex(struct ssh *ssh)
1097
0
{
1098
0
  if (ssh->kex == NULL) {
1099
0
    error_f("no kex");
1100
0
    return SSH_ERR_INTERNAL_ERROR;
1101
0
  }
1102
0
  if (ssh->kex->done == 0) {
1103
0
    error_f("requested twice");
1104
0
    return SSH_ERR_INTERNAL_ERROR;
1105
0
  }
1106
0
  ssh->kex->done = 0;
1107
0
  return kex_send_kexinit(ssh);
1108
0
}
1109
1110
static int
1111
choose_enc(struct sshenc *enc, char *client, char *server)
1112
116
{
1113
116
  char *name = match_list(client, server, NULL);
1114
1115
116
  if (name == NULL)
1116
19
    return SSH_ERR_NO_CIPHER_ALG_MATCH;
1117
97
  if ((enc->cipher = cipher_by_name(name)) == NULL) {
1118
0
    error_f("unsupported cipher %s", name);
1119
0
    free(name);
1120
0
    return SSH_ERR_INTERNAL_ERROR;
1121
0
  }
1122
97
  enc->name = name;
1123
97
  enc->enabled = 0;
1124
97
  enc->iv = NULL;
1125
97
  enc->iv_len = cipher_ivlen(enc->cipher);
1126
97
  enc->key = NULL;
1127
97
  enc->key_len = cipher_keylen(enc->cipher);
1128
97
  enc->block_size = cipher_blocksize(enc->cipher);
1129
97
  return 0;
1130
97
}
1131
1132
static int
1133
choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
1134
97
{
1135
97
  char *name = match_list(client, server, NULL);
1136
1137
97
  if (name == NULL)
1138
17
    return SSH_ERR_NO_MAC_ALG_MATCH;
1139
80
  if (mac_setup(mac, name) < 0) {
1140
0
    error_f("unsupported MAC %s", name);
1141
0
    free(name);
1142
0
    return SSH_ERR_INTERNAL_ERROR;
1143
0
  }
1144
80
  mac->name = name;
1145
80
  mac->key = NULL;
1146
80
  mac->enabled = 0;
1147
80
  return 0;
1148
80
}
1149
1150
static int
1151
choose_comp(struct sshcomp *comp, char *client, char *server)
1152
80
{
1153
80
  char *name = match_list(client, server, NULL);
1154
1155
80
  if (name == NULL)
1156
80
    return SSH_ERR_NO_COMPRESS_ALG_MATCH;
1157
0
#ifdef WITH_ZLIB
1158
0
  if (strcmp(name, "zlib@openssh.com") == 0) {
1159
0
    comp->type = COMP_DELAYED;
1160
0
  } else if (strcmp(name, "zlib") == 0) {
1161
0
    comp->type = COMP_ZLIB;
1162
0
  } else
1163
0
#endif  /* WITH_ZLIB */
1164
0
  if (strcmp(name, "none") == 0) {
1165
0
    comp->type = COMP_NONE;
1166
0
  } else {
1167
0
    error_f("unsupported compression scheme %s", name);
1168
0
    free(name);
1169
0
    return SSH_ERR_INTERNAL_ERROR;
1170
0
  }
1171
0
  comp->name = name;
1172
0
  return 0;
1173
0
}
1174
1175
static int
1176
choose_kex(struct kex *k, char *client, char *server)
1177
3.34k
{
1178
3.34k
  const struct kexalg *kexalg;
1179
1180
3.34k
  k->name = match_list(client, server, NULL);
1181
1182
3.34k
  debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
1183
3.34k
  if (k->name == NULL)
1184
2.83k
    return SSH_ERR_NO_KEX_ALG_MATCH;
1185
504
  if ((kexalg = kex_alg_by_name(k->name)) == NULL) {
1186
0
    error_f("unsupported KEX method %s", k->name);
1187
0
    return SSH_ERR_INTERNAL_ERROR;
1188
0
  }
1189
504
  k->kex_type = kexalg->type;
1190
504
  k->hash_alg = kexalg->hash_alg;
1191
504
  k->ec_nid = kexalg->ec_nid;
1192
504
  return 0;
1193
504
}
1194
1195
static int
1196
choose_hostkeyalg(struct kex *k, char *client, char *server)
1197
504
{
1198
504
  free(k->hostkey_alg);
1199
504
  k->hostkey_alg = match_list(client, server, NULL);
1200
1201
504
  debug("kex: host key algorithm: %s",
1202
504
      k->hostkey_alg ? k->hostkey_alg : "(no match)");
1203
504
  if (k->hostkey_alg == NULL)
1204
388
    return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
1205
116
  k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
1206
116
  if (k->hostkey_type == KEY_UNSPEC) {
1207
0
    error_f("unsupported hostkey algorithm %s", k->hostkey_alg);
1208
0
    return SSH_ERR_INTERNAL_ERROR;
1209
0
  }
1210
116
  k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
1211
116
  return 0;
1212
116
}
1213
1214
static int
1215
proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
1216
0
{
1217
0
  static int check[] = {
1218
0
    PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
1219
0
  };
1220
0
  int *idx;
1221
0
  char *p;
1222
1223
0
  for (idx = &check[0]; *idx != -1; idx++) {
1224
0
    if ((p = strchr(my[*idx], ',')) != NULL)
1225
0
      *p = '\0';
1226
0
    if ((p = strchr(peer[*idx], ',')) != NULL)
1227
0
      *p = '\0';
1228
0
    if (strcmp(my[*idx], peer[*idx]) != 0) {
1229
0
      debug2("proposal mismatch: my %s peer %s",
1230
0
          my[*idx], peer[*idx]);
1231
0
      return (0);
1232
0
    }
1233
0
  }
1234
0
  debug2("proposals match");
1235
0
  return (1);
1236
0
}
1237
1238
static int
1239
kexalgs_contains(char **peer, const char *ext)
1240
6.68k
{
1241
6.68k
  return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
1242
6.68k
}
1243
1244
static int
1245
kex_choose_conf(struct ssh *ssh, uint32_t seq)
1246
3.60k
{
1247
3.60k
  struct kex *kex = ssh->kex;
1248
3.60k
  struct newkeys *newkeys;
1249
3.60k
  char **my = NULL, **peer = NULL;
1250
3.60k
  char **cprop, **sprop;
1251
3.60k
  int nenc, nmac, ncomp;
1252
3.60k
  u_int mode, ctos, need, dh_need, authlen;
1253
3.60k
  int r, first_kex_follows;
1254
3.60k
  int auth_flag = 0;
1255
3.60k
  int log_flag = 0;
1256
1257
3.60k
  auth_flag = packet_authentication_state(ssh);
1258
3.60k
  debug("AUTH STATE IS %d", auth_flag);
1259
1260
3.60k
  debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
1261
3.60k
  if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
1262
0
    goto out;
1263
3.60k
  debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
1264
3.60k
  if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
1265
260
    goto out;
1266
1267
3.34k
  if (kex->server) {
1268
1.22k
    cprop=peer;
1269
1.22k
    sprop=my;
1270
2.12k
  } else {
1271
2.12k
    cprop=my;
1272
2.12k
    sprop=peer;
1273
2.12k
  }
1274
1275
  /* Check whether peer supports ext_info/kex_strict */
1276
3.34k
  if ((kex->flags & KEX_INITIAL) != 0) {
1277
3.34k
    if (kex->server) {
1278
1.22k
      kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
1279
1.22k
      kex->kex_strict = kexalgs_contains(peer,
1280
1.22k
          "kex-strict-c-v00@openssh.com");
1281
2.12k
    } else {
1282
2.12k
      kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
1283
2.12k
      kex->kex_strict = kexalgs_contains(peer,
1284
2.12k
          "kex-strict-s-v00@openssh.com");
1285
2.12k
    }
1286
3.34k
    if (kex->kex_strict) {
1287
0
      debug3_f("will use strict KEX ordering");
1288
0
      if (seq != 0)
1289
0
        ssh_packet_disconnect(ssh,
1290
0
            "strict KEX violation: "
1291
0
            "KEXINIT was not the first packet");
1292
0
    }
1293
3.34k
  }
1294
1295
  /* Check whether client supports rsa-sha2 algorithms */
1296
3.34k
  if (kex->server && (kex->flags & KEX_INITIAL)) {
1297
1.22k
    if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
1298
1.22k
        "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
1299
0
      kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
1300
1.22k
    if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
1301
1.22k
        "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
1302
0
      kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
1303
1.22k
  }
1304
1305
  /* Algorithm Negotiation */
1306
3.34k
  if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
1307
3.34k
      sprop[PROPOSAL_KEX_ALGS])) != 0) {
1308
2.83k
    kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
1309
2.83k
    peer[PROPOSAL_KEX_ALGS] = NULL;
1310
2.83k
    goto out;
1311
2.83k
  }
1312
504
  if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
1313
504
      sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
1314
388
    kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
1315
388
    peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
1316
388
    goto out;
1317
388
  }
1318
116
  for (mode = 0; mode < MODE_MAX; mode++) {
1319
116
    if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
1320
0
      r = SSH_ERR_ALLOC_FAIL;
1321
0
      goto out;
1322
0
    }
1323
116
    kex->newkeys[mode] = newkeys;
1324
116
    ctos = (!kex->server && mode == MODE_OUT) ||
1325
116
        (kex->server && mode == MODE_IN);
1326
116
    nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
1327
116
    nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
1328
116
    ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
1329
116
    if ((r = choose_enc(&newkeys->enc, cprop[nenc],
1330
116
        sprop[nenc])) != 0) {
1331
19
      kex->failed_choice = peer[nenc];
1332
19
      peer[nenc] = NULL;
1333
19
      goto out;
1334
19
    }
1335
97
#ifdef WITH_OPENSSL
1336
97
    if ((strcmp(newkeys->enc.name, "chacha20-poly1305@openssh.com")
1337
97
        == 0) && (match_list("chacha20-poly1305-mt@hpnssh.org",
1338
0
        my[nenc], NULL) != NULL)) {
1339
      /*
1340
       * if we're using the serial CC20 cipher while the
1341
       * multithreaded implementation is an option...
1342
       */
1343
0
      free(newkeys->enc.name);
1344
0
      newkeys->enc.cipher = cipher_by_name(
1345
0
          "chacha20-poly1305-mt@hpnssh.org");
1346
0
      if (newkeys->enc.cipher == NULL) {
1347
0
        error_f("%s cipher not found.",
1348
0
            "chacha20-poly1305-mt@hpnssh.org");
1349
0
        r = SSH_ERR_INTERNAL_ERROR;
1350
0
        kex->failed_choice = peer[nenc];
1351
0
        peer[nenc] = NULL;
1352
0
        goto out;
1353
0
      } else {
1354
0
        newkeys->enc.name = xstrdup(
1355
0
            "chacha20-poly1305-mt@hpnssh.org");
1356
0
      }
1357
      /* we promote to the multithreaded implementation */
1358
0
    }
1359
97
#endif
1360
97
    authlen = cipher_authlen(newkeys->enc.cipher);
1361
    /* ignore mac for authenticated encryption */
1362
97
    if (authlen == 0 &&
1363
97
        (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
1364
97
        sprop[nmac])) != 0) {
1365
17
      kex->failed_choice = peer[nmac];
1366
17
      peer[nmac] = NULL;
1367
17
      goto out;
1368
17
    }
1369
80
    if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
1370
80
        sprop[ncomp])) != 0) {
1371
80
      kex->failed_choice = peer[ncomp];
1372
80
      peer[ncomp] = NULL;
1373
80
      goto out;
1374
80
    }
1375
0
    debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
1376
0
    debug("REQUESTED MAC.NAME is '%s'", newkeys->mac.name);
1377
0
    if (strcmp(newkeys->enc.name, "none") == 0) {
1378
0
      if (auth_flag == 1) {
1379
0
        debug("None requested post authentication.");
1380
0
        ssh->none = 1;
1381
0
      }
1382
0
      else
1383
0
        fatal("Pre-authentication none cipher requests are not allowed.");
1384
1385
0
      if (newkeys->mac.name != NULL && strcmp(newkeys->mac.name, "none") == 0) {
1386
0
        debug("Requesting: NONEMAC. Authflag is %d", auth_flag);
1387
0
        ssh->none_mac = 1;
1388
0
      }
1389
0
    }
1390
1391
0
    debug("kex: %s cipher: %s MAC: %s compression: %s",
1392
0
        ctos ? "client->server" : "server->client",
1393
0
        newkeys->enc.name,
1394
0
        authlen == 0 ? newkeys->mac.name : "<implicit>",
1395
0
        newkeys->comp.name);
1396
    /*
1397
     * client starts with ctos = 0 && log flag = 0 and no log.
1398
     * 2nd client pass ctos = 1 and flag = 1 so no log.
1399
     * server starts with ctos = 1 && log_flag = 0 so log.
1400
     * 2nd sever pass ctos = 1 && log flag = 1 so no log.
1401
     * -cjr
1402
     */
1403
0
    if (ctos && !log_flag) {
1404
0
      logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s",
1405
0
          ssh_remote_ipaddr(ssh),
1406
0
          ssh_remote_port(ssh),
1407
0
          newkeys->enc.name,
1408
0
          authlen == 0 ? newkeys->mac.name : "<implicit>",
1409
0
          newkeys->comp.name);
1410
0
    }
1411
0
    log_flag = 1;
1412
0
  }
1413
0
  need = dh_need = 0;
1414
0
  for (mode = 0; mode < MODE_MAX; mode++) {
1415
0
    newkeys = kex->newkeys[mode];
1416
0
    need = MAXIMUM(need, newkeys->enc.key_len);
1417
0
    need = MAXIMUM(need, newkeys->enc.block_size);
1418
0
    need = MAXIMUM(need, newkeys->enc.iv_len);
1419
0
    need = MAXIMUM(need, newkeys->mac.key_len);
1420
0
    dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
1421
0
    dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
1422
0
    dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
1423
0
    dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
1424
0
  }
1425
  /* XXX need runden? */
1426
0
  kex->we_need = need;
1427
0
  kex->dh_need = dh_need;
1428
1429
  /* ignore the next message if the proposals do not match */
1430
0
  if (first_kex_follows && !proposals_match(my, peer))
1431
0
    ssh->dispatch_skip_packets = 1;
1432
0
  r = 0;
1433
3.60k
 out:
1434
3.60k
  kex_prop_free(my);
1435
3.60k
  kex_prop_free(peer);
1436
3.60k
  return r;
1437
0
}
1438
1439
static int
1440
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
1441
    const struct sshbuf *shared_secret, u_char **keyp)
1442
0
{
1443
0
  struct kex *kex = ssh->kex;
1444
0
  struct ssh_digest_ctx *hashctx = NULL;
1445
0
  char c = id;
1446
0
  u_int have;
1447
0
  size_t mdsz;
1448
0
  u_char *digest;
1449
0
  int r;
1450
1451
0
  if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
1452
0
    return SSH_ERR_INVALID_ARGUMENT;
1453
0
  if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
1454
0
    r = SSH_ERR_ALLOC_FAIL;
1455
0
    goto out;
1456
0
  }
1457
1458
  /* K1 = HASH(K || H || "A" || session_id) */
1459
0
  if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1460
0
      ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1461
0
      ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1462
0
      ssh_digest_update(hashctx, &c, 1) != 0 ||
1463
0
      ssh_digest_update_buffer(hashctx, kex->session_id) != 0 ||
1464
0
      ssh_digest_final(hashctx, digest, mdsz) != 0) {
1465
0
    r = SSH_ERR_LIBCRYPTO_ERROR;
1466
0
    error_f("KEX hash failed");
1467
0
    goto out;
1468
0
  }
1469
0
  ssh_digest_free(hashctx);
1470
0
  hashctx = NULL;
1471
1472
  /*
1473
   * expand key:
1474
   * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
1475
   * Key = K1 || K2 || ... || Kn
1476
   */
1477
0
  for (have = mdsz; need > have; have += mdsz) {
1478
0
    if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
1479
0
        ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
1480
0
        ssh_digest_update(hashctx, hash, hashlen) != 0 ||
1481
0
        ssh_digest_update(hashctx, digest, have) != 0 ||
1482
0
        ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
1483
0
      error_f("KDF failed");
1484
0
      r = SSH_ERR_LIBCRYPTO_ERROR;
1485
0
      goto out;
1486
0
    }
1487
0
    ssh_digest_free(hashctx);
1488
0
    hashctx = NULL;
1489
0
  }
1490
#ifdef DEBUG_KEX
1491
  fprintf(stderr, "key '%c'== ", c);
1492
  dump_digest("key", digest, need);
1493
#endif
1494
0
  *keyp = digest;
1495
0
  digest = NULL;
1496
0
  r = 0;
1497
0
 out:
1498
0
  free(digest);
1499
0
  ssh_digest_free(hashctx);
1500
0
  return r;
1501
0
}
1502
1503
0
#define NKEYS 6
1504
int
1505
kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
1506
    const struct sshbuf *shared_secret)
1507
0
{
1508
0
  struct kex *kex = ssh->kex;
1509
0
  u_char *keys[NKEYS];
1510
0
  u_int i, j, mode, ctos;
1511
0
  int r;
1512
1513
  /* save initial hash as session id */
1514
0
  if ((kex->flags & KEX_INITIAL) != 0) {
1515
0
    if (sshbuf_len(kex->session_id) != 0) {
1516
0
      error_f("already have session ID at kex");
1517
0
      return SSH_ERR_INTERNAL_ERROR;
1518
0
    }
1519
0
    if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0)
1520
0
      return r;
1521
0
  } else if (sshbuf_len(kex->session_id) == 0) {
1522
0
    error_f("no session ID in rekex");
1523
0
    return SSH_ERR_INTERNAL_ERROR;
1524
0
  }
1525
0
  for (i = 0; i < NKEYS; i++) {
1526
0
    if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
1527
0
        shared_secret, &keys[i])) != 0) {
1528
0
      for (j = 0; j < i; j++)
1529
0
        free(keys[j]);
1530
0
      return r;
1531
0
    }
1532
0
  }
1533
0
  for (mode = 0; mode < MODE_MAX; mode++) {
1534
0
    ctos = (!kex->server && mode == MODE_OUT) ||
1535
0
        (kex->server && mode == MODE_IN);
1536
0
    kex->newkeys[mode]->enc.iv  = keys[ctos ? 0 : 1];
1537
0
    kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
1538
0
    kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
1539
0
  }
1540
0
  return 0;
1541
0
}
1542
1543
int
1544
kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
1545
0
{
1546
0
  struct kex *kex = ssh->kex;
1547
1548
0
  *pubp = NULL;
1549
0
  *prvp = NULL;
1550
0
  if (kex->load_host_public_key == NULL ||
1551
0
      kex->load_host_private_key == NULL) {
1552
0
    error_f("missing hostkey loader");
1553
0
    return SSH_ERR_INVALID_ARGUMENT;
1554
0
  }
1555
0
  *pubp = kex->load_host_public_key(kex->hostkey_type,
1556
0
      kex->hostkey_nid, ssh);
1557
0
  *prvp = kex->load_host_private_key(kex->hostkey_type,
1558
0
      kex->hostkey_nid, ssh);
1559
0
  if (*pubp == NULL)
1560
0
    return SSH_ERR_NO_HOSTKEY_LOADED;
1561
0
  return 0;
1562
0
}
1563
1564
int
1565
kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
1566
0
{
1567
0
  struct kex *kex = ssh->kex;
1568
1569
0
  if (kex->verify_host_key == NULL) {
1570
0
    error_f("missing hostkey verifier");
1571
0
    return SSH_ERR_INVALID_ARGUMENT;
1572
0
  }
1573
0
  if (server_host_key->type != kex->hostkey_type ||
1574
0
      (kex->hostkey_type == KEY_ECDSA &&
1575
0
      server_host_key->ecdsa_nid != kex->hostkey_nid))
1576
0
    return SSH_ERR_KEY_TYPE_MISMATCH;
1577
0
  if (kex->verify_host_key(server_host_key, ssh) == -1)
1578
0
    return  SSH_ERR_SIGNATURE_INVALID;
1579
0
  return 0;
1580
0
}
1581
1582
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
1583
void
1584
dump_digest(const char *msg, const u_char *digest, int len)
1585
{
1586
  fprintf(stderr, "%s\n", msg);
1587
  sshbuf_dump_data(digest, len, stderr);
1588
}
1589
#endif
1590
1591
/*
1592
 * Send a plaintext error message to the peer, suffixed by \r\n.
1593
 * Only used during banner exchange, and there only for the server.
1594
 */
1595
static void
1596
send_error(struct ssh *ssh, char *msg)
1597
0
{
1598
0
  char *crnl = "\r\n";
1599
1600
0
  if (!ssh->kex->server)
1601
0
    return;
1602
1603
0
  if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1604
0
      msg, strlen(msg)) != strlen(msg) ||
1605
0
      atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1606
0
      crnl, strlen(crnl)) != strlen(crnl))
1607
0
    error_f("write: %.100s", strerror(errno));
1608
0
}
1609
1610
/*
1611
 * Sends our identification string and waits for the peer's. Will block for
1612
 * up to timeout_ms (or indefinitely if timeout_ms <= 0).
1613
 * Returns on 0 success or a ssherr.h code on failure.
1614
 */
1615
int
1616
kex_exchange_identification(struct ssh *ssh, int timeout_ms,
1617
    const char *version_addendum)
1618
0
{
1619
0
  int remote_major, remote_minor, mismatch, oerrno = 0;
1620
0
  size_t len, n;
1621
0
  int r, expect_nl;
1622
0
  u_char c;
1623
0
  struct sshbuf *our_version = ssh->kex->server ?
1624
0
      ssh->kex->server_version : ssh->kex->client_version;
1625
0
  struct sshbuf *peer_version = ssh->kex->server ?
1626
0
      ssh->kex->client_version : ssh->kex->server_version;
1627
0
  char *our_version_string = NULL, *peer_version_string = NULL;
1628
0
  char *cp, *remote_version = NULL;
1629
1630
  /* Prepare and send our banner */
1631
0
  sshbuf_reset(our_version);
1632
0
  if (version_addendum != NULL && *version_addendum == '\0')
1633
0
    version_addendum = NULL;
1634
0
  if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n",
1635
0
      PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE,
1636
0
      version_addendum == NULL ? "" : " ",
1637
0
      version_addendum == NULL ? "" : version_addendum)) != 0) {
1638
0
    oerrno = errno;
1639
0
    error_fr(r, "sshbuf_putf");
1640
0
    goto out;
1641
0
  }
1642
1643
0
  if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1644
0
      sshbuf_mutable_ptr(our_version),
1645
0
      sshbuf_len(our_version)) != sshbuf_len(our_version)) {
1646
0
    oerrno = errno;
1647
0
    debug_f("write: %.100s", strerror(errno));
1648
0
    r = SSH_ERR_SYSTEM_ERROR;
1649
0
    goto out;
1650
0
  }
1651
0
  if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
1652
0
    oerrno = errno;
1653
0
    error_fr(r, "sshbuf_consume_end");
1654
0
    goto out;
1655
0
  }
1656
0
  our_version_string = sshbuf_dup_string(our_version);
1657
0
  if (our_version_string == NULL) {
1658
0
    error_f("sshbuf_dup_string failed");
1659
0
    r = SSH_ERR_ALLOC_FAIL;
1660
0
    goto out;
1661
0
  }
1662
0
  debug("Local version string %.100s", our_version_string);
1663
1664
  /* Read other side's version identification. */
1665
0
  for (n = 0; ; n++) {
1666
0
    if (n >= SSH_MAX_PRE_BANNER_LINES) {
1667
0
      send_error(ssh, "No SSH identification string "
1668
0
          "received.");
1669
0
      error_f("No SSH version received in first %u lines "
1670
0
          "from server", SSH_MAX_PRE_BANNER_LINES);
1671
0
      r = SSH_ERR_INVALID_FORMAT;
1672
0
      goto out;
1673
0
    }
1674
0
    sshbuf_reset(peer_version);
1675
0
    expect_nl = 0;
1676
0
    for (;;) {
1677
0
      if (timeout_ms > 0) {
1678
0
        r = waitrfd(ssh_packet_get_connection_in(ssh),
1679
0
            &timeout_ms, NULL);
1680
0
        if (r == -1 && errno == ETIMEDOUT) {
1681
0
          send_error(ssh, "Timed out waiting "
1682
0
              "for SSH identification string.");
1683
0
          error("Connection timed out during "
1684
0
              "banner exchange");
1685
0
          r = SSH_ERR_CONN_TIMEOUT;
1686
0
          goto out;
1687
0
        } else if (r == -1) {
1688
0
          oerrno = errno;
1689
0
          error_f("%s", strerror(errno));
1690
0
          r = SSH_ERR_SYSTEM_ERROR;
1691
0
          goto out;
1692
0
        }
1693
0
      }
1694
1695
0
      len = atomicio(read, ssh_packet_get_connection_in(ssh),
1696
0
          &c, 1);
1697
0
      if (len != 1 && errno == EPIPE) {
1698
0
        verbose_f("Connection closed by remote host");
1699
0
        r = SSH_ERR_CONN_CLOSED;
1700
0
        goto out;
1701
0
      } else if (len != 1) {
1702
0
        oerrno = errno;
1703
0
        error_f("read: %.100s", strerror(errno));
1704
0
        r = SSH_ERR_SYSTEM_ERROR;
1705
0
        goto out;
1706
0
      }
1707
0
      if (c == '\r') {
1708
0
        expect_nl = 1;
1709
0
        continue;
1710
0
      }
1711
0
      if (c == '\n')
1712
0
        break;
1713
0
      if (c == '\0' || expect_nl) {
1714
0
        verbose_f("banner line contains invalid "
1715
0
            "characters");
1716
0
        goto invalid;
1717
0
      }
1718
0
      if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
1719
0
        oerrno = errno;
1720
0
        error_fr(r, "sshbuf_put");
1721
0
        goto out;
1722
0
      }
1723
0
      if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
1724
0
        verbose_f("banner line too long");
1725
0
        goto invalid;
1726
0
      }
1727
0
    }
1728
    /* Is this an actual protocol banner? */
1729
0
    if (sshbuf_len(peer_version) > 4 &&
1730
0
        memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
1731
0
      break;
1732
    /* If not, then just log the line and continue */
1733
0
    if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
1734
0
      error_f("sshbuf_dup_string failed");
1735
0
      r = SSH_ERR_ALLOC_FAIL;
1736
0
      goto out;
1737
0
    }
1738
    /* Do not accept lines before the SSH ident from a client */
1739
0
    if (ssh->kex->server) {
1740
0
      verbose_f("client sent invalid protocol identifier "
1741
0
          "\"%.256s\"", cp);
1742
0
      free(cp);
1743
0
      goto invalid;
1744
0
    }
1745
0
    debug_f("banner line %zu: %s", n, cp);
1746
0
    free(cp);
1747
0
  }
1748
0
  peer_version_string = sshbuf_dup_string(peer_version);
1749
0
  if (peer_version_string == NULL)
1750
0
    fatal_f("sshbuf_dup_string failed");
1751
  /* XXX must be same size for sscanf */
1752
0
  if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
1753
0
    error_f("calloc failed");
1754
0
    r = SSH_ERR_ALLOC_FAIL;
1755
0
    goto out;
1756
0
  }
1757
1758
  /*
1759
   * Check that the versions match.  In future this might accept
1760
   * several versions and set appropriate flags to handle them.
1761
   */
1762
0
  if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
1763
0
      &remote_major, &remote_minor, remote_version) != 3) {
1764
0
    error("Bad remote protocol version identification: '%.100s'",
1765
0
        peer_version_string);
1766
0
 invalid:
1767
0
    send_error(ssh, "Invalid SSH identification string.");
1768
0
    r = SSH_ERR_INVALID_FORMAT;
1769
0
    goto out;
1770
0
  }
1771
1772
  /* report the version information to syslog if this is the server */
1773
0
        if (timeout_ms == -1) { /* only the server uses this value */
1774
0
    logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s",
1775
0
          ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1776
0
          remote_major, remote_minor, remote_version);
1777
0
  }
1778
1779
0
  debug("Remote protocol version %d.%d, remote software version %.100s",
1780
0
      remote_major, remote_minor, remote_version);
1781
0
  compat_banner(ssh, remote_version);
1782
0
  if (ssh->compat & SSH_HPNSSH)
1783
0
    debug("HPN to HPN Connection.");
1784
0
  else
1785
0
    debug("Non-HPN to HPN Connection.");
1786
1787
0
  if(ssh->compat & SSH_RESTRICT_WINDOW)
1788
0
    debug ("Window size restricted.");
1789
1790
0
  mismatch = 0;
1791
0
  switch (remote_major) {
1792
0
  case 2:
1793
0
    break;
1794
0
  case 1:
1795
0
    if (remote_minor != 99)
1796
0
      mismatch = 1;
1797
0
    break;
1798
0
  default:
1799
0
    mismatch = 1;
1800
0
    break;
1801
0
  }
1802
0
  if (mismatch) {
1803
0
    error("Protocol major versions differ: %d vs. %d",
1804
0
        PROTOCOL_MAJOR_2, remote_major);
1805
0
    send_error(ssh, "Protocol major versions differ.");
1806
0
    r = SSH_ERR_NO_PROTOCOL_VERSION;
1807
0
    goto out;
1808
0
  }
1809
1810
0
  if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
1811
0
    logit("probed from %s port %d with %s.  Don't panic.",
1812
0
        ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1813
0
        peer_version_string);
1814
0
    r = SSH_ERR_CONN_CLOSED; /* XXX */
1815
0
    goto out;
1816
0
  }
1817
0
  if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
1818
0
    logit("scanned from %s port %d with %s.  Don't panic.",
1819
0
        ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1820
0
        peer_version_string);
1821
0
    r = SSH_ERR_CONN_CLOSED; /* XXX */
1822
0
    goto out;
1823
0
  }
1824
  /* success */
1825
0
  r = 0;
1826
0
 out:
1827
0
  free(our_version_string);
1828
0
  free(peer_version_string);
1829
0
  free(remote_version);
1830
0
  if (r == SSH_ERR_SYSTEM_ERROR)
1831
0
    errno = oerrno;
1832
0
  return r;
1833
0
}