Coverage Report

Created: 2026-10-19 07:16

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