1//
2// SecureSocketImpl.h
3//
4// Library: NetSSL_OpenSSL
5// Package: SSLSockets
6// Module: SecureSocketImpl
7//
8// Definition of the SecureSocketImpl 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_SecureSocketImpl_INCLUDED
18#define NetSSL_SecureSocketImpl_INCLUDED
19
20
21#include "Poco/Net/NetSSL.h"
22#include "Poco/Net/SocketImpl.h"
23#include "Poco/Net/Context.h"
24#include "Poco/Net/X509Certificate.h"
25#include "Poco/Net/Session.h"
26#include <openssl/bio.h>
27#include <openssl/ssl.h>
28
29
30namespace Poco {
31namespace Net {
32
33
34class HostEntry;
35
36
37class NetSSL_API SecureSocketImpl
38 /// The SocketImpl for SecureStreamSocket.
39{
40public:
41 SecureSocketImpl(Poco::AutoPtr<SocketImpl> pSocketImpl, Context::Ptr pContext);
42 /// Creates the SecureSocketImpl using an already
43 /// connected stream socket.
44
45 virtual ~SecureSocketImpl();
46 /// Destroys the SecureSocketImpl.
47
48 SocketImpl* acceptConnection(SocketAddress& clientAddr);
49 /// Get the next completed connection from the
50 /// socket's completed connection queue.
51 ///
52 /// If the queue is empty, waits until a connection
53 /// request completes.
54 ///
55 /// Returns a new SSL socket for the connection
56 /// with the client.
57 ///
58 /// The client socket's address is returned in clientAddr.
59
60 void connect(const SocketAddress& address, bool performHandshake);
61 /// Initializes the socket and establishes a secure connection to
62 /// the TCP server at the given address.
63 ///
64 /// If performHandshake is true, the SSL handshake is performed immediately
65 /// after establishing the connection. Otherwise, the handshake is performed
66 /// the first time sendBytes(), receiveBytes() or completeHandshake() is called.
67
68 void connect(const SocketAddress& address, const Poco::Timespan& timeout, bool performHandshake);
69 /// Initializes the socket, sets the socket timeout and
70 /// establishes a secure connection to the TCP server at the given address.
71 ///
72 /// If performHandshake is true, the SSL handshake is performed immediately
73 /// after establishing the connection. Otherwise, the handshake is performed
74 /// the first time sendBytes(), receiveBytes() or completeHandshake() is called.
75
76 void connectNB(const SocketAddress& address);
77 /// Initializes the socket and establishes a secure connection to
78 /// the TCP server at the given address. Prior to opening the
79 /// connection the socket is set to nonblocking mode.
80
81 void bind(const SocketAddress& address, bool reuseAddress = false, bool reusePort = false);
82 /// Bind a local address to the socket.
83 ///
84 /// This is usually only done when establishing a server
85 /// socket. SSL clients should not bind a socket to a
86 /// specific address.
87 ///
88 /// If reuseAddress is true, sets the SO_REUSEADDR
89 /// socket option.
90
91 void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
92 /// Bind a local IPv6 address to the socket.
93 ///
94 /// This is usually only done when establishing a server
95 /// socket. SSL clients should not bind a socket to a
96 /// specific address.
97 ///
98 /// If reuseAddress is true, sets the SO_REUSEADDR
99 /// socket option.
100 ///
101 /// The given address must be an IPv6 address. The
102 /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
103 /// according to the ipV6Only parameter.
104 ///
105 /// If the library has not been built with IPv6 support,
106 /// a Poco::NotImplementedException will be thrown.
107
108 void listen(int backlog = 64);
109 /// Puts the socket into listening state.
110 ///
111 /// The socket becomes a passive socket that
112 /// can accept incoming connection requests.
113 ///
114 /// The backlog argument specifies the maximum
115 /// number of connections that can be queued
116 /// for this socket.
117
118 void shutdown();
119 /// Shuts down the connection by attempting
120 /// an orderly SSL shutdown, then actually
121 /// shutting down the TCP connection.
122
123 void close();
124 /// Close the socket.
125
126 void abort();
127 /// Aborts the connection by closing the
128 /// underlying TCP connection. No orderly SSL shutdown
129 /// is performed.
130
131 int sendBytes(const void* buffer, int length, int flags = 0);
132 /// Sends the contents of the given buffer through
133 /// the socket. Any specified flags are ignored.
134 ///
135 /// Returns the number of bytes sent, which may be
136 /// less than the number of bytes specified.
137
138 int receiveBytes(void* buffer, int length, int flags = 0);
139 /// Receives data from the socket and stores it
140 /// in buffer. Up to length bytes are received.
141 ///
142 /// Returns the number of bytes received.
143
144 int available() const;
145 /// Returns the number of bytes available from the
146 /// SSL buffer for immediate reading.
147
148 int completeHandshake();
149 /// Completes the SSL handshake.
150 ///
151 /// If the SSL connection was the result of an accept(),
152 /// the server-side handshake is completed, otherwise
153 /// a client-side handshake is performed.
154
155 poco_socket_t sockfd();
156 /// Returns the underlying socket descriptor.
157
158 X509* peerCertificate() const;
159 /// Returns the peer's certificate.
160
161 Context::Ptr context() const;
162 /// Returns the SSL context used for this socket.
163
164 void verifyPeerCertificate();
165 /// Performs post-connect (or post-accept) peer certificate validation,
166 /// using the peer host name set with setPeerHostName(), or the peer's
167 /// IP address string if no peer host name has been set.
168
169 void verifyPeerCertificate(const std::string& hostName);
170 /// Performs post-connect (or post-accept) peer certificate validation
171 /// using the given peer host name.
172
173 void setPeerHostName(const std::string& hostName);
174 /// Sets the peer host name for certificate validation purposes.
175
176 const std::string& getPeerHostName() const;
177 /// Returns the peer host name.
178
179 Session::Ptr currentSession();
180 /// Returns the SSL session of the current connection,
181 /// for reuse in a future connection (if session caching
182 /// is enabled).
183 ///
184 /// If no connection is established, returns null.
185
186 void useSession(Session::Ptr pSession);
187 /// Sets the SSL session to use for the next
188 /// connection. Setting a previously saved Session
189 /// object is necessary to enable session caching.
190 ///
191 /// To remove the currently set session, a null pointer
192 /// can be given.
193 ///
194 /// Must be called before connect() to be effective.
195
196 bool sessionWasReused();
197 /// Returns true iff a reused session was negotiated during
198 /// the handshake.
199
200protected:
201 void acceptSSL();
202 /// Performs a server-side SSL handshake and certificate verification.
203
204 void connectSSL(bool performHandshake);
205 /// Performs a client-side SSL handshake and establishes a secure
206 /// connection over an already existing TCP connection.
207
208 long verifyPeerCertificateImpl(const std::string& hostName);
209 /// Performs post-connect (or post-accept) peer certificate validation.
210
211 static bool isLocalHost(const std::string& hostName);
212 /// Returns true iff the given host name is the local host
213 /// (either "localhost" or "127.0.0.1").
214
215 bool mustRetry(int rc);
216 /// Returns true if the last operation should be retried,
217 /// otherwise false.
218 ///
219 /// In case of an SSL_ERROR_WANT_READ error, and if the socket is
220 /// blocking, waits for the underlying socket to become readable.
221 ///
222 /// In case of an SSL_ERROR_WANT_WRITE error, and if the socket is
223 /// blocking, waits for the underlying socket to become writable.
224 ///
225 /// Can also throw a Poco::TimeoutException if the socket does
226 /// not become readable or writable within the sockets
227 /// receive or send timeout.
228
229 int handleError(int rc);
230 /// Handles an SSL error by throwing an appropriate exception.
231
232 void reset();
233 /// Prepares the socket for re-use.
234 ///
235 /// After closing and resetting a socket, the socket can
236 /// be used for a new connection.
237 ///
238 /// Note that simply closing a socket is not sufficient
239 /// to be able to re-use it again.
240
241private:
242 SecureSocketImpl(const SecureSocketImpl&);
243 SecureSocketImpl& operator = (const SecureSocketImpl&);
244
245 SSL* _pSSL;
246 Poco::AutoPtr<SocketImpl> _pSocket;
247 Context::Ptr _pContext;
248 bool _needHandshake;
249 std::string _peerHostName;
250 Session::Ptr _pSession;
251
252 friend class SecureStreamSocketImpl;
253};
254
255
256//
257// inlines
258//
259inline poco_socket_t SecureSocketImpl::sockfd()
260{
261 return _pSocket->sockfd();
262}
263
264
265inline Context::Ptr SecureSocketImpl::context() const
266{
267 return _pContext;
268}
269
270
271inline const std::string& SecureSocketImpl::getPeerHostName() const
272{
273 return _peerHostName;
274}
275
276
277} } // namespace Poco::Net
278
279
280#endif // NetSSL_SecureSocketImpl_INCLUDED
281