Coverage Report

Created: 2024-09-03 06:03

/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
516
{
149
516
  const struct kexalg *k;
150
151
5.35k
  for (k = kexalgs; k->name != NULL; k++) {
152
5.31k
    if (strcmp(k->name, name) == 0)
153
476
      return k;
154
5.31k
  }
155
40
  return NULL;
156
516
}
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
148k
{
185
148k
  char *cp;
186
187
148k
  if ((cp = match_list(proposal, algs, NULL)) == NULL)
188
148k
    return 0;
189
60
  free(cp);
190
60
  return 1;
191
148k
}
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
69.4k
{
200
69.4k
  char *ret = NULL, *tmp = NULL, *cp, *p;
201
69.4k
  size_t len;
202
203
69.4k
  if (a == NULL || *a == '\0')
204
0
    return strdup(b);
205
69.4k
  if (b == NULL || *b == '\0')
206
0
    return strdup(a);
207
69.4k
  if (strlen(b) > 1024*1024)
208
0
    return NULL;
209
69.4k
  len = strlen(a) + strlen(b) + 2;
210
69.4k
  if ((tmp = cp = strdup(b)) == NULL ||
211
69.4k
      (ret = calloc(1, len)) == NULL) {
212
0
    free(tmp);
213
0
    return NULL;
214
0
  }
215
69.4k
  strlcpy(ret, a, len);
216
208k
  for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
217
138k
    if (has_any_alg(ret, p))
218
0
      continue; /* Algorithm already present */
219
138k
    if (strlcat(ret, ",", len) >= len ||
220
138k
        strlcat(ret, p, len) >= len) {
221
0
      free(tmp);
222
0
      free(ret);
223
0
      return NULL; /* Shouldn't happen */
224
0
    }
225
138k
  }
226
69.4k
  free(tmp);
227
69.4k
  return ret;
228
69.4k
}
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
69.4k
{
344
69.4k
  const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER };
345
69.4k
  const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT };
346
69.4k
  const char **defprop = ssh->kex->server ? defpropserver : defpropclient;
347
69.4k
  u_int i;
348
69.4k
  char *cp;
349
350
69.4k
  if (prop == NULL)
351
0
    fatal_f("proposal missing");
352
353
  /* Append EXT_INFO signalling to KexAlgorithms */
354
69.4k
  if (kexalgos == NULL)
355
0
    kexalgos = defprop[PROPOSAL_KEX_ALGS];
356
69.4k
  if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
357
34.7k
      "ext-info-s,kex-strict-s-v00@openssh.com" :
358
69.4k
      "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
359
0
    fatal_f("kex_names_cat");
360
361
763k
  for (i = 0; i < PROPOSAL_MAX; i++) {
362
694k
    switch(i) {
363
69.4k
    case PROPOSAL_KEX_ALGS:
364
69.4k
      prop[i] = compat_kex_proposal(ssh, cp);
365
69.4k
      break;
366
69.4k
    case PROPOSAL_ENC_ALGS_CTOS:
367
138k
    case PROPOSAL_ENC_ALGS_STOC:
368
138k
      prop[i] = xstrdup(ciphers ? ciphers : defprop[i]);
369
138k
      break;
370
69.4k
    case PROPOSAL_MAC_ALGS_CTOS:
371
138k
    case PROPOSAL_MAC_ALGS_STOC:
372
138k
      prop[i]  = xstrdup(macs ? macs : defprop[i]);
373
138k
      break;
374
69.4k
    case PROPOSAL_COMP_ALGS_CTOS:
375
138k
    case PROPOSAL_COMP_ALGS_STOC:
376
138k
      prop[i] = xstrdup(comp ? comp : defprop[i]);
377
138k
      break;
378
69.4k
    case PROPOSAL_SERVER_HOST_KEY_ALGS:
379
69.4k
      prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]);
380
69.4k
      break;
381
138k
    default:
382
138k
      prop[i] = xstrdup(defprop[i]);
383
694k
    }
384
694k
  }
385
69.4k
  free(cp);
386
69.4k
}
387
388
void
389
kex_proposal_free_entries(char *prop[PROPOSAL_MAX])
390
69.4k
{
391
69.4k
  u_int i;
392
393
763k
  for (i = 0; i < PROPOSAL_MAX; i++)
394
694k
    free(prop[i]);
395
69.4k
}
396
397
/* put algorithm proposal into buffer */
398
int
399
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
400
89.1k
{
401
89.1k
  u_int i;
402
89.1k
  int r;
403
404
89.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.51M
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
411
1.42M
    if ((r = sshbuf_put_u8(b, 0)) != 0)
412
0
      return r;
413
1.42M
  }
414
980k
  for (i = 0; i < PROPOSAL_MAX; i++) {
415
891k
    if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
416
0
      return r;
417
891k
  }
418
89.1k
  if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
419
89.1k
      (r = sshbuf_put_u32(b, 0)) != 0)  /* uint32 reserved */
420
0
    return r;
421
89.1k
  return 0;
422
89.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
280
      error_fr(r, "parse proposal %u", i);
449
280
      goto out;
450
280
    }
451
271k
    debug2("%s: %s", proposal_names[i], proposal[i]);
452
271k
  }
453
  /* first kex follows / reserved */
454
26.9k
  if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
455
26.9k
      (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
456
0
    error_fr(r, "parse");
457
0
    goto out;
458
0
  }
459
26.9k
  if (first_kex_follows != NULL)
460
3.48k
    *first_kex_follows = v;
461
26.9k
  debug2("first_kex_follows %d ", v);
462
26.9k
  debug2("reserved %u ", i);
463
26.9k
  r = 0;
464
26.9k
  *propp = proposal;
465
27.2k
 out:
466
27.2k
  if (r != 0 && proposal != NULL)
467
280
    kex_prop_free(proposal);
468
27.2k
  sshbuf_free(b);
469
27.2k
  return r;
470
26.9k
}
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
280
    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
69.4k
{
505
69.4k
  ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
506
69.4k
      SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
507
69.4k
}
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
19.7k
{
823
19.7k
  u_char *cookie;
824
19.7k
  struct kex *kex = ssh->kex;
825
19.7k
  int r;
826
827
19.7k
  if (kex == NULL) {
828
0
    error_f("no kex");
829
0
    return SSH_ERR_INTERNAL_ERROR;
830
0
  }
831
19.7k
  if (kex->flags & KEX_INIT_SENT)
832
0
    return 0;
833
19.7k
  kex->done = 0;
834
835
  /* generate a random cookie */
836
19.7k
  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
19.7k
  if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
842
0
    error_f("buffer error");
843
0
    return SSH_ERR_INTERNAL_ERROR;
844
0
  }
845
19.7k
  arc4random_buf(cookie, KEX_COOKIE_LEN);
846
847
19.7k
  if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
848
19.7k
      (r = sshpkt_putb(ssh, kex->my)) != 0 ||
849
19.7k
      (r = sshpkt_send(ssh)) != 0) {
850
0
    error_fr(r, "compose reply");
851
0
    return r;
852
0
  }
853
19.7k
  debug("SSH2_MSG_KEXINIT sent");
854
19.7k
  kex->flags |= KEX_INIT_SENT;
855
19.7k
  return 0;
856
19.7k
}
857
858
int
859
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
860
9.38k
{
861
9.38k
  struct kex *kex = ssh->kex;
862
9.38k
  const u_char *ptr;
863
9.38k
  u_int i;
864
9.38k
  size_t dlen;
865
9.38k
  int r;
866
867
9.38k
  debug("SSH2_MSG_KEXINIT received");
868
9.38k
  if (kex == NULL) {
869
0
    error_f("no kex");
870
0
    return SSH_ERR_INTERNAL_ERROR;
871
0
  }
872
9.38k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
873
9.38k
  ptr = sshpkt_ptr(ssh, &dlen);
874
9.38k
  if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
875
0
    return r;
876
877
  /* discard packet */
878
151k
  for (i = 0; i < KEX_COOKIE_LEN; i++) {
879
142k
    if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
880
820
      error_fr(r, "discard cookie");
881
820
      return r;
882
820
    }
883
142k
  }
884
57.9k
  for (i = 0; i < PROPOSAL_MAX; i++) {
885
53.7k
    if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
886
4.34k
      error_fr(r, "discard proposal");
887
4.34k
      return r;
888
4.34k
    }
889
53.7k
  }
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.22k
  if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
901
4.22k
      (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
902
4.22k
      (r = sshpkt_get_end(ssh)) != 0)
903
460
      return r;
904
905
3.76k
  if (!(kex->flags & KEX_INIT_SENT))
906
0
    if ((r = kex_send_kexinit(ssh)) != 0)
907
0
      return r;
908
3.76k
  if ((r = kex_choose_conf(ssh, seq)) != 0)
909
3.76k
    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
69.4k
{
921
69.4k
  struct kex *kex;
922
923
69.4k
  if ((kex = calloc(1, sizeof(*kex))) == NULL ||
924
69.4k
      (kex->peer = sshbuf_new()) == NULL ||
925
69.4k
      (kex->my = sshbuf_new()) == NULL ||
926
69.4k
      (kex->client_version = sshbuf_new()) == NULL ||
927
69.4k
      (kex->server_version = sshbuf_new()) == NULL ||
928
69.4k
      (kex->session_id = sshbuf_new()) == NULL) {
929
0
    kex_free(kex);
930
0
    return NULL;
931
0
  }
932
69.4k
  return kex;
933
69.4k
}
934
935
void
936
kex_free_newkeys(struct newkeys *newkeys)
937
277k
{
938
277k
  if (newkeys == NULL)
939
277k
    return;
940
107
  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
107
  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
107
  free(newkeys->enc.name);
951
107
  explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
952
107
  free(newkeys->comp.name);
953
107
  explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
954
107
  mac_clear(&newkeys->mac);
955
107
  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
107
  free(newkeys->mac.name);
961
107
  explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
962
107
  freezero(newkeys, sizeof(*newkeys));
963
107
}
964
965
void
966
kex_free(struct kex *kex)
967
69.4k
{
968
69.4k
  u_int mode;
969
970
69.4k
  if (kex == NULL)
971
0
    return;
972
973
69.4k
#ifdef WITH_OPENSSL
974
69.4k
  DH_free(kex->dh);
975
69.4k
#ifdef OPENSSL_HAS_ECC
976
69.4k
  EC_KEY_free(kex->ec_client_key);
977
69.4k
#endif /* OPENSSL_HAS_ECC */
978
69.4k
#endif /* WITH_OPENSSL */
979
208k
  for (mode = 0; mode < MODE_MAX; mode++) {
980
138k
    kex_free_newkeys(kex->newkeys[mode]);
981
138k
    kex->newkeys[mode] = NULL;
982
138k
  }
983
69.4k
  sshbuf_free(kex->peer);
984
69.4k
  sshbuf_free(kex->my);
985
69.4k
  sshbuf_free(kex->client_version);
986
69.4k
  sshbuf_free(kex->server_version);
987
69.4k
  sshbuf_free(kex->client_pub);
988
69.4k
  sshbuf_free(kex->session_id);
989
69.4k
  sshbuf_free(kex->initial_sig);
990
69.4k
  sshkey_free(kex->initial_hostkey);
991
69.4k
  free(kex->failed_choice);
992
69.4k
  free(kex->hostkey_alg);
993
69.4k
  free(kex->name);
994
69.4k
  free(kex);
995
69.4k
}
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
138k
{
1005
138k
  char * adj = xstrdup(orig);
1006
138k
  char * match;
1007
138k
  u_int next;
1008
1009
138k
  const char * ccpstr = "chacha20-poly1305@openssh.com";
1010
138k
  const char * ccpmtstr = "chacha20-poly1305-mt@hpnssh.org";
1011
1012
138k
  match = match_list(ccpmtstr, orig, &next);
1013
138k
  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
138k
  return adj;
1039
138k
}
1040
1041
int
1042
kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
1043
69.4k
{
1044
69.4k
  int r = 0;
1045
1046
69.4k
#ifdef WITH_OPENSSL
1047
69.4k
  char * orig_ctos = proposal[PROPOSAL_ENC_ALGS_CTOS];
1048
69.4k
  char * orig_stoc = proposal[PROPOSAL_ENC_ALGS_STOC];
1049
69.4k
  proposal[PROPOSAL_ENC_ALGS_CTOS] =
1050
69.4k
      patch_list(proposal[PROPOSAL_ENC_ALGS_CTOS]);
1051
69.4k
  proposal[PROPOSAL_ENC_ALGS_STOC] =
1052
69.4k
      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
69.4k
#endif
1060
1061
69.4k
  if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
1062
0
    goto restoreProposal;
1063
69.4k
  ssh->kex->flags = KEX_INITIAL;
1064
69.4k
  kex_reset_dispatch(ssh);
1065
69.4k
  ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
1066
69.4k
 restoreProposal:
1067
69.4k
#ifdef WITH_OPENSSL
1068
69.4k
  free(proposal[PROPOSAL_ENC_ALGS_CTOS]);
1069
69.4k
  free(proposal[PROPOSAL_ENC_ALGS_STOC]);
1070
69.4k
  proposal[PROPOSAL_ENC_ALGS_CTOS] = orig_ctos;
1071
69.4k
  proposal[PROPOSAL_ENC_ALGS_STOC] = orig_stoc;
1072
69.4k
#endif
1073
69.4k
  return r;
1074
69.4k
}
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
107
{
1113
107
  char *name = match_list(client, server, NULL);
1114
1115
107
  if (name == NULL)
1116
18
    return SSH_ERR_NO_CIPHER_ALG_MATCH;
1117
89
  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
89
  enc->name = name;
1123
89
  enc->enabled = 0;
1124
89
  enc->iv = NULL;
1125
89
  enc->iv_len = cipher_ivlen(enc->cipher);
1126
89
  enc->key = NULL;
1127
89
  enc->key_len = cipher_keylen(enc->cipher);
1128
89
  enc->block_size = cipher_blocksize(enc->cipher);
1129
89
  return 0;
1130
89
}
1131
1132
static int
1133
choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
1134
89
{
1135
89
  char *name = match_list(client, server, NULL);
1136
1137
89
  if (name == NULL)
1138
16
    return SSH_ERR_NO_MAC_ALG_MATCH;
1139
73
  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
73
  mac->name = name;
1145
73
  mac->key = NULL;
1146
73
  mac->enabled = 0;
1147
73
  return 0;
1148
73
}
1149
1150
static int
1151
choose_comp(struct sshcomp *comp, char *client, char *server)
1152
73
{
1153
73
  char *name = match_list(client, server, NULL);
1154
1155
73
  if (name == NULL)
1156
73
    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.48k
{
1178
3.48k
  const struct kexalg *kexalg;
1179
1180
3.48k
  k->name = match_list(client, server, NULL);
1181
1182
3.48k
  debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
1183
3.48k
  if (k->name == NULL)
1184
2.96k
    return SSH_ERR_NO_KEX_ALG_MATCH;
1185
516
  if ((kexalg = kex_alg_by_name(k->name)) == NULL) {
1186
40
    error_f("unsupported KEX method %s", k->name);
1187
40
    return SSH_ERR_INTERNAL_ERROR;
1188
40
  }
1189
476
  k->kex_type = kexalg->type;
1190
476
  k->hash_alg = kexalg->hash_alg;
1191
476
  k->ec_nid = kexalg->ec_nid;
1192
476
  return 0;
1193
516
}
1194
1195
static int
1196
choose_hostkeyalg(struct kex *k, char *client, char *server)
1197
476
{
1198
476
  free(k->hostkey_alg);
1199
476
  k->hostkey_alg = match_list(client, server, NULL);
1200
1201
476
  debug("kex: host key algorithm: %s",
1202
476
      k->hostkey_alg ? k->hostkey_alg : "(no match)");
1203
476
  if (k->hostkey_alg == NULL)
1204
369
    return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
1205
107
  k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
1206
107
  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
107
  k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
1211
107
  return 0;
1212
107
}
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.96k
{
1241
6.96k
  return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
1242
6.96k
}
1243
1244
static int
1245
kex_choose_conf(struct ssh *ssh, uint32_t seq)
1246
3.76k
{
1247
3.76k
  struct kex *kex = ssh->kex;
1248
3.76k
  struct newkeys *newkeys;
1249
3.76k
  char **my = NULL, **peer = NULL;
1250
3.76k
  char **cprop, **sprop;
1251
3.76k
  int nenc, nmac, ncomp;
1252
3.76k
  u_int mode, ctos, need, dh_need, authlen;
1253
3.76k
  int r, first_kex_follows;
1254
3.76k
  int auth_flag = 0;
1255
3.76k
  int log_flag = 0;
1256
1257
3.76k
  auth_flag = packet_authentication_state(ssh);
1258
3.76k
  debug("AUTH STATE IS %d", auth_flag);
1259
1260
3.76k
  debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
1261
3.76k
  if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
1262
0
    goto out;
1263
3.76k
  debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
1264
3.76k
  if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
1265
280
    goto out;
1266
1267
3.48k
  if (kex->server) {
1268
1.38k
    cprop=peer;
1269
1.38k
    sprop=my;
1270
2.10k
  } else {
1271
2.10k
    cprop=my;
1272
2.10k
    sprop=peer;
1273
2.10k
  }
1274
1275
  /* Check whether peer supports ext_info/kex_strict */
1276
3.48k
  if ((kex->flags & KEX_INITIAL) != 0) {
1277
3.48k
    if (kex->server) {
1278
1.38k
      kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
1279
1.38k
      kex->kex_strict = kexalgs_contains(peer,
1280
1.38k
          "kex-strict-c-v00@openssh.com");
1281
2.10k
    } else {
1282
2.10k
      kex->ext_info_s = kexalgs_contains(peer, "ext-info-s");
1283
2.10k
      kex->kex_strict = kexalgs_contains(peer,
1284
2.10k
          "kex-strict-s-v00@openssh.com");
1285
2.10k
    }
1286
3.48k
    if (kex->kex_strict) {
1287
60
      debug3_f("will use strict KEX ordering");
1288
60
      if (seq != 0)
1289
0
        ssh_packet_disconnect(ssh,
1290
0
            "strict KEX violation: "
1291
0
            "KEXINIT was not the first packet");
1292
60
    }
1293
3.48k
  }
1294
1295
  /* Check whether client supports rsa-sha2 algorithms */
1296
3.48k
  if (kex->server && (kex->flags & KEX_INITIAL)) {
1297
1.38k
    if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
1298
1.38k
        "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
1299
0
      kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
1300
1.38k
    if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
1301
1.38k
        "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
1302
0
      kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
1303
1.38k
  }
1304
1305
  /* Algorithm Negotiation */
1306
3.48k
  if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
1307
3.48k
      sprop[PROPOSAL_KEX_ALGS])) != 0) {
1308
3.00k
    kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
1309
3.00k
    peer[PROPOSAL_KEX_ALGS] = NULL;
1310
3.00k
    goto out;
1311
3.00k
  }
1312
476
  if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
1313
476
      sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
1314
369
    kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
1315
369
    peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
1316
369
    goto out;
1317
369
  }
1318
107
  for (mode = 0; mode < MODE_MAX; mode++) {
1319
107
    if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
1320
0
      r = SSH_ERR_ALLOC_FAIL;
1321
0
      goto out;
1322
0
    }
1323
107
    kex->newkeys[mode] = newkeys;
1324
107
    ctos = (!kex->server && mode == MODE_OUT) ||
1325
107
        (kex->server && mode == MODE_IN);
1326
107
    nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
1327
107
    nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
1328
107
    ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
1329
107
    if ((r = choose_enc(&newkeys->enc, cprop[nenc],
1330
107
        sprop[nenc])) != 0) {
1331
18
      kex->failed_choice = peer[nenc];
1332
18
      peer[nenc] = NULL;
1333
18
      goto out;
1334
18
    }
1335
89
#ifdef WITH_OPENSSL
1336
89
    if ((strcmp(newkeys->enc.name, "chacha20-poly1305@openssh.com")
1337
89
        == 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
89
#endif
1360
89
    authlen = cipher_authlen(newkeys->enc.cipher);
1361
    /* ignore mac for authenticated encryption */
1362
89
    if (authlen == 0 &&
1363
89
        (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
1364
89
        sprop[nmac])) != 0) {
1365
16
      kex->failed_choice = peer[nmac];
1366
16
      peer[nmac] = NULL;
1367
16
      goto out;
1368
16
    }
1369
73
    if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
1370
73
        sprop[ncomp])) != 0) {
1371
73
      kex->failed_choice = peer[ncomp];
1372
73
      peer[ncomp] = NULL;
1373
73
      goto out;
1374
73
    }
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.76k
 out:
1434
3.76k
  kex_prop_free(my);
1435
3.76k
  kex_prop_free(peer);
1436
3.76k
  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
}