1//
2// FTPSClientSession.cpp
3//
4// Library: Net
5// Package: FTP
6// Module: FTPSClientSession
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/FTPSClientSession.h"
16#include "Poco/Net/SecureStreamSocket.h"
17#include "Poco/Net/SecureStreamSocketImpl.h"
18#include "Poco/Net/SSLManager.h"
19#include "Poco/Net/NetException.h"
20
21namespace Poco {
22namespace Net {
23
24FTPSClientSession::FTPSClientSession() :
25 FTPClientSession()
26{
27}
28
29
30FTPSClientSession::~FTPSClientSession()
31{
32}
33
34FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool tryUseFTPS) :
35 FTPClientSession(socket, readWelcomeMessage), _tryFTPS(tryUseFTPS)
36{
37}
38
39
40FTPSClientSession::FTPSClientSession(const std::string& host,
41 Poco::UInt16 port,
42 const std::string& username,
43 const std::string& password) :
44 FTPClientSession(host, port, username, password)
45{
46}
47
48void FTPSClientSession::tryFTPSmode(bool bTryFTPS)
49{
50 _tryFTPS = bTryFTPS;
51}
52
53void FTPSClientSession::beforeCreateDataSocket()
54{
55 if (_secureDataConnection)
56 return;
57 _secureDataConnection = false;
58 if (!_pControlSocket->secure())
59 return;
60 std::string sResponse;
61 int status = sendCommand("PBSZ 0", sResponse);
62 if (isPositiveCompletion(status))
63 {
64 status = sendCommand("PROT P", sResponse);
65 if (isPositiveCompletion(status))
66 _secureDataConnection = true;
67 }
68}
69
70void FTPSClientSession::afterCreateControlSocket()
71{
72 if (!_tryFTPS)
73 return;
74 _pControlSocket->setNoDelay(true);
75 if (_pControlSocket->secure())
76 return;
77
78 std::string sResponse;
79 int status = sendCommand("AUTH TLS", sResponse);
80 if (!isPositiveCompletion(status))
81 status = sendCommand("AUTH SSL", sResponse);
82
83 if (isPositiveCompletion(status))
84 {
85 //Server support FTPS
86 try
87 {
88 Poco::Net::SecureStreamSocket sss(Poco::Net::SecureStreamSocket::attach(*_pControlSocket, Poco::Net::SSLManager::instance().defaultClientContext()));
89 *_pControlSocket = sss;
90 }
91 catch (Poco::Exception&)
92 {
93 throw;
94 }
95 }
96 else
97 {
98 _tryFTPS = false;
99 }
100}
101
102StreamSocket FTPSClientSession::establishDataConnection(const std::string& command, const std::string& arg)
103{
104 beforeCreateDataSocket();
105
106 StreamSocket ss = FTPClientSession::establishDataConnection(command, arg);
107 ss.setNoDelay(true);
108
109 //SSL nogotiating of data socket
110 if ((_secureDataConnection) && (_pControlSocket->secure()))
111 {
112 //We need to reuse the control socket SSL session so the server can ensure that client that opened control socket is the same using data socket
113 Poco::Net::SecureStreamSocketImpl* pSecure = dynamic_cast<Poco::Net::SecureStreamSocketImpl*>(_pControlSocket->impl());
114 if (pSecure != nullptr)
115 {
116 Poco::Net::SecureStreamSocket sss(Poco::Net::SecureStreamSocket::attach(ss, pSecure->context(), pSecure->currentSession()));
117 ss = sss;
118 }
119 }
120 return ss;
121}
122
123void FTPSClientSession::receiveServerReadyReply()
124{
125 FTPClientSession::receiveServerReadyReply();
126 afterCreateControlSocket();
127}
128
129}
130} // namespace Poco::Net