NetSSL

Poco NetSSL (Schannel) User Guide

Introduction

NetSSL provides a socket class implementation that utilizes the Schannel API on Windows 32-bit platforms.

Sockets

Client Side

Adding NetSSL support to your existing POCO client application is simply a matter of creating a SecureSocketStream instead of a SocketStream:

#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/SecureStreamSocket.h"

[...]

Poco::Net::SocketAddress sa("localhost", 8888);
Poco::Net::SecureStreamSocket secureSocket(sa);

In most cases one will not work directly with a SecureStreamSocket, instead one will use a HTTPSStreamFactory and the URIStreamOpener to create an input stream:

#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"

[...]
// register the factory at the very beginning of your application
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::URI uri("https://wwww.myserver.com");
std::auto_ptr<std::istream> pStr(Poco::URIStreamOpener::defaultOpener().open(uri)); // creates an HTTPS input stream

Configuration

Before using the NetSSL library one must provide a configuration. NetSSL supports two different configuration options:

If you configure via a configuration file the initialization of the NetSSL library is delayed until the very first SSLSocket is created, or more precisely: the first call to Poco::Net::SSLManager::instance().defaultClientContext() performs the initialization.

Client Side Parameters

The following parameters are supported in NetSSL:

An example for a clientapp.properties configuration file would be:

schannel.client.certName =
schannel.client.verificationMode = relaxed
schannel.client.trustRoots = true
schannel.client.securityAlgo = tls1+ssl3
schannel.client.revocationChecking = false
schannel.client.invalidCertificateHandler.name = AcceptCertificateHandler

The same configuration can be set manually in the source code:

std::string certName; // empty means no cert
bool trustRoots = true;
bool revocationCheck = false;
bool isServer = false;
SharedPtr<InvalidCertificateHandler> ptrCert = new AcceptCertificateHandler(isServer);
SharedPtr<Context> ptrContext = new Context(isServer, certName, Context::SA_SSL3_TLS1, Context::VERIFY_RELAXED, revocationCheck, trustRoots);
SSLManager::instance().initializeClient(ptrCert, ptrContext);

Limitations

Windows 98/ME ignores the revocationCheck flag.

Handling Illegal Certificates

The schannel.client.invalidCertificateHandler.name allows users to provide their own callback code. An InvalidCertificateHandler is invoked whenever an error occurs verifying the certificate. The user must then inspect and accept/reject the certificate in the callback.

One can install one's own InvalidCertificateHandler by implementing the Poco::Net::InvalidCertificateHandler interface. Each subclass must provide a constructor that takes as input a single parameter bool handleErrorsOnServerSide. This flag tells the certificate handler if it is used on the server side or by the client:

namespace Poco {
namespace Net {

class NetSSL_API InvalidCertificateHandler
{
public:
    InvalidCertificateHandler(bool handleErrorsOnServerSide);
        /// Creates the InvalidCertificateHandler. 
        /// Set handleErrorsOnServerSide to true if the certificate handler is used on the server side.
        /// Automatically registers at one of the SSLManager::VerificationError events.

    virtual ~InvalidCertificateHandler();
        /// Destroys the InvalidCertificateHandler.

    virtual void onInvalidCertificate(const void* pSender, VerificationErrorArgs& errorCert) = 0;
        /// Receives the questionable certificate in parameter errorCert. If one wants to accept the
        /// certificate, call errorCert.setIgnoreError(true).

protected:
    bool _handleErrorsOnServerSide;
        /// Stores if the certificate handler gets invoked by the server (i.e. a client certificate is wrong)
        /// or the client (a server certificate is wrong)
};

} }

The onInvalidCertificate method tells the caller via the out parameter errorCert if it accepts the certificate. The most simple example is the implementation of the AcceptCertificateHandler:

void AcceptCertificateHandler::onInvalidCertificate(const void*, VerificationErrorArgs& errorCert)
{
    // no check, auto-accept
    errorCert.setIgnoreError(true);
}

Note that you must export your own InvalidCertificateHandlers in the startup code of your application. In this example we register a class MyGuiHandler:

Poco::Net::SSLManager::instance().certificateHandlerFactoryMgr().setFactory("MyGuiHandler", new Poco::Net::CertificateHandlerFactoryImpl<MyGuiHandler>());

Predefined Classes

NetSSL itself offers some predefined invalid certificate handlers which are always available:

Note that the predefined handlers are very simple. It is highly recommended that you write your own one!

Explicitly Trusted Root Certificates

After the context was initialized (either explicitly in the source code or implicitly from a configuration file by calling SSLManager::instance().defaultClientContext()), one has the possibility to add trusted certificates to the context. If a certificate is added explicitly to the context, it is automatically trustworthy as a CA, i.e. no expiry checking is performed!

#include "Poco/Net/Context.h"
#include "Poco/Net/SSLManager.h"


PCCERT_CONTEXT pCert = 0;
// init pCert somehow [...]
SSLManager::instance().defaultClientContext().addTrustedCert(pCert);

Limitations on Windows 98/ME

NetSSL

Poco