From e96fe70cabcb3a5a009821dbb453dc0160ddc3f5 Mon Sep 17 00:00:00 2001 From: Jim Fuller Date: Sun, 8 Mar 2020 18:35:21 +0100 Subject: [PATCH] sftp: fix segfault regression introduced by #4747 This fix adds a defensive check for the case where the char *name in struct libssh2_knownhost is NULL Fixes #5041 Closes #5062 --- lib/vssh/libssh2.c | 41 ++++++++++++++++++++++-------------- tests/data/Makefile.inc | 2 +- tests/data/test1459 | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 tests/data/test1459 diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index 8e043747e..c487ccabb 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -694,31 +694,40 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn) while(!libssh2_knownhost_get(sshc->kh, &store, store)) { /* For non-standard ports, the name will be enclosed in */ /* square brackets, followed by a colon and the port */ - if(store->name[0] == '[') { - kh_name_end = strstr(store->name, "]:"); - if(!kh_name_end) { - infof(data, "Invalid host pattern %s in %s\n", - store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); - continue; - } - port = atoi(kh_name_end + 2); - if(kh_name_end && (port == conn->remote_port)) { - kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end); - if(strncmp(store->name + 1, conn->host.name, kh_name_size) == 0) { + if(store) { + if(store->name) { + if(store->name[0] == '[') { + kh_name_end = strstr(store->name, "]:"); + if(!kh_name_end) { + infof(data, "Invalid host pattern %s in %s\n", + store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); + continue; + } + port = atoi(kh_name_end + 2); + if(kh_name_end && (port == conn->remote_port)) { + kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end); + if(strncmp(store->name + 1, + conn->host.name, kh_name_size) == 0) { + found = true; + break; + } + } + } + else if(strcmp(store->name, conn->host.name) == 0) { found = true; break; } } - } - else if(strcmp(store->name, conn->host.name) == 0) { - found = true; - break; + else { + found = true; + break; + } } } if(found) { infof(data, "Found host %s in %s\n", - store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); + conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) { #ifdef LIBSSH2_KNOWNHOST_KEY_ED25519 diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 3eca9d2c2..3d8565c36 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -171,7 +171,7 @@ test1424 test1425 test1426 test1427 \ test1428 test1429 test1430 test1431 test1432 test1433 test1434 test1435 \ test1436 test1437 test1438 test1439 test1440 test1441 test1442 test1443 \ test1444 test1445 test1446 test1447 test1448 test1449 test1450 test1451 \ -test1452 test1453 test1454 test1455 test1456 test1457 test1458\ +test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 \ test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \ diff --git a/tests/data/test1459 b/tests/data/test1459 new file mode 100644 index 000000000..3e89595e4 --- /dev/null +++ b/tests/data/test1459 @@ -0,0 +1,46 @@ + + + +SFTP +known_hosts + + + +# +# Client-side + + +sftp + + +mkdir -p %PWD/log/test1459.dir/.ssh + + +sftp + + +SFTP with corrupted known_hosts + + +-u : sftp://%HOSTIP:%SSHPORT/ -l + + +|1|qy29Y1x/+/F39AzdG5515YSSw+c=|iB2WX5jrU3ZTWc+ZfGau7HHEvBc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAynDN8cDJ3xNzRjTNNGciSHSxpubxhZ6YnkLdp1TkrGW8n\ +R93Ey5VtBeBblYTRlFXBWJgKFcTKBRJ/O4qBZwbUgt10AHj31i6h8NehfT19tR8wG/YCmj3KtYLHmwdzmW1edEL9G2NdX2KiKYv7/zuly3QvmP0QA0NhWkAz0KdWNM= + + +CURL_HOME=%PWD/log/test1459.dir + + + +# Verify data after the test has been "shot" + + +60 + + +disable + + + +