22#include "securesocket.h"
29#define LASTERROR WSAGetLastError()
30#define ERRNO_INTR WSAEINTR
32#define LASTERROR errno
33#define ERRNO_INTR EINTR
36using namespace NSROOT;
43 m_instance =
new SSLSessionFactory();
47void SSLSessionFactory::Destroy()
56#include <openssl/ssl.h>
57#include <openssl/err.h>
58#include <openssl/pem.h>
59#include <openssl/x509.h>
60#include <openssl/x509_vfy.h>
63const char*
const PREFERRED_CIPHERS =
"HIGH:!aNULL:!PSK:!SRP:!MD5:!RC4:!CAMELLIA:!DSS";
65SSLSessionFactory::SSLSessionFactory()
66: m_client_ctx(nullptr)
69 if (SSL_library_init() < 0)
70 DBG(DBG_ERROR,
"%s: Could not initialize the SSL library\n", __FUNCTION__);
73 SSL_load_error_strings();
78#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
79 SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
81 SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
84 DBG(DBG_ERROR,
"%s: Could not create the SSL client context\n", __FUNCTION__);
87 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
94 const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
95 (void)SSL_CTX_set_options(ctx, flags);
103 if (SSL_CTX_set_cipher_list(ctx, PREFERRED_CIPHERS) != 1)
104 DBG(DBG_ERROR,
"%s: Set cipher list failed\n", __FUNCTION__);
111 DBG(DBG_DEBUG,
"%s: SSL has been initialized\n", __FUNCTION__);
116SSLSessionFactory::~SSLSessionFactory()
119 SSL_CTX_free(
static_cast<SSL_CTX*
>(m_client_ctx));
122 DBG(DBG_INFO,
"%s: SSL resources destroyed\n", __FUNCTION__);
129 SSL* ssl = SSL_new(
static_cast<SSL_CTX*
>(m_client_ctx));
136 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
137 return new SecureSocket(ssl);
140SSLServerContext::~SSLServerContext()
144 DBG(DBG_DEBUG,
"%s: Free SSL server context (%p)\n", __FUNCTION__, m_server_ctx);
145 SSL_CTX_free(
static_cast<SSL_CTX*
>(m_server_ctx));
151 if (m_server_ctx || !SSLSessionFactory::Instance().IsEnabled())
155#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
156 SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
158 SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
162 DBG(DBG_ERROR,
"%s: Could not create the SSL server context\n", __FUNCTION__);
166 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
169 const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
170 (void)SSL_CTX_set_options(ctx, flags);
172 if (SSL_CTX_set_cipher_list(ctx,
"ALL:!EXPORT:!LOW:!aNULL:!eNULL:!SSLv2") != 1)
173 DBG(DBG_ERROR,
"%s: Set cipher list failed\n", __FUNCTION__);
179 if (SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str()) != 1)
181 DBG(DBG_ERROR,
"%s: Certificate file is invalid\n", __FUNCTION__);
186 if (SSL_CTX_use_PrivateKey_file(ctx, pkeyfile.c_str(), SSL_FILETYPE_PEM) != 1)
188 DBG(DBG_ERROR,
"%s: Private key file is invalid\n", __FUNCTION__);
193 if (SSL_CTX_check_private_key(ctx) != 1) {
194 DBG(DBG_ERROR,
"%s: Private key does not match the certificate public key\n", __FUNCTION__);
198 DBG(DBG_INFO,
"%s: Server certificate was successfully loaded\n", __FUNCTION__);
207 SSL* ssl = SSL_new(
static_cast<SSL_CTX*
>(m_server_ctx));
214 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
215 return new SecureSocket(ssl);
220 SSL_set_fd(
static_cast<SSL*
>(socket.
m_ssl), socket.m_socket);
221 SSL_set_accept_state(
static_cast<SSL*
>(socket.
m_ssl));
224 int r = SSL_accept(
static_cast<SSL*
>(socket.
m_ssl));
228 return TcpServerSocket::ACCEPT_FAILURE;
230 DBG(DBG_PROTO,
"%s: SSL handshake initialized\n", __FUNCTION__);
232 return TcpServerSocket::ACCEPT_SUCCESS;
235SecureSocket::SecureSocket(
void* ssl)
245SecureSocket::~SecureSocket()
248 SSL_free(
static_cast<SSL*
>(m_ssl));
264 SSL_set_fd(
static_cast<SSL*
>(m_ssl), m_socket);
265 SSL_set_tlsext_host_name(
static_cast<SSL*
>(m_ssl), server);
270 int r = SSL_connect(
static_cast<SSL*
>(m_ssl));
275 int err = SSL_get_error(
static_cast<SSL*
>(m_ssl), r);
276 if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
278 DBG(DBG_DEBUG,
"%s: SSL retry (%d)\n", __FUNCTION__, err);
283 DBG(DBG_ERROR,
"%s: SSL connect failed: %s\n", __FUNCTION__, GetSSLError());
287 DBG(DBG_PROTO,
"%s: SSL handshake initialized\n", __FUNCTION__);
291 if (!IsCertificateValid(str))
293 DBG(DBG_ERROR,
"%s: Could not get a valid certificate from the server\n", __FUNCTION__);
296 DBG(DBG_PROTO,
"%s: %s\n", __FUNCTION__, str.c_str());
302 if (m_connected && n > 0)
307 if (SSL_pending(
static_cast<SSL*
>(m_ssl)) == 0)
317 DBG(DBG_INFO,
"%s: socket(%p) timed out (%d)\n", __FUNCTION__, &m_socket, hangcount);
319 if (++hangcount >= m_attempt)
322 else if (m_errno != ERRNO_INTR)
327 int r = SSL_read(
static_cast<SSL*
>(m_ssl), buf, (
int) n);
330 int err = SSL_get_error(
static_cast<SSL*
>(m_ssl), r);
331 if (err == SSL_ERROR_WANT_READ)
333 DBG(DBG_DEBUG,
"%s: SSL retry\n", __FUNCTION__);
336 if (err == SSL_ERROR_WANT_WRITE)
338 DBG(DBG_DEBUG,
"%s: SSL wants write\n", __FUNCTION__);
343 DBG(DBG_ERROR,
"%s: SSL read failed: %s\n", __FUNCTION__, GetSSLError());
352 if (m_connected && n > 0)
357 int r = SSL_read(
static_cast<SSL*
>(m_ssl), buf, (
int) n);
360 int err = SSL_get_error(
static_cast<SSL*
>(m_ssl), r);
361 if (err == SSL_ERROR_WANT_READ)
363 DBG(DBG_DEBUG,
"%s: SSL retry\n", __FUNCTION__);
366 if (err == SSL_ERROR_WANT_WRITE)
368 DBG(DBG_DEBUG,
"%s: SSL wants write\n", __FUNCTION__);
373 DBG(DBG_ERROR,
"%s: SSL read failed: %s\n", __FUNCTION__, GetSSLError());
382 if (m_connected && size > 0)
387 int r = SSL_write(
static_cast<SSL*
>(m_ssl), buf, (
int) size);
388 if (r > 0 && size == (
size_t) r)
390 int err = SSL_get_error(
static_cast<SSL*
>(m_ssl), r);
391 if (err == SSL_ERROR_WANT_WRITE)
393 DBG(DBG_DEBUG,
"%s: SSL retry\n", __FUNCTION__);
396 if (err == SSL_ERROR_WANT_READ)
398 DBG(DBG_DEBUG,
"%s: SSL wants read\n", __FUNCTION__);
403 DBG(DBG_ERROR,
"%s: SSL write failed: %s\n", __FUNCTION__, GetSSLError());
414 SSL_shutdown(
static_cast<SSL*
>(m_ssl));
420 X509_free(
static_cast<X509*
>(m_cert));
425bool SecureSocket::IsCertificateValid(std::string& str)
428 X509_free(
static_cast<X509*
>(m_cert));
429 m_cert = SSL_get_peer_certificate(
static_cast<SSL*
>(m_ssl));
435 X509_NAME* name = X509_get_subject_name(
static_cast<X509*
>(m_cert));
436 str.assign(X509_NAME_oneline(name, buf,
sizeof(buf) - 1));
442#define ERROR_MSG_SIZE 256
443const char* SecureSocket::GetSSLError()
447 m_errmsg =
new char[ERROR_MSG_SIZE];
448 ERR_error_string_n(m_ssl_error, m_errmsg, ERROR_MSG_SIZE);
454SSLSessionFactory::SSLSessionFactory()
455: m_client_ctx(nullptr)
458 DBG(DBG_INFO,
"%s: SSL feature is disabled\n", __FUNCTION__);
461SSLSessionFactory::~SSLSessionFactory()
470SSLServerContext::~SSLServerContext()
486 return TcpServerSocket::ACCEPT_ERROR;
489SecureSocket::SecureSocket(
void* ssl)
498SecureSocket::~SecureSocket()
535bool SecureSocket::IsCertificateValid(std::string& str)
541const char* SecureSocket::GetSSLError()
543 return "SSL not available";
SecureSocket * NewServerSocket()
void * m_server_ctx
SSL server context.
bool InitContext(const std::string &certfile, const std::string &pkeyfile)
static TcpServerSocket::AcceptStatus SSLHandshake(SecureSocket &socket)
SecureSocket * NewClientSocket()
bool m_connected
SSL session state.
int m_ssl_error
SSL error code.
size_t ReceiveData(void *buf, size_t n)
bool SendData(const char *buf, size_t size)
void * m_cert
X509 certificate.
size_t BlockingRead(void *buf, size_t n)
char * m_errmsg
error message buffer
bool Connect(const char *server, unsigned port, int rcvbuf)
virtual void Disconnect()
virtual bool Connect(const char *server, unsigned port, int rcvbuf)
int Listen(timeval *timeout)