summaryrefslogtreecommitdiff
path: root/ssh_api.c
diff options
context:
space:
mode:
authordtucker@openbsd.org <dtucker@openbsd.org>2019-09-13 04:36:43 +0000
committerDamien Miller <djm@mindrot.org>2019-09-13 14:53:45 +1000
commitb36ee3fcb2f1601693b1b7fd60dd6bd96006ea75 (patch)
treea3306118a58e6d505af368300e93a18848ca428c /ssh_api.c
parent2aefdf1aef906cf7548a2e5927d35aacb55948d4 (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.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/ssh_api.c b/ssh_api.c
index 6ea40b5e7..03dac0982 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -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. */