ftpclient-cpp icon indicating copy to clipboard operation
ftpclient-cpp copied to clipboard

How to use PassiveMode?

Open matteocostantini opened this issue 4 years ago • 11 comments

matteocostantini avatar May 20 '20 10:05 matteocostantini

Hi Matteo,

It's possible to use the passive mode. I will give you an answer tonight.

Regards.

embeddedmz avatar May 20 '20 10:05 embeddedmz

@matteocostantini By default, the FTP client is in passive mode (m_bActive is initialized to false), so there's nothing to do.

To use the active mode use SetActive(true), in active mode, the client will choose a port and the FTP server will initialize the connection (not recommended if there's a firewall).

embeddedmz avatar May 20 '20 16:05 embeddedmz

This is my implementation, dont connect . i'm in UI environment.

How i can use?

My FTP credentials is valid ('m tryng with WINSCP!!)

in FTPCLient.cpp go in this rows else if (m_eSettingsFlags & ENABLE_LOG) m_oLog(StringFormat(LOG_ERROR_CURL_FILELIST_FORMAT, strRemoteFolder.c_str(), res, curl_easy_strerror(res)));

void BDImport::OnRunButton() { //m_pFTPClient = new CFTPClient(CFTPClient::LogFnCallback);

CFTPClient FTPClient([](const std::string& strLogMsg) { std::cout << strLogMsg << std::endl; });

CString host = _T("fqdnftp");
std::string stdHost = CT2CA(host);

CString user = _T("");
std::string stdUser = CT2CA(user);

CString pwd = _T("");
std::string stdpwd = CT2CA(pwd);

FTPClient.InitSession(stdHost, 6321, stdUser, stdpwd, CFTPClient::FTP_PROTOCOL::FTPES);

std::string strList;

FTPClient.List("/", strList, false);

matteocostantini avatar May 21 '20 11:05 matteocostantini

I never tested the FTP Client with this protocol CFTPClient::FTP_PROTOCOL::FTPES.

If you are trying to access a normal FTP server (port 21), remove that parameter (it will default to FTP_PROTOCOL::FTP) or set the protocol to FTP_PROTOCOL::SFTP if you want to connect to an SFTP server (port 22).

Also, in a debugger, check that the string parameters are well encoded (I don't know if CT2CA is doing its job properly). And that "stdHost" doesn't contain any protocol scheme.

embeddedmz avatar May 21 '20 11:05 embeddedmz

I'm not sure but to access secure servers, I think you need to set an SSL cert file with the static method SetSSLCertFile.

You can use this file : https://curl.haxx.se/ca/cacert.pem (from libcurl website)

and then CFTPClient::SetSSLCertFile("C:\\etc...............\\cacert.pem");

UPDATE : ignore this comment

embeddedmz avatar May 21 '20 11:05 embeddedmz

@matteocostantini You can also 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.

Also, don't forget to set a preprocessor macro WINDOWS as I believe you are not using the CMake scripts.

Regards.

embeddedmz avatar May 21 '20 12:05 embeddedmz

@embeddedmz : I'm able to connect to my server with this instructions:

curl_easy_setopt(m_pCurlSession, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_easy_setopt(m_pCurlSession, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_easy_setopt(m_pCurlSession, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0);
curl_easy_setopt(m_pCurlSession, CURLOPT_FTP_SSL, CURLOPT_FTPSSLAUTH);
curl_easy_setopt(m_pCurlSession, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS);

Can you improve this calls in your ::Perform()?

matteocostantini avatar May 22 '20 09:05 matteocostantini

First of all, to what kind of FTP servers are you connecting (SFTP, FTPES or FTPS). I know that the client work with SFTP but not the 2 others (FTPES, FTPS).

You can remove these 2 lines :

curl_easy_setopt(m_pCurlSession, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(m_pCurlSession, CURLOPT_SSL_VERIFYHOST, 0);

if you use this : curl_easy_setopt(m_pCurlSession, CURLOPT_CAINFO, "C:\....\cacert.pem");

In my previous comment I mistaken this for CFTPClient::SetSSLCertFile("C:\etc...............\cacert.pem"); it's missing in this client (but not in the httpclient-cpp). But your server must have a valid SSL certificate and not a quick & dirty one. Settings those 2 parameters to 0 is not good for all cases (security issues).

So, if you have the chance to add and test these getter/setters method :

// in .h static const std::string& GetCertificateFile() { return s_strCertificationAuthorityFile; } static void SetCertificateFile(const std::string& strPath) { s_strCertificationAuthorityFile = strPath; } //.... //SSL static std::string s_strCertificationAuthorityFile;

// in .cpp // just look to this https://github.com/embeddedmz/httpclient-cpp/blob/master/HTTP/HTTPClient.cpp and to the code that sets CURLOPT_CAINFO

In line 857 (if (m_eFtpProtocol == FTP_PROTOCOL::FTPS || m_eFtpProtocol == FTP_PROTOCOL::FTPES)) , you can add :

curl_easy_setopt(m_pCurlSession, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0);
curl_easy_setopt(m_pCurlSession, CURLOPT_FTP_SSL, CURLOPT_FTPSSLAUTH);
curl_easy_setopt(m_pCurlSession, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS);

and eventually remove curl_easy_setopt(m_pCurlSession, CURLOPT_USE_SSL, CURLUSESSL_ALL); if it's not necessary

If everything is OK, create a pull request and I will merge your patches.

embeddedmz avatar May 22 '20 09:05 embeddedmz

the connection function successfully only if i put curl_easy_setopt(m_pCurlSession, CURLOPT_USE_SSL, CURLUSESSL_ALL); curl_easy_setopt(m_pCurlSession, CURLOPT_SSL_VERIFYPEER, FALSE); curl_easy_setopt(m_pCurlSession, CURLOPT_SSL_VERIFYHOST, FALSE); curl_easy_setopt(m_pCurlSession, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0); curl_easy_setopt(m_pCurlSession, CURLOPT_FTP_SSL, CURLOPT_FTPSSLAUTH); curl_easy_setopt(m_pCurlSession, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS);

matteocostantini avatar May 22 '20 15:05 matteocostantini

The server is ftp with explicit autentication

matteocostantini avatar May 22 '20 17:05 matteocostantini

@matteocostantini OK, I googled curl FTPS/FTPES and I found the following stuff :

https://stackoverflow.com/questions/32491790/php-curl-ftpes-w-explicit-tls-ssl => in the code, instead of prefixing the URL with ftps:// prefix it with ftp:// that should be sufficient.

https://curl.haxx.se/docs/manual.html (curl doc.) => FTPS : It is just like for FTP, but you may also want to specify and use SSL-specific options for certificates etc. Note that using FTPS:// as prefix is the "implicit" way as described in the standards while the recommended "explicit" way is done by using FTP:// and the --ftp-ssl option.

So, can you please try this fix and tell me if the example you posted in the beginning of this thread is working : In line 194, add "case FTP_PROTOCOL::FTPES:" so that in a FTPES session, the url will be prefixed with ftp:// and remove the case of lines 203 and 205 (old code prefixing the url with ftpes://)

That should work fine (I hope so).

embeddedmz avatar May 22 '20 20:05 embeddedmz