00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00041 #include "BLOCXX_config.h"
00042 #include "blocxx/SSLSocketImpl.hpp"
00043 #include "blocxx/Format.hpp"
00044 #include "blocxx/Assertion.hpp"
00045 #ifdef BLOCXX_HAVE_OPENSSL
00046 #include <openssl/err.h>
00047 #include <blocxx/Format.hpp>
00048 #include <blocxx/SocketUtils.hpp>
00049
00050
00051 namespace BLOCXX_NAMESPACE
00052 {
00054 SSLSocketImpl::SSLSocketImpl(SSLClientCtxRef sslCtx)
00055 : SocketBaseImpl()
00056 , m_ssl(0)
00057 , m_sslCtx(sslCtx)
00058 {
00059 }
00060
00061 namespace
00062 {
00063
00064 void sslWaitForIO(SocketBaseImpl& s, int type)
00065 {
00066 if(type == SSL_ERROR_WANT_READ)
00067 {
00068 s.waitForInput();
00069 }
00070 else
00071 {
00072 s.waitForOutput();
00073 }
00074 }
00075
00076 void shutdownSSL(SSL* ssl)
00077 {
00078 BLOCXX_ASSERT(ssl != 0);
00079 if (SSL_shutdown(ssl) == -1)
00080 {
00081
00082 }
00083
00084
00085 }
00086
00087 void connectWithSSL(SSL* ssl, SocketBaseImpl& s)
00088 {
00089 BLOCXX_ASSERT(ssl != 0);
00090 int retries = 0;
00091 ERR_clear_error();
00092 int cc = SSL_connect(ssl);
00093 cc = SSL_get_error(ssl, cc);
00094 while((cc == SSL_ERROR_WANT_READ
00095 || cc == SSL_ERROR_WANT_WRITE)
00096 && retries < BLOCXX_SSL_RETRY_LIMIT)
00097 {
00098 sslWaitForIO(s, cc);
00099 ERR_clear_error();
00100 cc = SSL_connect(ssl);
00101 cc = SSL_get_error(ssl, cc);
00102 retries++;
00103 }
00104
00105 if (cc != SSL_ERROR_NONE)
00106 {
00107 BLOCXX_THROW(SSLException, Format("SSL connect error: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00108 }
00109 }
00110
00111 int acceptSSL(SSL* ssl, SocketBaseImpl& s, String& errorDescription)
00112 {
00113 BLOCXX_ASSERT(ssl != 0);
00114 int retries = 0;
00115 int cc = SSL_ERROR_WANT_READ;
00116 while((cc == SSL_ERROR_WANT_READ || cc == SSL_ERROR_WANT_WRITE)
00117 && retries < BLOCXX_SSL_RETRY_LIMIT)
00118 {
00119 sslWaitForIO(s, cc);
00120 ERR_clear_error();
00121 cc = SSL_accept(ssl);
00122 cc = SSL_get_error(ssl, cc);
00123 retries++;
00124 }
00125 if (cc == SSL_ERROR_NONE)
00126 {
00127 return 0;
00128 }
00129 else
00130 {
00131 errorDescription = SSLCtxMgr::getOpenSSLErrorDescription();
00132 return -1;
00133 }
00134 }
00135
00136 }
00137
00139 SSLSocketImpl::SSLSocketImpl(SocketHandle_t fd,
00140 SocketAddress::AddressType addrType, const SSLServerCtxRef& sslCtx)
00141 : SocketBaseImpl(fd, addrType)
00142 {
00143 BLOCXX_ASSERT(sslCtx);
00144 ERR_clear_error();
00145 m_ssl = SSL_new(sslCtx->getSSLCtx());
00146 if (!m_ssl)
00147 {
00148 BLOCXX_THROW(SSLException, Format("SSL_new failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00149 }
00150
00151 if (SSL_set_ex_data(m_ssl, SSLServerCtx::SSL_DATA_INDEX, &m_owctx) == 0)
00152 {
00153 BLOCXX_THROW(SSLException, Format("SSL_set_ex_data failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00154 }
00155
00156 BIO* bio = BIO_new_socket(fd, BIO_NOCLOSE);
00157 if (!bio)
00158 {
00159 SSL_free(m_ssl);
00160 BLOCXX_THROW(SSLException, Format("BIO_new_socket failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00161 }
00162
00163 SSL_set_bio(m_ssl, bio, bio);
00164 String errorDescription;
00165 if (acceptSSL(m_ssl, *this, errorDescription) != 0)
00166 {
00167 shutdownSSL(m_ssl);
00168 SSL_free(m_ssl);
00169 ERR_remove_state(0);
00170 BLOCXX_THROW(SSLException, Format("SSLSocketImpl ctor: SSL accept error while connecting to %1: %2", m_peerAddress.toString(), errorDescription).c_str());
00171 }
00172 if (!SSLCtxMgr::checkClientCert(m_ssl, m_peerAddress.getName()))
00173 {
00174 shutdownSSL(m_ssl);
00175 SSL_free(m_ssl);
00176 ERR_remove_state(0);
00177 BLOCXX_THROW(SSLException, "SSL failed to authenticate client");
00178 }
00179 }
00180
00181
00183 SSLSocketImpl::SSLSocketImpl(SocketHandle_t fd,
00184 SocketAddress::AddressType addrType)
00185 : SocketBaseImpl(fd, addrType)
00186 {
00187 ERR_clear_error();
00188 m_ssl = SSL_new(SSLCtxMgr::getSSLCtxServer());
00189 if (!m_ssl)
00190 {
00191 BLOCXX_THROW(SSLException, Format("SSL_new failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00192 }
00193
00194 m_sbio = BIO_new_socket(fd, BIO_NOCLOSE);
00195 if (!m_sbio)
00196 {
00197 SSL_free(m_ssl);
00198 BLOCXX_THROW(SSLException, Format("BIO_new_socket failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00199 }
00200
00201 SSL_set_bio(m_ssl, m_sbio, m_sbio);
00202 String errorDescription;
00203 if (acceptSSL(m_ssl, *this, errorDescription) != 0)
00204 {
00205 shutdownSSL(m_ssl);
00206 SSL_free(m_ssl);
00207 ERR_remove_state(0);
00208 BLOCXX_THROW(SSLException, Format("SSLSocketImpl ctor: SSL accept error while connecting to %1: %2", m_peerAddress.toString(), errorDescription).c_str());
00209 }
00210 if (!SSLCtxMgr::checkClientCert(m_ssl, m_peerAddress.getName()))
00211 {
00212 shutdownSSL(m_ssl);
00213 SSL_free(m_ssl);
00214 ERR_remove_state(0);
00215 BLOCXX_THROW(SSLException, "SSL failed to authenticate client");
00216 }
00217 }
00219 SSLSocketImpl::SSLSocketImpl(const SocketAddress& addr)
00220 : SocketBaseImpl(addr)
00221 {
00222 connectSSL();
00223 }
00225 SSLSocketImpl::~SSLSocketImpl()
00226 {
00227 try
00228 {
00229 disconnect();
00230 if (m_ssl)
00231 {
00232 SSL_free(m_ssl);
00233 m_ssl = 0;
00234 }
00235 ERR_remove_state(0);
00236 }
00237 catch (...)
00238 {
00239
00240 }
00241 }
00243 Select_t
00244 SSLSocketImpl::getSelectObj() const
00245 {
00246 #if defined(BLOCXX_WIN32)
00247 Select_t st;
00248 st.event = m_event;
00249 st.sockfd = m_sockfd;
00250 st.networkevents = FD_READ | FD_WRITE;
00251 st.doreset = true;
00252 return st;
00253 #else
00254 return m_sockfd;
00255 #endif
00256 }
00258 void
00259 SSLSocketImpl::connect(const SocketAddress& addr)
00260 {
00261 SocketBaseImpl::connect(addr);
00262 connectSSL();
00263 }
00265 void
00266 SSLSocketImpl::connectSSL()
00267 {
00268 m_isConnected = false;
00269 BLOCXX_ASSERT(m_sslCtx);
00270 if (m_ssl)
00271 {
00272 SSL_free(m_ssl);
00273 m_ssl = 0;
00274 }
00275 ERR_clear_error();
00276 m_ssl = SSL_new(m_sslCtx->getSSLCtx());
00277
00278 if (!m_ssl)
00279 {
00280 BLOCXX_THROW(SSLException, Format("SSL_new failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00281 }
00282 m_sbio = BIO_new_socket(m_sockfd, BIO_NOCLOSE);
00283 if (!m_sbio)
00284 {
00285 SSL_free(m_ssl);
00286 BLOCXX_THROW(SSLException, Format("BIO_new_socket failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
00287 }
00288 SSL_set_bio(m_ssl, m_sbio, m_sbio);
00289
00290 connectWithSSL(m_ssl, *this);
00291
00292 if (!SSLCtxMgr::checkServerCert(m_ssl, m_peerAddress.getName()))
00293 {
00294 BLOCXX_THROW(SSLException, "Failed to validate peer certificate");
00295 }
00296 m_isConnected = true;
00297 }
00299 void
00300 SSLSocketImpl::disconnect()
00301 {
00302 #if defined(BLOCXX_WIN32)
00303 if (m_sockfd != INVALID_SOCKET && m_isConnected)
00304 #else
00305 if (m_sockfd != -1 && m_isConnected)
00306 #endif
00307 {
00308 if (m_ssl)
00309 {
00310 shutdownSSL(m_ssl);
00311 }
00312 }
00313 SocketBaseImpl::disconnect();
00314 }
00316 int
00317 SSLSocketImpl::writeAux(const void* dataOut, int dataOutLen)
00318 {
00319 return SSLCtxMgr::sslWrite(m_ssl, static_cast<const char*>(dataOut),
00320 dataOutLen);
00321 }
00323 int
00324 SSLSocketImpl::readAux(void* dataIn, int dataInLen)
00325 {
00326 return SSLCtxMgr::sslRead(m_ssl, static_cast<char*>(dataIn),
00327 dataInLen);
00328 }
00330 SSL*
00331 SSLSocketImpl::getSSL() const
00332 {
00333 return m_ssl;
00334 }
00335
00337 bool
00338 SSLSocketImpl::peerCertVerified() const
00339 {
00340 return (m_owctx.peerCertPassedVerify == OWSSLContext::VERIFY_PASS);
00341 }
00342
00344
00345
00346 bool
00347 SSLSocketImpl::waitForInput(int timeOutSecs)
00348 {
00349
00350 if (SSL_pending(m_ssl))
00351 {
00352 return false;
00353 }
00354 return SocketBaseImpl::waitForInput(timeOutSecs);
00355 }
00357
00358 }
00359
00361 #endif // #ifdef BLOCXX_HAVE_OPENSSL
00362