Chapter 4 Using Secure Sockets
4.1 Getting Started with Secure Sockets
The following examples demonstrate some simple client and server programs using both the Communication Adapter Layer classes (through
RWSecureSocket) and the Portal Layer classes (through
RWSecureSocketPortal).
The examples in this section depend on the macros TRUSTED_CERTS_FILE, SERVER_DATA_FILE, SERVER_CERT_FILE, and SERVER_PRIVATE_KEY_FILE, which are defined in examples\secsock\secsockexampledefs.h. Several of the examples use these macros to determine certificates, servers, and ports.
4.1.1 Writing a Client Program That Uses RWSecureSocket
Example 1 is a client program that creates a secure socket and sends a message.
This example uses utility functions provided in util.h.
Example 1 – Client program that uses RWSecureSocket
// File: examples\secsock\manual\RWSecureSocketSimpleClient.cpp
#include <rw/network/RWWinSockInfo.h>
#include <rw/network/RWInetAddr.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/secsock/RWSecureSocket.h>
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <secsockexampledefs.h>
include <util.h>
int main(int argc, char **argv)
{
try {
RWWinSockInfo info; //1
RWSecureSocketPackageInit secsockInit; //2
#if defined(RW_SECSOCK_RNG_NEEDS_SEEDING)
RWSecureSocketPackageInit::seedRNGFromFile
(SEED_DATA_FILE); //3
#endif
int port = parseClientCommandLine(argc, argv);
RWSecureSocketContext context; //4
context.prepareToAuthenticate(TRUSTED_CERTS_FILE); //5
RWInetAddr addr(port, “localhost”) //6
RWSecureSocket sock(context); //7
sock.connect(addr); //8
sock.sendAtLeast("Hello World!"); //9
sock.close(); //10
} catch(const RWInternalErr& ie) {
cerr << ie.why() << endl;
return 1;
} catch(const RWExternalErr& ee) {
cerr << ee.why() << endl;
return 1;
}
return 0;
} //11
4.1.2 Writing a Client Program That Uses RWSecureSocketPortal
Example 2 is a client program that uses a portal to create a secure socket and send a message. This client is identical to the client in
Example 1, except that it uses the Portal layer classes.
This example uses utility functions provided in util.h.
Example 2 – Client program that uses RWSecureSocketPortal
// File: examples\secsock\manual\
// RWSecureSocketPortalSimpleClient.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>
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);
RWSecureSocketContext context;
context.prepareToAuthenticate(TRUSTED_CERTS_FILE);
RWInetAddr addr(port, "localhost");
RWSecureSocketPortal portal(addr, context); //1
portal.sendAtLeast("Hello World!"); //2
// portal goes out of scope here //3
} catch(const RWInternalErr& ie) {
cerr << ie.why() << endl;
return 1;
} catch(const RWExternalErr& ee) {
cerr << ee.why() << endl;
return 1;
}
return 0;
}
4.1.3 Writing a Server Program That Uses RWSecureSocket
Example 3 is a server program that creates a secure socket that waits for requests.
This example uses utility functions provided in util.h.
Example 3 – Server program that uses RWSecureSocket
// File: examples\secsock\manual\RWSecureSocketSimpleServer.cpp
#include <rw/network/RWWinSockInfo.h>
#include <rw/network/RWInetAddr.h>
#include <rw/secsock/RWSecureSocketPackageInit.h>
#include <rw/secsock/RWSecureSocketContext.h>
#include <rw/secsock/RWSecureSocket.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; //1
RWSecureSocketPackageInit secsockInit; //2
#if defined(RW_SECSOCK_RNG_NEEDS_SEEDING)
WSecureSocketPackageInit::seedRNGFromFile
(SEED_DATA_FILE); //3
#endif
int port = parseCommandLine(argc, argv);
RWSecureSocketContext context; //4
ifstream certf(SERVER_CERT_FILE);
RWX509Certificate cert(certf); //5
ifstream keyf(SERVER_PRIVATE_KEY_FILE);
RWPrivateKey key(keyf); //6
context.setIdentity(cert, key); //7
RWInetAddr addr(port, "localhost"); //8
RWSecureSocket listenSock(context); //9
listenSock.bind(addr); //10
listenSock.listen(); //11
// Display the port actually bound to
cout << listenSock.getsockname() << endl;
char buf[64];
for(volatile bool spin = true; spin ; /* */) {
RWSecureSocket newSock = listenSock.accept(); //12
buf[newSock.recv(buf, 63)] = 0; //13
cout << "Received: " << buf << endl; //14
newSock.close(); //15
} //for
} catch(const RWInternalErr& ie) {
cerr << ie.why() << endl;
return 1;
} catch(const RWExternalErr& ee) {
cerr << ee.why() << endl;
return 1;
}
return 0; //16
}
4.1.4 Writing a Server Program That Uses RWSecureSocketPortal
Example 4 is a server program that uses a portal to create a secure socket that waits for requests. Comments are included only for code that is different than
Example 3.
This example uses utility functions provided in util.h.
Example 4 – Server program that uses RWSecureSocketPortal
// File:
// examples\secsock\manual\RWSecureSocketPortalSimpleServer.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 <rw/rstream.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; //1
RWSecureSocketPackageInit secsockInit; //2
#if defined(RW_SECSOCK_RNG_NEEDS_SEEDING)
RWSecureSocketPackageInit::seedRNGFromFile(SEED_DATA_FILE);
#endif
int port = parseServerCommandLine(argc, argv);
RWSecureSocketContext context; //3
ifstream certf(SERVER_CERT_FILE);
RWX509Certificate cert(certf); //4
ifstream keyf(SERVER_PRIVATE_KEY_FILE);
RWPrivateKey key(keyf); //5
context.setIdentity(cert, key); //6
RWInetAddr addr(port, "localhost"); //7
RWSecureSocketListener listener(addr, context); //8
// Display the port actually bound to
cout << listener.getSocket().getsockname() << endl;
char buf[64];
for(volatile bool spin = true; spin ; /* */) {
RWSecureSocketPortal newPortal = listener(); //9
buf[newPortal.recv(buf, 63)] = 0; //10
cout << "Received: " << buf << endl; //11
}
} catch(const RWInternalErr& ie) {
cout << ie.why() << endl;
return 1;
} catch(const RWExternalErr& ee) {
cout << ee.why() << endl;
return 1;
}
return 0;
}
4.1.5 About the Keys and Certificates in the Example Programs
The keys and certificates supplied with the example programs were created using OpenSSL. They are located in the examples\certs directory. In subdirectories of that directory, readme.txt files describe the certificate infrastructure used for the examples and the scripts used to create them.
The scripts are provided on an as-is basis. Technical support will not be provided for them. Rogue Wave does support the example programs.