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 listen(int backlog = 64);
92 /// Puts the socket into listening state.
93 ///
94 /// The socket becomes a passive socket that
95 /// can accept incoming connection requests.
96 ///
97 /// The backlog argument specifies the maximum
98 /// number of connections that can be queued
99 /// for this socket.
100
101 void shutdown();
102 /// Shuts down the connection by attempting
103 /// an orderly SSL shutdown, then actually
104 /// shutting down the TCP connection.
105
106 void close();
107 /// Close the socket.
108
109 void abort();
110 /// Aborts the connection by closing the
111 /// underlying TCP connection. No orderly SSL shutdown
112 /// is performed.
113
114 int sendBytes(const void* buffer, int length, int flags = 0);
115 /// Sends the contents of the given buffer through
116 /// the socket. Any specified flags are ignored.
117 ///
118 /// Returns the number of bytes sent, which may be
119 /// less than the number of bytes specified.
120
121 int receiveBytes(void* buffer, int length, int flags = 0);
122 /// Receives data from the socket and stores it
123 /// in buffer. Up to length bytes are received.
124 ///
125 /// Returns the number of bytes received.
126
127 int available() const;
128 /// Returns the number of bytes available from the
129 /// SSL buffer for immediate reading.
130
131 int completeHandshake();
132 /// Completes the SSL handshake.
133 ///
134 /// If the SSL connection was the result of an accept(),
135 /// the server-side handshake is completed, otherwise
136 /// a client-side handshake is performed.
137
138 poco_socket_t sockfd();
139 /// Returns the underlying socket descriptor.
140
141 X509* peerCertificate() const;
142 /// Returns the peer's certificate.
143
144 Context::Ptr context() const;
145 /// Returns the SSL context used for this socket.
146
147 void verifyPeerCertificate();
148 /// Performs post-connect (or post-accept) peer certificate validation,
149 /// using the peer host name set with setPeerHostName(), or the peer's
150 /// IP address string if no peer host name has been set.
151
152 void verifyPeerCertificate(const std::string& hostName);
153 /// Performs post-connect (or post-accept) peer certificate validation
154 /// using the given peer host name.
155
156 void setPeerHostName(const std::string& hostName);
157 /// Sets the peer host name for certificate validation purposes.
158
159 const std::string& getPeerHostName() const;
160 /// Returns the peer host name.
161
162 Session::Ptr currentSession();
163 /// Returns the SSL session of the current connection,
164 /// for reuse in a future connection (if session caching
165 /// is enabled).
166 ///
167 /// If no connection is established, returns null.
168
169 void useSession(Session::Ptr pSession);
170 /// Sets the SSL session to use for the next
171 /// connection. Setting a previously saved Session
172 /// object is necessary to enable session caching.
173 ///
174 /// To remove the currently set session, a null pointer
175 /// can be given.
176 ///
177 /// Must be called before connect() to be effective.
178
179 bool sessionWasReused();
180 /// Returns true iff a reused session was negotiated during
181 /// the handshake.
182
183protected:
184 void acceptSSL();
185 /// Performs a server-side SSL handshake and certificate verification.
186
187 void connectSSL(bool performHandshake);
188 /// Performs a client-side SSL handshake and establishes a secure
189 /// connection over an already existing TCP connection.
190
191 long verifyPeerCertificateImpl(const std::string& hostName);
192 /// Performs post-connect (or post-accept) peer certificate validation.
193
194 static bool isLocalHost(const std::string& hostName);
195 /// Returns true iff the given host name is the local host
196 /// (either "localhost" or "127.0.0.1").
197
198 bool mustRetry(int rc);
199 /// Returns true if the last operation should be retried,
200 /// otherwise false.
201 ///
202 /// In case of an SSL_ERROR_WANT_READ error, and if the socket is
203 /// blocking, waits for the underlying socket to become readable.
204 ///
205 /// In case of an SSL_ERROR_WANT_WRITE error, and if the socket is
206 /// blocking, waits for the underlying socket to become writable.
207 ///
208 /// Can also throw a Poco::TimeoutException if the socket does
209 /// not become readable or writable within the sockets
210 /// receive or send timeout.
211
212 int handleError(int rc);
213 /// Handles an SSL error by throwing an appropriate exception.
214
215 void reset();
216 /// Prepares the socket for re-use.
217 ///
218 /// After closing and resetting a socket, the socket can
219 /// be used for a new connection.
220 ///
221 /// Note that simply closing a socket is not sufficient
222 /// to be able to re-use it again.
223
224private:
225 SecureSocketImpl(const SecureSocketImpl&);
226 SecureSocketImpl& operator = (const SecureSocketImpl&);
227
228 SSL* _pSSL;
229 Poco::AutoPtr<SocketImpl> _pSocket;
230 Context::Ptr _pContext;
231 bool _needHandshake;
232 std::string _peerHostName;
233 Session::Ptr _pSession;
234
235 friend class SecureStreamSocketImpl;
236};
237
238
239//
240// inlines
241//
242inline poco_socket_t SecureSocketImpl::sockfd()
243{
244 return _pSocket->sockfd();
245}
246
247
248inline Context::Ptr SecureSocketImpl::context() const
249{
250 return _pContext;
251}
252
253
254inline const std::string& SecureSocketImpl::getPeerHostName() const
255{
256 return _peerHostName;
257}
258
259
260} } // namespace Poco::Net
261
262
263#endif // NetSSL_SecureSocketImpl_INCLUDED
264