From: Daniel Stenberg Date: Fri, 16 May 2025 12:11:54 +0000 (+0200) Subject: libssh2: remove the 'actualcode' struct field X-Git-Tag: curl-8_14_0~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=74cfba6a6729b8db6f06f7dcb73bae0af07101cb;p=thirdparty%2Fcurl.git libssh2: remove the 'actualcode' struct field Return and use CURLcode to a larger extent to avoid the complicated double return code setup previously used. Closes #17369 --- diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index 0509615636..3e8aade54b 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -106,8 +106,8 @@ static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn, static CURLcode ssh_setup_connection(struct Curl_easy *data, struct connectdata *conn); static void ssh_attach(struct Curl_easy *data, struct connectdata *conn); -static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, - bool block); +static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, + bool block); /* * SCP protocol handler. */ @@ -548,7 +548,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data, FALLTHROUGH(); case CURLKHSTAT_DEFER: /* DEFER means bail out but keep the SSH_HOSTKEY state */ - result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + result = CURLE_PEER_FAILED_VERIFICATION; break; case CURLKHSTAT_FINE_REPLACE: /* remove old host+key that does not match */ @@ -629,8 +629,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, "Denied establishing ssh session: sha256 fingerprint " "not available"); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } /* The length of fingerprint is 32 bytes for SHA256. @@ -638,15 +637,13 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, if(curlx_base64_encode(fingerprint, 32, &fingerprint_b64, &fingerprint_b64_len) != CURLE_OK) { myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } if(!fingerprint_b64) { failf(data, "sha256 fingerprint could not be encoded"); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64); @@ -672,8 +669,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256); free(fingerprint_b64); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } free(fingerprint_b64); @@ -712,8 +708,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, "not available"); } myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } infof(data, "MD5 checksum match"); } @@ -734,14 +729,12 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, Curl_set_in_callback(data, FALSE); if(rc!= CURLKHMATCH_OK) { myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } } else { myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; - return sshc->actualcode; + return CURLE_PEER_FAILED_VERIFICATION; } return CURLE_OK; } @@ -1101,6 +1094,7 @@ sftp_upload_init(struct Curl_easy *data, LIBSSH2_SFTP_OPENFILE); if(!sshc->sftp_handle) { + CURLcode result; unsigned long sftperr; int rc = libssh2_session_last_errno(sshc->ssh_session); @@ -1118,11 +1112,9 @@ sftp_upload_init(struct Curl_easy *data, if(sshc->secondCreateDirs) { myssh_state(data, sshc, 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", sftp_libssh2_strerror(sftperr)); - return CURLE_OK; + return sftp_libssh2_error_to_CURLE(sftperr); } if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) || (sftperr == LIBSSH2_FX_FAILURE) || @@ -1135,20 +1127,19 @@ sftp_upload_init(struct Curl_easy *data, return CURLE_OK; } myssh_state(data, sshc, SSH_SFTP_CLOSE); - sshc->actualcode = sftperr != LIBSSH2_FX_OK ? - sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH; - if(!sshc->actualcode) { + result = sftp_libssh2_error_to_CURLE(sftperr); + if(!result) { /* Sometimes, for some reason libssh2_sftp_last_error() returns zero even though libssh2_sftp_open() failed previously! We need to work around that! */ - sshc->actualcode = CURLE_SSH; + result = CURLE_SSH; sftperr = LIBSSH2_FX_OK; } failf(data, "Upload failed: %s (%lu/%d)", sftperr != LIBSSH2_FX_OK ? sftp_libssh2_strerror(sftperr) : "ssh error", sftperr, rc); - return sshc->actualcode; + return result; } /* If we have a restart point then we need to seek to the correct @@ -1236,7 +1227,7 @@ sftp_upload_init(struct Curl_easy *data, /* make sure that this does not collide with an actual libssh2 error code */ #define ERROR_LIBBSH2 1 -static int ssh_state_pkey_init(struct Curl_easy *data, +static CURLcode ssh_state_pkey_init(struct Curl_easy *data, struct ssh_conn *sshc) { /* @@ -1309,8 +1300,7 @@ static int ssh_state_pkey_init(struct Curl_easy *data, Curl_safefree(sshc->rsa); Curl_safefree(sshc->rsa_pub); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - return ERROR_LIBBSH2; + return CURLE_OUT_OF_MEMORY; } sshc->passphrase = data->set.ssl.key_passwd; @@ -1622,8 +1612,7 @@ static CURLcode sftp_readdir(struct Curl_easy *data, } else { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); - result = sftp_libssh2_error_to_CURLE(sftperr); - sshc->actualcode = result ? result : CURLE_SSH; + result = sftperr ? sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH; failf(data, "Could not open remote file for reading: %s :: %d", sftp_libssh2_strerror(sftperr), libssh2_session_last_errno(sshc->ssh_session)); @@ -1632,54 +1621,49 @@ static CURLcode sftp_readdir(struct Curl_easy *data, return result; } -static int ssh_state_init(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_init(struct Curl_easy *data, + struct ssh_conn *sshc) { CURLcode result; sshc->secondCreateDirs = 0; sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_OK; /* Set libssh2 to non-blocking, since everything internally is non-blocking */ libssh2_session_set_blocking(sshc->ssh_session, 0); result = ssh_force_knownhost_key_type(data, sshc); - if(result) { + if(result) myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = result; - return ERROR_LIBBSH2; - } - - myssh_state(data, sshc, SSH_S_STARTUP); - return 0; + else + myssh_state(data, sshc, SSH_S_STARTUP); + return result; } -static int ssh_state_startup(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_startup(struct Curl_easy *data, + struct ssh_conn *sshc) { struct connectdata *conn = data->conn; int rc = libssh2_session_handshake(sshc->ssh_session, conn->sock[FIRSTSOCKET]); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc) { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_FAILED_INIT; - return rc; + return CURLE_FAILED_INIT; } myssh_state(data, sshc, SSH_HOSTKEY); - return 0; + return CURLE_OK; } -static int ssh_state_hostkey(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_hostkey(struct Curl_easy *data, + struct ssh_conn *sshc) { /* * Before we authenticate we should check the hostkey's fingerprint @@ -1687,15 +1671,13 @@ static int ssh_state_hostkey(struct Curl_easy *data, * whatever) is up to us. */ CURLcode result = ssh_check_fingerprint(data, sshc); - if(!result) { + if(!result) myssh_state(data, sshc, SSH_AUTHLIST); - return 0; - } - return ERROR_LIBBSH2; + return result; } -static int ssh_state_authlist(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_authlist(struct Curl_easy *data, + struct ssh_conn *sshc) { /* * Figure out authentication methods @@ -1718,26 +1700,24 @@ static int ssh_state_authlist(struct Curl_easy *data, sshc->authed = TRUE; infof(data, "SSH user accepted with no authentication"); myssh_state(data, sshc, SSH_AUTH_DONE); - return 0; + return CURLE_OK; } rc = libssh2_session_last_errno(sshc->ssh_session); if(rc == LIBSSH2_ERROR_EAGAIN) - rc = LIBSSH2_ERROR_EAGAIN; - else { - myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(rc); - } - return rc; + return CURLE_AGAIN; + + myssh_state(data, sshc, SSH_SESSION_FREE); + return libssh2_session_error_to_CURLE(rc); } infof(data, "SSH authentication methods available: %s", sshc->authlist); myssh_state(data, sshc, SSH_AUTH_PKEY_INIT); - return 0; + return CURLE_OK; } -static int ssh_state_auth_pkey(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_pkey(struct Curl_easy *data, + struct ssh_conn *sshc) { /* The function below checks if the files exists, no need to stat() here. */ @@ -1750,7 +1730,7 @@ static int ssh_state_auth_pkey(struct Curl_easy *data, sshc->rsa_pub, sshc->rsa, sshc->passphrase); if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; + return CURLE_AGAIN; Curl_safefree(sshc->rsa_pub); Curl_safefree(sshc->rsa); @@ -1774,13 +1754,12 @@ static int ssh_state_auth_pkey(struct Curl_easy *data, } infof(data, "SSH public key authentication failed: %s", err_msg); myssh_state(data, sshc, SSH_AUTH_PASS_INIT); - rc = 0; /* clear rc and continue */ } - return rc; + return CURLE_OK; } -static int ssh_state_auth_pass_init(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_pass_init(struct Curl_easy *data, + struct ssh_conn *sshc) { if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) && (strstr(sshc->authlist, "password") != NULL)) { @@ -1789,11 +1768,11 @@ static int ssh_state_auth_pass_init(struct Curl_easy *data, else { myssh_state(data, sshc, SSH_AUTH_HOST_INIT); } - return 0; + return CURLE_OK; } -static int ssh_state_auth_pass(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_pass(struct Curl_easy *data, + struct ssh_conn *sshc) { struct connectdata *conn = data->conn; int rc = @@ -1803,7 +1782,7 @@ static int ssh_state_auth_pass(struct Curl_easy *data, curlx_uztoui(strlen(conn->passwd)), NULL); if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; + return CURLE_AGAIN; } if(rc == 0) { sshc->authed = TRUE; @@ -1812,13 +1791,12 @@ static int ssh_state_auth_pass(struct Curl_easy *data, } else { myssh_state(data, sshc, SSH_AUTH_HOST_INIT); - rc = 0; /* clear rc and continue */ } - return rc; + return CURLE_OK; } -static int ssh_state_auth_host_init(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_host_init(struct Curl_easy *data, + struct ssh_conn *sshc) { if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && (strstr(sshc->authlist, "hostbased") != NULL)) { @@ -1827,10 +1805,10 @@ static int ssh_state_auth_host_init(struct Curl_easy *data, else { myssh_state(data, sshc, SSH_AUTH_AGENT_INIT); } - return 0; + return CURLE_OK; } -static int ssh_state_auth_agent_init(struct Curl_easy *data, +static CURLcode ssh_state_auth_agent_init(struct Curl_easy *data, struct ssh_conn *sshc) { int rc = 0; @@ -1846,17 +1824,16 @@ static int ssh_state_auth_agent_init(struct Curl_easy *data, infof(data, "Could not create agent object"); myssh_state(data, sshc, SSH_AUTH_KEY_INIT); - return 0; + return CURLE_OK; } } rc = libssh2_agent_connect(sshc->ssh_agent); if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; + return CURLE_AGAIN; if(rc < 0) { infof(data, "Failure connecting to agent"); myssh_state(data, sshc, SSH_AUTH_KEY_INIT); - rc = 0; /* clear rc and continue */ } else { myssh_state(data, sshc, SSH_AUTH_AGENT_LIST); @@ -1864,30 +1841,29 @@ static int ssh_state_auth_agent_init(struct Curl_easy *data, } else myssh_state(data, sshc, SSH_AUTH_KEY_INIT); - return rc; + return CURLE_OK; } -static int ssh_state_auth_agent_list(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_agent_list(struct Curl_easy *data, + struct ssh_conn *sshc) { int rc = libssh2_agent_list_identities(sshc->ssh_agent); if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; + return CURLE_AGAIN; if(rc < 0) { infof(data, "Failure requesting identities to agent"); myssh_state(data, sshc, SSH_AUTH_KEY_INIT); - rc = 0; /* clear rc and continue */ } else { myssh_state(data, sshc, SSH_AUTH_AGENT); sshc->sshagent_prev_identity = NULL; } - return rc; + return CURLE_OK; } -static int ssh_state_auth_agent(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_agent(struct Curl_easy *data, + struct ssh_conn *sshc) { /* as prev_identity evolves only after an identity user auth finished we can safely request it again as long as EAGAIN is returned here or by @@ -1896,7 +1872,7 @@ static int ssh_state_auth_agent(struct Curl_easy *data, &sshc->sshagent_identity, sshc->sshagent_prev_identity); if(rc == LIBSSH2_ERROR_EAGAIN) - return rc; + return CURLE_AGAIN; if(rc == 0) { struct connectdata *conn = data->conn; @@ -1908,7 +1884,7 @@ static int ssh_state_auth_agent(struct Curl_easy *data, /* tried and failed? go to next identity */ sshc->sshagent_prev_identity = sshc->sshagent_identity; } - return rc; + return CURLE_OK; } } @@ -1924,13 +1900,12 @@ static int ssh_state_auth_agent(struct Curl_easy *data, } else { myssh_state(data, sshc, SSH_AUTH_KEY_INIT); - rc = 0; /* clear rc and continue */ } - return rc; + return CURLE_OK; } -static int ssh_state_auth_key_init(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_key_init(struct Curl_easy *data, + struct ssh_conn *sshc) { if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { @@ -1939,10 +1914,10 @@ static int ssh_state_auth_key_init(struct Curl_easy *data, else { myssh_state(data, sshc, SSH_AUTH_DONE); } - return 0; + return CURLE_OK; } -static int ssh_state_auth_key(struct Curl_easy *data, +static CURLcode ssh_state_auth_key(struct Curl_easy *data, struct ssh_conn *sshc) { /* Authentication failed. Continue with keyboard-interactive now. */ @@ -1953,26 +1928,26 @@ static int ssh_state_auth_key(struct Curl_easy *data, curlx_uztoui( strlen(conn->user)), &kbd_callback); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc == 0) { sshc->authed = TRUE; infof(data, "Initialized keyboard interactive authentication"); + myssh_state(data, sshc, SSH_AUTH_DONE); + return CURLE_OK; } - myssh_state(data, sshc, SSH_AUTH_DONE); - return rc; + return CURLE_LOGIN_DENIED; } -static int ssh_state_auth_done(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_auth_done(struct Curl_easy *data, + struct ssh_conn *sshc) { struct connectdata *conn = data->conn; if(!sshc->authed) { failf(data, "Authentication failure"); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_LOGIN_DENIED; - return ERROR_LIBBSH2; + return CURLE_LOGIN_DENIED; } /* @@ -1987,15 +1962,15 @@ static int ssh_state_auth_done(struct Curl_easy *data, if(conn->handler->protocol == CURLPROTO_SFTP) { myssh_state(data, sshc, SSH_SFTP_INIT); - return 0; + return CURLE_OK; } infof(data, "SSH CONNECT phase done"); myssh_state(data, sshc, SSH_STOP); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_init(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_init(struct Curl_easy *data, + struct ssh_conn *sshc) { /* * Start the libssh2 sftp session @@ -2005,22 +1980,21 @@ static int ssh_state_sftp_init(struct Curl_easy *data, char *err_msg = NULL; if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) - return LIBSSH2_ERROR_EAGAIN; + return CURLE_AGAIN; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "Failure initializing sftp session: %s", err_msg); myssh_state(data, sshc, SSH_SESSION_FREE); - sshc->actualcode = CURLE_FAILED_INIT; - return ERROR_LIBBSH2; + return CURLE_FAILED_INIT; } myssh_state(data, sshc, SSH_SFTP_REALPATH); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_realpath(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { /* * Get the "home" directory @@ -2029,9 +2003,9 @@ static int ssh_state_sftp_realpath(struct Curl_easy *data, ".", curlx_uztoui(strlen(".")), sshp->readdir_filename, CURL_PATH_MAX, LIBSSH2_SFTP_REALPATH); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc > 0) { /* It seems that this string is not always NULL terminated */ sshp->readdir_filename[rc] = '\0'; @@ -2039,13 +2013,12 @@ static int ssh_state_sftp_realpath(struct Curl_easy *data, sshc->homedir = strdup(sshp->readdir_filename); if(!sshc->homedir) { myssh_state(data, sshc, SSH_SFTP_CLOSE); - sshc->actualcode = CURLE_OUT_OF_MEMORY; - return ERROR_LIBBSH2; + return CURLE_OUT_OF_MEMORY; } free(data->state.most_recent_ftp_entrypath); data->state.most_recent_ftp_entrypath = strdup(sshc->homedir); if(!data->state.most_recent_ftp_entrypath) - return ERROR_LIBBSH2; + return CURLE_OUT_OF_MEMORY; } else { /* Return the error type */ @@ -2057,11 +2030,10 @@ static int ssh_state_sftp_realpath(struct Curl_easy *data, /* in this case, the error was not in the SFTP level but for example a time-out or similar */ result = CURLE_SSH; - sshc->actualcode = result; DEBUGF(infof(data, "error = %lu makes libcurl = %d", sftperr, (int)result)); myssh_state(data, sshc, SSH_STOP); - return 0; + return result; } /* This is the last step in the SFTP connect phase. Do note that while @@ -2070,18 +2042,17 @@ static int ssh_state_sftp_realpath(struct Curl_easy *data, working path will not. */ DEBUGF(infof(data, "SSH CONNECT phase done")); myssh_state(data, sshc, SSH_STOP); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_init(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_quote_init(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { CURLcode result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); if(result) { - sshc->actualcode = result; myssh_state(data, sshc, SSH_STOP); - return ERROR_LIBBSH2; + return result; } if(data->set.quote) { @@ -2092,11 +2063,11 @@ static int ssh_state_sftp_quote_init(struct Curl_easy *data, else { myssh_state(data, sshc, SSH_SFTP_GETINFO); } - return 0; + return CURLE_OK; } -static int ssh_state_sftp_postquote_init(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_postquote_init(struct Curl_easy *data, + struct ssh_conn *sshc) { if(data->set.postquote) { infof(data, "Sending quote commands"); @@ -2106,25 +2077,24 @@ static int ssh_state_sftp_postquote_init(struct Curl_easy *data, else { myssh_state(data, sshc, SSH_STOP); } - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_quote(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { /* Send quote commands */ CURLcode result = sftp_quote(data, sshc, sshp); if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; } - return 0; + return result; } -static int ssh_state_sftp_next_quote(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_next_quote(struct Curl_easy *data, + struct ssh_conn *sshc) { Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); @@ -2143,36 +2113,34 @@ static int ssh_state_sftp_next_quote(struct Curl_easy *data, myssh_state(data, sshc, SSH_SFTP_GETINFO); } } - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_stat(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp, - bool *blockp) +static CURLcode ssh_state_sftp_quote_stat(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp, + bool *blockp) { CURLcode result = sftp_quote_stat(data, sshc, sshp, blockp); if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; - return ERROR_LIBBSH2; } - return 0; + return result; } -static int ssh_state_sftp_quote_setstat(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_quote_setstat(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2, curlx_uztoui(strlen(sshc->quote_path2)), LIBSSH2_SFTP_SETSTAT, &sshp->quote_attrs); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); @@ -2181,15 +2149,14 @@ static int ssh_state_sftp_quote_setstat(struct Curl_easy *data, sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_symlink(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_quote_symlink(struct Curl_easy *data, + struct ssh_conn *sshc) { int rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1, @@ -2197,9 +2164,9 @@ static int ssh_state_sftp_quote_symlink(struct Curl_easy *data, sshc->quote_path2, curlx_uztoui(strlen(sshc->quote_path2)), LIBSSH2_SFTP_SYMLINK); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); @@ -2208,22 +2175,21 @@ static int ssh_state_sftp_quote_symlink(struct Curl_easy *data, sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_mkdir(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_quote_mkdir(struct Curl_easy *data, + struct ssh_conn *sshc) { int rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1, curlx_uztoui(strlen(sshc->quote_path1)), (long)data->set.new_directory_perms); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); @@ -2231,15 +2197,14 @@ static int ssh_state_sftp_quote_mkdir(struct Curl_easy *data, sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_rename(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_quote_rename(struct Curl_easy *data, + struct ssh_conn *sshc) { int rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1, @@ -2250,9 +2215,9 @@ static int ssh_state_sftp_quote_rename(struct Curl_easy *data, LIBSSH2_SFTP_RENAME_ATOMIC | LIBSSH2_SFTP_RENAME_NATIVE); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); @@ -2261,21 +2226,20 @@ static int ssh_state_sftp_quote_rename(struct Curl_easy *data, sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_rmdir(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_quote_rmdir(struct Curl_easy *data, + struct ssh_conn *sshc) { int rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1, curlx_uztoui(strlen(sshc->quote_path1))); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); @@ -2283,35 +2247,33 @@ static int ssh_state_sftp_quote_rmdir(struct Curl_easy *data, sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_unlink(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_sftp_quote_unlink(struct Curl_easy *data, + struct ssh_conn *sshc) { int rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1, curlx_uztoui(strlen(sshc->quote_path1))); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_quote_statvfs(struct Curl_easy *data, +static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data, struct ssh_conn *sshc) { LIBSSH2_SFTP_STATVFS statvfs; @@ -2319,9 +2281,9 @@ static int ssh_state_sftp_quote_statvfs(struct Curl_easy *data, curlx_uztoui(strlen(sshc->quote_path1)), &statvfs); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); Curl_safefree(sshc->quote_path1); @@ -2329,8 +2291,7 @@ static int ssh_state_sftp_quote_statvfs(struct Curl_easy *data, sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = CURLE_QUOTE_ERROR; - return ERROR_LIBBSH2; + return CURLE_QUOTE_ERROR; } else if(rc == 0) { #ifdef _MSC_VER @@ -2358,10 +2319,9 @@ static int ssh_state_sftp_quote_statvfs(struct Curl_easy *data, statvfs.f_fsid, statvfs.f_flag, statvfs.f_namemax); if(!tmp) { - sshc->actualcode = CURLE_OUT_OF_MEMORY; myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - return ERROR_LIBBSH2; + return CURLE_OUT_OF_MEMORY; } result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); @@ -2369,24 +2329,24 @@ static int ssh_state_sftp_quote_statvfs(struct Curl_easy *data, if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; + return result; } } myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { /* 'mode' - parameter is preliminary - default to 0644 */ int rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path, curlx_uztoui(strlen(sshp->path)), (long)data->set.new_directory_perms); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + *sshc->slash_pos = '/'; ++sshc->slash_pos; if(rc < 0) { @@ -2395,30 +2355,26 @@ static int ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data, * permission was denied (creation might succeed further down the * path) - retry on unspecific FAILURE also */ - CURLcode result; unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) && (sftperr != LIBSSH2_FX_FAILURE) && (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) { - result = sftp_libssh2_error_to_CURLE(sftperr); myssh_state(data, sshc, SSH_SFTP_CLOSE); - sshc->actualcode = result ? result : CURLE_SSH; - return ERROR_LIBBSH2; + return sftp_libssh2_error_to_CURLE(sftperr); } - rc = 0; /* clear rc and continue */ } myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS); - return rc; + return CURLE_OK; } -static int ssh_state_sftp_readdir_init(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_readdir_init(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { Curl_pgrsSetDownloadSize(data, -1); if(data->req.no_body) { myssh_state(data, sshc, SSH_STOP); - return 0; + return CURLE_OK; } /* @@ -2431,26 +2387,22 @@ static int ssh_state_sftp_readdir_init(struct Curl_easy *data, 0, 0, LIBSSH2_SFTP_OPENDIR); if(!sshc->sftp_handle) { unsigned long sftperr; - CURLcode result; - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - return LIBSSH2_ERROR_EAGAIN; - } + if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + sftperr = libssh2_sftp_last_error(sshc->sftp_session); failf(data, "Could not open directory for reading: %s", sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); - result = sftp_libssh2_error_to_CURLE(sftperr); - sshc->actualcode = result ? result : CURLE_SSH; - return ERROR_LIBBSH2; + return sftp_libssh2_error_to_CURLE(sftperr); } myssh_state(data, sshc, SSH_SFTP_READDIR); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_readdir_link(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_readdir_link(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { CURLcode result; int rc = @@ -2460,28 +2412,23 @@ static int ssh_state_sftp_readdir_link(struct Curl_easy *data, curlx_dyn_len(&sshp->readdir_link), sshp->readdir_filename, CURL_PATH_MAX, LIBSSH2_SFTP_READLINK); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + curlx_dyn_free(&sshp->readdir_link); /* append filename and extra output */ - result = curlx_dyn_addf(&sshp->readdir, " -> %s", - sshp->readdir_filename); - - if(result) { + result = curlx_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename); + if(result) myssh_state(data, sshc, SSH_SFTP_CLOSE); - sshc->actualcode = result; - return ERROR_LIBBSH2; - } - - myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM); - return 0; + else + myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM); + return result; } -static int ssh_state_scp_download_init(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_scp_download_init(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { curl_off_t bytecount; @@ -2512,16 +2459,14 @@ static int ssh_state_scp_download_init(struct Curl_easy *data, char *err_msg = NULL; if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - return LIBSSH2_ERROR_EAGAIN; - } + LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0)); failf(data, "%s", err_msg); myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); - return ERROR_LIBBSH2; + return libssh2_session_error_to_CURLE(ssh_err); } /* download data */ @@ -2538,19 +2483,19 @@ static int ssh_state_scp_download_init(struct Curl_easy *data, data->state.select_bits = CURL_CSELECT_IN; myssh_state(data, sshc, SSH_STOP); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_close(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_close(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { int rc = 0; if(sshc->sftp_handle) { rc = libssh2_sftp_close(sshc->sftp_handle); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc < 0) { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, @@ -2575,10 +2520,10 @@ static int ssh_state_sftp_close(struct Curl_easy *data, else myssh_state(data, sshc, SSH_STOP); - return rc; + return CURLE_OK; } -static int ssh_state_sftp_shutdown(struct Curl_easy *data, +static CURLcode ssh_state_sftp_shutdown(struct Curl_easy *data, struct ssh_conn *sshc) { /* during times we get here due to a broken transfer and then the @@ -2587,9 +2532,9 @@ static int ssh_state_sftp_shutdown(struct Curl_easy *data, int rc = 0; if(sshc->sftp_handle) { rc = libssh2_sftp_close(sshc->sftp_handle); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc < 0) { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, @@ -2600,9 +2545,9 @@ static int ssh_state_sftp_shutdown(struct Curl_easy *data, } if(sshc->sftp_session) { rc = libssh2_sftp_shutdown(sshc->sftp_session); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc < 0) { infof(data, "Failed to stop libssh2 sftp subsystem"); } @@ -2612,12 +2557,12 @@ static int ssh_state_sftp_shutdown(struct Curl_easy *data, Curl_safefree(sshc->homedir); myssh_state(data, sshc, SSH_SESSION_DISCONNECT); - return 0; + return CURLE_OK; } -static int ssh_state_sftp_download_init(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_sftp_download_init(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { /* * Work on getting the specified file @@ -2629,26 +2574,23 @@ static int ssh_state_sftp_download_init(struct Curl_easy *data, LIBSSH2_SFTP_OPENFILE); if(!sshc->sftp_handle) { unsigned long sftperr; - CURLcode result; if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) { - return LIBSSH2_ERROR_EAGAIN; + return CURLE_AGAIN; } sftperr = libssh2_sftp_last_error(sshc->sftp_session); failf(data, "Could not open remote file for reading: %s", sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); - result = sftp_libssh2_error_to_CURLE(sftperr); - sshc->actualcode = result ? result : CURLE_SSH; - return ERROR_LIBBSH2; + return sftp_libssh2_error_to_CURLE(sftperr); } myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT); - return 0; + return CURLE_OK; } -static int ssh_state_scp_upload_init(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp) +static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp) { /* * libssh2 requires that the destination path is a full path that @@ -2663,22 +2605,22 @@ static int ssh_state_scp_upload_init(struct Curl_easy *data, if(!sshc->ssh_channel) { int ssh_err; char *err_msg = NULL; - + CURLcode result; if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - return LIBSSH2_ERROR_EAGAIN; - } + LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0)); failf(data, "%s", err_msg); myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err); + result = libssh2_session_error_to_CURLE(ssh_err); + /* Map generic errors to upload failed */ - if(sshc->actualcode == CURLE_SSH || - sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND) - sshc->actualcode = CURLE_UPLOAD_FAILED; - return ERROR_LIBBSH2; + if(result == CURLE_SSH || + result == CURLE_REMOTE_FILE_NOT_FOUND) + result = CURLE_UPLOAD_FAILED; + return result; } /* upload data */ @@ -2700,11 +2642,11 @@ static int ssh_state_scp_upload_init(struct Curl_easy *data, myssh_state(data, sshc, SSH_STOP); - return 0; + return CURLE_OK; } -static int ssh_state_session_disconnect(struct Curl_easy *data, - struct ssh_conn *sshc) +static CURLcode ssh_state_session_disconnect(struct Curl_easy *data, + struct ssh_conn *sshc) { /* during weird times when we have been prematurely aborted, the channel is still alive when we reach this state and we MUST kill the channel @@ -2712,9 +2654,9 @@ static int ssh_state_session_disconnect(struct Curl_easy *data, int rc = 0; if(sshc->ssh_channel) { rc = libssh2_channel_free(sshc->ssh_channel); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_OK; + if(rc < 0) { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, @@ -2727,9 +2669,9 @@ static int ssh_state_session_disconnect(struct Curl_easy *data, if(sshc->ssh_session) { rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown"); - if(rc == LIBSSH2_ERROR_EAGAIN) { - return rc; - } + if(rc == LIBSSH2_ERROR_EAGAIN) + return CURLE_AGAIN; + if(rc < 0) { char *err_msg = NULL; (void)libssh2_session_last_error(sshc->ssh_session, @@ -2742,7 +2684,7 @@ static int ssh_state_session_disconnect(struct Curl_easy *data, Curl_safefree(sshc->homedir); myssh_state(data, sshc, SSH_SESSION_FREE); - return 0; + return CURLE_OK; } /* * ssh_statemachine() runs the SSH state machine as far as it can without @@ -2758,49 +2700,48 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, { CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - int rc = LIBSSH2_ERROR_NONE; *block = 0; /* we are not blocking by default */ do { switch(sshc->state) { case SSH_INIT: - rc = ssh_state_init(data, sshc); - if(rc) + result = ssh_state_init(data, sshc); + if(result) break; FALLTHROUGH(); case SSH_S_STARTUP: - rc = ssh_state_startup(data, sshc); - if(rc) + result = ssh_state_startup(data, sshc); + if(result) break; FALLTHROUGH(); case SSH_HOSTKEY: - rc = ssh_state_hostkey(data, sshc); + result = ssh_state_hostkey(data, sshc); break; case SSH_AUTHLIST: - rc = ssh_state_authlist(data, sshc); + result = ssh_state_authlist(data, sshc); break; case SSH_AUTH_PKEY_INIT: - rc = ssh_state_pkey_init(data, sshc); + result = ssh_state_pkey_init(data, sshc); break; case SSH_AUTH_PKEY: - rc = ssh_state_auth_pkey(data, sshc); + result = ssh_state_auth_pkey(data, sshc); break; case SSH_AUTH_PASS_INIT: - rc = ssh_state_auth_pass_init(data, sshc); + result = ssh_state_auth_pass_init(data, sshc); break; case SSH_AUTH_PASS: - rc = ssh_state_auth_pass(data, sshc); + result = ssh_state_auth_pass(data, sshc); break; case SSH_AUTH_HOST_INIT: - rc = ssh_state_auth_host_init(data, sshc); + result = ssh_state_auth_host_init(data, sshc); break; case SSH_AUTH_HOST: @@ -2808,83 +2749,83 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_AUTH_AGENT_INIT: - rc = ssh_state_auth_agent_init(data, sshc); + result = ssh_state_auth_agent_init(data, sshc); break; case SSH_AUTH_AGENT_LIST: - rc = ssh_state_auth_agent_list(data, sshc); + result = ssh_state_auth_agent_list(data, sshc); break; case SSH_AUTH_AGENT: - rc = ssh_state_auth_agent(data, sshc); + result = ssh_state_auth_agent(data, sshc); break; case SSH_AUTH_KEY_INIT: - rc = ssh_state_auth_key_init(data, sshc); + result = ssh_state_auth_key_init(data, sshc); break; case SSH_AUTH_KEY: - rc = ssh_state_auth_key(data, sshc); + result = ssh_state_auth_key(data, sshc); break; case SSH_AUTH_DONE: - rc = ssh_state_auth_done(data, sshc); + result = ssh_state_auth_done(data, sshc); break; case SSH_SFTP_INIT: - rc = ssh_state_sftp_init(data, sshc); + result = ssh_state_sftp_init(data, sshc); break; case SSH_SFTP_REALPATH: - rc = ssh_state_sftp_realpath(data, sshc, sshp); + result = ssh_state_sftp_realpath(data, sshc, sshp); break; case SSH_SFTP_QUOTE_INIT: - rc = ssh_state_sftp_quote_init(data, sshc, sshp); + result = ssh_state_sftp_quote_init(data, sshc, sshp); break; case SSH_SFTP_POSTQUOTE_INIT: - rc = ssh_state_sftp_postquote_init(data, sshc); + result = ssh_state_sftp_postquote_init(data, sshc); break; case SSH_SFTP_QUOTE: - rc = ssh_state_sftp_quote(data, sshc, sshp); + result = ssh_state_sftp_quote(data, sshc, sshp); break; case SSH_SFTP_NEXT_QUOTE: - rc = ssh_state_sftp_next_quote(data, sshc); + result = ssh_state_sftp_next_quote(data, sshc); break; case SSH_SFTP_QUOTE_STAT: - rc = ssh_state_sftp_quote_stat(data, sshc, sshp, block); + result = ssh_state_sftp_quote_stat(data, sshc, sshp, block); break; case SSH_SFTP_QUOTE_SETSTAT: - rc = ssh_state_sftp_quote_setstat(data, sshc, sshp); + result = ssh_state_sftp_quote_setstat(data, sshc, sshp); break; case SSH_SFTP_QUOTE_SYMLINK: - rc = ssh_state_sftp_quote_symlink(data, sshc); + result = ssh_state_sftp_quote_symlink(data, sshc); break; case SSH_SFTP_QUOTE_MKDIR: - rc = ssh_state_sftp_quote_mkdir(data, sshc); + result = ssh_state_sftp_quote_mkdir(data, sshc); break; case SSH_SFTP_QUOTE_RENAME: - rc = ssh_state_sftp_quote_rename(data, sshc); + result = ssh_state_sftp_quote_rename(data, sshc); break; case SSH_SFTP_QUOTE_RMDIR: - rc = ssh_state_sftp_quote_rmdir(data, sshc); + result = ssh_state_sftp_quote_rmdir(data, sshc); break; case SSH_SFTP_QUOTE_UNLINK: - rc = ssh_state_sftp_quote_unlink(data, sshc); + result = ssh_state_sftp_quote_unlink(data, sshc); break; case SSH_SFTP_QUOTE_STATVFS: - rc = ssh_state_sftp_quote_statvfs(data, sshc); + result = ssh_state_sftp_quote_statvfs(data, sshc); break; case SSH_SFTP_GETINFO: @@ -2900,10 +2841,11 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, { LIBSSH2_SFTP_ATTRIBUTES attrs; - rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, - curlx_uztoui(strlen(sshp->path)), - LIBSSH2_SFTP_STAT, &attrs); + int 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; } if(rc == 0) { @@ -2930,7 +2872,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; } break; @@ -2957,24 +2898,22 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_CREATE_DIRS_MKDIR: - rc = ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp); + result = ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp); break; case SSH_SFTP_READDIR_INIT: - rc = ssh_state_sftp_readdir_init(data, sshc, sshp); + result = ssh_state_sftp_readdir_init(data, sshc, sshp); break; case SSH_SFTP_READDIR: result = sftp_readdir(data, sshc, sshp, block); if(result) { - sshc->actualcode = result; myssh_state(data, sshc, SSH_SFTP_CLOSE); - rc = ERROR_LIBBSH2; } break; case SSH_SFTP_READDIR_LINK: - rc = ssh_state_sftp_readdir_link(data, sshc, sshp); + result = ssh_state_sftp_readdir_link(data, sshc, sshp); break; case SSH_SFTP_READDIR_BOTTOM: @@ -2985,7 +2924,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, curlx_dyn_len(&sshp->readdir)); if(result) { - sshc->actualcode = result; curlx_dyn_free(&sshp->readdir); myssh_state(data, sshc, SSH_STOP); } @@ -2996,20 +2934,19 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_READDIR_DONE: - if(libssh2_sftp_closedir(sshc->sftp_handle) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } - sshc->sftp_handle = NULL; + if(libssh2_sftp_closedir(sshc->sftp_handle) == LIBSSH2_ERROR_EAGAIN) + result = CURLE_AGAIN; + else { + sshc->sftp_handle = NULL; - /* no data to transfer */ - Curl_xfer_setup_nop(data); - myssh_state(data, sshc, SSH_STOP); + /* no data to transfer */ + Curl_xfer_setup_nop(data); + myssh_state(data, sshc, SSH_STOP); + } break; case SSH_SFTP_DOWNLOAD_INIT: - rc = ssh_state_sftp_download_init(data, sshc, sshp); + result = ssh_state_sftp_download_init(data, sshc, sshp); break; case SSH_SFTP_DOWNLOAD_STAT: @@ -3017,22 +2954,20 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; - sshc->actualcode = result; } break; case SSH_SFTP_CLOSE: - rc = ssh_state_sftp_close(data, sshc, sshp); + result = ssh_state_sftp_close(data, sshc, sshp); break; case SSH_SFTP_SHUTDOWN: - rc = ssh_state_sftp_shutdown(data, sshc); + result = ssh_state_sftp_shutdown(data, sshc); break; case SSH_SCP_TRANS_INIT: result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); if(result) { - sshc->actualcode = result; myssh_state(data, sshc, SSH_STOP); break; } @@ -3040,7 +2975,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, if(data->state.upload) { if(data->state.infilesize < 0) { failf(data, "SCP requires a known file size for upload"); - sshc->actualcode = CURLE_UPLOAD_FAILED; + result = CURLE_UPLOAD_FAILED; myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE); break; } @@ -3052,11 +2987,11 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SCP_UPLOAD_INIT: - rc = ssh_state_scp_upload_init(data, sshc, sshp); + result = ssh_state_scp_upload_init(data, sshc, sshp); break; case SSH_SCP_DOWNLOAD_INIT: - rc = ssh_state_scp_download_init(data, sshc, sshp); + result = ssh_state_scp_download_init(data, sshc, sshp); break; case SSH_SCP_DONE: @@ -3068,8 +3003,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, case SSH_SCP_SEND_EOF: if(sshc->ssh_channel) { - rc = libssh2_channel_send_eof(sshc->ssh_channel); + int rc = libssh2_channel_send_eof(sshc->ssh_channel); if(rc == LIBSSH2_ERROR_EAGAIN) { + result = CURLE_AGAIN; break; } if(rc) { @@ -3085,8 +3021,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, case SSH_SCP_WAIT_EOF: if(sshc->ssh_channel) { - rc = libssh2_channel_wait_eof(sshc->ssh_channel); + int rc = libssh2_channel_wait_eof(sshc->ssh_channel); if(rc == LIBSSH2_ERROR_EAGAIN) { + result = CURLE_AGAIN; break; } if(rc) { @@ -3101,8 +3038,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, case SSH_SCP_WAIT_CLOSE: if(sshc->ssh_channel) { - rc = libssh2_channel_wait_closed(sshc->ssh_channel); + int rc = libssh2_channel_wait_closed(sshc->ssh_channel); if(rc == LIBSSH2_ERROR_EAGAIN) { + result = CURLE_AGAIN; break; } if(rc) { @@ -3117,8 +3055,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, case SSH_SCP_CHANNEL_FREE: if(sshc->ssh_channel) { - rc = libssh2_channel_free(sshc->ssh_channel); + int rc = libssh2_channel_free(sshc->ssh_channel); if(rc == LIBSSH2_ERROR_EAGAIN) { + result = CURLE_AGAIN; break; } if(rc < 0) { @@ -3131,45 +3070,41 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, sshc->ssh_channel = NULL; } DEBUGF(infof(data, "SCP DONE phase complete")); -#if 0 /* PREV */ - myssh_state(data, sshc, SSH_SESSION_DISCONNECT); -#endif myssh_state(data, sshc, SSH_STOP); break; case SSH_SESSION_DISCONNECT: - rc = ssh_state_session_disconnect(data, sshc); + result = ssh_state_session_disconnect(data, sshc); break; case SSH_SESSION_FREE: - rc = sshc_cleanup(sshc, data, FALSE); - if(rc == LIBSSH2_ERROR_EAGAIN) + result = sshc_cleanup(sshc, data, FALSE); + if(result) break; /* the code we are about to return */ memset(sshc, 0, sizeof(struct ssh_conn)); connclose(conn, "SSH session free"); sshc->state = SSH_SESSION_FREE; /* current */ - sshc->nextstate = SSH_NO_STATE; myssh_state(data, sshc, SSH_STOP); break; case SSH_QUIT: default: /* internal error */ - sshc->nextstate = SSH_NO_STATE; myssh_state(data, sshc, SSH_STOP); break; } - } while(!rc && (sshc->state != SSH_STOP)); + } while(!result && (sshc->state != SSH_STOP)); - if(rc == LIBSSH2_ERROR_EAGAIN) { + if(result == CURLE_AGAIN) { /* we would block, we need to wait for the socket to be ready (in the right direction too)! */ *block = TRUE; + result = CURLE_OK; } - return sshc->actualcode; + return result; } /* called by the multi interface to figure out what socket(s) to wait for and @@ -3655,8 +3590,6 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done) return CURLE_FAILED_INIT; data->req.size = -1; /* make sure this is unknown at this point */ - - sshc->actualcode = CURLE_OK; /* reset error code */ sshc->secondCreateDirs = 0; /* reset the create dir attempt state variable */ @@ -3673,8 +3606,8 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done) return result; } -static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, - bool block) +static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, + bool block) { int rc; @@ -3686,9 +3619,9 @@ static int 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 rc; - } + 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, @@ -3707,9 +3640,9 @@ static int 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 rc; - } + 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, @@ -3721,9 +3654,9 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, if(sshc->ssh_channel) { rc = libssh2_channel_free(sshc->ssh_channel); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) { - return rc; - } + 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, @@ -3736,9 +3669,9 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, if(sshc->sftp_session) { rc = libssh2_sftp_shutdown(sshc->sftp_session); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) { - return rc; - } + 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; @@ -3746,9 +3679,9 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, if(sshc->ssh_session) { rc = libssh2_session_free(sshc->ssh_session); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) { - return rc; - } + 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, @@ -3773,7 +3706,7 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, Curl_safefree(sshc->homedir); sshc->initialised = FALSE; } - return 0; + return CURLE_OK; } @@ -3796,7 +3729,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data, } if(sshc) - sshc_cleanup(sshc, data, TRUE); + return sshc_cleanup(sshc, data, TRUE); return result; } diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h index db8ad88511..feee886562 100644 --- a/lib/vssh/ssh.h +++ b/lib/vssh/ssh.h @@ -148,7 +148,6 @@ struct ssh_conn { char *rsa; /* strdup'ed private key file */ sshstate state; /* always use ssh.c:state() to change state! */ sshstate nextstate; /* the state to goto after stopping */ - CURLcode actualcode; /* the actual error code */ struct curl_slist *quote_item; /* for the quote option */ char *quote_path1; /* two generic pointers for the QUOTE stuff */ char *quote_path2; @@ -164,6 +163,7 @@ struct ssh_conn { char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ #if defined(USE_LIBSSH) + CURLcode actualcode; /* the actual error code */ char *readdir_linkPath; size_t readdir_len; struct dynbuf readdir_buf; @@ -208,6 +208,7 @@ struct ssh_conn { struct libssh2_agent_publickey *sshagent_prev_identity; LIBSSH2_KNOWNHOSTS *kh; #elif defined(USE_WOLFSSH) + CURLcode actualcode; /* the actual error code */ WOLFSSH *ssh_session; WOLFSSH_CTX *ctx; word32 handleSz;