How to use a SFTP mode on FTPClient
ayhamal opened this issue · comments
Hi, I interested to use this build on my project, but I have problems to connect using sftp to my server.
I tried:
FTPClient.InitSession("xxx.xx.xx.xx:xx, 22, "username", "password");
But on console I have an error 1 indicating protocol not supported.
It works good using FTP protocol, but you know it's not recommend to use.
Please help,
Thanks
Hi @ayhamal
Try this : FTPClient.InitSession("xxx.xx.xx.xx:xx, 22, "username", "password", CFTPClient::FTP_PROTOCOL::SFTP);
The 5th parameter is used to set the protocol type (FTP, SFTP (SSH) or FTPS/ES (TLS).
The 6th can be used to enable/disable log messsages.
Hope that helps !
Hi @embeddedmz I try that but not working.
I'm using this commands:
FTPClient.InitSession("xxx.xx.xx.xx:xx", 22, "username", "password", CFTPClient::FTP_PROTOCOL::SFTP);
Next I use:
FTPClient.List("/", srtList);
And on console have the results:
Operation 'InitSession' status: 1
[FTPClient][Error] Unable to connect to remote folder / (Error = 1 | Unsupported protocol).
Please help,
Thanks
Can you remove the :xx from the hostname and retry ?
Of course, I did it and I have the same result.
@ayhamal Can you compile with this preprocessor macro: DEBUG_CURL, and use this method : static void SetCurlTraceLogDirectory(const std::string &strPath); to specify a directory where debug logs will be stored. They will give you an information on why things are not working properly. Can you post the content please.
Also, don't forget to set a preprocessor macro WINDOWS if you are compiling on Windows and without CMake and Visual Studio.
On what operating system are you working ? how libcurl is installed on your machine ? Did you try to connect to your server with FileZilla for example ?
In the readme, there's a procedure to install libcurl on Windows. On Windows, you can also use "vcpkg" to install libcurl and it will be directly accessible in Visual Studio without an effort.
On Linux, ensure that curl and its library are installed with SSH support (google is your friend).
I have similar issue with sftp.
FTPClient.InitSession("127.0.0.1", 22, "user", "pass", embeddedmz::CFTPClient::FTP_PROTOCOL::SFTP);
std::string stringList;
FTPClient.List("/", stringList);
std::cout << stringList <<std::endl;
FTPClient.CleanupSession();
and error:
[FTPClient][Error] Unable to connect to remote folder / (Error = 2 | Failed initialization).
@nicraMarcin I can see you're connecting to a local server (maybe it's not a real SFTP server), personnally, IIRC, I never succeeded in creating an SFTP server (unlike FTPS/ES). But if you try with a real SFTP server, there's no reason the class won't work (already achieved that in the past but maybe something changed). Above, there's instructions to enable additional debug messages to understand what's going on.
Yes, I try with real server and noticed, that given port isn't put into connection, if I change it I see that still want to connect with port 22
FTPClient.InitSession("my.sftp.com", 6022, "user", "pass", embeddedmz::CFTPClient::FTP_PROTOCOL::SFTP);
I have to change hostname with port my.sftp.com:6022
and now it try to connect with proper port, but I get login denied
[FTPClient][Error] Unable to connect to remote folder / (Error = 67 | Login denied).
With the same credentials I connect with FileZilla and works so this is no login/pass issue
@embeddedmz Hi, do you have any suggestions with sftp?
@nicraMarcin try this example from curl website : https://curl.se/libcurl/c/sftpget.html and tell me if it's working with your server.
It doesn't work
{
CURL *curl;
CURLcode res;
struct FtpFile ftpfile = {
"/tmp/script.sh", /* name to store the file as if successful */
NULL
};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/*
* You better replace the URL with one that works!
*/
curl_easy_setopt(curl, CURLOPT_URL,
"sftp://user:password@host.com/tmp/script.sh");
curl_easy_setopt(curl, CURLOPT_PORT, 60022);
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
And console writes:
* Trying 2001::254a:60022...
* TCP_NODELAY set
* Connected to host.com (2001::254a) port 60022 (#0)
* User: user
* Authentication using SSH public key file
* Closing connection 0
curl told us 67
from console it works
$ curl -v --insecure sftp://user:passowrd@host.com:60022
* Trying 2001::254a:60022...
* TCP_NODELAY set
* Connected to vps.nicram.net (200::254a) port 60022 (#0)
* User: user
* Authentication using SSH public key file
* Completed password authentication
* Authentication complete
[...] // here prints files list
curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
curl_easy_setopt(curl, CURLOPT_URL, "sftp://user:password@host.com/deploy.sh");
curl_easy_setopt(curl, CURLOPT_PORT, 60022);
curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
and console
* Trying 2001::254a:60022...
* TCP_NODELAY set
* Connected to host.com (2001::254a) port 60022 (#0)
* User: user
* Authentication using SSH public key file
* Completed password authentication
* Authentication complete
* Connection #0 to host host.com left intact
Hi @ayhamal and @nicraMarcin, I fixed the issue I will commit the fix and give you some insights (the SSH agent must be disabled in libcurl and the SSL verifications must be disabled) before the end of the day. Sorry, if this took so long, I didn't have time to debug/investigate.
The whole story :
I launched a download unit test with a local SFTP server using RebexTinySftpServer (https://www.rebex.net/tiny-sftp-server/ - I didn't find a public SFTP server) and libcurl told me that the protocol is not supported (SSH probably).
So as I'm using VCPKG actually and CMake to generate the Visual Studio solution (Look at README), I installed another libcurl package to fix that issue :
.\vcpkg instal curl[ssh]:x64-windows
So, first of all, ensure that your libcurl version is compiled with SSH support.
Then, if your not using a CA file, turn on insecure mode to disable peer/host verification (In the readme, you will find an example).
If you want to launch SFTP unit tests, here's a configuration file (You can use CMake/VCPKG for that purpose, look at the README file) :
[tests]
ftp=no
sftp=yes
http-proxy=no
...
[sftp]
host=127.0.0.1
port=22
username=tester
password=password
remote_file=file.png ; put a file name file.png in the root of the SFTP server (use filezilla or the file explorer)
remote_file_sha1sum=sha1_sum_of_file_png ; you can use this command under windows : certutil -hashfile file.png SHA256
remote_upload_folder=/upload/ ; create this empty folder on the root of the SFTP server
remote_download_folder= ; download with a wildcarded URL doesn't work with SFTP
Best regards.
Hello,
I couldn't use SFTP on my application. Examples are not clear. I'm trying everything you did but never. I got only this error
OS Version: Ubuntu 23.04
GCC: version 8.3.1
libcurl-7.79
[FTPClient][Error] Unable to upload file test_upload.txt (Error = 1 | Unsupported protocol).
I tried to all combinations of SettingsFlag or inSecure things, but now working.
This is my code.
`
C++
try {
// For SFTP
std::unique_ptrembeddedmz::CFTPClient SFTP;
SFTP.reset(new embeddedmz::CFTPClient(PRINT_LOG));
SFTP->InitSession("192.168.xx.xx", 22, "aaa", "ccc", embeddedmz::CFTPClient::FTP_PROTOCOL::SFTP, embeddedmz::CFTPClient::SettingsFlag::ENABLE_SSH_AGENT);
SFTP->SetInsecure(true);
SFTP->SetProgressFnCallback(SFTP.get(), &TestUPProgressCallback);
std::ostringstream ssTimestamp;
TimeStampTest(ssTimestamp);
std::ofstream ofTestUpload("test_upload.txt");
ofTestUpload << "Unit Test TestUploadFile executed on " + ssTimestamp.str() + "\n" +
"This file is uploaded via FTPClient-C++ API.\n" +
"If this file exists, that means that the unit test is passed.\n";
ofTestUpload.close();
SFTP->UploadFile("test_upload.txt", "/test_upload.txt", true);
std::cout << std::endl;
std::cout << std::endl;
SFTP->CleanupSession();
SFTP.reset();
} catch (const std::runtime_error& e) {
std::cerr << e.what() << '\n';
}
`
My libcurl info option is default
with_libssh2=False
Is it cause?
My libcurl info option is default
with_libssh2=False
Is it cause?
Yes, you need a libcurl version with SSH builtin, you can install it with apt or if you have built curl on your own, you will have to configure the build script.
Thank you. It's work.