summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/ContextOpenSSL.cpp
diff options
context:
space:
mode:
authorMarc Laukien <marc@zeroc.com>2002-04-02 17:08:47 +0000
committerMarc Laukien <marc@zeroc.com>2002-04-02 17:08:47 +0000
commitc98649e0be8c8bcbc8eba686f9a08f1ed17d36cb (patch)
treecd9ddef90cf2f5496be9abc07e3018bb294d8213 /cpp/src/Ice/ContextOpenSSL.cpp
parentremoved shutdown() from acceptor (diff)
downloadice-c98649e0be8c8bcbc8eba686f9a08f1ed17d36cb.tar.bz2
ice-c98649e0be8c8bcbc8eba686f9a08f1ed17d36cb.tar.xz
ice-c98649e0be8c8bcbc8eba686f9a08f1ed17d36cb.zip
cleanup
Diffstat (limited to 'cpp/src/Ice/ContextOpenSSL.cpp')
-rw-r--r--cpp/src/Ice/ContextOpenSSL.cpp1222
1 files changed, 611 insertions, 611 deletions
diff --git a/cpp/src/Ice/ContextOpenSSL.cpp b/cpp/src/Ice/ContextOpenSSL.cpp
index 3275f65d432..b301d1c4ff4 100644
--- a/cpp/src/Ice/ContextOpenSSL.cpp
+++ b/cpp/src/Ice/ContextOpenSSL.cpp
@@ -1,611 +1,611 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <Ice/Instance.h>
-#include <Ice/Properties.h>
-
-#include <Ice/DefaultCertificateVerifier.h>
-#include <Ice/SslException.h>
-#include <Ice/RSAKeyPair.h>
-#include <Ice/CertificateDesc.h>
-#include <Ice/SslConnectionOpenSSL.h>
-#include <Ice/ContextOpenSSL.h>
-
-#include <Ice/OpenSSLJanitors.h>
-#include <Ice/OpenSSLUtils.h>
-#include <openssl/err.h>
-
-using IceSSL::ConnectionPtr;
-
-void ::IceInternal::incRef(::IceSSL::OpenSSL::Context* p) { p->__incRef(); }
-void ::IceInternal::decRef(::IceSSL::OpenSSL::Context* p) { p->__decRef(); }
-
-IceSSL::OpenSSL::Context::~Context()
-{
- if (_sslContext != 0)
- {
- SSL_CTX_free(_sslContext);
-
- _sslContext = 0;
- }
-}
-
-bool
-IceSSL::OpenSSL::Context::isConfigured()
-{
- return (_sslContext != 0 ? true : false);
-}
-
-void
-IceSSL::OpenSSL::Context::setCertificateVerifier(const CertificateVerifierPtr& verifier)
-{
- _certificateVerifier = verifier;
-}
-
-void
-IceSSL::OpenSSL::Context::addTrustedCertificateBase64(const std::string& trustedCertString)
-{
- RSAPublicKey pubKey(trustedCertString);
-
- addTrustedCertificate(pubKey);
-}
-
-void
-IceSSL::OpenSSL::Context::addTrustedCertificate(const Ice::ByteSeq& trustedCert)
-{
- RSAPublicKey pubKey(trustedCert);
-
- addTrustedCertificate(pubKey);
-}
-
-void
-IceSSL::OpenSSL::Context::setRSAKeysBase64(const std::string& privateKey,
- const std::string& publicKey)
-{
- addKeyCert(privateKey, publicKey);
-}
-
-void
-IceSSL::OpenSSL::Context::setRSAKeys(const Ice::ByteSeq& privateKey, const Ice::ByteSeq& publicKey)
-{
- addKeyCert(privateKey, publicKey);
-}
-
-void
-IceSSL::OpenSSL::Context::configure(const GeneralConfig& generalConfig,
- const CertificateAuthority& certificateAuthority,
- const BaseCertificates& baseCertificates)
-{
- // Create an SSL Context based on the context params.
- createContext(generalConfig.getProtocol());
-
- // Get the cipherlist and set it in the context.
- setCipherList(generalConfig.getCipherList());
-
- // Set the certificate verification mode.
- SSL_CTX_set_verify(_sslContext, generalConfig.getVerifyMode(), verifyCallback);
-
- // Set the certificate verify depth
- SSL_CTX_set_verify_depth(_sslContext, generalConfig.getVerifyDepth());
-
- // Process the RSA Certificate
- setKeyCert(baseCertificates.getRSACert(), _rsaPrivateKeyProperty, _rsaPublicKeyProperty);
-
- // Process the DSA Certificate
- setKeyCert(baseCertificates.getDSACert(), _dsaPrivateKeyProperty, _dsaPublicKeyProperty);
-
- // Set the DH key agreement parameters.
- if (baseCertificates.getDHParams().getKeySize() != 0)
- {
- setDHParams(baseCertificates);
- }
-}
-
-//
-// Protected
-//
-
-IceSSL::OpenSSL::Context::Context(const IceInternal::InstancePtr& instance) :
- _traceLevels(instance->traceLevels()),
- _logger(instance->logger()),
- _properties(instance->properties())
-{
- assert(_traceLevels != 0);
- assert(_logger != 0);
- assert(_properties != 0);
-
- _certificateVerifier = new DefaultCertificateVerifier(instance);
- _sslContext = 0;
-}
-
-SSL_METHOD*
-IceSSL::OpenSSL::Context::getSslMethod(SslProtocol sslVersion)
-{
- SSL_METHOD* sslMethod = 0;
-
- switch (sslVersion)
- {
- case SSL_V2 :
- {
- sslMethod = SSLv2_method();
- break;
- }
-
- case SSL_V23 :
- {
- sslMethod = SSLv23_method();
- break;
- }
-
- case SSL_V3 :
- {
- sslMethod = SSLv3_method();
- break;
- }
-
- case TLS_V1 :
- {
- sslMethod = TLSv1_method();
- break;
- }
-
- default :
- {
- if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
- {
- std::string errorString;
-
- errorString = "ssl version ";
- errorString += sslVersion;
- errorString += " not supported (defaulting to SSL_V23)";
- _logger->trace(_traceLevels->securityCat, "WRN " + errorString);
- }
-
- sslMethod = SSLv23_method();
- }
- }
-
- return sslMethod;
-}
-
-void
-IceSSL::OpenSSL::Context::createContext(SslProtocol sslProtocol)
-{
- if (_sslContext != 0)
- {
- SSL_CTX_free(_sslContext);
- _sslContext = 0;
- }
-
- _sslContext = SSL_CTX_new(getSslMethod(sslProtocol));
-
- if (_sslContext == 0)
- {
- IceSSL::OpenSSL::ContextInitializationException contextInitEx(__FILE__, __LINE__);
-
- contextInitEx._message = "unable to create ssl context\n" + sslGetErrors();
-
- throw contextInitEx;
- }
-
- // Turn off session caching, supposedly fixes a problem with multithreading.
- SSL_CTX_set_session_cache_mode(_sslContext, SSL_SESS_CACHE_OFF);
-}
-
-void
-IceSSL::OpenSSL::Context::loadCertificateAuthority(const CertificateAuthority& certAuth)
-{
- assert(_sslContext != 0);
-
- std::string fileName = certAuth.getCAFileName();
- std::string certPath = certAuth.getCAPath();
-
- const char* caFile = 0;
- const char* caPath = 0;
-
- // The following checks are required to send the expected values to the OpenSSL library.
- // It does not like receiving "", but prefers NULLs.
-
- if (!fileName.empty())
- {
- caFile = fileName.c_str();
- }
-
- if (!certPath.length())
- {
- caPath = certPath.c_str();
- }
-
- // SSL_CTX_set_default_passwd_cb(sslContext, passwordCallback);
-
- // Check the Certificate Authority file(s).
- int loadVerifyRet = SSL_CTX_load_verify_locations(_sslContext, caFile, caPath);
-
- if (!loadVerifyRet)
- {
- if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
- {
- _logger->trace(_traceLevels->securityCat, "WRN unable to load certificate authorities.");
- }
- }
- else
- {
- int setDefaultVerifyPathsRet = SSL_CTX_set_default_verify_paths(_sslContext);
-
-
- if (!setDefaultVerifyPathsRet && (_traceLevels->security >= IceSSL::SECURITY_WARNINGS))
- {
- _logger->trace(_traceLevels->securityCat, "WRN unable to verify certificate authorities.");
- }
- }
-
- // Now we add whatever override/addition that we wish to put into the trusted certificates list
- std::string caCertBase64 = _properties->getProperty(_caCertificateProperty);
- if (!caCertBase64.empty())
- {
- addTrustedCertificateBase64(caCertBase64);
- }
-}
-
-void
-IceSSL::OpenSSL::Context::setKeyCert(const CertificateDesc& certDesc,
- const std::string& privateProperty,
- const std::string& publicProperty)
-{
- std::string privateKey;
- std::string publicKey;
-
- if (!privateProperty.empty())
- {
- privateKey = _properties->getProperty(privateProperty);
- }
-
- if (!publicProperty.empty())
- {
- publicKey = _properties->getProperty(publicProperty);
- }
-
- if (!privateKey.empty() && !publicKey.empty())
- {
- addKeyCert(privateKey, publicKey);
- }
- else if (certDesc.getKeySize() != 0)
- {
- const CertificateFile& privateKey = certDesc.getPrivate();
- const CertificateFile& publicKey = certDesc.getPublic();
-
- addKeyCert(privateKey, publicKey);
- }
-}
-
-void
-IceSSL::OpenSSL::Context::checkKeyCert()
-{
- assert(_sslContext != 0);
-
- // Check to see if the Private and Public keys that have been
- // set against the SSL context match up.
- if (!SSL_CTX_check_private_key(_sslContext))
- {
- IceSSL::OpenSSL::CertificateKeyMatchException certKeyMatchEx(__FILE__, __LINE__);
-
- certKeyMatchEx._message = "private key does not match the certificate public key";
- std::string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- certKeyMatchEx._message += "\n";
- certKeyMatchEx._message += sslError;
- }
-
- throw certKeyMatchEx;
- }
-}
-
-void
-IceSSL::OpenSSL::Context::addTrustedCertificate(const RSAPublicKey& trustedCertificate)
-{
- if (_sslContext == 0)
- {
- IceSSL::OpenSSL::ContextNotConfiguredException contextConfigEx(__FILE__, __LINE__);
-
- contextConfigEx._message = "ssl context not configured";
-
- throw contextConfigEx;
- }
-
- X509_STORE* certStore = SSL_CTX_get_cert_store(_sslContext);
-
- assert(certStore != 0);
-
- if (X509_STORE_add_cert(certStore, trustedCertificate.getX509PublicKey()) == 0)
- {
- IceSSL::OpenSSL::TrustedCertificateAddException trustEx(__FILE__, __LINE__);
-
- trustEx._message = sslGetErrors();
-
- throw trustEx;
- }
-}
-
-void
-IceSSL::OpenSSL::Context::addKeyCert(const CertificateFile& privateKey, const CertificateFile& publicCert)
-{
- assert(_sslContext != 0);
-
- if (!publicCert.getFileName().empty())
- {
- std::string publicCertFile = publicCert.getFileName();
- const char* publicFile = publicCertFile.c_str();
- int publicEncoding = publicCert.getEncoding();
-
- std::string privCertFile = privateKey.getFileName();
- const char* privKeyFile = privCertFile.c_str();
- int privKeyFileType = privateKey.getEncoding();
-
- // Set which Public Key file to use.
- if (SSL_CTX_use_certificate_file(_sslContext, publicFile, publicEncoding) <= 0)
- {
- IceSSL::OpenSSL::CertificateLoadException certLoadEx(__FILE__, __LINE__);
-
- certLoadEx._message = "unable to load certificate from '";
- certLoadEx._message += publicFile;
- certLoadEx._message += "'\n";
- certLoadEx._message += sslGetErrors();
-
- throw certLoadEx;
- }
-
- if (privateKey.getFileName().empty())
- {
- if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
- {
- _logger->trace(_traceLevels->securityCat, "WRN no private key specified -- using the certificate");
- }
-
- privKeyFile = publicFile;
- privKeyFileType = publicEncoding;
- }
-
- // Set which Private Key file to use.
- if (SSL_CTX_use_PrivateKey_file(_sslContext, privKeyFile, privKeyFileType) <= 0)
- {
- int errCode = ERR_GET_REASON(ERR_peek_error());
-
- // Note: Because OpenSSL currently (V0.9.6b) performs a check to see if the
- // key matches the private key when calling SSL_CTX_use_PrivateKey_file().
- if (errCode == X509_R_KEY_VALUES_MISMATCH || errCode == X509_R_KEY_TYPE_MISMATCH)
- {
- IceSSL::OpenSSL::CertificateKeyMatchException certKeyMatchEx(__FILE__, __LINE__);
-
- certKeyMatchEx._message = "private key does not match the certificate public key";
- std::string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- certKeyMatchEx._message += "\n";
- certKeyMatchEx._message += sslError;
- }
-
- throw certKeyMatchEx;
- }
- else
- {
- IceSSL::OpenSSL::PrivateKeyLoadException pklEx(__FILE__, __LINE__);
-
- pklEx._message = "unable to load private key from '";
- pklEx._message += privKeyFile;
- pklEx._message += "'\n";
- pklEx._message += sslGetErrors();
-
- throw pklEx;
- }
- }
-
- checkKeyCert();
- }
-}
-
-void
-IceSSL::OpenSSL::Context::addKeyCert(const RSAKeyPair& keyPair)
-{
- if (_sslContext == 0)
- {
- IceSSL::OpenSSL::ContextNotConfiguredException contextConfigEx(__FILE__, __LINE__);
-
- contextConfigEx._message = "ssl context not configured";
-
- throw contextConfigEx;
- }
-
- // Note: Normally I would use an X509Janitor and RSAJanitor to ensure that
- // memory was being freed properly when exceptions are thrown, but
- // both SSL_CTX_use_certificate and SSL_CTX_use_RSAPrivateKey free
- // certificate/key memory regardless if the call succeeded.
-
- // Set which Public Key file to use.
- if (SSL_CTX_use_certificate(_sslContext, keyPair.getX509PublicKey()) <= 0)
- {
- IceSSL::OpenSSL::CertificateLoadException certLoadEx(__FILE__, __LINE__);
-
- certLoadEx._message = "unable to set certificate from memory";
- std::string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- certLoadEx._message += "\n";
- certLoadEx._message += sslError;
- }
-
- throw certLoadEx;
- }
-
- // Set which Private Key file to use.
- if (SSL_CTX_use_RSAPrivateKey(_sslContext, keyPair.getRSAPrivateKey()) <= 0)
- {
- int errCode = ERR_GET_REASON(ERR_peek_error());
-
- // Note: Because OpenSSL currently (V0.9.6b) performs a check to see if the
- // key matches the private key when calling SSL_CTX_use_PrivateKey_file().
- if (errCode == X509_R_KEY_VALUES_MISMATCH || errCode == X509_R_KEY_TYPE_MISMATCH)
- {
- IceSSL::OpenSSL::CertificateKeyMatchException certKeyMatchEx(__FILE__, __LINE__);
-
- certKeyMatchEx._message = "private key does not match the certificate public key";
- std::string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- certKeyMatchEx._message += "\n";
- certKeyMatchEx._message += sslError;
- }
-
- throw certKeyMatchEx;
- }
- else
- {
- IceSSL::OpenSSL::PrivateKeyLoadException pklEx(__FILE__, __LINE__);
-
- pklEx._message = "unable to set private key from memory";
- std::string sslError = sslGetErrors();
-
- if (!sslError.empty())
- {
- pklEx._message += "\n";
- pklEx._message += sslError;
- }
-
- throw pklEx;
- }
- }
-
- checkKeyCert();
-}
-
-void
-IceSSL::OpenSSL::Context::addKeyCert(const Ice::ByteSeq& privateKey, const Ice::ByteSeq& publicKey)
-{
- Ice::ByteSeq privKey = privateKey;
-
- if (privKey.empty())
- {
- if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
- {
- _logger->trace(_traceLevels->securityCat, "WRN no private key specified -- using the certificate");
- }
-
- privKey = publicKey;
- }
-
- // Make a key pair based on the DER encoded byte sequences.
- addKeyCert(RSAKeyPair(privKey, publicKey));
-}
-
-void
-IceSSL::OpenSSL::Context::addKeyCert(const std::string& privateKey, const std::string& publicKey)
-{
- std::string privKey = privateKey;
-
- if (privKey.empty())
- {
- if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
- {
- _logger->trace(_traceLevels->securityCat, "WRN no private key specified -- using the certificate");
- }
-
- privKey = publicKey;
- }
-
- // Make a key pair based on the Base64 encoded strings.
- addKeyCert(RSAKeyPair(privKey, publicKey));
-}
-
-SSL*
-IceSSL::OpenSSL::Context::createSSLConnection(int socket)
-{
- assert(_sslContext != 0);
-
- SSL* sslConnection = SSL_new(_sslContext);
- assert(sslConnection != 0);
-
- SSL_clear(sslConnection);
-
- SSL_set_fd(sslConnection, socket);
-
- return sslConnection;
-}
-
-void
-IceSSL::OpenSSL::Context::connectionSetup(const ConnectionPtr& connection)
-{
- // Set the Post-Handshake Read timeout
- // This timeout is implemented once on the first read after hanshake.
- int handshakeReadTimeout;
- std::string value = _properties->getProperty(_handshakeTimeoutProperty);
-
- if (!value.empty())
- {
- handshakeReadTimeout = atoi(value.c_str());
- }
- else
- {
- handshakeReadTimeout = 5000;
- }
-
- connection->setHandshakeReadTimeout(handshakeReadTimeout);
-}
-
-void
-IceSSL::OpenSSL::Context::setCipherList(const std::string& cipherList)
-{
- assert(_sslContext != 0);
-
- if (!cipherList.empty() && (!SSL_CTX_set_cipher_list(_sslContext, cipherList.c_str())) &&
- (_traceLevels->security >= IceSSL::SECURITY_WARNINGS))
- {
- std::string errorString = "WRN error setting cipher list " + cipherList + " -- using default list\n";
- errorString += sslGetErrors();
- _logger->trace(_traceLevels->securityCat, errorString);
- }
-}
-
-void
-IceSSL::OpenSSL::Context::setDHParams(const BaseCertificates& baseCerts)
-{
- DH* dh = 0;
-
- std::string dhFile = baseCerts.getDHParams().getFileName();
- int encoding = baseCerts.getDHParams().getEncoding();
-
- // File type must be PEM - that's the only way we can load DH Params, apparently.
- if ((!dhFile.empty()) && (encoding == SSL_FILETYPE_PEM))
- {
- dh = loadDHParam(dhFile.c_str());
- }
-
- if (dh == 0)
- {
- if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
- {
- _logger->trace(_traceLevels->securityCat,
- "WRN Could not load Diffie-Hellman params, generating a temporary 512bit key.");
- }
-
- dh = getTempDH512();
- }
-
- if (dh != 0)
- {
- SSL_CTX_set_tmp_dh(_sslContext, dh);
-
- DH_free(dh);
- }
-}
-
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/Instance.h>
+#include <Ice/Properties.h>
+
+#include <Ice/DefaultCertificateVerifier.h>
+#include <Ice/SslException.h>
+#include <Ice/RSAKeyPair.h>
+#include <Ice/CertificateDesc.h>
+#include <Ice/SslConnectionOpenSSL.h>
+#include <Ice/ContextOpenSSL.h>
+
+#include <Ice/OpenSSLJanitors.h>
+#include <Ice/OpenSSLUtils.h>
+#include <openssl/err.h>
+
+using IceSSL::ConnectionPtr;
+
+void ::IceInternal::incRef(::IceSSL::OpenSSL::Context* p) { p->__incRef(); }
+void ::IceInternal::decRef(::IceSSL::OpenSSL::Context* p) { p->__decRef(); }
+
+IceSSL::OpenSSL::Context::~Context()
+{
+ if (_sslContext != 0)
+ {
+ SSL_CTX_free(_sslContext);
+
+ _sslContext = 0;
+ }
+}
+
+bool
+IceSSL::OpenSSL::Context::isConfigured()
+{
+ return (_sslContext != 0 ? true : false);
+}
+
+void
+IceSSL::OpenSSL::Context::setCertificateVerifier(const CertificateVerifierPtr& verifier)
+{
+ _certificateVerifier = verifier;
+}
+
+void
+IceSSL::OpenSSL::Context::addTrustedCertificateBase64(const std::string& trustedCertString)
+{
+ RSAPublicKey pubKey(trustedCertString);
+
+ addTrustedCertificate(pubKey);
+}
+
+void
+IceSSL::OpenSSL::Context::addTrustedCertificate(const Ice::ByteSeq& trustedCert)
+{
+ RSAPublicKey pubKey(trustedCert);
+
+ addTrustedCertificate(pubKey);
+}
+
+void
+IceSSL::OpenSSL::Context::setRSAKeysBase64(const std::string& privateKey,
+ const std::string& publicKey)
+{
+ addKeyCert(privateKey, publicKey);
+}
+
+void
+IceSSL::OpenSSL::Context::setRSAKeys(const Ice::ByteSeq& privateKey, const Ice::ByteSeq& publicKey)
+{
+ addKeyCert(privateKey, publicKey);
+}
+
+void
+IceSSL::OpenSSL::Context::configure(const GeneralConfig& generalConfig,
+ const CertificateAuthority& certificateAuthority,
+ const BaseCertificates& baseCertificates)
+{
+ // Create an SSL Context based on the context params.
+ createContext(generalConfig.getProtocol());
+
+ // Get the cipherlist and set it in the context.
+ setCipherList(generalConfig.getCipherList());
+
+ // Set the certificate verification mode.
+ SSL_CTX_set_verify(_sslContext, generalConfig.getVerifyMode(), verifyCallback);
+
+ // Set the certificate verify depth
+ SSL_CTX_set_verify_depth(_sslContext, generalConfig.getVerifyDepth());
+
+ // Process the RSA Certificate
+ setKeyCert(baseCertificates.getRSACert(), _rsaPrivateKeyProperty, _rsaPublicKeyProperty);
+
+ // Process the DSA Certificate
+ setKeyCert(baseCertificates.getDSACert(), _dsaPrivateKeyProperty, _dsaPublicKeyProperty);
+
+ // Set the DH key agreement parameters.
+ if (baseCertificates.getDHParams().getKeySize() != 0)
+ {
+ setDHParams(baseCertificates);
+ }
+}
+
+//
+// Protected
+//
+
+IceSSL::OpenSSL::Context::Context(const IceInternal::InstancePtr& instance) :
+ _traceLevels(instance->traceLevels()),
+ _logger(instance->logger()),
+ _properties(instance->properties())
+{
+ assert(_traceLevels != 0);
+ assert(_logger != 0);
+ assert(_properties != 0);
+
+ _certificateVerifier = new DefaultCertificateVerifier(instance);
+ _sslContext = 0;
+}
+
+SSL_METHOD*
+IceSSL::OpenSSL::Context::getSslMethod(SslProtocol sslVersion)
+{
+ SSL_METHOD* sslMethod = 0;
+
+ switch (sslVersion)
+ {
+ case SSL_V2 :
+ {
+ sslMethod = SSLv2_method();
+ break;
+ }
+
+ case SSL_V23 :
+ {
+ sslMethod = SSLv23_method();
+ break;
+ }
+
+ case SSL_V3 :
+ {
+ sslMethod = SSLv3_method();
+ break;
+ }
+
+ case TLS_V1 :
+ {
+ sslMethod = TLSv1_method();
+ break;
+ }
+
+ default :
+ {
+ if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
+ {
+ std::string errorString;
+
+ errorString = "ssl version ";
+ errorString += sslVersion;
+ errorString += " not supported (defaulting to SSL_V23)";
+ _logger->trace(_traceLevels->securityCat, "WRN " + errorString);
+ }
+
+ sslMethod = SSLv23_method();
+ }
+ }
+
+ return sslMethod;
+}
+
+void
+IceSSL::OpenSSL::Context::createContext(SslProtocol sslProtocol)
+{
+ if (_sslContext != 0)
+ {
+ SSL_CTX_free(_sslContext);
+ _sslContext = 0;
+ }
+
+ _sslContext = SSL_CTX_new(getSslMethod(sslProtocol));
+
+ if (_sslContext == 0)
+ {
+ IceSSL::OpenSSL::ContextInitializationException contextInitEx(__FILE__, __LINE__);
+
+ contextInitEx._message = "unable to create ssl context\n" + sslGetErrors();
+
+ throw contextInitEx;
+ }
+
+ // Turn off session caching, supposedly fixes a problem with multithreading.
+ SSL_CTX_set_session_cache_mode(_sslContext, SSL_SESS_CACHE_OFF);
+}
+
+void
+IceSSL::OpenSSL::Context::loadCertificateAuthority(const CertificateAuthority& certAuth)
+{
+ assert(_sslContext != 0);
+
+ std::string fileName = certAuth.getCAFileName();
+ std::string certPath = certAuth.getCAPath();
+
+ const char* caFile = 0;
+ const char* caPath = 0;
+
+ // The following checks are required to send the expected values to the OpenSSL library.
+ // It does not like receiving "", but prefers NULLs.
+
+ if (!fileName.empty())
+ {
+ caFile = fileName.c_str();
+ }
+
+ if (!certPath.length())
+ {
+ caPath = certPath.c_str();
+ }
+
+ // SSL_CTX_set_default_passwd_cb(sslContext, passwordCallback);
+
+ // Check the Certificate Authority file(s).
+ int loadVerifyRet = SSL_CTX_load_verify_locations(_sslContext, caFile, caPath);
+
+ if (!loadVerifyRet)
+ {
+ if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
+ {
+ _logger->trace(_traceLevels->securityCat, "WRN unable to load certificate authorities.");
+ }
+ }
+ else
+ {
+ int setDefaultVerifyPathsRet = SSL_CTX_set_default_verify_paths(_sslContext);
+
+
+ if (!setDefaultVerifyPathsRet && (_traceLevels->security >= IceSSL::SECURITY_WARNINGS))
+ {
+ _logger->trace(_traceLevels->securityCat, "WRN unable to verify certificate authorities.");
+ }
+ }
+
+ // Now we add whatever override/addition that we wish to put into the trusted certificates list
+ std::string caCertBase64 = _properties->getProperty(_caCertificateProperty);
+ if (!caCertBase64.empty())
+ {
+ addTrustedCertificateBase64(caCertBase64);
+ }
+}
+
+void
+IceSSL::OpenSSL::Context::setKeyCert(const CertificateDesc& certDesc,
+ const std::string& privateProperty,
+ const std::string& publicProperty)
+{
+ std::string privateKey;
+ std::string publicKey;
+
+ if (!privateProperty.empty())
+ {
+ privateKey = _properties->getProperty(privateProperty);
+ }
+
+ if (!publicProperty.empty())
+ {
+ publicKey = _properties->getProperty(publicProperty);
+ }
+
+ if (!privateKey.empty() && !publicKey.empty())
+ {
+ addKeyCert(privateKey, publicKey);
+ }
+ else if (certDesc.getKeySize() != 0)
+ {
+ const CertificateFile& privateKey = certDesc.getPrivate();
+ const CertificateFile& publicKey = certDesc.getPublic();
+
+ addKeyCert(privateKey, publicKey);
+ }
+}
+
+void
+IceSSL::OpenSSL::Context::checkKeyCert()
+{
+ assert(_sslContext != 0);
+
+ // Check to see if the Private and Public keys that have been
+ // set against the SSL context match up.
+ if (!SSL_CTX_check_private_key(_sslContext))
+ {
+ IceSSL::OpenSSL::CertificateKeyMatchException certKeyMatchEx(__FILE__, __LINE__);
+
+ certKeyMatchEx._message = "private key does not match the certificate public key";
+ std::string sslError = sslGetErrors();
+
+ if (!sslError.empty())
+ {
+ certKeyMatchEx._message += "\n";
+ certKeyMatchEx._message += sslError;
+ }
+
+ throw certKeyMatchEx;
+ }
+}
+
+void
+IceSSL::OpenSSL::Context::addTrustedCertificate(const RSAPublicKey& trustedCertificate)
+{
+ if (_sslContext == 0)
+ {
+ IceSSL::OpenSSL::ContextNotConfiguredException contextConfigEx(__FILE__, __LINE__);
+
+ contextConfigEx._message = "ssl context not configured";
+
+ throw contextConfigEx;
+ }
+
+ X509_STORE* certStore = SSL_CTX_get_cert_store(_sslContext);
+
+ assert(certStore != 0);
+
+ if (X509_STORE_add_cert(certStore, trustedCertificate.getX509PublicKey()) == 0)
+ {
+ IceSSL::OpenSSL::TrustedCertificateAddException trustEx(__FILE__, __LINE__);
+
+ trustEx._message = sslGetErrors();
+
+ throw trustEx;
+ }
+}
+
+void
+IceSSL::OpenSSL::Context::addKeyCert(const CertificateFile& privateKey, const CertificateFile& publicCert)
+{
+ assert(_sslContext != 0);
+
+ if (!publicCert.getFileName().empty())
+ {
+ std::string publicCertFile = publicCert.getFileName();
+ const char* publicFile = publicCertFile.c_str();
+ int publicEncoding = publicCert.getEncoding();
+
+ std::string privCertFile = privateKey.getFileName();
+ const char* privKeyFile = privCertFile.c_str();
+ int privKeyFileType = privateKey.getEncoding();
+
+ // Set which Public Key file to use.
+ if (SSL_CTX_use_certificate_file(_sslContext, publicFile, publicEncoding) <= 0)
+ {
+ IceSSL::OpenSSL::CertificateLoadException certLoadEx(__FILE__, __LINE__);
+
+ certLoadEx._message = "unable to load certificate from '";
+ certLoadEx._message += publicFile;
+ certLoadEx._message += "'\n";
+ certLoadEx._message += sslGetErrors();
+
+ throw certLoadEx;
+ }
+
+ if (privateKey.getFileName().empty())
+ {
+ if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
+ {
+ _logger->trace(_traceLevels->securityCat, "WRN no private key specified -- using the certificate");
+ }
+
+ privKeyFile = publicFile;
+ privKeyFileType = publicEncoding;
+ }
+
+ // Set which Private Key file to use.
+ if (SSL_CTX_use_PrivateKey_file(_sslContext, privKeyFile, privKeyFileType) <= 0)
+ {
+ int errCode = ERR_GET_REASON(ERR_peek_error());
+
+ // Note: Because OpenSSL currently (V0.9.6b) performs a check to see if the
+ // key matches the private key when calling SSL_CTX_use_PrivateKey_file().
+ if (errCode == X509_R_KEY_VALUES_MISMATCH || errCode == X509_R_KEY_TYPE_MISMATCH)
+ {
+ IceSSL::OpenSSL::CertificateKeyMatchException certKeyMatchEx(__FILE__, __LINE__);
+
+ certKeyMatchEx._message = "private key does not match the certificate public key";
+ std::string sslError = sslGetErrors();
+
+ if (!sslError.empty())
+ {
+ certKeyMatchEx._message += "\n";
+ certKeyMatchEx._message += sslError;
+ }
+
+ throw certKeyMatchEx;
+ }
+ else
+ {
+ IceSSL::OpenSSL::PrivateKeyLoadException pklEx(__FILE__, __LINE__);
+
+ pklEx._message = "unable to load private key from '";
+ pklEx._message += privKeyFile;
+ pklEx._message += "'\n";
+ pklEx._message += sslGetErrors();
+
+ throw pklEx;
+ }
+ }
+
+ checkKeyCert();
+ }
+}
+
+void
+IceSSL::OpenSSL::Context::addKeyCert(const RSAKeyPair& keyPair)
+{
+ if (_sslContext == 0)
+ {
+ IceSSL::OpenSSL::ContextNotConfiguredException contextConfigEx(__FILE__, __LINE__);
+
+ contextConfigEx._message = "ssl context not configured";
+
+ throw contextConfigEx;
+ }
+
+ // Note: Normally I would use an X509Janitor and RSAJanitor to ensure that
+ // memory was being freed properly when exceptions are thrown, but
+ // both SSL_CTX_use_certificate and SSL_CTX_use_RSAPrivateKey free
+ // certificate/key memory regardless if the call succeeded.
+
+ // Set which Public Key file to use.
+ if (SSL_CTX_use_certificate(_sslContext, keyPair.getX509PublicKey()) <= 0)
+ {
+ IceSSL::OpenSSL::CertificateLoadException certLoadEx(__FILE__, __LINE__);
+
+ certLoadEx._message = "unable to set certificate from memory";
+ std::string sslError = sslGetErrors();
+
+ if (!sslError.empty())
+ {
+ certLoadEx._message += "\n";
+ certLoadEx._message += sslError;
+ }
+
+ throw certLoadEx;
+ }
+
+ // Set which Private Key file to use.
+ if (SSL_CTX_use_RSAPrivateKey(_sslContext, keyPair.getRSAPrivateKey()) <= 0)
+ {
+ int errCode = ERR_GET_REASON(ERR_peek_error());
+
+ // Note: Because OpenSSL currently (V0.9.6b) performs a check to see if the
+ // key matches the private key when calling SSL_CTX_use_PrivateKey_file().
+ if (errCode == X509_R_KEY_VALUES_MISMATCH || errCode == X509_R_KEY_TYPE_MISMATCH)
+ {
+ IceSSL::OpenSSL::CertificateKeyMatchException certKeyMatchEx(__FILE__, __LINE__);
+
+ certKeyMatchEx._message = "private key does not match the certificate public key";
+ std::string sslError = sslGetErrors();
+
+ if (!sslError.empty())
+ {
+ certKeyMatchEx._message += "\n";
+ certKeyMatchEx._message += sslError;
+ }
+
+ throw certKeyMatchEx;
+ }
+ else
+ {
+ IceSSL::OpenSSL::PrivateKeyLoadException pklEx(__FILE__, __LINE__);
+
+ pklEx._message = "unable to set private key from memory";
+ std::string sslError = sslGetErrors();
+
+ if (!sslError.empty())
+ {
+ pklEx._message += "\n";
+ pklEx._message += sslError;
+ }
+
+ throw pklEx;
+ }
+ }
+
+ checkKeyCert();
+}
+
+void
+IceSSL::OpenSSL::Context::addKeyCert(const Ice::ByteSeq& privateKey, const Ice::ByteSeq& publicKey)
+{
+ Ice::ByteSeq privKey = privateKey;
+
+ if (privKey.empty())
+ {
+ if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
+ {
+ _logger->trace(_traceLevels->securityCat, "WRN no private key specified -- using the certificate");
+ }
+
+ privKey = publicKey;
+ }
+
+ // Make a key pair based on the DER encoded byte sequences.
+ addKeyCert(RSAKeyPair(privKey, publicKey));
+}
+
+void
+IceSSL::OpenSSL::Context::addKeyCert(const std::string& privateKey, const std::string& publicKey)
+{
+ std::string privKey = privateKey;
+
+ if (privKey.empty())
+ {
+ if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
+ {
+ _logger->trace(_traceLevels->securityCat, "WRN no private key specified -- using the certificate");
+ }
+
+ privKey = publicKey;
+ }
+
+ // Make a key pair based on the Base64 encoded strings.
+ addKeyCert(RSAKeyPair(privKey, publicKey));
+}
+
+SSL*
+IceSSL::OpenSSL::Context::createSSLConnection(int socket)
+{
+ assert(_sslContext != 0);
+
+ SSL* sslConnection = SSL_new(_sslContext);
+ assert(sslConnection != 0);
+
+ SSL_clear(sslConnection);
+
+ SSL_set_fd(sslConnection, socket);
+
+ return sslConnection;
+}
+
+void
+IceSSL::OpenSSL::Context::connectionSetup(const ConnectionPtr& connection)
+{
+ // Set the Post-Handshake Read timeout
+ // This timeout is implemented once on the first read after hanshake.
+ int handshakeReadTimeout;
+ std::string value = _properties->getProperty(_handshakeTimeoutProperty);
+
+ if (!value.empty())
+ {
+ handshakeReadTimeout = atoi(value.c_str());
+ }
+ else
+ {
+ handshakeReadTimeout = 5000;
+ }
+
+ connection->setHandshakeReadTimeout(handshakeReadTimeout);
+}
+
+void
+IceSSL::OpenSSL::Context::setCipherList(const std::string& cipherList)
+{
+ assert(_sslContext != 0);
+
+ if (!cipherList.empty() && (!SSL_CTX_set_cipher_list(_sslContext, cipherList.c_str())) &&
+ (_traceLevels->security >= IceSSL::SECURITY_WARNINGS))
+ {
+ std::string errorString = "WRN error setting cipher list " + cipherList + " -- using default list\n";
+ errorString += sslGetErrors();
+ _logger->trace(_traceLevels->securityCat, errorString);
+ }
+}
+
+void
+IceSSL::OpenSSL::Context::setDHParams(const BaseCertificates& baseCerts)
+{
+ DH* dh = 0;
+
+ std::string dhFile = baseCerts.getDHParams().getFileName();
+ int encoding = baseCerts.getDHParams().getEncoding();
+
+ // File type must be PEM - that's the only way we can load DH Params, apparently.
+ if ((!dhFile.empty()) && (encoding == SSL_FILETYPE_PEM))
+ {
+ dh = loadDHParam(dhFile.c_str());
+ }
+
+ if (dh == 0)
+ {
+ if (_traceLevels->security >= IceSSL::SECURITY_WARNINGS)
+ {
+ _logger->trace(_traceLevels->securityCat,
+ "WRN Could not load Diffie-Hellman params, generating a temporary 512bit key.");
+ }
+
+ dh = getTempDH512();
+ }
+
+ if (dh != 0)
+ {
+ SSL_CTX_set_tmp_dh(_sslContext, dh);
+
+ DH_free(dh);
+ }
+}
+