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 | |
21 | namespace Poco { |
22 | namespace Net { |
23 | |
24 | FTPSClientSession::FTPSClientSession() : |
25 | FTPClientSession() |
26 | { |
27 | } |
28 | |
29 | |
30 | FTPSClientSession::~FTPSClientSession() |
31 | { |
32 | } |
33 | |
34 | FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool tryUseFTPS) : |
35 | FTPClientSession(socket, readWelcomeMessage), _tryFTPS(tryUseFTPS) |
36 | { |
37 | } |
38 | |
39 | |
40 | FTPSClientSession::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 | |
48 | void FTPSClientSession::tryFTPSmode(bool bTryFTPS) |
49 | { |
50 | _tryFTPS = bTryFTPS; |
51 | } |
52 | |
53 | void 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 | |
70 | void 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 | |
102 | StreamSocket 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 | |
123 | void FTPSClientSession::receiveServerReadyReply() |
124 | { |
125 | FTPClientSession::receiveServerReadyReply(); |
126 | afterCreateControlSocket(); |
127 | } |
128 | |
129 | } |
130 | } // namespace Poco::Net |