void TLSSocket::EvaluateResult(int result) { switch (SSL_get_error(session, result)) { case SSL_ERROR_WANT_READ : case SSL_ERROR_WANT_WRITE : { break; } case SSL_ERROR_SSL : { throw TLSProtocolError(); } case SSL_ERROR_ZERO_RETURN : { throw EndOfStream(); } case SSL_ERROR_SYSCALL : { int error = ERR_get_error(); if (error) throw TLSProtocolError(); else if (!result) throw EndOfStream(); else if (result == -1) throw TLSSystemError(errno); } default : { throw TLSError(); } } }
void TLSSocket::Handshake(TCPSocket& socket, HandshakeRole role, TLSSocket* reuse) { SSL_CTX* ctx = role == Client ? TLSClientContext::Get() : TLSServerContext::Get(); if (!ctx) throw TLSError("TLS context not initialised."); session = SSL_new(ctx); if (!session) throw TLSProtocolError(); if (SSL_set_fd(session, socket.Socket()) != 1) throw TLSProtocolError(); if (reuse) { assert(reuse->session); SSL_copy_session_id(session, reuse->session); } if (role == Client) SSL_set_connect_state(session); else SSL_set_accept_state(session); int result; while (true) { if (role == Client) result = SSL_connect(session); else result = SSL_accept(session); boost::this_thread::interruption_point(); if (result == 1) break; else EvaluateResult(result); } }
void TLSServerContext::CreateContext() { context = SSL_CTX_new(SSLv23_server_method()); if (!context) throw TLSProtocolError(); unsigned long options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TICKET; #if (OPENSSL_VERSION_NUMBER >= 0x10000000) options |= SSL_OP_NO_COMPRESSION; #endif SSL_CTX_set_options(context, options); }
void TLSContext::LoadCertificate() { if (!certificate.empty()) { if (SSL_CTX_use_certificate_chain_file(context, certificate.c_str()) != 1 || SSL_CTX_use_PrivateKey_file( context, certificate.c_str(), SSL_FILETYPE_PEM) != 1 || SSL_CTX_check_private_key(context) != 1) throw TLSProtocolError(); } SSL_CTX_set_tmp_rsa_callback(context, TempRSACallback); }
void TLSSocket::Handshake(TCPSocket& socket, HandshakeRole role) { session = SSL_new(role == Client ? TLSClientContext::Get() : TLSServerContext::Get()); if (!session) throw TLSProtocolError(); if (SSL_set_fd(session, socket.Socket()) != 1) throw TLSProtocolError(); if (role == Client) SSL_set_connect_state(session); else SSL_set_accept_state(session); int result; while (true) { if (role == Client) result = SSL_connect(session); else result = SSL_accept(session); boost::this_thread::interruption_point(); if (result == 1) break; else EvaluateResult(result); } std::cout << SSL_version(session) << std::endl; }
void TLSClientContext::CreateContext() { context = SSL_CTX_new(SSLv23_client_method()); if (!context) throw TLSProtocolError(); SSL_CTX_set_options(context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TICKET); }