0

I am trying to get SSL working with the activemq-cpp library. I've had no problems with a normal TCP connection, but with an SSL broker URL the connection start method never returns. Here's my code:

#include <iostream>

#include <activemq/library/ActiveMQCPP.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <decaf/lang/System.h>
#include <cms/Connection.h>

/*                                                                                                                                                                                                                                              
 * Build exe with: g++ -std=c++11 -o main -I/usr/include/activemq-cpp-3.9.3 -I/usr/include/apr-1 -lactivemq-cpp -ldl -luuid main.cpp                                                                                                            
 */

int main()
{

  using namespace cms;

  activemq::library::ActiveMQCPP::initializeLibrary();

  {
    // Setting SSL params                                                                                                                                                                                                                       
    decaf::lang::System::setProperty( "decaf.net.ssl.keyStore", "/home/pcarter/tmp/active_mq_question/client.pem" );
    decaf::lang::System::setProperty( "decaf.net.ssl.keyStorePassword", "password" );
    decaf::lang::System::setProperty( "decaf.net.ssl.trustStore", "/home/pcarter/tmp/active_mq_question/broker.pem" );

    // Program works fine with tcp url below                                                                                                                                                                                                    
    //std::string broker_url = "failover:(tcp://localhost:61616)";                                                                                                                                                                              

    // Program locks up in start() call with ssl url below:                                                                                                                                                                                     
    std::string broker_url = "failover:(ssl://localhost:61617)";

    // Create a ConnectionFactory                                                                                                                                                                                                               
    std::unique_ptr<ConnectionFactory> connection_factory(
             ConnectionFactory::createCMSConnectionFactory(broker_url));

    // Create a Connection                                                                                                                                                                                                                      
    std::unique_ptr<cms::Connection> connection(connection_factory->createConnection());

    std::cout << "Calling start()" << std::endl;
    connection->start();   // This never returns
    std::cout << "start() returned" << std::endl;

  }
  activemq::library::ActiveMQCPP::shutdownLibrary();

  return 0;
}

I am using the default activemq.xml file with the following connectors section

<transportConnectors>
   <transportConnector name="stomp+ssl" uri="stomp+nio+ssl://0.0.0.0:61613?transport.enabledProtocols=TLSv1.2&amp;needClientAuth=true" />
   <transportConnector name="ssl" uri="ssl://0.0.0.0:61617?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600&amp;needClientAuth=true" />
   <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

However, I don't think the problem is on the broker side. tcpdump shows no packets being sent to port 61617 when I run my code.

I have been able to get SSL working with a python STOMP client.

I'm using CentOS 7 and installed ActiveMQ-cpp version 3.9.3 using yum. I'm using the stock gcc compiler version 4.8.5.

My main reference for SSL and C++ was this question: activemq-cpp c++ client how to use ssl url to connect server

And I created the certs using the procedure described here: ActiveMQ - STOMP+SSL with Python STOMP client

pcarter
  • 1,516
  • 14
  • 21

1 Answers1

0

When I tried removing the "failover" from the broker URI, the program reported an error (this is from a slightly modified test program that catches the cms:::CMSException):

$ ./main                                                                                                                                                                                               
Caught: Error occurred while accessing an OpenSSL library method:
error:0906D06C:PEM routines:PEM_read_bio:no start line
error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
Error occurred while accessing an OpenSSL library method:
error:0906D06C:PEM routines:PEM_read_bio:no start line
error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

Using gdb to break on the exception throw, showed that the error was being throw from this snippet:

// Here we load the configured KeyStore, this is where the client and server certificate are
// stored, a client doesn't necessary need this if the server doesn't enforce client authentication.
std::string keyStorePath = System::getProperty( "decaf.net.ssl.keyStore" );
this->data->password = System::getProperty( "decaf.net.ssl.keyStorePassword" );

// We assume the Public and Private keys are in the same file.
if( !keyStorePath.empty() ) {
  if( SSL_CTX_use_certificate_chain_file( this->data->openSSLContext, keyStorePath.c_str() ) != 1 ) {
     throw OpenSSLSocketException( __FILE__, __LINE__ );
  }
  if( SSL_CTX_use_PrivateKey_file( this->data->openSSLContext, keyStorePath.c_str(), SSL_FILETYPE_PEM ) != 1 ) {
    // This is where exception was thrown
    throw OpenSSLSocketException( __FILE__, __LINE__ );
  }
}

The comment about assuming the public and private keys were in the same file explained the cause of the failure. Adding the contents of my client.key file (with the private key) to the client.pem file fixed the issue.

I was also able to re-add the "failover" to the broker URI after this as well.

pcarter
  • 1,516
  • 14
  • 21