void OpenSSLSocket::startHandshake()

in activemq-cpp/src/main/decaf/internal/net/ssl/openssl/OpenSSLSocket.cpp [331:425]


void OpenSSLSocket::startHandshake() {

    if (!this->isConnected()) {
        throw IOException(__FILE__, __LINE__, "Socket is not connected.");
    }

    if (this->isClosed()) {
        throw IOException(__FILE__, __LINE__, "Socket already closed.");
    }

    try {

#ifdef HAVE_OPENSSL
        synchronized( &(this->data->handshakeLock ) ) {

            if (this->data->handshakeStarted) {
                return;
            }

            this->data->handshakeStarted = true;

            bool peerVerifyDisabled = Boolean::parseBoolean(System::getProperty("decaf.net.ssl.disablePeerVerification", "false"));

            if (this->parameters->getUseClientMode()) {

                // Since we are a client we want to enforce peer verification, we set a
                // callback so we can collect data on why a verify failed for debugging.
                if (!peerVerifyDisabled) {
                                        // Check host https://wiki.openssl.org/index.php/Hostname_validation
                                        X509_VERIFY_PARAM *param = SSL_get0_param(this->parameters->getSSL());

                                        X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
                                        X509_VERIFY_PARAM_set1_host(param, this->data->commonName.c_str(), 0);

                    SSL_set_verify(this->parameters->getSSL(), SSL_VERIFY_PEER, SocketData::verifyCallback);
                } else {
                    SSL_set_verify(this->parameters->getSSL(), SSL_VERIFY_NONE, NULL);
                }

                std::vector<std::string> serverNames = this->parameters->getServerNames();
                if (!serverNames.empty()) {
                    std::string serverName = serverNames.at(0);
                    SSL_set_tlsext_host_name(this->parameters->getSSL(), serverName.c_str());
                }

                int result = SSL_connect(this->parameters->getSSL());

                // Checks the error status
                switch (SSL_get_error(this->parameters->getSSL(), result)) {
                case SSL_ERROR_NONE:
                    break;
                case SSL_ERROR_SSL:
                case SSL_ERROR_ZERO_RETURN:
                case SSL_ERROR_SYSCALL:
                               default:
                    SSLSocket::close();
                    throw OpenSSLSocketException(__FILE__, __LINE__);
                }

            } else { // We are in Server Mode.

                int mode = SSL_VERIFY_NONE;

                if (!peerVerifyDisabled) {

                    if (this->parameters->getWantClientAuth()) {
                        mode = SSL_VERIFY_PEER;
                    }

                    if (this->parameters->getNeedClientAuth()) {
                        mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
                    }
                }

                // Since we are a server we want to enforce peer verification, we set a
                // callback so we can collect data on why a verify failed for debugging.
                SSL_set_verify(this->parameters->getSSL(), mode, SocketData::verifyCallback);

                int result = SSL_accept(this->parameters->getSSL());

                if (result != SSL_ERROR_NONE) {
                    SSLSocket::close();
                    throw OpenSSLSocketException(__FILE__, __LINE__);
                }
            }

            this->data->handshakeCompleted = true;
        }
#else
        throw IOException( __FILE__, __LINE__, "SSL Not Supported." );
#endif
    }
    DECAF_CATCH_RETHROW(IOException)
    DECAF_CATCHALL_THROW(IOException)
}