summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vssh/libssh2.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vssh/libssh2.c')
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c1004
1 files changed, 558 insertions, 446 deletions
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index 4f56bb44c..3130dcc74 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -103,30 +103,24 @@ static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);
-static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn);
-static CURLcode ssh_connect(struct connectdata *conn, bool *done);
-static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode ssh_do(struct connectdata *conn, bool *done);
-
-static CURLcode scp_done(struct connectdata *conn,
- CURLcode, bool premature);
-static CURLcode scp_doing(struct connectdata *conn,
- bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
-
-static CURLcode sftp_done(struct connectdata *conn,
- CURLcode, bool premature);
-static CURLcode sftp_doing(struct connectdata *conn,
- bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
-static
-CURLcode sftp_perform(struct connectdata *conn,
- bool *connected,
- bool *dophase_done);
-static int ssh_getsock(struct connectdata *conn, curl_socket_t *sock);
-static int ssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
-static CURLcode ssh_setup_connection(struct connectdata *conn);
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
+static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode ssh_do(struct Curl_easy *data, bool *done);
+static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection);
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
+ bool *dophase_done);
+static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *sock);
+static CURLcode ssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* SCP protocol handler.
@@ -144,12 +138,13 @@ const struct Curl_handler Curl_handler_scp = {
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ssh_perform_getsock, /* perform_getsock */
+ ssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
+ CURLPROTO_SCP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -171,12 +166,13 @@ const struct Curl_handler Curl_handler_sftp = {
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ssh_perform_getsock, /* perform_getsock */
+ ssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -306,8 +302,9 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct connectdata *conn, sshstate nowstate)
+static void state(struct Curl_easy *data, sshstate nowstate)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -378,7 +375,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(conn->data, "SFTP %p state change from %s to %s\n",
+ infof(data, "SFTP %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -432,16 +429,16 @@ static int sshkeycallback(struct Curl_easy *easy,
#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
#endif
-static CURLcode ssh_knownhost(struct connectdata *conn)
+static CURLcode ssh_knownhost(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
- struct Curl_easy *data = conn->data;
-
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
/* we're asked to verify the host against a file */
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
+ struct libssh2_knownhost *host = NULL;
int rc;
int keytype;
size_t keylen;
@@ -456,7 +453,6 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
* What host name does OpenSSH store in its file if an IDN name is
* used?
*/
- struct libssh2_knownhost *host;
enum curl_khmatch keymatch;
curl_sshkeycallback func =
data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
@@ -562,13 +558,19 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
default: /* unknown return codes will equal reject */
/* FALLTHROUGH */
case CURLKHSTAT_REJECT:
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case CURLKHSTAT_DEFER:
/* DEFER means bail out but keep the SSH_HOSTKEY state */
result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
break;
+ case CURLKHSTAT_FINE_REPLACE:
+ /* remove old host+key that doesn't match */
+ if(host)
+ libssh2_knownhost_del(sshc->kh, host);
+ /*FALLTHROUGH*/
case CURLKHSTAT_FINE:
+ /*FALLTHROUGH*/
case CURLKHSTAT_FINE_ADD_TO_FILE:
/* proceed */
if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
@@ -583,7 +585,8 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
if(addrc)
infof(data, "Warning adding the known host %s failed!\n",
conn->host.name);
- else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
+ else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
+ rc == CURLKHSTAT_FINE_REPLACE) {
/* now we write the entire in-memory list of known hosts to the
known_hosts file */
int wrc =
@@ -600,15 +603,15 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
}
}
#else /* HAVE_LIBSSH2_KNOWNHOST_API */
- (void)conn;
+ (void)data;
#endif
return result;
}
-static CURLcode ssh_check_fingerprint(struct connectdata *conn)
+static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
char md5buffer[33];
@@ -635,7 +638,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
else
failf(data,
"Denied establishing ssh session: md5 fingerprint not available");
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
return sshc->actualcode;
}
@@ -643,14 +646,14 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
/* as we already matched, we skip the check for known hosts */
return CURLE_OK;
}
- return ssh_knownhost(conn);
+ return ssh_knownhost(data);
}
/*
* ssh_force_knownhost_key_type() will check the known hosts file and try to
* force a specific public key type from the server if an entry is found.
*/
-static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
@@ -678,8 +681,8 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
= "ssh-dss";
const char *hostkey_method = NULL;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
struct libssh2_knownhost* store = NULL;
const char *kh_name_end = NULL;
size_t kh_name_size = 0;
@@ -754,18 +757,18 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
hostkey_method = hostkey_method_ssh_dss;
break;
case LIBSSH2_KNOWNHOST_KEY_RSA1:
- failf(data, "Found host key type RSA1 which is not supported\n");
+ failf(data, "Found host key type RSA1 which is not supported");
return CURLE_SSH;
default:
- failf(data, "Unknown host key type: %i\n",
+ failf(data, "Unknown host key type: %i",
(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
return CURLE_SSH;
}
infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
result = libssh2_session_error_to_CURLE(
- libssh2_session_method_pref(
- sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
+ libssh2_session_method_pref(
+ sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
}
else {
infof(data, "Did not find host %s in %s\n",
@@ -785,11 +788,11 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
* meaning it wants to be called again when the socket is ready
*/
-static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *sftp_scp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *sshp = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc = LIBSSH2_ERROR_NONE;
@@ -800,7 +803,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*block = 0; /* we're not blocking by default */
do {
-
switch(sshc->state) {
case SSH_INIT:
sshc->secondCreateDirs = 0;
@@ -811,13 +813,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
non-blocking */
libssh2_session_set_blocking(sshc->ssh_session, 0);
- result = ssh_force_knownhost_key_type(conn);
+ result = ssh_force_knownhost_key_type(data);
if(result) {
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
+ sshc->actualcode = result;
break;
}
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
@@ -830,12 +833,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_FAILED_INIT;
break;
}
- state(conn, SSH_HOSTKEY);
+ state(data, SSH_HOSTKEY);
/* FALLTHROUGH */
case SSH_HOSTKEY:
@@ -844,9 +847,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* against our known hosts. How that is handled (reading from file,
* whatever) is up to us.
*/
- result = ssh_check_fingerprint(conn);
+ result = ssh_check_fingerprint(data);
if(!result)
- state(conn, SSH_AUTHLIST);
+ state(data, SSH_AUTHLIST);
/* ssh_check_fingerprint sets state appropriately on error */
break;
@@ -869,14 +872,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(libssh2_userauth_authenticated(sshc->ssh_session)) {
sshc->authed = TRUE;
infof(data, "SSH user accepted with no authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
ssherr = libssh2_session_last_errno(sshc->ssh_session);
if(ssherr == LIBSSH2_ERROR_EAGAIN)
rc = LIBSSH2_ERROR_EAGAIN;
else {
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
}
break;
@@ -884,7 +887,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "SSH authentication methods available: %s\n",
sshc->authlist);
- state(conn, SSH_AUTH_PKEY_INIT);
+ state(data, SSH_AUTH_PKEY_INIT);
break;
case SSH_AUTH_PKEY_INIT:
@@ -956,7 +959,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(out_of_memory || sshc->rsa == NULL) {
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->rsa_pub);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -969,10 +972,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
- state(conn, SSH_AUTH_PKEY);
+ state(data, SSH_AUTH_PKEY);
}
else {
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
}
break;
@@ -995,14 +998,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
infof(data, "Initialized SSH public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
infof(data, "SSH public key authentication failed: %s\n", err_msg);
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1010,10 +1013,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_PASS_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
(strstr(sshc->authlist, "password") != NULL)) {
- state(conn, SSH_AUTH_PASS);
+ state(data, SSH_AUTH_PASS);
}
else {
- state(conn, SSH_AUTH_HOST_INIT);
+ state(data, SSH_AUTH_HOST_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1030,10 +1033,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
infof(data, "Initialized password authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
- state(conn, SSH_AUTH_HOST_INIT);
+ state(data, SSH_AUTH_HOST_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1041,15 +1044,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_HOST_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
(strstr(sshc->authlist, "hostbased") != NULL)) {
- state(conn, SSH_AUTH_HOST);
+ state(data, SSH_AUTH_HOST);
}
else {
- state(conn, SSH_AUTH_AGENT_INIT);
+ state(data, SSH_AUTH_AGENT_INIT);
}
break;
case SSH_AUTH_HOST:
- state(conn, SSH_AUTH_AGENT_INIT);
+ state(data, SSH_AUTH_AGENT_INIT);
break;
case SSH_AUTH_AGENT_INIT:
@@ -1065,7 +1068,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(!sshc->ssh_agent) {
infof(data, "Could not create agent object\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
break;
}
}
@@ -1075,16 +1078,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
if(rc < 0) {
infof(data, "Failure connecting to agent\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
else {
- state(conn, SSH_AUTH_AGENT_LIST);
+ state(data, SSH_AUTH_AGENT_LIST);
}
}
else
#endif /* HAVE_LIBSSH2_AGENT_API */
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
break;
case SSH_AUTH_AGENT_LIST:
@@ -1095,11 +1098,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
if(rc < 0) {
infof(data, "Failure requesting identities to agent\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
else {
- state(conn, SSH_AUTH_AGENT);
+ state(data, SSH_AUTH_AGENT);
sshc->sshagent_prev_identity = NULL;
}
#endif
@@ -1137,10 +1140,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_NONE) {
sshc->authed = TRUE;
infof(data, "Agent based authentication successful\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
#endif
@@ -1149,10 +1152,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_KEY_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
&& (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
- state(conn, SSH_AUTH_KEY);
+ state(data, SSH_AUTH_KEY);
}
else {
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
break;
@@ -1170,13 +1173,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->authed = TRUE;
infof(data, "Initialized keyboard interactive authentication\n");
}
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_DONE:
if(!sshc->authed) {
failf(data, "Authentication failure");
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_LOGIN_DENIED;
break;
}
@@ -1186,17 +1189,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
infof(data, "Authentication complete\n");
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -1215,11 +1218,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
failf(data, "Failure initializing sftp session: %s", err_msg);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_FAILED_INIT;
break;
}
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
break;
case SSH_SFTP_REALPATH:
@@ -1239,11 +1242,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
tempHome[rc] = '\0';
sshc->homedir = strdup(tempHome);
if(!sshc->homedir) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ data->state.most_recent_ftp_entrypath = sshc->homedir;
}
else {
/* Return the error type */
@@ -1255,9 +1258,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
a time-out or similar */
result = CURLE_SSH;
sshc->actualcode = result;
- DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
+ DEBUGF(infof(data, "error = %lu makes libcurl = %d\n",
sftperr, (int)result));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
}
@@ -1266,25 +1269,25 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
since the homedir will remain the same between request but the
working path will not. */
DEBUGF(infof(data, "SSH CONNECT phase done\n"));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
@@ -1292,10 +1295,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -1326,29 +1329,28 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(strcasecompare("pwd", cmd)) {
/* output debug output if that is requested */
char *tmp = aprintf("257 \"%s\" is current directory.\n",
- sftp_scp->path);
+ sshp->path);
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
- }
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"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
current directory can be read very similar to how it is read when
using ordinary FTP. */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
{
@@ -1360,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(cp == NULL) {
failf(data, "Syntax error command '%s'. Missing parameter!",
cmd);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1376,7 +1378,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
@@ -1390,7 +1392,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ) {
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -1402,13 +1406,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else
failf(data, "Syntax error in %s: Bad second parameter", cmd);
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- state(conn, SSH_SFTP_QUOTE_STAT);
+ memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(data, SSH_SFTP_QUOTE_STAT);
break;
}
if(strncasecompare(cmd, "ln ", 3) ||
@@ -1424,17 +1428,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data,
"Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
break;
}
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
- state(conn, SSH_SFTP_QUOTE_MKDIR);
+ state(data, SSH_SFTP_QUOTE_MKDIR);
break;
}
else if(strncasecompare(cmd, "rename ", 7)) {
@@ -1448,26 +1452,26 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_QUOTE_RENAME);
+ state(data, SSH_SFTP_QUOTE_RENAME);
break;
}
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
- state(conn, SSH_SFTP_QUOTE_RMDIR);
+ state(data, SSH_SFTP_QUOTE_RMDIR);
break;
}
else if(strncasecompare(cmd, "rm ", 3)) {
- state(conn, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_UNLINK);
break;
}
#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(conn, SSH_SFTP_QUOTE_STATVFS);
+ state(data, SSH_SFTP_QUOTE_STATVFS);
break;
}
#endif
@@ -1475,7 +1479,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1490,15 +1494,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
}
break;
@@ -1526,7 +1530,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
curlx_uztoui(strlen(sshc->quote_path2)),
LIBSSH2_SFTP_STAT,
- &sshc->quote_attrs);
+ &sshp->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1536,7 +1540,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1545,51 +1549,79 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* Now set the new attributes... */
if(strncasecompare(cmd, "chgrp", 5)) {
- sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
- if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
else if(strncasecompare(cmd, "chmod", 5)) {
- sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
/* permissions are octal */
- if(sshc->quote_attrs.permissions == 0 &&
+ if(sshp->quote_attrs.permissions == 0 &&
!ISDIGIT(sshc->quote_path1[0])) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
else if(strncasecompare(cmd, "chown", 5)) {
- sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
- if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
+ else if(strncasecompare(cmd, "atime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect access date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ sshp->quote_attrs.atime = (unsigned long)date;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
+ }
+ else if(strncasecompare(cmd, "mtime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect modification date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ sshp->quote_attrs.mtime = (unsigned long)date;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
+ }
/* Now send the completed structure... */
- state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ state(data, SSH_SFTP_QUOTE_SETSTAT);
break;
}
@@ -1597,7 +1629,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
curlx_uztoui(strlen(sshc->quote_path2)),
LIBSSH2_SFTP_SETSTAT,
- &sshc->quote_attrs);
+ &sshp->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1607,12 +1639,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1630,12 +1662,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1650,12 +1682,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1676,12 +1708,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1695,12 +1727,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1713,12 +1745,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
#ifdef HAS_STATVFS_SUPPORT
@@ -1737,7 +1769,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1758,30 +1790,30 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
statvfs.f_namemax);
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
#endif
case SSH_SFTP_GETINFO:
{
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
}
@@ -1790,8 +1822,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -1800,18 +1832,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->info.filetime = attrs.mtime;
}
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
- if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ if(sshp->path[strlen(sshp->path)-1] == '/')
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
@@ -1828,8 +1860,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from != 0) {
LIBSSH2_SFTP_ATTRIBUTES attrs;
if(data->state.resume_from < 0) {
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -1855,12 +1887,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
flags, data->set.new_file_perms,
LIBSSH2_SFTP_OPENFILE);
@@ -1878,7 +1910,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
if(sshc->secondCreateDirs) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
failf(data, "Creating the dir/file failed: %s",
@@ -1889,14 +1921,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(sftperr == LIBSSH2_FX_FAILURE) ||
(sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
(data->set.ftp_create_missing_dirs &&
- (strlen(sftp_scp->path) > 1))) {
+ (strlen(sshp->path) > 1))) {
/* try to create the path remotely */
rc = 0; /* clear rc and continue */
sshc->secondCreateDirs = 1;
- state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ state(data, SSH_SFTP_CREATE_DIRS_INIT);
break;
}
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
if(!sshc->actualcode) {
@@ -1906,7 +1938,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_SSH;
sftperr = LIBSSH2_FX_OK;
}
- failf(data, "Upload failed: %s (%d/%d)",
+ failf(data, "Upload failed: %s (%lu/%d)",
sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_strerror(sftperr):"ssh error",
sftperr, rc);
@@ -1975,7 +2007,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
@@ -1993,18 +2025,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
case SSH_SFTP_CREATE_DIRS_INIT:
- if(strlen(sftp_scp->path) > 1) {
- sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
- state(conn, SSH_SFTP_CREATE_DIRS);
+ if(strlen(sshp->path) > 1) {
+ sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
+ state(data, SSH_SFTP_CREATE_DIRS);
}
else {
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -2013,17 +2045,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
- infof(data, "Creating directory '%s'\n", sftp_scp->path);
- state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ infof(data, "Creating directory '%s'\n", sshp->path);
+ state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
/* 'mode' - parameter is preliminary - default to 0644 */
- rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
data->set.new_directory_perms);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -2041,19 +2073,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(sftperr != LIBSSH2_FX_FAILURE) &&
(sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
result = sftp_libssh2_error_to_CURLE(sftperr);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
rc = 0; /* clear rc and continue */
}
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2062,9 +2094,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* listing
*/
sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
- sftp_scp->path,
+ sshp->path,
curlx_uztoui(
- strlen(sftp_scp->path)),
+ strlen(sshp->path)),
0, 0, LIBSSH2_SFTP_OPENDIR);
if(!sshc->sftp_handle) {
if(libssh2_session_last_errno(sshc->ssh_session) ==
@@ -2075,51 +2107,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open directory for reading: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- sshc->readdir_filename = malloc(PATH_MAX + 1);
- if(!sshc->readdir_filename) {
- state(conn, SSH_SFTP_CLOSE);
+ sshp->readdir_filename = malloc(PATH_MAX + 1);
+ if(!sshp->readdir_filename) {
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- sshc->readdir_longentry = malloc(PATH_MAX + 1);
- if(!sshc->readdir_longentry) {
- Curl_safefree(sshc->readdir_filename);
- state(conn, SSH_SFTP_CLOSE);
+ sshp->readdir_longentry = malloc(PATH_MAX + 1);
+ if(!sshp->readdir_longentry) {
+ Curl_safefree(sshp->readdir_filename);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- Curl_dyn_init(&sshc->readdir, PATH_MAX * 2);
- state(conn, SSH_SFTP_READDIR);
+ Curl_dyn_init(&sshp->readdir, PATH_MAX * 2);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
- sshc->readdir_filename,
+ sshp->readdir_filename,
PATH_MAX,
- sshc->readdir_longentry,
+ sshp->readdir_longentry,
PATH_MAX,
- &sshc->readdir_attrs);
+ &sshp->readdir_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
if(rc > 0) {
readdir_len = (size_t) rc;
- sshc->readdir_filename[readdir_len] = '\0';
+ sshp->readdir_filename[readdir_len] = '\0';
if(data->set.ftp_list_only) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- sshc->readdir_filename,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ sshp->readdir_filename,
readdir_len);
if(!result)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)"\n", 1);
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
/* since this counts what we send to the client, we include the
@@ -2127,39 +2159,37 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->req.bytecount += readdir_len + 1;
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename,
- readdir_len);
- Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
- }
+ Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
+ readdir_len);
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
}
else {
- result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry);
+ result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
if(!result) {
- if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
- ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
- Curl_dyn_init(&sshc->readdir_link, PATH_MAX);
- result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path);
- state(conn, SSH_SFTP_READDIR_LINK);
+ Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
+ result = Curl_dyn_add(&sshp->readdir_link, sshp->path);
+ state(data, SSH_SFTP_READDIR_LINK);
if(!result)
break;
}
else {
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
sshc->actualcode = result;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
break;
}
}
else if(rc == 0) {
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_READDIR_DONE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_READDIR_DONE);
break;
}
else if(rc < 0) {
@@ -2169,9 +2199,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Could not open remote file for reading: %s :: %d",
sftp_libssh2_strerror(sftperr),
libssh2_session_last_errno(sshc->ssh_session));
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_CLOSE);
break;
}
break;
@@ -2179,55 +2209,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_LINK:
rc =
libssh2_sftp_symlink_ex(sshc->sftp_session,
- Curl_dyn_ptr(&sshc->readdir_link),
- (int)Curl_dyn_len(&sshc->readdir_link),
- sshc->readdir_filename,
+ Curl_dyn_ptr(&sshp->readdir_link),
+ (int)Curl_dyn_len(&sshp->readdir_link),
+ sshp->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- readdir_len = (size_t) rc;
- Curl_dyn_free(&sshc->readdir_link);
+ Curl_dyn_free(&sshp->readdir_link);
/* append filename and extra output */
- result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename);
+ result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
if(result) {
sshc->readdir_line = NULL;
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
case SSH_SFTP_READDIR_BOTTOM:
- result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
+ result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
if(!result)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&sshc->readdir),
- Curl_dyn_len(&sshc->readdir));
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&sshp->readdir),
+ Curl_dyn_len(&sshp->readdir));
if(!result) {
-
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_IN,
- Curl_dyn_ptr(&sshc->readdir),
- Curl_dyn_len(&sshc->readdir));
- }
- data->req.bytecount += Curl_dyn_len(&sshc->readdir);
+ Curl_debug(data, CURLINFO_DATA_IN,
+ Curl_dyn_ptr(&sshp->readdir),
+ Curl_dyn_len(&sshp->readdir));
+ data->req.bytecount += Curl_dyn_len(&sshp->readdir);
}
if(result) {
- Curl_dyn_free(&sshc->readdir);
- state(conn, SSH_STOP);
+ Curl_dyn_free(&sshp->readdir);
+ state(data, SSH_STOP);
}
else {
- Curl_dyn_reset(&sshc->readdir);
- state(conn, SSH_SFTP_READDIR);
+ Curl_dyn_reset(&sshp->readdir);
+ state(data, SSH_SFTP_READDIR);
}
break;
@@ -2238,12 +2264,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
sshc->sftp_handle = NULL;
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -2251,8 +2277,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* Work on getting the specified file
*/
sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_FXF_READ, data->set.new_file_perms,
LIBSSH2_SFTP_OPENFILE);
if(!sshc->sftp_handle) {
@@ -2264,20 +2290,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open remote file for reading: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -2302,14 +2328,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME;
}
- if(conn->data->state.use_range) {
+ if(data->state.use_range) {
curl_off_t from, to;
char *ptr;
char *ptr2;
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
@@ -2340,7 +2366,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
size = to - from + 1;
}
- SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
+ SFTP_SEEK(sshc->sftp_handle, from);
}
data->req.size = size;
data->req.maxdownload = size;
@@ -2383,7 +2409,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -2399,11 +2425,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -2422,7 +2448,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->sftp_handle = NULL;
}
- Curl_safefree(sftp_scp->path);
+ Curl_safefree(sshp->path);
DEBUGF(infof(data, "SFTP DONE done\n"));
@@ -2431,11 +2457,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -2470,16 +2496,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
break;
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2487,13 +2513,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
}
- state(conn, SSH_SCP_UPLOAD_INIT);
+ state(data, SSH_SCP_UPLOAD_INIT);
}
else {
- state(conn, SSH_SCP_DOWNLOAD_INIT);
+ state(data, SSH_SCP_DOWNLOAD_INIT);
}
break;
@@ -2505,7 +2531,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* directory in the path.
*/
sshc->ssh_channel =
- SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
+ SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
data->state.infilesize);
if(!sshc->ssh_channel) {
int ssh_err;
@@ -2519,8 +2545,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0));
- failf(conn->data, "%s", err_msg);
- state(conn, SSH_SCP_CHANNEL_FREE);
+ failf(data, "%s", err_msg);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
/* Map generic errors to upload failed */
if(sshc->actualcode == CURLE_SSH ||
@@ -2538,7 +2564,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = result;
}
else {
@@ -2551,7 +2577,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_OUT;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -2573,12 +2599,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
struct stat sb;
memset(&sb, 0, sizeof(struct stat));
sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
- sftp_scp->path, &sb);
+ sshp->path, &sb);
#else
libssh2_struct_stat sb;
memset(&sb, 0, sizeof(libssh2_struct_stat));
sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
- sftp_scp->path, &sb);
+ sshp->path, &sb);
#endif
if(!sshc->ssh_channel) {
@@ -2594,8 +2620,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0));
- failf(conn->data, "%s", err_msg);
- state(conn, SSH_SCP_CHANNEL_FREE);
+ failf(data, "%s", err_msg);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
break;
}
@@ -2614,19 +2640,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->cselect_bits = CURL_CSELECT_IN;
if(result) {
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = result;
}
else
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
case SSH_SCP_DONE:
if(data->set.upload)
- state(conn, SSH_SCP_SEND_EOF);
+ state(data, SSH_SCP_SEND_EOF);
else
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -2643,7 +2669,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc, err_msg);
}
}
- state(conn, SSH_SCP_WAIT_EOF);
+ state(data, SSH_SCP_WAIT_EOF);
break;
case SSH_SCP_WAIT_EOF:
@@ -2659,7 +2685,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
}
}
- state(conn, SSH_SCP_WAIT_CLOSE);
+ state(data, SSH_SCP_WAIT_CLOSE);
break;
case SSH_SCP_WAIT_CLOSE:
@@ -2675,7 +2701,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
}
}
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -2695,9 +2721,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
DEBUGF(infof(data, "SCP DONE phase complete\n"));
#if 0 /* PREV */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
#endif
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
break;
@@ -2735,9 +2761,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
break;
case SSH_SESSION_FREE:
@@ -2805,11 +2831,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
Curl_safefree(sshc->homedir);
-
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
Curl_safefree(sshc->readdir_line);
- Curl_dyn_free(&sshc->readdir);
/* the code we are about to return */
result = sshc->actualcode;
@@ -2819,7 +2841,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_QUIT:
@@ -2827,7 +2849,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2844,11 +2866,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int ssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int ssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
int bitmap = GETSOCK_BLANK;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
@@ -2859,32 +2882,8 @@ static int ssh_perform_getsock(const struct connectdata *conn,
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
return bitmap;
-#else
- /* if we don't know the direction we can use the generic *_getsock()
- function even for the protocol_connect and doing states */
- return Curl_single_getsock(conn, sock);
-#endif
-}
-
-/* Generic function called by the multi interface to figure out what socket(s)
- to wait for and for what actions during the DOING and PROTOCONNECT states*/
-static int ssh_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
-#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
- (void)conn;
- (void)sock;
- /* if we don't know any direction we can just play along as we used to and
- not provide any sensible info */
- return GETSOCK_BLANK;
-#else
- /* if we know the direction we can use the generic *_getsock() function even
- for the protocol_connect and doing states */
- return ssh_perform_getsock(conn, sock);
-#endif
}
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
/*
* When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
* function is used to figure out in what direction and stores this info so
@@ -2892,8 +2891,9 @@ static int ssh_getsock(struct connectdata *conn,
* function in all cases so that when it _doesn't_ return EAGAIN we can
* restore the default wait bits.
*/
-static void ssh_block2waitfor(struct connectdata *conn, bool block)
+static void ssh_block2waitfor(struct Curl_easy *data, bool block)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
int dir = 0;
if(block) {
@@ -2909,46 +2909,43 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
the original set */
conn->waitfor = sshc->orig_waitfor;
}
-#else
- /* no libssh2 directional support so we simply don't know */
-#define ssh_block2waitfor(x,y) Curl_nop_stmt
-#endif
/* called repeatedly until done from multi.c */
-static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
do {
- result = ssh_statemach_act(conn, &block);
+ result = ssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */
} while(!result && !*done && !block);
- ssh_block2waitfor(conn, block);
+ ssh_block2waitfor(data, block);
return result;
}
-static CURLcode ssh_block_statemach(struct connectdata *conn,
- bool duringconnect)
+static CURLcode ssh_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool duringconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = ssh_statemach_act(conn, &block);
+ result = ssh_statemach_act(data, &block);
if(result)
break;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -2961,7 +2958,6 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
if(block) {
int dir = libssh2_session_block_directions(sshc->ssh_session);
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -2975,8 +2971,6 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
(void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
left>1000?1000:left);
}
-#endif
-
}
return result;
@@ -2985,11 +2979,13 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
/*
* SSH setup and connection
*/
-static CURLcode ssh_setup_connection(struct connectdata *conn)
+static CURLcode ssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -2999,36 +2995,83 @@ static CURLcode ssh_setup_connection(struct connectdata *conn)
static Curl_recv scp_recv, sftp_recv;
static Curl_send scp_send, sftp_send;
+#ifndef CURL_DISABLE_PROXY
+static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
+ size_t length, int flags, void **abstract)
+{
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
+ ssize_t nread;
+ CURLcode result;
+ struct connectdata *conn = data->conn;
+ Curl_recv *backup = conn->recv[0];
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void)flags;
+
+ /* swap in the TLS reader function for this call only, and then swap back
+ the SSH one again */
+ conn->recv[0] = ssh->tls_recv;
+ result = Curl_read(data, sock, buffer, length, &nread);
+ conn->recv[0] = backup;
+ if(result == CURLE_AGAIN)
+ 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);
+ return nread;
+}
+
+static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
+ size_t length, int flags, void **abstract)
+{
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
+ ssize_t nwrite;
+ CURLcode result;
+ struct connectdata *conn = data->conn;
+ Curl_send *backup = conn->send[0];
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void)flags;
+
+ /* swap in the TLS writer function for this call only, and then swap back
+ the SSH one again */
+ conn->send[0] = ssh->tls_send;
+ result = Curl_write(data, sock, buffer, length, &nwrite);
+ conn->send[0] = backup;
+ if(result == CURLE_AGAIN)
+ return -EAGAIN; /* magic return code for libssh2 */
+ else if(result)
+ return -1; /* error */
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
+ return nwrite;
+}
+#endif
+
/*
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
*/
-static CURLcode ssh_connect(struct connectdata *conn, bool *done)
+static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
{
#ifdef CURL_LIBSSH2_DEBUG
curl_socket_t sock;
#endif
- struct ssh_conn *ssh;
+ struct SSHPROTO *sshp = data->req.p.ssh;
+ struct ssh_conn *sshc;
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- ssh_setup_connection(conn);
+ if(!sshp) {
+ result = ssh_setup_connection(data, conn);
+ if(result)
+ return result;
+ sshp = data->req.p.ssh;
+ }
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
connkeep(conn, "SSH default");
- if(conn->handler->protocol & CURLPROTO_SCP) {
- conn->recv[FIRSTSOCKET] = scp_recv;
- conn->send[FIRSTSOCKET] = scp_send;
- }
- else {
- conn->recv[FIRSTSOCKET] = sftp_recv;
- conn->send[FIRSTSOCKET] = sftp_send;
- }
- ssh = &conn->proto.sshc;
+ sshc = &conn->proto.sshc;
#ifdef CURL_LIBSSH2_DEBUG
if(conn->user) {
@@ -3040,17 +3083,72 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
sock = conn->sock[FIRSTSOCKET];
#endif /* CURL_LIBSSH2_DEBUG */
- ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
- my_libssh2_free,
- my_libssh2_realloc, conn);
- if(ssh->ssh_session == NULL) {
+ sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
+ my_libssh2_free,
+ my_libssh2_realloc, data);
+ if(sshc->ssh_session == NULL) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
+#ifndef CURL_DISABLE_PROXY
+ if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ /*
+ * This crazy union dance is here to avoid assigning a void pointer a
+ * function pointer as it is invalid C. The problem is of course that
+ * libssh2 has such an API...
+ */
+ union receive {
+ void *recvp;
+ ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
+ };
+ union transfer {
+ void *sendp;
+ ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
+ };
+ union receive sshrecv;
+ union transfer sshsend;
+
+ sshrecv.recvptr = ssh_tls_recv;
+ sshsend.sendptr = ssh_tls_send;
+
+ infof(data, "Uses HTTPS proxy!\n");
+ /*
+ Setup libssh2 callbacks to make it read/write TLS from the socket.
+
+ ssize_t
+ recvcb(libssh2_socket_t sock, void *buffer, size_t length,
+ int flags, void **abstract);
+
+ ssize_t
+ sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
+ int flags, void **abstract);
+
+ */
+ libssh2_session_callback_set(sshc->ssh_session,
+ LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
+ libssh2_session_callback_set(sshc->ssh_session,
+ LIBSSH2_CALLBACK_SEND, sshsend.sendp);
+
+ /* Store the underlying TLS recv/send function pointers to be used when
+ reading from the proxy */
+ sshc->tls_recv = conn->recv[FIRSTSOCKET];
+ sshc->tls_send = conn->send[FIRSTSOCKET];
+ }
+
+#endif /* CURL_DISABLE_PROXY */
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ conn->recv[FIRSTSOCKET] = scp_recv;
+ conn->send[FIRSTSOCKET] = scp_send;
+ }
+ else {
+ conn->recv[FIRSTSOCKET] = sftp_recv;
+ conn->send[FIRSTSOCKET] = sftp_send;
+ }
+
if(data->set.ssh_compression) {
#if LIBSSH2_VERSION_NUM >= 0x010208
- if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
+ if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
#endif
infof(data, "Failed to enable compression for ssh session\n");
}
@@ -3058,14 +3156,14 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
int rc;
- ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
- if(!ssh->kh) {
- libssh2_session_free(ssh->ssh_session);
+ sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
+ if(!sshc->kh) {
+ libssh2_session_free(sshc->ssh_session);
return CURLE_FAILED_INIT;
}
/* read all known hosts from there */
- rc = libssh2_knownhost_readfile(ssh->kh,
+ rc = libssh2_knownhost_readfile(sshc->kh,
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(rc < 0)
@@ -3075,13 +3173,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
#ifdef CURL_LIBSSH2_DEBUG
- libssh2_trace(ssh->ssh_session, ~0);
+ libssh2_trace(sshc->ssh_session, ~0);
infof(data, "SSH socket: %d\n", (int)sock);
#endif /* CURL_LIBSSH2_DEBUG */
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
- result = ssh_multi_statemach(conn, done);
+ result = ssh_multi_statemach(data, done);
return result;
}
@@ -3096,40 +3194,41 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
*/
static
-CURLcode scp_perform(struct connectdata *conn,
- bool *connected,
- bool *dophase_done)
+CURLcode scp_perform(struct Curl_easy *data,
+ bool *connected,
+ bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SCP_TRANS_INIT);
+ state(data, SSH_SCP_TRANS_INIT);
/* run the state-machine */
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode scp_doing(struct connectdata *conn,
- bool *dophase_done)
+static CURLcode scp_doing(struct Curl_easy *data,
+ bool *dophase_done)
{
CURLcode result;
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -3139,11 +3238,11 @@ static CURLcode scp_doing(struct connectdata *conn,
* separate ones but this way means less duplicated code.
*/
-static CURLcode ssh_do(struct connectdata *conn, bool *done)
+static CURLcode ssh_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -3160,9 +3259,9 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = scp_perform(conn, &connected, done);
+ result = scp_perform(data, &connected, done);
else
- result = sftp_perform(conn, &connected, done);
+ result = sftp_perform(data, &connected, done);
return result;
}
@@ -3170,18 +3269,20 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
/* 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 */
-static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ 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's a session still around to use! */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(data, conn, FALSE);
}
return result;
@@ -3189,51 +3290,56 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *sftp_scp = conn->data->req.protop;
+ struct SSHPROTO *sshp = data->req.p.ssh;
+ struct connectdata *conn = data->conn;
if(!status) {
/* run the state-machine */
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(data, conn, FALSE);
}
else
result = status;
- if(sftp_scp)
- Curl_safefree(sftp_scp->path);
- if(Curl_pgrsDone(conn))
+ Curl_safefree(sshp->path);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ Curl_dyn_free(&sshp->readdir);
+
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
-static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void)premature; /* not used */
if(!status)
- state(conn, SSH_SCP_DONE);
+ state(data, SSH_SCP_DONE);
- return ssh_done(conn, status);
+ return ssh_done(data, status);
}
-static ssize_t scp_send(struct connectdata *conn, int sockindex,
+static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_write() returns int! */
- nwrite = (ssize_t)
- libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
+ nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3247,17 +3353,18 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
-static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_read() returns int */
- nread = (ssize_t)
- libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
+ nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
@@ -3280,39 +3387,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = ssh_multi_statemach(conn, dophase_done);
+ CURLcode result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -3320,53 +3427,56 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* 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 */
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
CURLcode result = CURLE_OK;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
- if(conn->proto.sshc.ssh_session) {
+ if(sshc->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(conn, FALSE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = ssh_block_statemach(data, conn, FALSE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
- if(!premature && conn->data->set.postquote && !conn->bits.retry)
+ if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
}
- return ssh_done(conn, status);
+ return ssh_done(data, status);
}
/* return number of sent bytes */
-static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
- ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
- but is changed to ssize_t in 0.15. These days we don't
- support libssh2 0.15*/
+ ssize_t nwrite;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex;
- nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
+ nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3384,15 +3494,17 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex;
- nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
+ nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;