summaryrefslogtreecommitdiff
path: root/ssh_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh_api.c')
-rw-r--r--ssh_api.c174
1 files changed, 96 insertions, 78 deletions
diff --git a/ssh_api.c b/ssh_api.c
index c84b4e713..57509973b 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */ 1/* $OpenBSD: ssh_api.c,v 1.15 2019/01/21 10:38:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2012 Markus Friedl. All rights reserved. 3 * Copyright (c) 2012 Markus Friedl. All rights reserved.
4 * 4 *
@@ -29,17 +29,19 @@
29#include "ssherr.h" 29#include "ssherr.h"
30#include "sshbuf.h" 30#include "sshbuf.h"
31 31
32#include "openbsd-compat/openssl-compat.h"
33
32#include <string.h> 34#include <string.h>
33 35
34int _ssh_exchange_banner(struct ssh *); 36int _ssh_exchange_banner(struct ssh *);
35int _ssh_send_banner(struct ssh *, char **); 37int _ssh_send_banner(struct ssh *, struct sshbuf *);
36int _ssh_read_banner(struct ssh *, char **); 38int _ssh_read_banner(struct ssh *, struct sshbuf *);
37int _ssh_order_hostkeyalgs(struct ssh *); 39int _ssh_order_hostkeyalgs(struct ssh *);
38int _ssh_verify_host_key(struct sshkey *, struct ssh *); 40int _ssh_verify_host_key(struct sshkey *, struct ssh *);
39struct sshkey *_ssh_host_public_key(int, int, struct ssh *); 41struct sshkey *_ssh_host_public_key(int, int, struct ssh *);
40struct sshkey *_ssh_host_private_key(int, int, struct ssh *); 42struct sshkey *_ssh_host_private_key(int, int, struct ssh *);
41int _ssh_host_key_sign(struct sshkey *, struct sshkey *, 43int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *,
42 u_char **, size_t *, const u_char *, size_t, const char *, u_int); 44 u_char **, size_t *, const u_char *, size_t, const char *);
43 45
44/* 46/*
45 * stubs for the server side implementation of kex. 47 * stubs for the server side implementation of kex.
@@ -79,9 +81,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
79 int r; 81 int r;
80 82
81 if (!called) { 83 if (!called) {
82#ifdef WITH_OPENSSL 84 seed_rng();
83 OpenSSL_add_all_algorithms();
84#endif /* WITH_OPENSSL */
85 called = 1; 85 called = 1;
86 } 86 }
87 87
@@ -92,42 +92,44 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
92 92
93 /* Initialize key exchange */ 93 /* Initialize key exchange */
94 proposal = kex_params ? kex_params->proposal : myproposal; 94 proposal = kex_params ? kex_params->proposal : myproposal;
95 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) { 95 if ((r = kex_ready(ssh, proposal)) != 0) {
96 ssh_free(ssh); 96 ssh_free(ssh);
97 return r; 97 return r;
98 } 98 }
99 ssh->kex->server = is_server; 99 ssh->kex->server = is_server;
100 if (is_server) { 100 if (is_server) {
101#ifdef WITH_OPENSSL 101#ifdef WITH_OPENSSL
102 ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 102 ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
103 ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 103 ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
104 ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; 104 ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
105 ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; 105 ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
106 ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; 106 ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
107 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 107 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
108 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 108 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
109# ifdef OPENSSL_HAS_ECC 109# ifdef OPENSSL_HAS_ECC
110 ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 110 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
111# endif 111# endif
112#endif /* WITH_OPENSSL */ 112#endif /* WITH_OPENSSL */
113 ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; 113 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
114 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
114 ssh->kex->load_host_public_key=&_ssh_host_public_key; 115 ssh->kex->load_host_public_key=&_ssh_host_public_key;
115 ssh->kex->load_host_private_key=&_ssh_host_private_key; 116 ssh->kex->load_host_private_key=&_ssh_host_private_key;
116 ssh->kex->sign=&_ssh_host_key_sign; 117 ssh->kex->sign=&_ssh_host_key_sign;
117 } else { 118 } else {
118#ifdef WITH_OPENSSL 119#ifdef WITH_OPENSSL
119 ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 120 ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
120 ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 121 ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
121 ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; 122 ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
122 ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; 123 ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
123 ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; 124 ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
124 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 125 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
125 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 126 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
126# ifdef OPENSSL_HAS_ECC 127# ifdef OPENSSL_HAS_ECC
127 ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 128 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
128# endif 129# endif
129#endif /* WITH_OPENSSL */ 130#endif /* WITH_OPENSSL */
130 ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; 131 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
132 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
131 ssh->kex->verify_host_key =&_ssh_verify_host_key; 133 ssh->kex->verify_host_key =&_ssh_verify_host_key;
132 } 134 }
133 *sshp = ssh; 135 *sshp = ssh;
@@ -236,8 +238,8 @@ ssh_packet_next(struct ssh *ssh, u_char *typep)
236 * enough data. 238 * enough data.
237 */ 239 */
238 *typep = SSH_MSG_NONE; 240 *typep = SSH_MSG_NONE;
239 if (ssh->kex->client_version_string == NULL || 241 if (sshbuf_len(ssh->kex->client_version) == 0 ||
240 ssh->kex->server_version_string == NULL) 242 sshbuf_len(ssh->kex->server_version) == 0)
241 return _ssh_exchange_banner(ssh); 243 return _ssh_exchange_banner(ssh);
242 /* 244 /*
243 * If we enough data and a dispatch function then 245 * If we enough data and a dispatch function then
@@ -312,39 +314,46 @@ ssh_input_space(struct ssh *ssh, size_t len)
312 314
313/* Read other side's version identification. */ 315/* Read other side's version identification. */
314int 316int
315_ssh_read_banner(struct ssh *ssh, char **bannerp) 317_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
316{ 318{
317 struct sshbuf *input; 319 struct sshbuf *input = ssh_packet_get_input(ssh);
318 const char *s;
319 char buf[256], remote_version[256]; /* must be same size! */
320 const char *mismatch = "Protocol mismatch.\r\n"; 320 const char *mismatch = "Protocol mismatch.\r\n";
321 int r, remote_major, remote_minor; 321 const u_char *s = sshbuf_ptr(input);
322 size_t i, n, j, len; 322 u_char c;
323 char *cp, *remote_version;
324 int r, remote_major, remote_minor, expect_nl;
325 size_t n, j;
323 326
324 *bannerp = NULL;
325 input = ssh_packet_get_input(ssh);
326 len = sshbuf_len(input);
327 s = (const char *)sshbuf_ptr(input);
328 for (j = n = 0;;) { 327 for (j = n = 0;;) {
329 for (i = 0; i < sizeof(buf) - 1; i++) { 328 sshbuf_reset(banner);
330 if (j >= len) 329 expect_nl = 0;
331 return (0); 330 for (;;) {
332 buf[i] = s[j++]; 331 if (j >= sshbuf_len(input))
333 if (buf[i] == '\r') { 332 return 0; /* insufficient data in input buf */
334 buf[i] = '\n'; 333 c = s[j++];
335 buf[i + 1] = 0; 334 if (c == '\r') {
336 continue; /**XXX wait for \n */ 335 expect_nl = 1;
336 continue;
337 } 337 }
338 if (buf[i] == '\n') { 338 if (c == '\n')
339 buf[i + 1] = 0;
340 break; 339 break;
341 } 340 if (expect_nl)
341 goto bad;
342 if ((r = sshbuf_put_u8(banner, c)) != 0)
343 return r;
344 if (sshbuf_len(banner) > SSH_MAX_BANNER_LEN)
345 goto bad;
342 } 346 }
343 buf[sizeof(buf) - 1] = 0; 347 if (sshbuf_len(banner) >= 4 &&
344 if (strncmp(buf, "SSH-", 4) == 0) 348 memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0)
345 break; 349 break;
346 debug("ssh_exchange_identification: %s", buf); 350 if ((cp = sshbuf_dup_string(banner)) == NULL)
347 if (ssh->kex->server || ++n > 65536) { 351 return SSH_ERR_ALLOC_FAIL;
352 debug("%s: %s", __func__, cp);
353 free(cp);
354 /* Accept lines before banner only on client */
355 if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) {
356 bad:
348 if ((r = sshbuf_put(ssh_packet_get_output(ssh), 357 if ((r = sshbuf_put(ssh_packet_get_output(ssh),
349 mismatch, strlen(mismatch))) != 0) 358 mismatch, strlen(mismatch))) != 0)
350 return r; 359 return r;
@@ -354,11 +363,17 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
354 if ((r = sshbuf_consume(input, j)) != 0) 363 if ((r = sshbuf_consume(input, j)) != 0)
355 return r; 364 return r;
356 365
366 if ((cp = sshbuf_dup_string(banner)) == NULL)
367 return SSH_ERR_ALLOC_FAIL;
368 /* XXX remote version must be the same size as banner for sscanf */
369 if ((remote_version = calloc(1, sshbuf_len(banner))) == NULL)
370 return SSH_ERR_ALLOC_FAIL;
371
357 /* 372 /*
358 * Check that the versions match. In future this might accept 373 * Check that the versions match. In future this might accept
359 * several versions and set appropriate flags to handle them. 374 * several versions and set appropriate flags to handle them.
360 */ 375 */
361 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", 376 if (sscanf(cp, "SSH-%d.%d-%[^\n]\n",
362 &remote_major, &remote_minor, remote_version) != 3) 377 &remote_major, &remote_minor, remote_version) != 3)
363 return SSH_ERR_INVALID_FORMAT; 378 return SSH_ERR_INVALID_FORMAT;
364 debug("Remote protocol version %d.%d, remote software version %.100s", 379 debug("Remote protocol version %d.%d, remote software version %.100s",
@@ -371,27 +386,29 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
371 } 386 }
372 if (remote_major != 2) 387 if (remote_major != 2)
373 return SSH_ERR_PROTOCOL_MISMATCH; 388 return SSH_ERR_PROTOCOL_MISMATCH;
374 chop(buf); 389 debug("Remote version string %.100s", cp);
375 debug("Remote version string %.100s", buf); 390 free(cp);
376 if ((*bannerp = strdup(buf)) == NULL)
377 return SSH_ERR_ALLOC_FAIL;
378 return 0; 391 return 0;
379} 392}
380 393
381/* Send our own protocol version identification. */ 394/* Send our own protocol version identification. */
382int 395int
383_ssh_send_banner(struct ssh *ssh, char **bannerp) 396_ssh_send_banner(struct ssh *ssh, struct sshbuf *banner)
384{ 397{
385 char buf[256]; 398 char *cp;
386 int r; 399 int r;
387 400
388 snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION); 401 if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0)
389 if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0) 402 return r;
403 if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0)
404 return r;
405 /* Remove trailing \r\n */
406 if ((r = sshbuf_consume_end(banner, 2)) != 0)
390 return r; 407 return r;
391 chop(buf); 408 if ((cp = sshbuf_dup_string(banner)) == NULL)
392 debug("Local version string %.100s", buf);
393 if ((*bannerp = strdup(buf)) == NULL)
394 return SSH_ERR_ALLOC_FAIL; 409 return SSH_ERR_ALLOC_FAIL;
410 debug("Local version string %.100s", cp);
411 free(cp);
395 return 0; 412 return 0;
396} 413}
397 414
@@ -408,25 +425,25 @@ _ssh_exchange_banner(struct ssh *ssh)
408 425
409 r = 0; 426 r = 0;
410 if (kex->server) { 427 if (kex->server) {
411 if (kex->server_version_string == NULL) 428 if (sshbuf_len(ssh->kex->server_version) == 0)
412 r = _ssh_send_banner(ssh, &kex->server_version_string); 429 r = _ssh_send_banner(ssh, ssh->kex->server_version);
413 if (r == 0 && 430 if (r == 0 &&
414 kex->server_version_string != NULL && 431 sshbuf_len(ssh->kex->server_version) != 0 &&
415 kex->client_version_string == NULL) 432 sshbuf_len(ssh->kex->client_version) == 0)
416 r = _ssh_read_banner(ssh, &kex->client_version_string); 433 r = _ssh_read_banner(ssh, ssh->kex->client_version);
417 } else { 434 } else {
418 if (kex->server_version_string == NULL) 435 if (sshbuf_len(ssh->kex->server_version) == 0)
419 r = _ssh_read_banner(ssh, &kex->server_version_string); 436 r = _ssh_read_banner(ssh, ssh->kex->server_version);
420 if (r == 0 && 437 if (r == 0 &&
421 kex->server_version_string != NULL && 438 sshbuf_len(ssh->kex->server_version) != 0 &&
422 kex->client_version_string == NULL) 439 sshbuf_len(ssh->kex->client_version) == 0)
423 r = _ssh_send_banner(ssh, &kex->client_version_string); 440 r = _ssh_send_banner(ssh, ssh->kex->client_version);
424 } 441 }
425 if (r != 0) 442 if (r != 0)
426 return r; 443 return r;
427 /* start initial kex as soon as we have exchanged the banners */ 444 /* start initial kex as soon as we have exchanged the banners */
428 if (kex->server_version_string != NULL && 445 if (sshbuf_len(ssh->kex->server_version) != 0 &&
429 kex->client_version_string != NULL) { 446 sshbuf_len(ssh->kex->client_version) != 0) {
430 if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 || 447 if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 ||
431 (r = kex_send_kexinit(ssh)) != 0) 448 (r = kex_send_kexinit(ssh)) != 0)
432 return r; 449 return r;
@@ -532,9 +549,10 @@ _ssh_order_hostkeyalgs(struct ssh *ssh)
532} 549}
533 550
534int 551int
535_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey, 552_ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey,
536 u_char **signature, size_t *slen, const u_char *data, size_t dlen, 553 struct sshkey *pubkey, u_char **signature, size_t *slen,
537 const char *alg, u_int compat) 554 const u_char *data, size_t dlen, const char *alg)
538{ 555{
539 return sshkey_sign(privkey, signature, slen, data, dlen, alg, compat); 556 return sshkey_sign(privkey, signature, slen, data, dlen,
557 alg, ssh->compat);
540} 558}