Remote Call Framework 3.4
Encryption and Authentication

OpenSSL SSL Server

This sample demonstrates a SSL-encrypted server, using OpenSSL.

#include <iostream>
#include <RCF/RCF.hpp>
#include <RCF/PemCertificate.hpp>
#ifndef RCF_FEATURE_OPENSSL
#error Please define RCF_FEATURE_OPENSSL=1 to build this sample with OpenSSL support.
#endif
// Define RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
class PrintService
{
public:
void Print(const std::string & msg)
{
std::cout << "I_PrintService service: " << msg << std::endl;
}
};
int main()
{
try
{
RCF::RcfInit rcfInit;
RCF::RcfServer server(RCF::TcpEndpoint("127.0.0.1", 50001));
PrintService printService;
server.bind<I_PrintService>(printService);
// Load server certificate.
"serverCert.pem",
"password"));
server.setCertificate(serverCertPtr);
// Require all clients to use SSL.
std::vector<RCF::TransportProtocol> supportedProtocols = { RCF::Tp_Ssl };
server.setSupportedTransportProtocols(supportedProtocols);
server.start();
std::cout << "Press Enter to exit..." << std::endl;
std::cin.get();
}
catch ( const RCF::Exception & e )
{
std::cout << "Error: " << e.getErrorMessage() << std::endl;
}
return 0;
}

OpenSSL SSL Client

This sample demonstrates a SSL-encrypted client, using OpenSSL.

#include <iostream>
#include <RCF/RCF.hpp>
#include <RCF/PemCertificate.hpp>
#ifndef RCF_FEATURE_OPENSSL
#error Please define RCF_FEATURE_OPENSSL=1 to build this sample with OpenSSL support.
#endif
// Define RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
// Callback function to validate the certificate the server presents.
bool validateServerCertificate(RCF::Certificate * pCert)
{
RCF::X509Certificate * pX509Cert = dynamic_cast<RCF::X509Certificate *>(pCert);
if ( pX509Cert )
{
std::string certName = pX509Cert->getCertificateName();
std::string issuerName = pX509Cert->getIssuerName();
X509 * pX509 = pX509Cert->getX509();
// Custom code to inspect and validate certificate here.
// ...
std::cout << "Server certificate name: " << certName << std::endl;
std::cout << "Server certificate issuer: " << issuerName << std::endl;
}
// Return true if valid, false if not.
return true;
}
int main()
{
try
{
RCF::RcfInit rcfInit;
RcfClient<I_PrintService> client(RCF::TcpEndpoint("127.0.0.1", 50001));
client.getClientStub().setTransportProtocol(RCF::Tp_Ssl);
// Configure server certificate validation.
bool useCertificateAuthority = false;
bool useCustomCallback = true;
if ( useCertificateAuthority )
{
// Certificate validation with certificate authority.
// Load a certificate authority certificate.
"clientCaCertificate.pem",
"password"));
client.getClientStub().setCaCertificate(caCertPtr);
}
else if ( useCustomCallback )
{
// Certificate validation with custom callback.
client.getClientStub().setCertificateValidationCallback(&validateServerCertificate);
}
// Configure a client certificate (optional).
"clientCert.pem",
"password"));
client.getClientStub().setCertificate(clientCertPtr);
client.Print("Hello World");
}
catch ( const RCF::Exception & e )
{
std::cout << "Error: " << e.getErrorMessage() << std::endl;
}
return 0;
}

Schannel SSL Server

This sample demonstrates a SSL-encrypted server, using Schannel. This code will only run on Windows.

#include <iostream>
#include <RCF/RCF.hpp>
#include <RCF/Win32Certificate.hpp>
#ifndef RCF_WINDOWS
#error This sample requires Schannel and can only be built on Windows.
#endif
// Define RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
class PrintService
{
public:
void Print(const std::string & msg)
{
std::cout << "I_PrintService service: " << msg << std::endl;
}
};
int main()
{
try
{
RCF::RcfInit rcfInit;
RCF::RcfServer server(RCF::TcpEndpoint("127.0.0.1", 50001));
PrintService printService;
server.bind<I_PrintService>(printService);
// Load server certificate.
bool loadCertFromFile = true;
bool loadCertFromStore = false;
if ( loadCertFromFile )
{
// Load server certificate from a file.
"serverCert.p12",
"password",
"CertificateName"));
server.setCertificate(serverCertPtr);
}
else if ( loadCertFromStore )
{
// Load server certificate from a Windows certificate store.
"CertificateName"));
server.setCertificate(serverCertPtr);
}
// Require all clients to use SSL.
std::vector<RCF::TransportProtocol> supportedProtocols = { RCF::Tp_Ssl };
server.setSupportedTransportProtocols(supportedProtocols);
server.start();
std::cout << "Press Enter to exit..." << std::endl;
std::cin.get();
}
catch ( const RCF::Exception & e )
{
std::cout << "Error: " << e.getErrorMessage() << std::endl;
}
return 0;
}

Schannel SSL Client

This sample demonstrates a SSL-encrypted client, using Schannel. This code will only run on Windows.

#include <iostream>
#include <RCF/RCF.hpp>
#include <RCF/Win32Certificate.hpp>
#ifndef RCF_WINDOWS
#error This sample requires Schannel and can only be built on Windows.
#endif
// Define RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
#include <iostream>
#include <RCF/RCF.hpp>
// Callback function to validate the certificate the server presents.
bool validateServerCertificate(RCF::Certificate * pCert)
{
RCF::Win32Certificate * pWin32Cert = dynamic_cast<RCF::Win32Certificate *>(pCert);
if ( pWin32Cert )
{
std::string certName = pWin32Cert->getCertificateName();
std::string issuerName = pWin32Cert->getIssuerName();
PCCERT_CONTEXT pCertCtx = pWin32Cert->getWin32Context();
// Custom code to inspect and validate certificate here.
// ...
std::cout << "Server certificate name: " << certName << std::endl;
std::cout << "Server certificate issuer: " << issuerName << std::endl;
}
// Return true if valid, false if not.
return true;
}
int main()
{
try
{
RCF::RcfInit rcfInit;
RcfClient<I_PrintService> client(RCF::TcpEndpoint("127.0.0.1", 50001));
client.getClientStub().setTransportProtocol(RCF::Tp_Ssl);
// Configure server certificate validation.
bool useCertificateAuthority = false;
bool useCustomCallback = true;
bool useSchannelValidation = false;
if ( useCertificateAuthority )
{
// Certificate validation with certificate authority.
"C:\\clientCaCertificate.p12",
"password",
"CaCertificatename"));
client.getClientStub().setCaCertificate(caCertPtr);
}
else if ( useCustomCallback )
{
// Certificate validation with custom callback.
client.getClientStub().setCertificateValidationCallback(&validateServerCertificate);
}
else if ( useSchannelValidation )
{
// Certificate validation using built-in Schannel validation.
client.getClientStub().setEnableSchannelCertificateValidation("CertificateName");
}
client.Print("Hello World");
}
catch ( const RCF::Exception & e )
{
std::cout << "Error: " << e.getErrorMessage() << std::endl;
}
return 0;
}

Kerberos and NTLM Server

This sample demonstrates a Kerberos and NTLM encrypted server. This code will only run on Windows.

#include <iostream>
#include <RCF/RCF.hpp>
#ifndef RCF_WINDOWS
#error This sample requires Kerberos and NTLM SSPI providers and can only be built on Windows.
#endif
// Define RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
class PrintService
{
public:
void Print(const std::string & msg)
{
RCF::TransportProtocol transportProtocol = session.getTransportProtocol();
// Determine which encryption protocol the client is using.
std::cout << std::endl;
if ( transportProtocol == RCF::Tp_Ntlm )
{
std::cout << "Client connection authenticated and encrypted using NTLM." << std::endl;
}
else if ( transportProtocol == RCF::Tp_Kerberos )
{
std::cout << "Client connection authenticated and encrypted using Kerberos." << std::endl;
}
else if ( transportProtocol == RCF::Tp_Negotiate )
{
std::cout << "Client connection authenticated and encrypted using Negotiate." << std::endl;
}
// Determine the user name the client was authenticated as.
std::cout << "Client user name: " << session.getClientUserName() << std::endl;
std::cout << "I_PrintService service: " << msg << std::endl;
}
};
int main()
{
try
{
RCF::RcfInit rcfInit;
RCF::RcfServer server(RCF::TcpEndpoint("127.0.0.1", 50001));
PrintService printService;
server.bind<I_PrintService>(printService);
// Require all clients to use NTLM, Kerberos or Negotiate.
std::vector<RCF::TransportProtocol> supportedProtocols = { RCF::Tp_Ntlm, RCF::Tp_Kerberos, RCF::Tp_Negotiate };
server.setSupportedTransportProtocols(supportedProtocols);
server.start();
std::cout << "Press Enter to exit..." << std::endl;
std::cin.get();
}
catch ( const RCF::Exception & e )
{
std::cout << "Error: " << e.getErrorMessage() << std::endl;
}
return 0;
}

Kerberos and NTLM Client

This sample demonstrates a Kerberos and NTLM encrypted client. This code will only run on Windows.

#include <iostream>
#include <RCF/RCF.hpp>
// Define RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
int main()
{
try
{
RCF::RcfInit rcfInit;
RcfClient<I_PrintService> client(RCF::TcpEndpoint("127.0.0.1", 50001));
// Configure explicit client credentials.
bool useExplicitCreds = false;
std::string explicitUserName = "Domain\\JoeBloggs";
std::string explicitPassword = "MyPassword";
if ( useExplicitCreds )
{
client.getClientStub().setUserName(explicitUserName);
client.getClientStub().setPassword(explicitPassword);
}
else
{
// If explicit credentials are not specified, the client will pick up
// the credentials of the currently logged on user.
}
// Connect using NTLM.
std::cout << "Connecting using NTLM." << std::endl;
client.getClientStub().setTransportProtocol(RCF::Tp_Ntlm);
client.Print("Hello World");
// Connect using Kerberos.
std::cout << "Connecting using Kerberos." << std::endl;
client.getClientStub().setTransportProtocol(RCF::Tp_Kerberos);
client.getClientStub().setKerberosSpn("Domain\\ServerAccount");
client.Print("Hello World");
// Connect using Negotiate.
std::cout << "Connecting using Negotiate." << std::endl;
client.getClientStub().setTransportProtocol(RCF::Tp_Negotiate);
client.getClientStub().setKerberosSpn("Domain\\ServerAccount");
client.Print("Hello World");
}
catch ( const RCF::Exception & e )
{
std::cout << "Error: " << e.getErrorMessage() << std::endl;
}
return 0;
}