Secure Communication Module User’s Guide : PART II Secure Sockets Package : Chapter 5 Advanced Topics : Implementing Both Client and Server Authentication
Implementing Both Client and Server Authentication
The following examples demonstrate a client and server that perform both client and server authentication using Portal Layer classes. These examples are in examples\secsock\manual\ClientServerAuthenticationClient.cpp and examples\secsock\manual\ClientServerAuthenticationServer.cpp.
These examples are identical to the RWSecureSocketPortal client and server examples in “Getting Started with Secure Sockets” except for context initialization.
The examples in this chapter depend on the macros TRUSTED_CERTS_FILE, SERVER_PORT, SERVER_NAME, CLIENT_CERT_FILE, and CLIENT_PRIVATE_KEY_FILE, which are defined in examples\secsock\secsockexampledefs.h. Several of the examples use these macros to determine certificates, servers, and ports.
Client Example
Comments are included only for the lines that differ from the previous examples.
This example uses utility functions provided in util.h.
Example 7 – Writing a client program that performs client and server authentication
// File:
// examples\secsock\manual\ClientServerAuthenticationClient.cpp
 
#include <rw/network/RWWinSockInfo.h>
#include <rw/network/RWInetAddr.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/secsock/RWSecureSocketPortal.h>
 
#include <iostream>
#include <fstream>
using std::ifstream;
using std::cout;
using std::cerr;
using std::endl;
 
#include <secsockexampledefs.h>
#include <util.h>
 
int main(int argc, char **argv)
{
try {
RWWinSockInfo info;
RWSecureSocketPackageInit secsockInit;
#if defined(RW_SECSOCK_RNG_NEEDS_SEEDING)
RWSecureSocketPackageInit::seedRNGFromFile(SEED_DATA_FILE);
#endif
int port = parseClientCommandLine(argc, argv);
 
ifstream certf(CLIENT_CERT_FILE); //1
RWX509Certificate cert(certf);
ifstream keyf(CLIENT_PRIVATE_KEY_FILE); //2
RWPrivateKey key(keyf);
RWSecureSocketContext context;
context.prepareToAuthenticate(TRUSTED_CERTS_FILE); //3
context.setIdentity(cert,key); //4
 
RWInetAddr addr(port, "localhost");
RWSecureSocketPortal portal(addr, context);
 
portal.sendAtLeast("Hello World!");
} catch (const RWxmsg& m) {
cerr << m.why() << endl;
}
return 0;
}
//1 Open the PEM file that contains the client’s certificate, and create the certificate object.
//2 Open the PEM file that contains the client’s private key, and create the key object.
//3 Set up the context so that it authenticates the server using the certificates trusted by the client.
//4 Establish the identity of this client so that the server can verify its identity.
Server Example
Comments are included only for the lines that differ from the previous examples.
This example uses utility functions provided in util.h.
Example 8 – Writing a server program that performs client and server authentication
// File:
// examples\secsock\manual\ClientServerAuthenticationServer.cpp
 
#include <rw/network/RWWinSockInfo.h>
#include <rw/network/RWInetAddr.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/secsock/RWSecureSocketPortal.h>
#include <rw/secsock/RWSecureSocketListener.h>
 
#include <iostream>
#include <fstream>
using std::ifstream;
using std::cout;
using std::cerr;
using std::endl;
 
#include <secsockexampledefs.h>
#include <util.h>
 
int main(int argc, char **argv)
{
try {
RWWinSockInfo info;
RWSecureSocketPackageInit secsockInit;
#if defined(RW_SECSOCK_RNG_NEEDS_SEEDING)
RWSecureSocketPackageInit::seedRNGFromFile(SEED_DATA_FILE);
#endif
int port = parseServerCommandLine(argc, argv);
 
RWSecureSocketContext context;
 
ifstream certf(SERVER_CERT_FILE); //1
RWX509Certificate cert(certf);
ifstream keyf(SERVER_PRIVATE_KEY_FILE); //2
RWPrivateKey key(keyf);
 
context.prepareToAuthenticate(TRUSTED_CERTS_FILE); //3
context.setIdentity(cert, key); //4
 
RWInetAddr addr(port, "localhost");
RWSecureSocketListener listener(addr, context);
 
// Display the address actually bound to
cout << listener.getSocket().getsockname() << endl;
 
char buf[64];
for(;;) {
RWSecureSocketPortal newSock = listener();
 
buf[newSock.recv(buf, 63)] = 0;
cout << "Received: " << buf << endl;
}
} catch(const RWxmsg& m) {
cerr << m.why() << endl;
return 1;
}
 
return 0;
}
//1 Open the PEM file that contains the server’s certificate, and create the certificate object.
//2 Open the PEM file that contains the server’s private key, and create the key object.
//3 Set up the context so that it authenticates the client using the certificates trusted by the server.
//4 Establish the identity of this server so the client can verify its identity.