version 1.115, 2013/03/19 17:00:55
|
version 1.123, 2014/03/24 19:55:16
|
|
|
# include <openssl/err.h> | # include <openssl/err.h> |
# include <openssl/ssl.h> | # include <openssl/ssl.h> |
# include <openssl/rand.h> | # include <openssl/rand.h> |
|
# include <openssl/tls1.h> |
#else | #else |
# define SSL_CTX void | # define SSL_CTX void |
#endif // end of PEGASUS_HAS_SSL | #endif // end of PEGASUS_HAS_SSL |
|
|
const String& crlPath, | const String& crlPath, |
SSLCertificateVerifyFunction* verifyCert, | SSLCertificateVerifyFunction* verifyCert, |
const String& randomFile, | const String& randomFile, |
const String& cipherSuite) |
const String& cipherSuite, |
|
const Boolean& sslCompatibility) |
{ | { |
PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()"); | PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()"); |
| |
|
|
_crlPath = crlPath; | _crlPath = crlPath; |
_certificateVerifyFunction = verifyCert; | _certificateVerifyFunction = verifyCert; |
_cipherSuite = cipherSuite; | _cipherSuite = cipherSuite; |
|
_sslCompatibility = sslCompatibility; |
// | // |
// If a truststore and/or peer verification function is specified, | // If a truststore and/or peer verification function is specified, |
// enable peer verification | // enable peer verification |
|
|
_certificateVerifyFunction = sslContextRep._certificateVerifyFunction; | _certificateVerifyFunction = sslContextRep._certificateVerifyFunction; |
_randomFile = sslContextRep._randomFile; | _randomFile = sslContextRep._randomFile; |
_cipherSuite = sslContextRep._cipherSuite; | _cipherSuite = sslContextRep._cipherSuite; |
|
_sslCompatibility = sslContextRep._sslCompatibility; |
_sslContext = _makeSSLContext(); | _sslContext = _makeSSLContext(); |
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
|
|
{ | { |
PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()"); | PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()"); |
| |
SSL_CTX * sslContext = 0; |
|
| |
// | // |
// create SSL Context Area | // create SSL Context Area |
// | // |
|
SSL_CTX *sslContext = NULL; |
if (!(sslContext = SSL_CTX_new(SSLv23_method()))) | if (!(sslContext = SSL_CTX_new(SSLv23_method()))) |
{ | { |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
|
|
throw SSLException(parms); | throw SSLException(parms); |
} | } |
| |
|
|
|
int options = SSL_OP_ALL; |
|
|
|
|
|
|
|
SSL_CTX_set_options(sslContext, options); |
|
if ( _sslCompatibility == false ) |
|
{ |
|
|
|
#ifdef TLS1_2_VERSION |
|
// Enable only TLSv1.2 and disable all other protocol (SSL v2, SSL v3, |
|
// TLS v1.0, TLSv1.1) |
|
|
|
options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_SSLv3; |
|
#endif |
|
} |
|
|
|
options |= SSL_OP_NO_SSLv2; |
|
SSL_CTX_set_options(sslContext, options); |
|
|
#ifdef PEGASUS_SSL_WEAKENCRYPTION | #ifdef PEGASUS_SSL_WEAKENCRYPTION |
if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40))) | if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40))) |
{ | { |
SSL_CTX_free(sslContext); | SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
| |
MessageLoaderParms parms( | MessageLoaderParms parms( |
"Common.SSLContext.COULD_NOT_SET_CIPHER_LIST", | "Common.SSLContext.COULD_NOT_SET_CIPHER_LIST", |
|
|
} | } |
#endif | #endif |
| |
if (_cipherSuite != String::EMPTY) |
if (_cipherSuite.size() != 0) |
{ | { |
if (!(SSL_CTX_set_cipher_list(sslContext, _cipherSuite.getCString()))) | if (!(SSL_CTX_set_cipher_list(sslContext, _cipherSuite.getCString()))) |
{ | { |
SSL_CTX_free(sslContext); | SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
| |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, | PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, |
"---> SSL: Cipher Suite could not be specified"); | "---> SSL: Cipher Suite could not be specified"); |
|
|
// | // |
// set overall SSL Context flags | // set overall SSL Context flags |
// | // |
|
// For OpenSSLversion >1.0.0 use SSL_OP_NO_COMPRESSION to disable the |
|
// compression For TLS 1.2 version, compression does not suffer from |
|
// CRIME attack so don.t disable compression For other OpenSSL versions |
|
// zero out the compression methods. |
|
#ifdef SSL_OP_NO_COMPRESSION |
|
#ifndef TLS1_2_VERSION |
|
SSL_CTX_set_options(sslContext, SSL_OP_NO_COMPRESSION); |
|
#endif |
|
#elif OPENSSL_VERSION_NUMBER >= 0x00908000L |
|
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); |
|
#endif |
SSL_CTX_set_quiet_shutdown(sslContext, 1); | SSL_CTX_set_quiet_shutdown(sslContext, 1); |
SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY); | SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY); |
SSL_CTX_set_mode(sslContext, SSL_MODE_ENABLE_PARTIAL_WRITE); | SSL_CTX_set_mode(sslContext, SSL_MODE_ENABLE_PARTIAL_WRITE); |
|
|
SSL_CTX_set_mode (sslContext, SSL_MODE_RELEASE_BUFFERS); | SSL_CTX_set_mode (sslContext, SSL_MODE_RELEASE_BUFFERS); |
#endif | #endif |
| |
int options = SSL_OP_ALL; |
|
#ifndef PEGASUS_ENABLE_SSLV2 //SSLv2 is disabled by default |
|
options |= SSL_OP_NO_SSLv2; |
|
#endif |
|
SSL_CTX_set_options(sslContext, options); |
|
|
|
if (_verifyPeer) | if (_verifyPeer) |
{ | { |
// ATTN: We might still need a flag to specify | // ATTN: We might still need a flag to specify |
|
|
| |
if (_certificateVerifyFunction != NULL) | if (_certificateVerifyFunction != NULL) |
{ | { |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL4, |
"---> SSL: certificate verification callback specified"); | "---> SSL: certificate verification callback specified"); |
SSL_CTX_set_verify(sslContext, | SSL_CTX_set_verify(sslContext, |
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback); | SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback); |
} | } |
else | else |
{ | { |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Trust Store specified"); | "---> SSL: Trust Store specified"); |
SSL_CTX_set_verify(sslContext, | SSL_CTX_set_verify(sslContext, |
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | | SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | |
|
|
// Check if there is CA certificate file or directory specified. If | // Check if there is CA certificate file or directory specified. If |
// specified, and is not empty, load the certificates from the Trust store. | // specified, and is not empty, load the certificates from the Trust store. |
// | // |
if (_trustStore != String::EMPTY) |
if (_trustStore.size() != 0) |
{ | { |
// | // |
// The truststore may be a single file of CA certificates OR | // The truststore may be a single file of CA certificates OR |
|
|
// | // |
if (FileSystem::isDirectory(_trustStore)) | if (FileSystem::isDirectory(_trustStore)) |
{ | { |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Truststore is a directory"); | "---> SSL: Truststore is a directory"); |
// | // |
// load certificates from the trust store | // load certificates from the trust store |
// | // |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Loading certificates from the trust store: %s", | "---> SSL: Loading certificates from the trust store: %s", |
(const char*)_trustStore.getCString())); | (const char*)_trustStore.getCString())); |
| |
|
|
MessageLoaderParms parms( | MessageLoaderParms parms( |
"Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES", | "Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES", |
"Could not load certificates in to trust store."); | "Could not load certificates in to trust store."); |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
// | // |
// load certificates from the trust store | // load certificates from the trust store |
// | // |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Loading certificates from the trust store: %s", | "---> SSL: Loading certificates from the trust store: %s", |
(const char*)_trustStore.getCString())); | (const char*)_trustStore.getCString())); |
| |
|
|
MessageLoaderParms parms( | MessageLoaderParms parms( |
"Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES", | "Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES", |
"Could not load certificates in to trust store."); | "Could not load certificates in to trust store."); |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
} | } |
} | } |
| |
if (_crlPath != String::EMPTY) |
if (_crlPath.size() != 0) |
{ | { |
// need to save this -- can we make it static since there's only | // need to save this -- can we make it static since there's only |
// one CRL for cimserver? | // one CRL for cimserver? |
|
|
_crlStore.reset(X509_STORE_new()); | _crlStore.reset(X509_STORE_new()); |
if (_crlStore.get() == NULL) | if (_crlStore.get() == NULL) |
{ | { |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw PEGASUS_STD(bad_alloc)(); | throw PEGASUS_STD(bad_alloc)(); |
} | } |
|
|
// during server startup | // during server startup |
if (FileSystem::isDirectory(_crlPath)) | if (FileSystem::isDirectory(_crlPath)) |
{ | { |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: CRL store is a directory in %s", | "---> SSL: CRL store is a directory in %s", |
(const char*)_crlPath.getCString())); | (const char*)_crlPath.getCString())); |
| |
|
|
"Common.SSLContext.COULD_NOT_LOAD_CRLS", | "Common.SSLContext.COULD_NOT_LOAD_CRLS", |
"Could not load certificate revocation list."); | "Could not load certificate revocation list."); |
_crlStore.reset(); | _crlStore.reset(); |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
} | } |
else | else |
{ | { |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: CRL store is the file %s", | "---> SSL: CRL store is the file %s", |
(const char*)_crlPath.getCString())); | (const char*)_crlPath.getCString())); |
| |
|
|
"Common.SSLContext.COULD_NOT_LOAD_CRLS", | "Common.SSLContext.COULD_NOT_LOAD_CRLS", |
"Could not load certificate revocation list."); | "Could not load certificate revocation list."); |
_crlStore.reset(); | _crlStore.reset(); |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
X509_LOOKUP_load_file( | X509_LOOKUP_load_file( |
pLookup, (const char*)_crlPath.getCString(), X509_FILETYPE_PEM); | pLookup, (const char*)_crlPath.getCString(), X509_FILETYPE_PEM); |
| |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Successfully configured CRL file"); | "---> SSL: Successfully configured CRL file"); |
} | } |
} | } |
|
|
// certificate) specified. If specified, validate and load the | // certificate) specified. If specified, validate and load the |
// certificate. | // certificate. |
// | // |
if (_certPath != String::EMPTY) |
if (_certPath.size() != 0) |
{ | { |
// | // |
// load the specified server certificates | // load the specified server certificates |
// | // |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Loading server certificate from: %s", | "---> SSL: Loading server certificate from: %s", |
(const char*)_certPath.getCString())); | (const char*)_certPath.getCString())); |
| |
|
|
"Common.SSLContext.COULD_NOT_ACCESS_SERVER_CERTIFICATE", | "Common.SSLContext.COULD_NOT_ACCESS_SERVER_CERTIFICATE", |
"Could not access server certificate in $0.", | "Could not access server certificate in $0.", |
(const char*)_certPath.getCString()); | (const char*)_certPath.getCString()); |
|
|
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
// As of 2.4, if a keyfile is specified, its location is verified | // As of 2.4, if a keyfile is specified, its location is verified |
// during server startup and will throw an error if the path is invalid. | // during server startup and will throw an error if the path is invalid. |
// | // |
if (_keyPath == String::EMPTY) |
if (_keyPath.size() == 0) |
{ | { |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: Key file empty, loading private key from " | "---> SSL: Key file empty, loading private key from " |
"certificate file: %s",(const char*)_certPath.getCString())); | "certificate file: %s",(const char*)_certPath.getCString())); |
// | // |
|
|
MessageLoaderParms parms( | MessageLoaderParms parms( |
"Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY", | "Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY", |
"Could not get private key."); | "Could not get private key."); |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
// private key) specified and the key was not already loaded. | // private key) specified and the key was not already loaded. |
// If specified, validate and load the key. | // If specified, validate and load the key. |
// | // |
if (_keyPath != String::EMPTY && !keyLoaded) |
if (_keyPath.size() != 0 && !keyLoaded ) |
{ | { |
PEG_TRACE((TRC_SSL, Tracer::LEVEL3, |
PEG_TRACE((TRC_SSL, Tracer::LEVEL4, |
"---> SSL: loading private key from: %s", | "---> SSL: loading private key from: %s", |
(const char*)_keyPath.getCString())); | (const char*)_keyPath.getCString())); |
// | // |
|
|
MessageLoaderParms parms( | MessageLoaderParms parms( |
"Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY", | "Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY", |
"Could not get private key."); | "Could not get private key."); |
|
SSL_CTX_free(sslContext); |
|
sslContext = NULL; |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw SSLException(parms); | throw SSLException(parms); |
} | } |
|
|
const String&, | const String&, |
SSLCertificateVerifyFunction*, | SSLCertificateVerifyFunction*, |
const String&, | const String&, |
const String&) |
const String&, |
|
const Boolean&) |
{ | { |
} | } |
| |
|
|
String::EMPTY, | String::EMPTY, |
verifyCert, | verifyCert, |
randomFile, | randomFile, |
String::EMPTY); |
String::EMPTY, |
|
false); |
} | } |
| |
SSLContext::SSLContext( | SSLContext::SSLContext( |
|
|
const String& crlPath, | const String& crlPath, |
SSLCertificateVerifyFunction* verifyCert, | SSLCertificateVerifyFunction* verifyCert, |
const String& randomFile, | const String& randomFile, |
const String& cipherSuite) |
const String& cipherSuite, |
|
const Boolean& sslCompatibility) |
{ | { |
#ifndef PEGASUS_ENABLE_SSL_CRL_VERIFICATION | #ifndef PEGASUS_ENABLE_SSL_CRL_VERIFICATION |
if (crlPath.size() > 0) | if (crlPath.size() > 0) |
|
|
#endif | #endif |
_rep = new SSLContextRep( | _rep = new SSLContextRep( |
trustStore, certPath, keyPath, crlPath, verifyCert, randomFile, | trustStore, certPath, keyPath, crlPath, verifyCert, randomFile, |
cipherSuite); |
cipherSuite,sslCompatibility); |
} | } |
#endif | #endif |
| |