diff options
Diffstat (limited to 'libs/libcurl/src/vssh')
| -rw-r--r-- | libs/libcurl/src/vssh/libssh.c | 210 | ||||
| -rw-r--r-- | libs/libcurl/src/vssh/libssh2.c | 311 | ||||
| -rw-r--r-- | libs/libcurl/src/vssh/ssh.h | 1 | ||||
| -rw-r--r-- | libs/libcurl/src/vssh/wolfssh.c | 48 |
4 files changed, 335 insertions, 235 deletions
diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c index 87ed34ee62..cb98738fc3 100644 --- a/libs/libcurl/src/vssh/libssh.c +++ b/libs/libcurl/src/vssh/libssh.c @@ -65,7 +65,7 @@ #include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
-#include "strtoofft.h"
+#include "strparse.h"
#include "multiif.h"
#include "select.h"
#include "warnless.h"
@@ -138,6 +138,7 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block); static CURLcode myssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
+static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data);
/*
* SCP protocol handler.
@@ -943,7 +944,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
break;
}
- data->state.most_recent_ftp_entrypath = sshc->homedir;
+ free(data->state.most_recent_ftp_entrypath);
+ data->state.most_recent_ftp_entrypath = strdup(sshc->homedir);
+ if(!data->state.most_recent_ftp_entrypath)
+ return CURLE_OUT_OF_MEMORY;
/* This is the last step in the SFTP connect phase. Do note that while
we get the homedir here, we get the "workingpath" in the DO action
@@ -1602,29 +1606,29 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) }
if(data->state.use_range) {
curl_off_t from, to;
- char *ptr;
- char *ptr2;
- CURLofft to_t;
- CURLofft from_t;
+ const char *p = data->state.range;
+ int from_t, to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
- if(from_t == CURL_OFFT_FLOW) {
+ from_t = Curl_str_number(&p, &from, CURL_OFF_T_MAX);
+ if(from_t == STRE_OVERFLOW)
return CURLE_RANGE_ERROR;
- }
- while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
- if(to_t == CURL_OFFT_FLOW) {
+ Curl_str_passblanks(&p);
+ (void)Curl_str_single(&p, '-');
+
+ to_t = Curl_str_numblanks(&p, &to);
+ if(to_t == STRE_OVERFLOW)
return CURLE_RANGE_ERROR;
- }
- if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
- || (to >= size)) {
+
+ if((to_t == STRE_NO_NUM) || (to >= size)) {
to = size - 1;
+ to_t = STRE_OK;
}
- if(from_t) {
+
+ if(from_t == STRE_NO_NUM) {
/* from is relative to end of file */
from = size - to;
to = size - 1;
+ from_t = STRE_OK;
}
if(from > size) {
failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
@@ -1762,7 +1766,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) }
SSH_STRING_FREE_CHAR(sshc->homedir);
- data->state.most_recent_ftp_entrypath = NULL;
state(data, SSH_SESSION_DISCONNECT);
break;
@@ -1814,9 +1817,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) break;
}
- rc = ssh_scp_push_file(sshc->scp_session, protop->path,
- (size_t)data->state.infilesize,
- (int)data->set.new_file_perms);
+ rc = ssh_scp_push_file64(sshc->scp_session, protop->path,
+ (uint64_t)data->state.infilesize,
+ (int)data->set.new_file_perms);
+
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
failf(data, "%s", err_msg);
@@ -1937,53 +1941,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) }
SSH_STRING_FREE_CHAR(sshc->homedir);
- data->state.most_recent_ftp_entrypath = NULL;
state(data, SSH_SESSION_FREE);
FALLTHROUGH();
case SSH_SESSION_FREE:
- if(sshc->ssh_session) {
- ssh_free(sshc->ssh_session);
- sshc->ssh_session = NULL;
- }
-
- /* worst-case scenario cleanup */
-
- DEBUGASSERT(sshc->ssh_session == NULL);
- DEBUGASSERT(sshc->scp_session == NULL);
-
- if(sshc->readdir_tmp) {
- ssh_string_free_char(sshc->readdir_tmp);
- sshc->readdir_tmp = NULL;
- }
-
- if(sshc->quote_attrs)
- sftp_attributes_free(sshc->quote_attrs);
-
- if(sshc->readdir_attrs)
- sftp_attributes_free(sshc->readdir_attrs);
-
- if(sshc->readdir_link_attrs)
- sftp_attributes_free(sshc->readdir_link_attrs);
-
- if(sshc->privkey)
- ssh_key_free(sshc->privkey);
- if(sshc->pubkey)
- ssh_key_free(sshc->pubkey);
-
- Curl_safefree(sshc->rsa_pub);
- Curl_safefree(sshc->rsa);
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- Curl_dyn_free(&sshc->readdir_buf);
- Curl_safefree(sshc->readdir_linkPath);
- SSH_STRING_FREE_CHAR(sshc->homedir);
-
+ sshc_cleanup(sshc, data);
/* the code we are about to return */
result = sshc->actualcode;
-
memset(sshc, 0, sizeof(struct ssh_conn));
-
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
@@ -2121,10 +2086,14 @@ static CURLcode myssh_setup_connection(struct Curl_easy *data, struct SSHPROTO *ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
+ if(!sshc->initialised) {
+ Curl_dyn_init(&sshc->readdir_buf, CURL_PATH_MAX * 2);
+ sshc->initialised = TRUE;
+ }
+
data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&sshc->readdir_buf, CURL_PATH_MAX * 2);
return CURLE_OK;
}
@@ -2327,6 +2296,55 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done) return result;
}
+static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
+{
+ (void)data;
+ if(sshc->initialised) {
+ if(sshc->ssh_session) {
+ ssh_free(sshc->ssh_session);
+ sshc->ssh_session = NULL;
+ }
+
+ /* worst-case scenario cleanup */
+ DEBUGASSERT(sshc->ssh_session == NULL);
+ DEBUGASSERT(sshc->scp_session == NULL);
+
+ if(sshc->readdir_tmp) {
+ ssh_string_free_char(sshc->readdir_tmp);
+ sshc->readdir_tmp = NULL;
+ }
+ if(sshc->quote_attrs) {
+ sftp_attributes_free(sshc->quote_attrs);
+ sshc->quote_attrs = NULL;
+ }
+ if(sshc->readdir_attrs) {
+ sftp_attributes_free(sshc->readdir_attrs);
+ sshc->readdir_attrs = NULL;
+ }
+ if(sshc->readdir_link_attrs) {
+ sftp_attributes_free(sshc->readdir_link_attrs);
+ sshc->readdir_link_attrs = NULL;
+ }
+ if(sshc->privkey) {
+ ssh_key_free(sshc->privkey);
+ sshc->privkey = NULL;
+ }
+ if(sshc->pubkey) {
+ ssh_key_free(sshc->pubkey);
+ sshc->pubkey = NULL;
+ }
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ Curl_dyn_free(&sshc->readdir_buf);
+ Curl_safefree(sshc->readdir_linkPath);
+ SSH_STRING_FREE_CHAR(sshc->homedir);
+ sshc->initialised = FALSE;
+ }
+}
+
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
@@ -2335,10 +2353,10 @@ static CURLcode scp_disconnect(struct Curl_easy *data, bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *ssh = &conn->proto.sshc;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- if(ssh->ssh_session) {
+ if(sshc->ssh_session) {
/* only if there is a session still around to use! */
state(data, SSH_SESSION_DISCONNECT);
@@ -2346,6 +2364,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data, result = myssh_block_statemach(data, TRUE);
}
+ sshc_cleanup(sshc, data);
return result;
}
@@ -2499,6 +2518,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, struct connectdata *conn,
bool dead_connection)
{
+ struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
(void) dead_connection;
@@ -2511,9 +2531,9 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, }
DEBUGF(infof(data, "SSH DISCONNECT is done"));
+ sshc_cleanup(sshc, data);
return result;
-
}
static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
@@ -2686,7 +2706,7 @@ static void sftp_quote(struct Curl_easy *data) sshc->nextstate = SSH_NO_STATE;
return;
}
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_OUT, "PWD\n", 4);
Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
/* this sends an FTP-like "header" to the header callback so that the
@@ -2739,11 +2759,11 @@ static void sftp_quote(struct Curl_easy *data) * OpenSSH's sftp program and call the appropriate libssh
* functions.
*/
- if(strncasecompare(cmd, "chgrp ", 6) ||
- strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ||
- strncasecompare(cmd, "atime ", 6) ||
- strncasecompare(cmd, "mtime ", 6)) {
+ if(!strncmp(cmd, "chgrp ", 6) ||
+ !strncmp(cmd, "chmod ", 6) ||
+ !strncmp(cmd, "chown ", 6) ||
+ !strncmp(cmd, "atime ", 6) ||
+ !strncmp(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -2765,8 +2785,8 @@ static void sftp_quote(struct Curl_easy *data) state(data, SSH_SFTP_QUOTE_STAT);
return;
}
- if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
+ if(!strncmp(cmd, "ln ", 3) ||
+ !strncmp(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@@ -2785,12 +2805,12 @@ static void sftp_quote(struct Curl_easy *data) state(data, SSH_SFTP_QUOTE_SYMLINK);
return;
}
- else if(strncasecompare(cmd, "mkdir ", 6)) {
+ else if(!strncmp(cmd, "mkdir ", 6)) {
/* create dir */
state(data, SSH_SFTP_QUOTE_MKDIR);
return;
}
- else if(strncasecompare(cmd, "rename ", 7)) {
+ else if(!strncmp(cmd, "rename ", 7)) {
/* rename file */
/* first param is the source path */
/* second param is the dest. path */
@@ -2809,17 +2829,17 @@ static void sftp_quote(struct Curl_easy *data) state(data, SSH_SFTP_QUOTE_RENAME);
return;
}
- else if(strncasecompare(cmd, "rmdir ", 6)) {
+ else if(!strncmp(cmd, "rmdir ", 6)) {
/* delete dir */
state(data, SSH_SFTP_QUOTE_RMDIR);
return;
}
- else if(strncasecompare(cmd, "rm ", 3)) {
+ else if(!strncmp(cmd, "rm ", 3)) {
state(data, SSH_SFTP_QUOTE_UNLINK);
return;
}
#ifdef HAS_STATVFS_SUPPORT
- else if(strncasecompare(cmd, "statvfs ", 8)) {
+ else if(!strncmp(cmd, "statvfs ", 8)) {
state(data, SSH_SFTP_QUOTE_STATVFS);
return;
}
@@ -2870,10 +2890,13 @@ static void sftp_quote_stat(struct Curl_easy *data) }
/* Now set the new attributes... */
- if(strncasecompare(cmd, "chgrp", 5)) {
- sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
+ if(!strncmp(cmd, "chgrp", 5)) {
+ const char *p = sshc->quote_path1;
+ curl_off_t gid;
+ (void)Curl_str_number(&p, &gid, UINT_MAX);
+ sshc->quote_attrs->gid = (uint32_t)gid;
if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
- !sshc->acceptfail) {
+ !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
@@ -2884,11 +2907,10 @@ static void sftp_quote_stat(struct Curl_easy *data) }
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
- else if(strncasecompare(cmd, "chmod", 5)) {
- mode_t perms;
- perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
- /* permissions are octal */
- if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
+ else if(!strncmp(cmd, "chmod", 5)) {
+ curl_off_t perms;
+ const char *p = sshc->quote_path1;
+ if(Curl_str_octal(&p, &perms, 07777)) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
@@ -2897,13 +2919,15 @@ static void sftp_quote_stat(struct Curl_easy *data) sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
- sshc->quote_attrs->permissions = perms;
+ sshc->quote_attrs->permissions = (mode_t)perms;
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
}
- else if(strncasecompare(cmd, "chown", 5)) {
- sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
+ else if(!strncmp(cmd, "chown", 5)) {
+ const char *p = sshc->quote_path1;
+ curl_off_t uid;
+ (void)Curl_str_number(&p, &uid, UINT_MAX);
if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
- !sshc->acceptfail) {
+ !sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
@@ -2914,8 +2938,8 @@ static void sftp_quote_stat(struct Curl_easy *data) }
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
- else if(strncasecompare(cmd, "atime", 5) ||
- strncasecompare(cmd, "mtime", 5)) {
+ else if(!strncmp(cmd, "atime", 5) ||
+ !strncmp(cmd, "mtime", 5)) {
time_t date = Curl_getdate_capped(sshc->quote_path1);
bool fail = FALSE;
if(date == -1) {
@@ -2936,7 +2960,7 @@ static void sftp_quote_stat(struct Curl_easy *data) sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
- if(strncasecompare(cmd, "atime", 5))
+ if(!strncmp(cmd, "atime", 5))
sshc->quote_attrs->atime = (uint32_t)date;
else /* mtime */
sshc->quote_attrs->mtime = (uint32_t)date;
diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c index a75397e95c..4ecf198e17 100644 --- a/libs/libcurl/src/vssh/libssh2.c +++ b/libs/libcurl/src/vssh/libssh2.c @@ -68,12 +68,11 @@ #include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
-#include "strtoofft.h"
#include "multiif.h"
#include "select.h"
#include "warnless.h"
#include "curl_path.h"
-
+#include "strparse.h"
#include <curl_base64.h> /* for base64 encoding/decoding */
#include <curl_sha256.h>
@@ -107,7 +106,8 @@ static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn, static CURLcode ssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static void ssh_attach(struct Curl_easy *data, struct connectdata *conn);
-
+static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
+ bool block);
/*
* SCP protocol handler.
*/
@@ -369,7 +369,7 @@ static void state(struct Curl_easy *data, sshstate nowstate) };
/* a precaution to make sure the lists are in sync */
- DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
+ DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
if(sshc->state != nowstate) {
infof(data, "SFTP %p state change from %s to %s",
@@ -598,9 +598,9 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data) const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
infof(data, "SSH MD5 public key: %s",
- pubkey_md5 != NULL ? pubkey_md5 : "NULL");
+ pubkey_md5 != NULL ? pubkey_md5 : "NULL");
infof(data, "SSH SHA256 public key: %s",
- pubkey_sha256 != NULL ? pubkey_sha256 : "NULL");
+ pubkey_sha256 != NULL ? pubkey_sha256 : "NULL");
if(pubkey_sha256) {
const char *fingerprint = NULL;
@@ -684,7 +684,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data) if(pubkey_md5) {
char md5buffer[33];
- const char *fingerprint = NULL;
+ const char *fingerprint;
fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
LIBSSH2_HOSTKEY_HASH_MD5);
@@ -796,7 +796,9 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data) int port = 0;
bool found = FALSE;
- if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
+ if(sshc->kh &&
+ !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
+ !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]) {
/* lets try to find our host in the known hosts file */
while(!libssh2_knownhost_get(sshc->kh, &store, store)) {
/* For non-standard ports, the name will be enclosed in */
@@ -931,7 +933,7 @@ static CURLcode sftp_quote(struct Curl_easy *data, char *tmp = aprintf("257 \"%s\" is current directory.\n", sshp->path);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_OUT, "PWD\n", 4);
Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
/* this sends an FTP-like "header" to the header callback so that the
@@ -970,11 +972,11 @@ static CURLcode sftp_quote(struct Curl_easy *data, * Instead, we scan for commands used by OpenSSH's sftp program and call the
* appropriate libssh2 functions.
*/
- if(strncasecompare(cmd, "chgrp ", 6) ||
- strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ||
- strncasecompare(cmd, "atime ", 6) ||
- strncasecompare(cmd, "mtime ", 6)) {
+ if(!strncmp(cmd, "chgrp ", 6) ||
+ !strncmp(cmd, "chmod ", 6) ||
+ !strncmp(cmd, "chown ", 6) ||
+ !strncmp(cmd, "atime ", 6) ||
+ !strncmp(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -990,8 +992,8 @@ static CURLcode sftp_quote(struct Curl_easy *data, state(data, SSH_SFTP_QUOTE_STAT);
return result;
}
- if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
+ if(!strncmp(cmd, "ln ", 3) ||
+ !strncmp(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@@ -1005,12 +1007,12 @@ static CURLcode sftp_quote(struct Curl_easy *data, state(data, SSH_SFTP_QUOTE_SYMLINK);
return result;
}
- else if(strncasecompare(cmd, "mkdir ", 6)) {
+ else if(!strncmp(cmd, "mkdir ", 6)) {
/* create dir */
state(data, SSH_SFTP_QUOTE_MKDIR);
return result;
}
- else if(strncasecompare(cmd, "rename ", 7)) {
+ else if(!strncmp(cmd, "rename ", 7)) {
/* rename file */
/* first param is the source path */
/* second param is the dest. path */
@@ -1024,16 +1026,16 @@ static CURLcode sftp_quote(struct Curl_easy *data, state(data, SSH_SFTP_QUOTE_RENAME);
return result;
}
- else if(strncasecompare(cmd, "rmdir ", 6)) {
+ else if(!strncmp(cmd, "rmdir ", 6)) {
/* delete dir */
state(data, SSH_SFTP_QUOTE_RMDIR);
return result;
}
- else if(strncasecompare(cmd, "rm ", 3)) {
+ else if(!strncmp(cmd, "rm ", 3)) {
state(data, SSH_SFTP_QUOTE_UNLINK);
return result;
}
- else if(strncasecompare(cmd, "statvfs ", 8)) {
+ else if(!strncmp(cmd, "statvfs ", 8)) {
state(data, SSH_SFTP_QUOTE_STATVFS);
return result;
}
@@ -1263,7 +1265,7 @@ sftp_pkey_init(struct Curl_easy *data, if(!sshc->rsa)
out_of_memory = TRUE;
else if(stat(sshc->rsa, &sbuf)) {
- Curl_safefree(sshc->rsa);
+ free(sshc->rsa);
sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
if(!sshc->rsa)
out_of_memory = TRUE;
@@ -1277,10 +1279,10 @@ sftp_pkey_init(struct Curl_easy *data, /* Nothing found; try the current dir. */
sshc->rsa = strdup("id_rsa");
if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
- Curl_safefree(sshc->rsa);
+ free(sshc->rsa);
sshc->rsa = strdup("id_dsa");
if(sshc->rsa && stat(sshc->rsa, &sbuf)) {
- Curl_safefree(sshc->rsa);
+ free(sshc->rsa);
/* Out of guesses. Set to the empty string to avoid
* surprising info messages. */
sshc->rsa = strdup("");
@@ -1345,7 +1347,7 @@ sftp_quote_stat(struct Curl_easy *data, sshc->acceptfail = TRUE;
}
- if(!strncasecompare(cmd, "chmod", 5)) {
+ if(!!strncmp(cmd, "chmod", 5)) {
/* Since chown and chgrp only set owner OR group but libssh2 wants to set
* them both at once, we need to obtain the current ownership first. This
* takes an extra protocol round trip.
@@ -1367,8 +1369,11 @@ sftp_quote_stat(struct Curl_easy *data, }
/* Now set the new attributes... */
- if(strncasecompare(cmd, "chgrp", 5)) {
- sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ if(!strncmp(cmd, "chgrp", 5)) {
+ const char *p = sshc->quote_path1;
+ curl_off_t gid;
+ (void)Curl_str_number(&p, &gid, ULONG_MAX);
+ sshp->quote_attrs.gid = (unsigned long)gid;
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
@@ -1376,18 +1381,23 @@ sftp_quote_stat(struct Curl_easy *data, goto fail;
}
}
- else if(strncasecompare(cmd, "chmod", 5)) {
- sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
- sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ else if(!strncmp(cmd, "chmod", 5)) {
+ curl_off_t perms;
+ const char *p = sshc->quote_path1;
/* permissions are octal */
- if(sshp->quote_attrs.permissions == 0 &&
- !ISDIGIT(sshc->quote_path1[0])) {
+ if(Curl_str_octal(&p, &perms, 07777)) {
failf(data, "Syntax error: chmod permissions not a number");
goto fail;
}
+
+ sshp->quote_attrs.permissions = (unsigned long)perms;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
}
- else if(strncasecompare(cmd, "chown", 5)) {
- sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ else if(!strncmp(cmd, "chown", 5)) {
+ const char *p = sshc->quote_path1;
+ curl_off_t uid;
+ (void)Curl_str_number(&p, &uid, ULONG_MAX);
+ sshp->quote_attrs.uid = (unsigned long)uid;
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
@@ -1395,8 +1405,8 @@ sftp_quote_stat(struct Curl_easy *data, goto fail;
}
}
- else if(strncasecompare(cmd, "atime", 5) ||
- strncasecompare(cmd, "mtime", 5)) {
+ else if(!strncmp(cmd, "atime", 5) ||
+ !strncmp(cmd, "mtime", 5)) {
time_t date = Curl_getdate_capped(sshc->quote_path1);
bool fail = FALSE;
@@ -1413,7 +1423,7 @@ sftp_quote_stat(struct Curl_easy *data, #endif
if(fail)
goto fail;
- if(strncasecompare(cmd, "atime", 5))
+ if(!strncmp(cmd, "atime", 5))
sshp->quote_attrs.atime = (unsigned long)date;
else /* mtime */
sshp->quote_attrs.mtime = (unsigned long)date;
@@ -1466,20 +1476,19 @@ sftp_download_stat(struct Curl_easy *data, }
if(data->state.use_range) {
curl_off_t from, to;
- char *ptr;
- char *ptr2;
- CURLofft to_t;
- CURLofft from_t;
+ const char *p = data->state.range;
+ int to_t, from_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
- if(from_t == CURL_OFFT_FLOW)
+ from_t = Curl_str_number(&p, &from, CURL_OFF_T_MAX);
+ if(from_t == STRE_OVERFLOW)
return CURLE_RANGE_ERROR;
- while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
- if(to_t == CURL_OFFT_FLOW)
+ Curl_str_passblanks(&p);
+ (void)Curl_str_single(&p, '-');
+
+ to_t = Curl_str_numblanks(&p, &to);
+ if(to_t == STRE_OVERFLOW)
return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
+ if((to_t == STRE_NO_NUM) /* no "to" value given */
|| (to >= size)) {
to = size - 1;
}
@@ -1585,8 +1594,7 @@ static CURLcode sftp_readdir(struct Curl_easy *data, sshp->readdir_filename,
readdir_len);
if(!result)
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, "\n", 1);
if(result)
return result;
}
@@ -1597,7 +1605,6 @@ static CURLcode sftp_readdir(struct Curl_easy *data, if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
- Curl_dyn_init(&sshp->readdir_link, CURL_PATH_MAX);
result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
sshp->readdir_filename);
state(data, SSH_SFTP_READDIR_LINK);
@@ -1995,13 +2002,17 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) if(rc > 0) {
/* It seems that this string is not always NULL terminated */
sshp->readdir_filename[rc] = '\0';
+ free(sshc->homedir);
sshc->homedir = strdup(sshp->readdir_filename);
if(!sshc->homedir) {
state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- data->state.most_recent_ftp_entrypath = sshc->homedir;
+ free(data->state.most_recent_ftp_entrypath);
+ data->state.most_recent_ftp_entrypath = strdup(sshc->homedir);
+ if(!data->state.most_recent_ftp_entrypath)
+ return CURLE_OUT_OF_MEMORY;
}
else {
/* Return the error type */
@@ -2019,13 +2030,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) break;
}
- /* This is the last step in the SFTP connect phase. Do note that while
- we get the homedir here, we get the "workingpath" in the DO action
- since the homedir will remain the same between request but the
- working path will not. */
- DEBUGF(infof(data, "SSH CONNECT phase done"));
- state(data, SSH_STOP);
- break;
+ /* This is the last step in the SFTP connect phase. Do note that while
+ we get the homedir here, we get the "workingpath" in the DO action
+ since the homedir will remain the same between request but the
+ working path will not. */
+ DEBUGF(infof(data, "SSH CONNECT phase done"));
+ state(data, SSH_STOP);
+ break;
case SSH_SFTP_QUOTE_INIT:
@@ -2288,7 +2299,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) }
case SSH_SFTP_GETINFO:
- {
if(data->set.get_filetime) {
state(data, SSH_SFTP_FILETIME);
}
@@ -2296,7 +2306,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) state(data, SSH_SFTP_TRANS_INIT);
}
break;
- }
case SSH_SFTP_FILETIME:
{
@@ -2418,7 +2427,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) sshc->actualcode = result ? result : CURLE_SSH;
break;
}
- Curl_dyn_init(&sshp->readdir, CURL_PATH_MAX * 2);
state(data, SSH_SFTP_READDIR);
break;
@@ -2584,7 +2592,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) }
Curl_safefree(sshc->homedir);
- data->state.most_recent_ftp_entrypath = NULL;
state(data, SSH_SESSION_DISCONNECT);
break;
@@ -2850,72 +2857,17 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block) }
Curl_safefree(sshc->homedir);
- data->state.most_recent_ftp_entrypath = NULL;
state(data, SSH_SESSION_FREE);
break;
case SSH_SESSION_FREE:
- if(sshc->kh) {
- libssh2_knownhost_free(sshc->kh);
- sshc->kh = NULL;
- }
-
- if(sshc->ssh_agent) {
- rc = libssh2_agent_disconnect(sshc->ssh_agent);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- infof(data, "Failed to disconnect from libssh2 agent: %d %s",
- rc, err_msg);
- }
- libssh2_agent_free(sshc->ssh_agent);
- sshc->ssh_agent = NULL;
-
- /* NB: there is no need to free identities, they are part of internal
- agent stuff */
- sshc->sshagent_identity = NULL;
- sshc->sshagent_prev_identity = NULL;
- }
-
- if(sshc->ssh_session) {
- rc = libssh2_session_free(sshc->ssh_session);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
- }
- sshc->ssh_session = NULL;
- }
-
- /* worst-case scenario cleanup */
-
- DEBUGASSERT(sshc->ssh_session == NULL);
- DEBUGASSERT(sshc->ssh_channel == NULL);
- DEBUGASSERT(sshc->sftp_session == NULL);
- DEBUGASSERT(sshc->sftp_handle == NULL);
- DEBUGASSERT(sshc->kh == NULL);
- DEBUGASSERT(sshc->ssh_agent == NULL);
-
- Curl_safefree(sshc->rsa_pub);
- Curl_safefree(sshc->rsa);
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- Curl_safefree(sshc->homedir);
-
+ rc = sshc_cleanup(sshc, data, FALSE);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ break;
/* the code we are about to return */
result = sshc->actualcode;
-
memset(sshc, 0, sizeof(struct ssh_conn));
-
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
@@ -3068,13 +3020,23 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, static CURLcode ssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct ssh_conn *sshc = &conn->proto.sshc;
struct SSHPROTO *ssh;
(void)conn;
+ if(!sshc->initialised) {
+ /* other ssh implementations do something here, let's keep
+ * the initialised flag correct even if this implementation does not. */
+ sshc->initialised = TRUE;
+ }
+
data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&ssh->readdir, CURL_PATH_MAX * 2);
+ Curl_dyn_init(&ssh->readdir_link, CURL_PATH_MAX);
+
return CURLE_OK;
}
@@ -3103,7 +3065,7 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer, return -EAGAIN; /* magic return code for libssh2 */
else if(result)
return -1; /* generic error */
- Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
+ Curl_debug(data, CURLINFO_DATA_IN, (const char *)buffer, (size_t)nread);
return nread;
}
@@ -3128,7 +3090,7 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, return -EAGAIN; /* magic return code for libssh2 */
else if(result)
return -1; /* error */
- Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, nwrite);
+ Curl_debug(data, CURLINFO_DATA_OUT, (const char *)buffer, nwrite);
return (ssize_t)nwrite;
}
#endif
@@ -3146,6 +3108,34 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) CURLcode result;
struct connectdata *conn = data->conn;
+#if LIBSSH2_VERSION_NUM >= 0x010b00
+ {
+ const char *crypto_str;
+ switch(libssh2_crypto_engine()) {
+ case libssh2_gcrypt:
+ crypto_str = "libgcrypt";
+ break;
+ case libssh2_mbedtls:
+ crypto_str = "mbedTLS";
+ break;
+ case libssh2_openssl:
+ crypto_str = "openssl compatible";
+ break;
+ case libssh2_os400qc3:
+ crypto_str = "OS400QC3";
+ break;
+ case libssh2_wincng:
+ crypto_str = "WinCNG";
+ break;
+ default:
+ crypto_str = NULL;
+ break;
+ }
+ if(crypto_str)
+ infof(data, "libssh2 cryptography backend: %s", crypto_str);
+ }
+#endif
+
/* initialize per-handle data if not already */
if(!data->req.p.ssh) {
result = ssh_setup_connection(data, conn);
@@ -3159,10 +3149,11 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) sshc = &conn->proto.sshc;
+ if(conn->user)
+ infof(data, "User: '%s'", conn->user);
+ else
+ infof(data, "User: NULL");
#ifdef CURL_LIBSSH2_DEBUG
- if(conn->user) {
- infof(data, "User: %s", conn->user);
- }
if(conn->passwd) {
infof(data, "Password: %s", conn->passwd);
}
@@ -3369,6 +3360,71 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done) return result;
}
+static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
+ bool block)
+{
+ int rc;
+
+ if(sshc->initialised) {
+ if(sshc->kh) {
+ libssh2_knownhost_free(sshc->kh);
+ sshc->kh = NULL;
+ }
+
+ if(sshc->ssh_agent) {
+ rc = libssh2_agent_disconnect(sshc->ssh_agent);
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
+ return rc;
+ }
+ if(rc < 0) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect from libssh2 agent: %d %s",
+ rc, err_msg);
+ }
+ libssh2_agent_free(sshc->ssh_agent);
+ sshc->ssh_agent = NULL;
+
+ /* NB: there is no need to free identities, they are part of internal
+ agent stuff */
+ sshc->sshagent_identity = NULL;
+ sshc->sshagent_prev_identity = NULL;
+ }
+
+ if(sshc->ssh_session) {
+ rc = libssh2_session_free(sshc->ssh_session);
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
+ return rc;
+ }
+ if(rc < 0) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
+ }
+ sshc->ssh_session = NULL;
+ }
+
+ /* worst-case scenario cleanup */
+ DEBUGASSERT(sshc->ssh_session == NULL);
+ DEBUGASSERT(sshc->ssh_channel == NULL);
+ DEBUGASSERT(sshc->sftp_session == NULL);
+ DEBUGASSERT(sshc->sftp_handle == NULL);
+ DEBUGASSERT(sshc->kh == NULL);
+ DEBUGASSERT(sshc->ssh_agent == NULL);
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ Curl_safefree(sshc->homedir);
+ sshc->initialised = FALSE;
+ }
+ return 0;
+}
+
+
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
@@ -3386,6 +3442,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data, result = ssh_block_statemach(data, conn, TRUE);
}
+ sshc_cleanup(sshc, data, TRUE);
return result;
}
@@ -3405,6 +3462,7 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status) Curl_safefree(sshp->path);
Curl_dyn_free(&sshp->readdir);
+ Curl_dyn_free(&sshp->readdir_link);
if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
@@ -3542,6 +3600,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, }
DEBUGF(infof(data, "SSH DISCONNECT is done"));
+ sshc_cleanup(sshc, data, TRUE);
return result;
diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h index 4f13ffbb0c..0ed3ffa84e 100644 --- a/libs/libcurl/src/vssh/ssh.h +++ b/libs/libcurl/src/vssh/ssh.h @@ -212,6 +212,7 @@ struct ssh_conn { byte handle[WOLFSSH_MAX_HANDLE];
curl_off_t offset;
#endif /* USE_LIBSSH */
+ BIT(initialised);
};
#ifdef USE_LIBSSH
diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c index 910e5c6d6d..4b278ce62f 100644 --- a/libs/libcurl/src/vssh/wolfssh.c +++ b/libs/libcurl/src/vssh/wolfssh.c @@ -34,7 +34,6 @@ #include "sendf.h"
#include "progress.h"
#include "curl_path.h"
-#include "strtoofft.h"
#include "transfer.h"
#include "speedcheck.h"
#include "select.h"
@@ -71,6 +70,7 @@ static int wssh_getsock(struct Curl_easy *data, curl_socket_t *sock);
static CURLcode wssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
+static void wssh_sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data);
#if 0
/*
@@ -208,7 +208,7 @@ static void state(struct Curl_easy *data, sshstate nowstate) };
/* a precaution to make sure the lists are in sync */
- DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
+ DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST);
if(sshc->state != nowstate) {
infof(data, "wolfssh %p state change from %s to %s",
@@ -264,7 +264,7 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex, rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle,
sshc->handleSz,
&offset[0],
- (byte *)mem, (word32)len);
+ (byte *)CURL_UNCONST(mem), (word32)len);
if(rc == WS_FATAL_ERROR)
rc = wolfSSH_get_error(sshc->ssh_session);
@@ -368,7 +368,7 @@ static int userauth(byte authtype, static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc;
+ struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
@@ -388,7 +388,6 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done) conn->recv[FIRSTSOCKET] = wsftp_recv;
conn->send[FIRSTSOCKET] = wsftp_send;
}
- sshc = &conn->proto.sshc;
sshc->ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
if(!sshc->ctx) {
failf(data, "No wolfSSH context");
@@ -429,8 +428,7 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done) return wssh_multi_statemach(data, done);
error:
- wolfSSH_free(sshc->ssh_session);
- wolfSSH_CTX_free(sshc->ctx);
+ wssh_sshc_cleanup(sshc, data);
return CURLE_FAILED_INIT;
}
@@ -505,7 +503,8 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) }
break;
case SSH_SFTP_REALPATH:
- name = wolfSSH_SFTP_RealPath(sshc->ssh_session, (char *)".");
+ name = wolfSSH_SFTP_RealPath(sshc->ssh_session,
+ (char *)CURL_UNCONST("."));
rc = wolfSSH_get_error(sshc->ssh_session);
if(rc == WS_WANT_READ) {
*block = TRUE;
@@ -810,11 +809,15 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) break;
}
case SSH_SFTP_CLOSE:
- if(sshc->handleSz)
+ if(sshc->handleSz) {
rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle,
sshc->handleSz);
- else
+ if(rc != WS_SUCCESS)
+ rc = wolfSSH_get_error(sshc->ssh_session);
+ }
+ else {
rc = WS_SUCCESS; /* directory listing */
+ }
if(rc == WS_WANT_READ) {
*block = TRUE;
conn->waitfor = KEEP_RECV;
@@ -888,9 +891,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) return CURLE_SSH;
case SSH_SFTP_SHUTDOWN:
- Curl_safefree(sshc->homedir);
- wolfSSH_free(sshc->ssh_session);
- wolfSSH_CTX_free(sshc->ctx);
+ wssh_sshc_cleanup(sshc, data);
state(data, SSH_STOP);
return CURLE_OK;
default:
@@ -1060,6 +1061,20 @@ static CURLcode wssh_done(struct Curl_easy *data, CURLcode status) return result;
}
+static void wssh_sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
+{
+ (void)data;
+ if(sshc->ssh_session) {
+ wolfSSH_free(sshc->ssh_session);
+ sshc->ssh_session = NULL;
+ }
+ if(sshc->ctx) {
+ wolfSSH_CTX_free(sshc->ctx);
+ sshc->ctx = NULL;
+ }
+ Curl_safefree(sshc->homedir);
+}
+
#if 0
static CURLcode wscp_done(struct Curl_easy *data,
CURLcode code, bool premature)
@@ -1085,11 +1100,10 @@ static CURLcode wscp_doing(struct Curl_easy *data, static CURLcode wscp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
+ struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- (void)data;
- (void)conn;
(void)dead_connection;
-
+ wssh_sshc_cleanup(sshc, data);
return result;
}
#endif
@@ -1118,6 +1132,7 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data, struct connectdata *conn,
bool dead)
{
+ struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
(void)dead;
@@ -1129,6 +1144,7 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data, result = wssh_block_statemach(data, TRUE);
}
+ wssh_sshc_cleanup(sshc, data);
DEBUGF(infof(data, "SSH DISCONNECT is done"));
return result;
}
|
