Admittedly, the topic of this post is very specific but I hope it will still be of some value for some people.The task for today is to setup SSL server and client with POCO framework classes. I will leave out the whole certificate managing issues and just assume that the right files are at hand.
The SSL related part of the POCO libraries essentially wraps the OpenSSL library into a nice object-oriented interface. When you know OpenSSL, you can instantly relate to classes like Poco::Net::Context, or the …Handler classes (if you replace “handler” with “callback”).
“SSL” stands for Secure Socket Layer, so the first thing to discover is class Poco::Net::SecureServerSocket. As you would expect, this class is derived from Poco::Net::ServerSocket, extending it only with SSL related stuff. And sure enough, some constructors of Poco::Net::ServerSocket take a Poco::Net::ContextPtr as argument.
But why only some constructors? Since there is no setContext method, there must be some other mechanism in place by which SecureServerSockets get their SSL context.
Introducing Poco::Net::SSLManager. From the API docs:
Proper initialization of SSLManager is critical.
Aha! So all the constructors of SecureServerSocket that do not take Context pointers simply get it from the SSLManager singleton.
But how to initialize SSLManager?
1. The POCO Way:
If you developed your application with POCO from the ground up there probably exists a sub-class of Poco::Application, and all the configuration is handled by the built-in configuration classes.
With this in place, all you have to do is to add the proper ssl configuration elements:
openSSL.server.privateKeyFile = /path/to/key/file openSSL.server.certificateFile = /path/to/certificate/file openSSL.server.verificationMode = none openSSL.server.verificationDepth = 9 openSSL.server.loadDefaultCAFile = false openSSL.server.cypherList = ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH openSSL.server.privateKeyPassphraseHandler.name = KeyFileHandler openSSL.server.privateKeyPassphraseHandler.options.password = securePassword openSSL.server.invalidCertificateHandler = AcceptCertificateHandler
Depending on which side you are – client or server – you have to call SSLManager::initializeClient or SSLManager::initializeServer. Both methods take three arguments:
- PrivateKeyPassphraseHandler pointer
- InvalidCertificateHandler pointer
- Context pointer
This is where it becomes a little bit tricky: If you try to instantiate a Context with a privateKey file in order to provide it as argument to the initialize… method, a PrivateKeyPassphraseHandler might be needed. This handler is fetched from the SSLManager singleton – which you are just about to initialize!.
This circular dependency between Context and SSLManager can be overcome e.g. if you call SSLManager::initializeServer first only with a PrivateKeyPassphraseHandler, a InvalidCertificateHandler and null Context pointer. Then instantiate the Context and call SSLManager::initializeServer again.
Now that SSL Manager is initialized we can use Secure… prefixed classes as we would used their non-SSL counterparts. As with SecureServerSocket, other Secure… classes are derieved from corresponding non-secure base classes.
Conclusion: Once you got around the initialization of SSLManager singelton, using SSL POCO classes is very easy and straight forward. Check it out!