Page tree
Skip to end of metadata
Go to start of metadata

Overveiw

SSL feature was added to FIX Antenna C++ in version 2.13

The following parameters were added for configuring SSL sessions:

  • Engine::SessionExtraParameters::sslContext_  in FIX Antenna C++.
  • com::b2bits::fixantenna::sessionExtraParameters::SSLContext in FIX Antenna .NET.

Since some security issues with SSL v3 and RC4 encryption algorithm have been discovered recently and TLS 1.0, TLS 1.1 also contain known vulnerabilities, we strongly recommend to useTLS 1.2 protocol.

Starting from version 2.26 SSL interface has been slightly changed:

  • com::b2bits::fixantenna::sessionExtraParameters::SSLContext FIX Antenna .NET object got retired and doesn't exist any more.
  • Engine::SessionExtraParameters::sslContext_ FIX Antenna C++ object has lost configuration routines such as loadCertificateAndPrivateKey() and informational properties such as certFileName_ and privKeyFileName_.
  • New FIX Antenna C++ interface to configure SSL has been introduced System::SSLContextConfigurator (along with accompanying Engine::SSLContextConfiguratorConverter )which is used to pass certificates, keys and so on to SSL engine.
  • FIX Antenna C++ Engine::FAProperties::getSSLContextConfiguratorInstance() API static routine has been introduced. This routine returns newly created instance of System::SSLContextConfigurator using built in implementation.

Using SSL in acceptor

Parameters for SSL Acceptor are configured in the properties file and can't be changed after Engine initialization. They are common for all SSL-enabled acceptors.

See the full list of parameters there: SSL parameters.

FIX Antenna 2.26.0. introduces updated SSL support (with an extended variety of formats accepted) and password protected certificates/keys support. 

The password is specified within the plain text in engine.properties.

Typical configuration:


engine.properties
######### Engine wide properties #########
# Used for all acceptor sessions and as default values for Initiator sessions. if ListenSSLPort is specified and optional otherwise.
ListenSSLPort = 9106
# Mandatory. Set protocols accepted by the engine.
SSLProtocols = TLSv1_2
# Optional. Engine default values used if omitted.
SSLCiphersList = AES+aRSA:AES+aECDH:AES+aECDSA:@STRENGTH
# mandatory. Certificate file to use.
SSLCertificate = mycert.pem
# Optional. Applicable if only certificates is password protected.
SSLCertificatePassword = mycertPassword
# Optionality is correlated with SSLCertificate.
# It means if no SSLCertificate  specified then this property becomes seamless. It becomes optional if private key is already contained inside SSLCertificate file.
# This is possible for PEM and PFX formats but not for DER!
SSLPrivateKey = mycertKey.pem
# Optional if private key is not password protected. Please pay attention to the fact the this password is used for private key stored within certificate file as well.
# So it has meaning even if SSLPrivateKey is empty in this case.
SSLPrivateKeyPassword = mycertKeyPassword
# Optional if no peer certificate validation is required. This is a path to the file containing CA certificates (all in one file on after another, PEM format only!).
# This certificates are used to build accepted certificates list sent to peer as well.
SSLCACertificate = CACerts.pem
# Optional. false by default. Setting this property to true requires SSL engine to validate counter-party's certificate against CAs provided. 
# If validation has failed or no certificate was provided by counter-party connection is terminated immediately.
# Set this to true in order to accept only connection verified with certificate.
ValidatePeerCertificate = true


Using SSL in initiator in FIX Antenna C++.

To enable SSL in initiator Session just create SSL Client Context in extra parameters before creating session:

SSLQuickStart.cpp
FIXApp application;
Engine::SessionExtraParameters params;
params.sslContext_ = System::SSLClientContext();

Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession( &application, "TargetCompID", "SenderCompID",  Engine::FIX44, &params );

For advanced configuration use System::SSLClientContext::loadCertificateAndPrivateKey method to specify certificate, private key paths. Set last boolean value to true to check if a private key matches the server certificate.

SSLQuickStart.cpp
System::SSLClientContext sslContext;
sslContext.loadCertificateAndPrivateKey("cert.pem", "cert.pem", true);
params.sslContext_ = sslContext;

Using SSL in initiator in FIX Antenna .NET.

To enable SSL in initiator Session create the session with the SSLContext parameter.

SSLQuickStart.cs
SessionExtraParameters @params = new SessionExtraParameters();   
 
SessionExtraParameters.SSLContextParameters sslContext = new SessionExtraParameters.SSLContextParameters(); 
@params.SSLContext = sslContext; 
 
Session session = FixEngine.Instance.CreateSession(new SessionId("Sender", "Target", null), FixVersion.FIX50SP2, @params, MessageStorageType.Persistent);

For advanced configuration also specify SSL protocols to use, certificate, private key paths and set a boolean value to check if a private key matches the server certificate.

SSLQuickStart.cs
sslContext.SSLProtocolsUsed = SSLProtocols.TLSv1 | SSLProtocols.TLSv1_1 | SSLProtocols.TLSv1_2; 
sslContext.SSLCertificate = "cert.pem"; 
sslContext.SSLPrivateKey = "cert.pem"; 
sslContext.SSLCheckPrivateKey = true;

Ciphers configuration in FIX Antenna C++ based applications

The feature was added to FIX Antenna C++ in version 2.25.1

The allowed ciphers list can be configured with SSLCiphersList in engine.properties. 

The parameter is optional. The default OpenSSL built-in configuration is used in case of the parameter absence.

The list is passed as is  to OpenSSL during engine initialization in case of acceptor sessions (acceptor sessions are sharing the same configuration) and during session initialization in case of initiator sessions. See a list of the supported ciphers and list format is at official OpenSSL site: https://www.openssl.org/docs/man1.0.2/apps/ciphers.html

engine.properties
SSLCiphersList = AES+aRSA:AES+aECDH:AES+aECDSA:@STRENGTH

C++ Example. Simple

Server.cpp
int main(int argc, char **argv)
{
    try {
        Engine::FixEngine::InitParameters params;
        params.propertiesFileName_ = "engine.properties";
 
        // Initializes engine.
        Engine::FixEngine::init( params );

		//FIXApp class derived from Engine::Application
        FIXApp acceptor;
 		Engine::SessionExtraParameters params;
	 
        // Create FIX session instance
        Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession( &acceptor, "SenderCompID", "TargetCompID", Engine::FIX44);

        // Connect session as acceptor
        pSI ->connect();
 
		//wait for data in acceptor
        string cmd;
        while( "exit" != cmd ) {
            cout << "Type 'exit' to exit > ";
            getline( cin, cmd );
        }

        // disconnect and release
        pSI->disconnectNonGracefully();
        pSI->release();
    } catch( const std::exception& ex ) {
        cout << "Error: " << ex.what() << endl;
    } catch ( ... ) {
        cout << "Unknown error." << endl;
    }
    // stop engine
    Engine::FixEngine::destroy();
    return 0;
}
Clent.cpp
int main(int argc, char **argv)
{
    try {
        // Initialize engine.
        Engine::FixEngine::init( "engine.properties" );

		//FIXApp class derived from Engine::Application
        FIXApp initiator;
 
        // Create FIX session instance with SSL.
        Engine::SessionExtraParameters params;
		params.sslContext_ = System::SSLClientContext();
        Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession( &initiator, "TargetCompID", "SenderCompID",  Engine::FIX44, &params );
        // Connect session as initiator to LISTENER_IP address
        pSI->connect( 30, LISTENER_IP, 9107);
 
        // create FIX 4.4 New Order Single using the Flat model
        std::auto_ptr<Engine::FIXMessage> pMessage( Engine::FIXMsgFactory::singleton()->newSkel( Engine::FIX44, "D" ) );
        string clordid;
        Engine::UTCTimestamp::now().toFixString( &clordid );
        pMessage->set( FIXField::ClOrdID, clordid );
        pMessage->set( FIXField::Symbol, "MSFT" );
        pMessage->set( FIXField::Side, '1' ); // Buy
        pMessage->set( FIXField::OrderQty, 400 );
        pMessage->set( FIXField::OrdType, '2' ); // Limit
        pMessage->set( FIXField::Price, Engine::Decimal( 1132, -2 ) );
        pMessage->set( FIXField::TransactTime, Engine::UTCTimestamp::now() );

        // Send order to session initiator
        pSI->put( pMessage.get() );
 
		// Wait message processed.
		System::Thread::sleep(2000);
        // disconnect and release session
        pSI->disconnect();
        pSI->release();
    } catch( const std::exception& ex ) {
        cout << "Error: " << ex.what() << endl;
    } catch ( ... ) {
        cout << "Unknown error." << endl;
    }
    // stop engine
    Engine::FixEngine::destroy();
    return 0;
}

C++ Example. Advanced (configure SSL with no changes in engine.properties)

Server.cpp
int main(int argc, char **argv)
{
    try {
        Engine::FixEngine::InitParameters params;
        params.propertiesFileName_ = "engine.properties";

		// Setup SSL parameters
        params.properties_[Engine::FIXPropertiesNames::LISTEN_SSL_PORT_PARAM] = "9107";
        params.properties_[Engine::FIXPropertiesNames::LISTEN_SSL_CHECK_PRIVATE_KEY_PARAM] = "true";
        params.properties_[Engine::FIXPropertiesNames::LISTEN_SSL_CERTIFICATE_PARAM] = "cert.pem";
        params.properties_[Engine::FIXPropertiesNames::LISTEN_SSL_PRIVATE_KEY_PARAM] = "cert.pem";
        params.properties_[Engine::FIXPropertiesNames::LISTEN_SSL_PROTOCOLS_PARAM] = "TLSv1, TLSv1_1, TLSv1_2";
 
        // Initializes engine.
        Engine::FixEngine::init( params );

		//FIXApp class derived from Engine::Application
        FIXApp acceptor;
 		Engine::SessionExtraParameters params;

        // Create FIX session instance
        Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession( &acceptor, "SenderCompID", "TargetCompID", Engine::FIX44, &params);

        // Connect session as acceptor
        pSI ->connect();
 
		//wait for data in acceptor
        string cmd;
        while( "exit" != cmd ) {
            cout << "Type 'exit' to exit > ";
            getline( cin, cmd );
        }

        // disconnect and release
        pSI->disconnectNonGracefully();
        pSI->release();
    } catch( const std::exception& ex ) {
        cout << "Error: " << ex.what() << endl;
    } catch ( ... ) {
        cout << "Unknown error." << endl;
    }
    // stop engine
    Engine::FixEngine::destroy();
    return 0;
}
Clent.cpp
int main(int argc, char **argv)
{
    try {
        // Initialize engine.
        Engine::FixEngine::init( "engine.properties" );

		//FIXApp class derived from Engine::Application
        FIXApp initiator;
 
        // Create FIX session instance with SSL.
        Engine::SessionExtraParameters params;
        System::SSLClientContext sslContext;
        sslContext.loadCertificateAndPrivateKey("cert.pem", "cert.pem", true);
        params.sslContext_ = sslContext;
        Engine::Session* pSI =  Engine::FixEngine::singleton()->createSession( &initiator, "TargetCompID", "SenderCompID",  Engine::FIX44, &params );
        // Connect session as initiator to LISTENER_IP address
        pSI->connect( 30, LISTENER_IP, 9107);
 
        // create FIX 4.4 New Order Single using the Flat model
        std::auto_ptr<Engine::FIXMessage> pMessage( Engine::FIXMsgFactory::singleton()->newSkel( Engine::FIX44, "D" ) );
        string clordid;
        Engine::UTCTimestamp::now().toFixString( &clordid );
        pMessage->set( FIXField::ClOrdID, clordid );
        pMessage->set( FIXField::Symbol, "MSFT" );
        pMessage->set( FIXField::Side, '1' ); // Buy
        pMessage->set( FIXField::OrderQty, 400 );
        pMessage->set( FIXField::OrdType, '2' ); // Limit
        pMessage->set( FIXField::Price, Engine::Decimal( 1132, -2 ) );
        pMessage->set( FIXField::TransactTime, Engine::UTCTimestamp::now() );

        // Send order to session initiator
        pSI->put( pMessage.get() );
 
		// Wait message processed.
		System::Thread::sleep(2000);
        // disconnect and release session
        pSI->disconnect();
        pSI->release();
    } catch( const std::exception& ex ) {
        cout << "Error: " << ex.what() << endl;
    } catch ( ... ) {
        cout << "Unknown error." << endl;
    }
    // stop engine
    Engine::FixEngine::destroy();
    return 0;
}

Also samples ./samples/FIX_QuickStart in FIX Antenna C++ package  or ./samples/SimpleClient FIX Antenna .NET in package show how to create session throught SSL connection.

reference

Please read FIX Antenna Quick Start Guide and Installation Guide for information about creating application with FIX Antenna C++.

Migration to version 2.26.0 FIX Antenna C++

The following properties have changes their names or removed. Please modify code accordingly if you use them.

  • Engine::FIXPropertiesNames::LISTEN_SSL_PROTOCOLS_PARAM→ Engine::FIXPropertiesNames::SSL_PROTOCOLS_PARAM
  • Engine::FIXPropertiesNames::LISTEN_SSL_CIPHERS_LIST_PARAM→ Engine::FIXPropertiesNames::SSL_CIPHERS_LIST_PARAM
  • Engine::FIXPropertiesNames::LISTEN_SSL_CERTIFICATE_PARAM→ Engine::FIXPropertiesNames::SSL_CERTIFICATE_PARAM
  • Engine::FIXPropertiesNames::LISTEN_SSL_PRIVATE_KEY_PARAM→ Engine::FIXPropertiesNames::SSL_PRIVATE_KEY_PARAM
  • Engine::FIXPropertiesNames::LISTEN_SSL_CA_CERTIFICATE_PARAM→ Engine::FIXPropertiesNames::SSL_CA_CERTIFICATE_PARAM
  • Engine::FIXPropertiesNames::LISTEN_SSL_REQ_CLIENT_CERT_PARAM → Engine::FIXPropertiesNames::SSL_VALIDATE_PEER_CERT_PARAM
  • Engine::FIXPropertiesNames::LISTEN_SSL_CHECK_PRIVATE_KEY_PARAM  has retired no longer defined. Execution flow goes that way as this property is always true.

Acceptors migration is transparent. Since all acceptors share the same configuration defined globally no changes are required.

Initiators migration is not complicated. See sample below.

Before
System::SSLClientContext sslContext;
sslContext.loadCertificateAndPrivateKey("cert.pem", "cert.pem", true);
params.sslContext_ = sslContext
After
System::SSLContextConfiguratorPtr pSSLContextConfigurator = Engine::FAProperties::getSSLContextConfiguratorInstance(0, "", "", "cert.pem", "cert.pem", "" ,"", false);
System::SSLClientContext sslContext(Engine::FixEngine::singleton()->getProperties()->getSSLUseProtocols(), pSSLContextConfigurator );
params.sslContext_ = sslContext;

Migration to version 2.26.0 FIX Antenna .NET

Acceptors migration is transparent. Since all acceptors share the same configuration defined globally no changes are required.

if you want to limit session to SSL socket only set SessionExtraParameters SSL property to true. See the sample for initiators below. The same flow applies to acceptors as well.

Initiators migration is not complicated. See sample below.

Before
SessionExtraParameters @params = new SessionExtraParameters();   
  
SessionExtraParameters.SSLContextParameters sslContext = new SessionExtraParameters.SSLContextParameters(); 
sslContext.SSLProtocolsUsed = SSLProtocols.TLSv1 | SSLProtocols.TLSv1_1 | SSLProtocols.TLSv1_2; 
sslContext.SSLCertificate = "cert.pem"; 
sslContext.SSLPrivateKey = "cert.pem"; 
sslContext.SSLCheckPrivateKey = true;
@params.SSLContext = sslContext; 
  
Session session = FixEngine.Instance.CreateSession(new SessionId("Sender", "Target", null), FixVersion.FIX50SP2, @params, MessageStorageType.Persistent);
After
SessionExtraParameters @params = new SessionExtraParameters();   
 
@params.SSL = true; 
@params.SSLProtocolsUsed = SSLProtocols.TLSv1 | SSLProtocols.TLSv1_1 | SSLProtocols.TLSv1_2; 
@params.SSLCertificate = "cert.pem"; 
@params.SSLPrivateKey = "cert.pem"; 
Session session = FixEngine.Instance.CreateSession(new SessionId("Sender", "Target", null), FixVersion.FIX50SP2, @params, MessageStorageType.Persistent);


There is no content with the specified labels