1 | // |
2 | // SecureStreamSocket.h |
3 | // |
4 | // Library: NetSSL_OpenSSL |
5 | // Package: SSLSockets |
6 | // Module: SecureStreamSocket |
7 | // |
8 | // Definition of the SecureStreamSocket class. |
9 | // |
10 | // Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef NetSSL_SecureStreamSocket_INCLUDED |
18 | #define NetSSL_SecureStreamSocket_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Net/NetSSL.h" |
22 | #include "Poco/Net/StreamSocket.h" |
23 | #include "Poco/Net/Context.h" |
24 | #include "Poco/Net/Session.h" |
25 | #include "Poco/Net/X509Certificate.h" |
26 | |
27 | |
28 | namespace Poco { |
29 | namespace Net { |
30 | |
31 | |
32 | class NetSSL_API SecureStreamSocket: public StreamSocket |
33 | /// A subclass of StreamSocket for secure SSL sockets. |
34 | /// |
35 | /// A few notes about nonblocking IO: |
36 | /// sendBytes() and receiveBytes() can return a |
37 | /// negative value when using a nonblocking socket, which means |
38 | /// a SSL handshake is currently in progress and more data |
39 | /// needs to be read or written for the handshake to continue. |
40 | /// If sendBytes() or receiveBytes() return ERR_SSL_WANT_WRITE, |
41 | /// sendBytes() must be called as soon as possible (usually, after |
42 | /// select() indicates that data can be written). Likewise, if |
43 | /// ERR_SSL_WANT_READ is returned, receiveBytes() must be called |
44 | /// as soon as data is available for reading (indicated by select()). |
45 | /// |
46 | /// The SSL handshake is delayed until the first sendBytes() or |
47 | /// receiveBytes() operation is performed on the socket. No automatic |
48 | /// post connection check (checking the peer certificate for a valid |
49 | /// hostname) is performed when using nonblocking I/O. To manually |
50 | /// perform peer certificate validation, call verifyPeerCertificate() |
51 | /// after the SSL handshake has been completed. |
52 | { |
53 | public: |
54 | enum |
55 | { |
56 | ERR_SSL_WANT_READ = -1, |
57 | ERR_SSL_WANT_WRITE = -2 |
58 | }; |
59 | |
60 | SecureStreamSocket(); |
61 | /// Creates an unconnected secure stream socket |
62 | /// using the default client SSL context. |
63 | /// |
64 | /// Before sending or receiving data, the socket |
65 | /// must be connected with a call to connect(). |
66 | |
67 | explicit SecureStreamSocket(Context::Ptr pContext); |
68 | /// Creates an unconnected secure stream socket |
69 | /// using the given SSL context. |
70 | /// |
71 | /// Before sending or receiving data, the socket |
72 | /// must be connected with a call to connect(). |
73 | |
74 | SecureStreamSocket(Context::Ptr pContext, Session::Ptr pSession); |
75 | /// Creates an unconnected secure stream socket |
76 | /// using the given SSL context. |
77 | /// |
78 | /// Before sending or receiving data, the socket |
79 | /// must be connected with a call to connect(). |
80 | /// |
81 | /// The given Session is reused, if possible (client session |
82 | /// caching is enabled for the given Context, and the server |
83 | /// agrees to reuse the session). |
84 | |
85 | explicit SecureStreamSocket(const SocketAddress& address); |
86 | /// Creates a secure stream socket using the default |
87 | /// client SSL context and connects it to |
88 | /// the socket specified by address. |
89 | |
90 | SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext); |
91 | /// Creates a secure stream socket using the given |
92 | /// client SSL context and connects it to |
93 | /// the socket specified by address. |
94 | |
95 | SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext, Session::Ptr pSession); |
96 | /// Creates a secure stream socket using the given |
97 | /// client SSL context and connects it to |
98 | /// the socket specified by address. |
99 | /// |
100 | /// The given Session is reused, if possible (client session |
101 | /// caching is enabled for the given Context, and the server |
102 | /// agrees to reuse the session). |
103 | |
104 | SecureStreamSocket(const SocketAddress& address, const std::string& hostName); |
105 | /// Creates a secure stream socket using the default |
106 | /// client SSL context and connects it to |
107 | /// the socket specified by address. |
108 | /// |
109 | /// The given host name is used for certificate verification. |
110 | |
111 | SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext); |
112 | /// Creates a secure stream socket using the given |
113 | /// client SSL context and connects it to |
114 | /// the socket specified by address. |
115 | /// |
116 | /// The given host name is used for certificate verification. |
117 | |
118 | SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext, Session::Ptr pSession); |
119 | /// Creates a secure stream socket using the given |
120 | /// client SSL context and connects it to |
121 | /// the socket specified by address. |
122 | /// |
123 | /// The given host name is used for certificate verification. |
124 | /// |
125 | /// The given Session is reused, if possible (client session |
126 | /// caching is enabled for the given Context, and the server |
127 | /// agrees to reuse the session). |
128 | |
129 | SecureStreamSocket(const Socket& socket); |
130 | /// Creates the SecureStreamSocket with the SocketImpl |
131 | /// from another socket. The SocketImpl must be |
132 | /// a SecureStreamSocketImpl, otherwise an InvalidArgumentException |
133 | /// will be thrown. |
134 | |
135 | virtual ~SecureStreamSocket(); |
136 | /// Destroys the StreamSocket. |
137 | |
138 | SecureStreamSocket& operator = (const Socket& socket); |
139 | /// Assignment operator. |
140 | /// |
141 | /// Releases the socket's SocketImpl and |
142 | /// attaches the SocketImpl from the other socket and |
143 | /// increments the reference count of the SocketImpl. |
144 | |
145 | bool havePeerCertificate() const; |
146 | /// Returns true iff the peer has presented a |
147 | /// certificate. |
148 | |
149 | X509Certificate peerCertificate() const; |
150 | /// Returns the peer's X509 certificate. |
151 | /// |
152 | /// Throws a SSLException if the peer did not |
153 | /// present a certificate. |
154 | |
155 | void setPeerHostName(const std::string& hostName); |
156 | /// Sets the peer's host name used for certificate validation. |
157 | |
158 | const std::string& getPeerHostName() const; |
159 | /// Returns the peer's host name used for certificate validation. |
160 | |
161 | static SecureStreamSocket attach(const StreamSocket& streamSocket); |
162 | /// Creates a SecureStreamSocket over an existing socket |
163 | /// connection. The given StreamSocket must be connected. |
164 | /// A SSL handshake will be performed. |
165 | |
166 | static SecureStreamSocket attach(const StreamSocket& streamSocket, Context::Ptr pContext); |
167 | /// Creates a SecureStreamSocket over an existing socket |
168 | /// connection. The given StreamSocket must be connected. |
169 | /// A SSL handshake will be performed. |
170 | |
171 | static SecureStreamSocket attach(const StreamSocket& streamSocket, Context::Ptr pContext, Session::Ptr pSession); |
172 | /// Creates a SecureStreamSocket over an existing socket |
173 | /// connection. The given StreamSocket must be connected. |
174 | /// A SSL handshake will be performed. |
175 | /// |
176 | /// The given Session is reused, if possible (client session |
177 | /// caching is enabled for the given Context, and the server |
178 | /// agrees to reuse the session). |
179 | |
180 | static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName); |
181 | /// Creates a SecureStreamSocket over an existing socket |
182 | /// connection. The given StreamSocket must be connected. |
183 | /// A SSL handshake will be performed. |
184 | |
185 | static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext); |
186 | /// Creates a SecureStreamSocket over an existing socket |
187 | /// connection. The given StreamSocket must be connected. |
188 | /// A SSL handshake will be performed. |
189 | |
190 | static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext, Session::Ptr pSession); |
191 | /// Creates a SecureStreamSocket over an existing socket |
192 | /// connection. The given StreamSocket must be connected. |
193 | /// A SSL handshake will be performed. |
194 | /// |
195 | /// The given Session is reused, if possible (client session |
196 | /// caching is enabled for the given Context, and the server |
197 | /// agrees to reuse the session). |
198 | |
199 | Context::Ptr context() const; |
200 | /// Returns the SSL context used by this socket. |
201 | |
202 | void setLazyHandshake(bool flag = true); |
203 | /// Enable lazy SSL handshake. If enabled, the SSL handshake |
204 | /// will be performed the first time date is sent or |
205 | /// received over the connection. |
206 | |
207 | bool getLazyHandshake() const; |
208 | /// Returns true if setLazyHandshake(true) has been called. |
209 | |
210 | void verifyPeerCertificate(); |
211 | /// Performs post-connect (or post-accept) peer certificate validation, |
212 | /// using the peer host name set with setPeerHostName(), or the peer's |
213 | /// IP address string if no peer host name has been set. |
214 | /// |
215 | /// Should only be used for non-blocking connections, after the |
216 | /// initial SSL handshake has been performed (see completeHandshake()). |
217 | |
218 | void verifyPeerCertificate(const std::string& hostName); |
219 | /// Performs post-connect (or post-accept) peer certificate validation |
220 | /// using the given host name. |
221 | /// |
222 | /// Should only be used for non-blocking connections, after the |
223 | /// initial SSL handshake has been performed (see completeHandshake()). |
224 | |
225 | int completeHandshake(); |
226 | /// Completes the SSL handshake. |
227 | /// |
228 | /// If the SSL connection was the result of an accept(), |
229 | /// the server-side handshake is completed, otherwise |
230 | /// a client-side handshake is performed. |
231 | /// |
232 | /// Returns 1 if the handshake was successful, ERR_SSL_WANT_READ or |
233 | /// ERR_SSL_WANT_WRITE if more data is required to complete the |
234 | /// handshake. In this case, completeHandshake() should be called |
235 | /// again, after the necessary condition has been met. |
236 | |
237 | Session::Ptr currentSession(); |
238 | /// Returns the SSL session of the current connection, |
239 | /// for reuse in a future connection (if session caching |
240 | /// is enabled). |
241 | /// |
242 | /// If no connection is established, returns null. |
243 | |
244 | void useSession(Session::Ptr pSession); |
245 | /// Sets the SSL session to use for the next |
246 | /// connection. Setting a previously saved Session |
247 | /// object is necessary to enable session caching. |
248 | /// |
249 | /// To remove the currently set session, a null pointer |
250 | /// can be given. |
251 | /// |
252 | /// Must be called before connect() to be effective. |
253 | |
254 | bool sessionWasReused(); |
255 | /// Returns true iff a reused session was negotiated during |
256 | /// the handshake. |
257 | |
258 | void abort(); |
259 | /// Aborts the SSL connection by closing the underlying |
260 | /// TCP connection. No orderly SSL shutdown is performed. |
261 | |
262 | protected: |
263 | SecureStreamSocket(SocketImpl* pImpl); |
264 | |
265 | friend class SecureServerSocket; |
266 | }; |
267 | |
268 | |
269 | } } // namespace Poco::Net |
270 | |
271 | |
272 | #endif // NetSSL_SecureStreamSocket_INCLUDED |
273 | |