pocoproject / poco

The POCO C++ Libraries are powerful cross-platform C++ libraries for building network- and internet-based applications that run on desktop, server, mobile, IoT, and embedded systems.
https://pocoproject.org
Other
8.05k stars 2.11k forks source link

Couldn't establish an encrypted FTP data connection with FTP(S)ClientSession #4498

Closed zussel closed 3 months ago

zussel commented 3 months ago

I've tried to establish a FTP connection (implicit and explicit, with valid and invalid certificate) to a vsftpd server within a docker container (based on this container: https://hub.docker.com/r/loicmathieu/vsftpd) with POCO FTP(S)ClientSession.

See my code example for an implicit FTP connection expecting a self signed certificate below:


#include <Poco/Net/AcceptCertificateHandler.h>
#include <Poco/Net/FTPClientSession.h>
#include <Poco/Net/SSLManager.h>

#include <iostream>

try {

    Poco::Net::initializeSSL();
    Poco::Net::SSLManager::InvalidCertificateHandlerPtr ptrHandler( new Poco::Net::AcceptCertificateHandler( true) );

    const Poco::Net::Context::Ptr context = new Poco::Net::Context(
        Poco::Net::Context::CLIENT_USE, "", "", "",
        Poco::Net::Context::VERIFY_RELAXED, 9, false,
        "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH" );

    Poco::Net::SSLManager::instance().initializeClient( nullptr, ptrHandler, context );

    auto address = Poco::Net::SocketAddress( "<hostname>:990" );
    auto socket = Poco::Net::SecureStreamSocket( address, "<hostname>", context );
    auto ftps = std::make_unique<Poco::Net::FTPClientSession>( socket, true );
    ftps->login( "<user>", "<password>" );

    std::cout << ftps->welcomeMessage() << std::endl;

    std::cout << "current dir: " << ftps->getWorkingDirectory() << "\n";

   // Here the exception is thrown.
    auto& stream = ftps->beginList("/");
    std::vector<std::string> entries;
    std::string entry;
    while ( std::getline( stream, entry ) ) {
        entries.push_back( entry );
    }

    ftps->endList();
} catch ( const Poco::Exception& e )     {
    std::cout << e.message() << std::endl;
}

I always receive an error as soon as a data channel is about to becreated: NLST command failed: 522 Data connections must be encrypted. In the example the line where FTPCLientSession::beginList() is called.

I'm using:

Thanks for your support.

micheleselea commented 3 months ago

I always use FTPS (explicit) connection without problem in my code since years. You have to use Poco::Net::FTPSClientSession

micheleselea commented 3 months ago

For example

bool bReadWelcomeMessage = true;
bool bTryUseFTPS = true;
Poco::Net::Context::Ptr pContext = Poco::Net::SSLManager::instance().defaultClientContext();
Poco::Net::StreamSocket ftpSocket;
Poco::Net::SocketAddress sa(sHost, iPort);
ftpSocket.connect(sa, spanConnectionTimeout);
ftpSocket.setReuseAddress(true);
ftpSocket.setNoDelay(true);
Poco::Net::FTPSClientSession cFtp(ftpSocket, bReadWelcomeMessage, bTryUseFTPS, pContext);