43#include "blocxx/BLOCXX_config.h"
45#ifdef BLOCXX_HAVE_OPENSSL
51#include <openssl/err.h>
69void sslWaitForIO(SocketBaseImpl& s,
int type)
71 if(type == SSL_ERROR_WANT_READ)
73 s.waitForInput(Timeout::infinite);
77 s.waitForOutput(Timeout::infinite);
81void shutdownSSL(SSL* ssl)
84 if (SSL_shutdown(ssl) == -1)
92void connectWithSSL(SSL* ssl, SocketBaseImpl& s)
97 int cc = SSL_connect(ssl);
98 cc = SSL_get_error(ssl, cc);
99 while((cc == SSL_ERROR_WANT_READ
100 || cc == SSL_ERROR_WANT_WRITE)
101 && retries < BLOCXX_SSL_RETRY_LIMIT)
105 cc = SSL_connect(ssl);
106 cc = SSL_get_error(ssl, cc);
110 if (cc != SSL_ERROR_NONE)
112 BLOCXX_THROW(SSLException, Format(
"SSL connect error: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
116int acceptSSL(SSL* ssl, SocketBaseImpl& s, String& errorDescription)
120 int cc = SSL_ERROR_WANT_READ;
121 while((cc == SSL_ERROR_WANT_READ || cc == SSL_ERROR_WANT_WRITE)
122 && retries < BLOCXX_SSL_RETRY_LIMIT)
126 cc = SSL_accept(ssl);
127 cc = SSL_get_error(ssl, cc);
130 if (cc == SSL_ERROR_NONE)
136 errorDescription = SSLCtxMgr::getOpenSSLErrorDescription();
144SSLSocketImpl::SSLSocketImpl()
151SSLSocketImpl::SSLSocketImpl(SocketHandle_t fd,
152 SocketAddress::AddressType addrType,
const SSLServerCtxRef& sslCtx)
153 : SocketBaseImpl(fd, addrType)
157 m_ssl = SSL_new(sslCtx->getSSLCtx());
160 BLOCXX_THROW(SSLException, Format(
"SSL_new failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
163 if (SSL_set_ex_data(m_ssl, SSLServerCtx::SSL_DATA_INDEX, &m_owctx) == 0)
165 BLOCXX_THROW(SSLException, Format(
"SSL_set_ex_data failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
168 BIO* bio = BIO_new_socket(fd, BIO_NOCLOSE);
172 BLOCXX_THROW(SSLException, Format(
"BIO_new_socket failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
175 SSL_set_bio(m_ssl, bio, bio);
176 String errorDescription;
177 if (acceptSSL(m_ssl, *
this, errorDescription) != 0)
182 BLOCXX_THROW(SSLException, Format(
"SSLSocketImpl ctor: SSL accept error while connecting to %1: %2", m_peerAddress.toString(), errorDescription).c_str());
184 if (!SSLCtxMgr::checkClientCert(m_ssl, m_peerAddress.getName()))
189 BLOCXX_THROW(SSLException,
"SSL failed to authenticate client");
195SSLSocketImpl::SSLSocketImpl(SocketHandle_t fd,
196 SocketAddress::AddressType addrType)
197 : SocketBaseImpl(fd, addrType)
200 m_ssl = SSL_new(SSLCtxMgr::getSSLCtxServer());
203 BLOCXX_THROW(SSLException, Format(
"SSL_new failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
206 m_sbio = BIO_new_socket(fd, BIO_NOCLOSE);
210 BLOCXX_THROW(SSLException, Format(
"BIO_new_socket failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
213 SSL_set_bio(m_ssl, m_sbio, m_sbio);
214 String errorDescription;
215 if (acceptSSL(m_ssl, *
this, errorDescription) != 0)
220 BLOCXX_THROW(SSLException, Format(
"SSLSocketImpl ctor: SSL accept error while connecting to %1: %2", m_peerAddress.toString(), errorDescription).c_str());
222 if (!SSLCtxMgr::checkClientCert(m_ssl, m_peerAddress.getName()))
227 BLOCXX_THROW(SSLException,
"SSL failed to authenticate client");
231SSLSocketImpl::SSLSocketImpl(
const SocketAddress& addr)
232 : SocketBaseImpl(addr)
237SSLSocketImpl::~SSLSocketImpl()
256SSLSocketImpl::getSelectObj()
const
258#if defined(BLOCXX_WIN32)
261 st.sockfd = m_sockfd;
263 st.networkevents = FD_READ | FD_WRITE;
272SSLSocketImpl::connect(
const SocketAddress& addr)
274 SocketBaseImpl::connect(addr);
279SSLSocketImpl::connectSSL()
281 m_isConnected =
false;
289 m_ssl = SSL_new(m_sslCtx->getSSLCtx());
293 BLOCXX_THROW(SSLException, Format(
"SSL_new failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
295 m_sbio = BIO_new_socket(m_sockfd, BIO_NOCLOSE);
299 BLOCXX_THROW(SSLException, Format(
"BIO_new_socket failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
301 SSL_set_bio(m_ssl, m_sbio, m_sbio);
303 connectWithSSL(m_ssl, *
this);
305 if (!SSLCtxMgr::checkServerCert(m_ssl, m_peerAddress.getName()))
307 BLOCXX_THROW(SSLException,
"Failed to validate peer certificate");
309 m_isConnected =
true;
313SSLSocketImpl::disconnect()
315#if defined(BLOCXX_WIN32)
318 if (m_sockfd != -1 && m_isConnected)
326 SocketBaseImpl::disconnect();
330SSLSocketImpl::writeAux(
const void* dataOut,
int dataOutLen)
332 return SSLCtxMgr::sslWrite(m_ssl,
static_cast<const char*
>(dataOut),
337SSLSocketImpl::readAux(
void* dataIn,
int dataInLen)
339 return SSLCtxMgr::sslRead(m_ssl,
static_cast<char*
>(dataIn),
344SSLSocketImpl::getSSL()
const
351SSLSocketImpl::peerCertVerified()
const
353 return (m_owctx.peerCertPassedVerify == OWSSLContext::VERIFY_PASS);
360SSLSocketImpl::waitForInput(
const Timeout& timeout)
363 if (SSL_pending(m_ssl))
367 return SocketBaseImpl::waitForInput(timeout);
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(),...
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
IntrusiveReference< SSLClientCtx > SSLClientCtxRef