I'm using boost asio to connect to my valid certificate (signed by root CA). The code I'm using is the ssl client example available from boost docs.
The only line I added is:
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23_client);
ctx.set_default_verify_paths(); <------------- Add default verification paths
ctx.set_password_callback(&password_callback);
client c(io_service, ctx, iterator);
io_service.run();
the problem is: when using this code with a locally installed copy of openSSH (installed from a msi installer) the paths are found correctly and my certificate validated. When I download my own copy of the openSSH repository and compile it this line no longer works and I don't have root CA certificates to validate my own one (therefore it fails).
Since I'd like to eventually distribute these clients on customer machines I'd like to avoid setting environment variables like SSL_CERT_DIR
and the like. How can I find root CA certificates with boost asio reliably or alternatively configure my openSSH from source compilation to find them?
You can load the root CAs from the windows CA store. It already contains the "default" trusted root CA certificates and can be managed through certmgr. Use the following function to replace set_default_verify_paths under windows:
#include <boost/asio/ssl/context.hpp>
#include <wincrypt.h>
void add_windows_root_certs(boost::asio::ssl::context &ctx)
{
HCERTSTORE hStore = CertOpenSystemStore(0, "ROOT");
if (hStore == NULL) {
return;
}
X509_STORE *store = X509_STORE_new();
PCCERT_CONTEXT pContext = NULL;
while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
X509 *x509 = d2i_X509(NULL,
(const unsigned char **)&pContext->pbCertEncoded,
pContext->cbCertEncoded);
if(x509 != NULL) {
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
}
CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
SSL_CTX_set_cert_store(ctx.native_handle(), store);
}
This will load the certificates from the windows ca store. It uses d2i_X509 to convert them to the internal OpenSSL format and adds them to an OpenSSL X509_STORE. Then SSL_CTX_set_cert_store attaches that store to the boost ssl context. You can use that to set up your ssl context:
namespace ssl = boost::asio::ssl;
ssl::context ctx(ssl::context::tlsv12_client);
ctx.set_options(ssl::context::default_workarounds
| ssl::context::no_sslv2
| ssl::context::no_sslv3
| ssl::context::tlsv12_client);
#if BOOST_OS_WINDOWS
add_windows_root_certs(ctx);
#else
ctx.set_default_verify_paths();
#endif
ctx.set_password_callback(&password_callback);
client c(io_service, ctx, iterator);
io_service.run();
Note: You will probably need to add crypt32 to your linked libraries.
Note 2: BOOST_OS_WINDOWS needs Boost Predef
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With