diff options
author | dtucker@openbsd.org <dtucker@openbsd.org> | 2019-09-13 04:36:43 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-09-13 14:53:45 +1000 |
commit | b36ee3fcb2f1601693b1b7fd60dd6bd96006ea75 (patch) | |
tree | a3306118a58e6d505af368300e93a18848ca428c /ssh_api.c | |
parent | 2aefdf1aef906cf7548a2e5927d35aacb55948d4 (diff) |
upstream: Plug mem leaks on error paths, based in part on github
pr#120 from David Carlier. ok djm@.
OpenBSD-Commit-ID: c57adeb1022a8148fc86e5a88837b3b156dbdb7e
Diffstat (limited to 'ssh_api.c')
-rw-r--r-- | ssh_api.c | 34 |
1 files changed, 19 insertions, 15 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh_api.c,v 1.17 2019/09/06 05:23:55 djm Exp $ */ | 1 | /* $OpenBSD: ssh_api.c,v 1.18 2019/09/13 04:36:43 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2012 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2012 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -330,8 +330,8 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) | |||
330 | const char *mismatch = "Protocol mismatch.\r\n"; | 330 | const char *mismatch = "Protocol mismatch.\r\n"; |
331 | const u_char *s = sshbuf_ptr(input); | 331 | const u_char *s = sshbuf_ptr(input); |
332 | u_char c; | 332 | u_char c; |
333 | char *cp, *remote_version; | 333 | char *cp = NULL, *remote_version = NULL; |
334 | int r, remote_major, remote_minor, expect_nl; | 334 | int r = 0, remote_major, remote_minor, expect_nl; |
335 | size_t n, j; | 335 | size_t n, j; |
336 | 336 | ||
337 | for (j = n = 0;;) { | 337 | for (j = n = 0;;) { |
@@ -357,10 +357,8 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) | |||
357 | if (sshbuf_len(banner) >= 4 && | 357 | if (sshbuf_len(banner) >= 4 && |
358 | memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0) | 358 | memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0) |
359 | break; | 359 | break; |
360 | if ((cp = sshbuf_dup_string(banner)) == NULL) | 360 | debug("%s: %.*s", __func__, (int)sshbuf_len(banner), |
361 | return SSH_ERR_ALLOC_FAIL; | 361 | sshbuf_ptr(banner)); |
362 | debug("%s: %s", __func__, cp); | ||
363 | free(cp); | ||
364 | /* Accept lines before banner only on client */ | 362 | /* Accept lines before banner only on client */ |
365 | if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) { | 363 | if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) { |
366 | bad: | 364 | bad: |
@@ -373,19 +371,22 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) | |||
373 | if ((r = sshbuf_consume(input, j)) != 0) | 371 | if ((r = sshbuf_consume(input, j)) != 0) |
374 | return r; | 372 | return r; |
375 | 373 | ||
376 | if ((cp = sshbuf_dup_string(banner)) == NULL) | ||
377 | return SSH_ERR_ALLOC_FAIL; | ||
378 | /* XXX remote version must be the same size as banner for sscanf */ | 374 | /* XXX remote version must be the same size as banner for sscanf */ |
379 | if ((remote_version = calloc(1, sshbuf_len(banner))) == NULL) | 375 | if ((cp = sshbuf_dup_string(banner)) == NULL || |
380 | return SSH_ERR_ALLOC_FAIL; | 376 | (remote_version = calloc(1, sshbuf_len(banner))) == NULL) { |
377 | r = SSH_ERR_ALLOC_FAIL; | ||
378 | goto out; | ||
379 | } | ||
381 | 380 | ||
382 | /* | 381 | /* |
383 | * Check that the versions match. In future this might accept | 382 | * Check that the versions match. In future this might accept |
384 | * several versions and set appropriate flags to handle them. | 383 | * several versions and set appropriate flags to handle them. |
385 | */ | 384 | */ |
386 | if (sscanf(cp, "SSH-%d.%d-%[^\n]\n", | 385 | if (sscanf(cp, "SSH-%d.%d-%[^\n]\n", |
387 | &remote_major, &remote_minor, remote_version) != 3) | 386 | &remote_major, &remote_minor, remote_version) != 3) { |
388 | return SSH_ERR_INVALID_FORMAT; | 387 | r = SSH_ERR_INVALID_FORMAT; |
388 | goto out; | ||
389 | } | ||
389 | debug("Remote protocol version %d.%d, remote software version %.100s", | 390 | debug("Remote protocol version %d.%d, remote software version %.100s", |
390 | remote_major, remote_minor, remote_version); | 391 | remote_major, remote_minor, remote_version); |
391 | 392 | ||
@@ -395,10 +396,13 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) | |||
395 | remote_minor = 0; | 396 | remote_minor = 0; |
396 | } | 397 | } |
397 | if (remote_major != 2) | 398 | if (remote_major != 2) |
398 | return SSH_ERR_PROTOCOL_MISMATCH; | 399 | r = SSH_ERR_PROTOCOL_MISMATCH; |
400 | |||
399 | debug("Remote version string %.100s", cp); | 401 | debug("Remote version string %.100s", cp); |
402 | out: | ||
400 | free(cp); | 403 | free(cp); |
401 | return 0; | 404 | free(remote_version); |
405 | return r; | ||
402 | } | 406 | } |
403 | 407 | ||
404 | /* Send our own protocol version identification. */ | 408 | /* Send our own protocol version identification. */ |