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 args.h.
Example 7 – Writing a client program that performs client and server authentication
// File:
// examples\secsock\manual\ClientServerAuthenticationClient.cpp
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketPortal.h>
#include <rw/network/RWInetAddr.h>
#include <rw/network/RWWinSockInfo.h>
#include <iostream>
#include <fstream>
#include "args.h"
#include "secsockexampledefs.h"
using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
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;
}
Server Example
Comments are included only for the lines that differ from the previous examples.
This example uses utility functions provided in args.h.
Example 8 – Writing a server program that performs client and server authentication
// File:
// examples\secsock\manual\ClientServerAuthenticationServer.cpp
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/secsock/RWSecureSocketListener.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketPortal.h>
#include <rw/network/RWInetAddr.h>
#include <rw/network/RWWinSockInfo.h>
#include <fstream>
#include <iostream>
#include "args.h"
#include "secsockexampledefs.h"
using std::cerr;
using std::cout;
using std::endl;
using std::ifstream;
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;
}