← Commit list

1e85cb4b7b

Stefan Eissing
Stefan Eissing
2025-10-31
SUCCESS Duration: 149s

Subject

scp/sftp: fix disconnect

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/vssh/libssh.c+45 -16
@@ -1979,13 +1979,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
rc = myssh_in_SFTP_REALPATH(data, sshc);
break;
case SSH_SFTP_QUOTE_INIT:
- rc = myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp);
+ rc = sshp ? myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_POSTQUOTE_INIT:
rc = myssh_in_SFTP_POSTQUOTE_INIT(data, sshc);
break;
case SSH_SFTP_QUOTE:
- rc = myssh_in_SFTP_QUOTE(data, sshc, sshp);
+ rc = sshp ? myssh_in_SFTP_QUOTE(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_NEXT_QUOTE:
rc = myssh_in_SFTP_NEXT_QUOTE(data, sshc);
@@ -2115,7 +2117,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
case SSH_SFTP_FILETIME: {
sftp_attributes attrs;
-
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
attrs = sftp_stat(sshc->sftp_session, sshp->path);
if(attrs) {
data->info.filetime = attrs->mtime;
@@ -2129,20 +2134,27 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
case SSH_SFTP_TRANS_INIT:
if(data->state.upload)
myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
- else {
+ else if(sshp) {
if(sshp->path[strlen(sshp->path)-1] == '/')
myssh_to(data, sshc, SSH_SFTP_READDIR_INIT);
else
myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
}
+ else
+ result = CURLE_FAILED_INIT;
break;
case SSH_SFTP_UPLOAD_INIT:
- rc = myssh_in_UPLOAD_INIT(data, sshc, sshp);
+ rc = sshp ? myssh_in_UPLOAD_INIT(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_CREATE_DIRS_INIT:
- if(strlen(sshp->path) > 1) {
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
+ else if(strlen(sshp->path) > 1) {
sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
}
@@ -2153,7 +2165,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
case SSH_SFTP_CREATE_DIRS:
sshc->slash_pos = strchr(sshc->slash_pos, '/');
- if(sshc->slash_pos) {
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
+ else if(sshc->slash_pos) {
*sshc->slash_pos = 0;
infof(data, "Creating directory '%s'", sshp->path);
@@ -2165,6 +2181,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
case SSH_SFTP_CREATE_DIRS_MKDIR:
/* 'mode' - parameter is preliminary - default to 0644 */
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
rc = sftp_mkdir(sshc->sftp_session, sshp->path,
(mode_t)data->set.new_directory_perms);
*sshc->slash_pos = '/';
@@ -2188,10 +2208,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
break;
case SSH_SFTP_READDIR_INIT:
- rc = myssh_in_SFTP_READDIR_INIT(data, sshc, sshp);
+ rc = sshp ? myssh_in_SFTP_READDIR_INIT(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_READDIR:
- rc = myssh_in_SFTP_READDIR(data, sshc, sshp);
+ rc = sshp ? myssh_in_SFTP_READDIR(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_READDIR_LINK:
rc = myssh_in_SFTP_READDIR_LINK(data, sshc);
@@ -2203,19 +2225,25 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
rc = myssh_in_SFTP_READDIR_DONE(data, sshc);
break;
case SSH_SFTP_DOWNLOAD_INIT:
- rc = myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp);
+ rc = sshp ? myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_DOWNLOAD_STAT:
rc = myssh_in_SFTP_DOWNLOAD_STAT(data, sshc);
break;
case SSH_SFTP_CLOSE:
- rc = myssh_in_SFTP_CLOSE(data, sshc, sshp);
+ rc = sshp ? myssh_in_SFTP_CLOSE(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_SHUTDOWN:
rc = myssh_in_SFTP_SHUTDOWN(data, sshc);
break;
case SSH_SCP_TRANS_INIT:
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
@@ -2252,7 +2280,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data,
break;
case SSH_SCP_UPLOAD_INIT:
-
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
@@ -2832,11 +2863,9 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
(void)dead_connection;
- if(sshc && sshc->ssh_session && sshp) {
+ if(sshc && sshc->ssh_session) {
/* only if there is a session still around to use! */
-
myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
-
result = myssh_block_statemach(data, sshc, sshp, TRUE);
}
@@ -3012,7 +3041,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
- if(sshc && sshc->ssh_session && sshp) {
+ if(sshc && sshc->ssh_session) {
/* only if there is a session still around to use! */
myssh_to(data, sshc, SSH_SFTP_SHUTDOWN);
result = myssh_block_statemach(data, sshc, sshp, TRUE);
lib/vssh/libssh2.c+75 -38
@@ -826,7 +826,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
char *errmsg = NULL;
int errlen;
libssh2_session_last_error(sshc->ssh_session, &errmsg, &errlen, 0);
- failf(data, "libssh2: %s", errmsg);
+ failf(data, "libssh2 method '%s' failed: %s", hostkey_method, errmsg);
result = libssh2_session_error_to_CURLE(rc);
}
}
@@ -2721,11 +2721,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_REALPATH:
- result = ssh_state_sftp_realpath(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_realpath(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_QUOTE_INIT:
- result = ssh_state_sftp_quote_init(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_quote_init(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_POSTQUOTE_INIT:
@@ -2733,7 +2735,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_QUOTE:
- result = ssh_state_sftp_quote(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_quote(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_NEXT_QUOTE:
@@ -2741,11 +2744,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_QUOTE_STAT:
- result = ssh_state_sftp_quote_stat(data, sshc, sshp, block);
+ result = sshp ? ssh_state_sftp_quote_stat(data, sshc, sshp, block) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_QUOTE_SETSTAT:
- result = ssh_state_sftp_quote_setstat(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_quote_setstat(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -2784,10 +2789,15 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
case SSH_SFTP_FILETIME:
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
+ int rc;
- int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
- curlx_uztoui(strlen(sshp->path)),
- LIBSSH2_SFTP_STAT, &attrs);
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
+ LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
result = CURLE_AGAIN;
break;
@@ -2803,16 +2813,19 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
case SSH_SFTP_TRANS_INIT:
if(data->state.upload)
myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
- else {
+ else if(sshp) {
if(sshp->path[strlen(sshp->path)-1] == '/')
myssh_state(data, sshc, SSH_SFTP_READDIR_INIT);
else
myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
}
+ else
+ result = CURLE_FAILED_INIT;
break;
case SSH_SFTP_UPLOAD_INIT:
- result = sftp_upload_init(data, sshc, sshp, block);
+ result = sshp ? sftp_upload_init(data, sshc, sshp, block) :
+ CURLE_FAILED_INIT;
if(result) {
myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
@@ -2820,7 +2833,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_CREATE_DIRS_INIT:
- if(strlen(sshp->path) > 1) {
+ if(!sshp)
+ result = CURLE_FAILED_INIT;
+ else if(strlen(sshp->path) > 1) {
sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
}
@@ -2830,6 +2845,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_CREATE_DIRS:
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
sshc->slash_pos = strchr(sshc->slash_pos, '/');
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
@@ -2842,25 +2861,33 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
- result = ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_READDIR_INIT:
- result = ssh_state_sftp_readdir_init(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_readdir_init(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_READDIR:
- result = sftp_readdir(data, sshc, sshp, block);
+ result = sshp ? sftp_readdir(data, sshc, sshp, block) :
+ CURLE_FAILED_INIT;
if(result) {
myssh_state(data, sshc, SSH_SFTP_CLOSE);
}
break;
case SSH_SFTP_READDIR_LINK:
- result = ssh_state_sftp_readdir_link(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_readdir_link(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_READDIR_BOTTOM:
+ if(!sshp) {
+ result = CURLE_FAILED_INIT;
+ break;
+ }
result = curlx_dyn_addn(&sshp->readdir, "\n", 1);
if(!result)
result = Curl_client_write(data, CLIENTWRITE_BODY,
@@ -2890,11 +2917,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_DOWNLOAD_INIT:
- result = ssh_state_sftp_download_init(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_download_init(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_DOWNLOAD_STAT:
- result = sftp_download_stat(data, sshc, sshp, block);
+ result = sshp ? sftp_download_stat(data, sshc, sshp, block) :
+ CURLE_FAILED_INIT;
if(result) {
myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
@@ -2902,7 +2931,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SFTP_CLOSE:
- result = ssh_state_sftp_close(data, sshc, sshp);
+ result = sshp ? ssh_state_sftp_close(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SFTP_SHUTDOWN:
@@ -2910,7 +2940,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
+ result = sshp ? Curl_getworkingpath(data, sshc->homedir, &sshp->path) :
+ CURLE_FAILED_INIT;
if(result) {
myssh_state(data, sshc, SSH_STOP);
break;
@@ -2931,11 +2962,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data,
break;
case SSH_SCP_UPLOAD_INIT:
- result = ssh_state_scp_upload_init(data, sshc, sshp);
+ result = sshp ? ssh_state_scp_upload_init(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SCP_DOWNLOAD_INIT:
- result = ssh_state_scp_download_init(data, sshc, sshp);
+ result = sshp ? ssh_state_scp_download_init(data, sshc, sshp) :
+ CURLE_FAILED_INIT;
break;
case SSH_SCP_DONE:
@@ -3559,9 +3592,6 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
if(sshc->ssh_agent) {
rc = libssh2_agent_disconnect(sshc->ssh_agent);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
- return CURLE_AGAIN;
-
if((rc < 0) && data) {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
@@ -3569,6 +3599,9 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
infof(data, "Failed to disconnect from libssh2 agent: %d %s",
rc, err_msg);
}
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
libssh2_agent_free(sshc->ssh_agent);
sshc->ssh_agent = NULL;
@@ -3580,23 +3613,20 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
if(sshc->sftp_handle) {
rc = libssh2_sftp_close(sshc->sftp_handle);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
- return CURLE_AGAIN;
-
if((rc < 0) && data) {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
NULL, 0);
infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
}
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
sshc->sftp_handle = NULL;
}
if(sshc->ssh_channel) {
rc = libssh2_channel_free(sshc->ssh_channel);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
- return CURLE_AGAIN;
-
if((rc < 0) && data) {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
@@ -3604,30 +3634,37 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
infof(data, "Failed to free libssh2 scp subsystem: %d %s",
rc, err_msg);
}
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
sshc->ssh_channel = NULL;
}
if(sshc->sftp_session) {
rc = libssh2_sftp_shutdown(sshc->sftp_session);
+ if((rc < 0) && data) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to stop libssh2 sftp subsystem: %d %s", rc, err_msg);
+ }
if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
return CURLE_AGAIN;
- if((rc < 0) && data)
- infof(data, "Failed to stop libssh2 sftp subsystem");
sshc->sftp_session = NULL;
}
if(sshc->ssh_session) {
rc = libssh2_session_free(sshc->ssh_session);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
- return CURLE_AGAIN;
-
if((rc < 0) && data) {
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);
}
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
sshc->ssh_session = NULL;
}
@@ -3661,7 +3698,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
(void)dead_connection;
- if(sshc && sshc->ssh_session && sshp) {
+ if(sshc && sshc->ssh_session) {
/* only if there is a session still around to use! */
myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
result = ssh_block_statemach(data, sshc, sshp, TRUE);
@@ -3834,7 +3871,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
(void)dead_connection;
if(sshc) {
- if(sshc->ssh_session && sshp) {
+ if(sshc->ssh_session) {
/* only if there is a session still around to use! */
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
myssh_state(data, sshc, SSH_SFTP_SHUTDOWN);