version 1.2, 2002/06/01 00:56:37
|
version 1.3, 2002/07/31 21:08:40
|
|
|
#include <Pegasus/Common/Destroyer.h> | #include <Pegasus/Common/Destroyer.h> |
#include <Pegasus/Common/Socket.h> | #include <Pegasus/Common/Socket.h> |
#include <Pegasus/Common/Tracer.h> | #include <Pegasus/Common/Tracer.h> |
|
#include <Pegasus/Config/ConfigManager.h> |
| |
#include "SSLContext.h" | #include "SSLContext.h" |
#include "SSLContextRep.h" | #include "SSLContextRep.h" |
|
|
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
| |
// debug flag |
|
#define SSLCONTEXT_DEBUG(X) // X |
|
|
|
// switch on 'server needs certified client' |
|
//#define CLIENT_CERTIFY |
|
|
|
|
|
#ifdef PEGASUS_HAS_SSL |
|
// | // |
// use the following definitions only if SSL is available | // use the following definitions only if SSL is available |
// | // |
|
#ifdef PEGASUS_HAS_SSL |
| |
// | // |
// certificate handling routine | // certificate handling routine |
|
|
| |
static int cert_verify(SSL_CTX *ctx, char *cert_file, char *key_file) | static int cert_verify(SSL_CTX *ctx, char *cert_file, char *key_file) |
{ | { |
|
PEG_METHOD_ENTER(TRC_SSL, "cert_verify()"); |
| |
if (cert_file != NULL) | if (cert_file != NULL) |
{ | { |
if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <=0) | if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <=0) |
{ | { |
SSLCONTEXT_DEBUG(cerr << "no certificate found in " << cert_file << endl;) |
PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, |
|
"---> SSL: no certificate found in " + String(cert_file)); |
|
PEG_METHOD_EXIT(); |
return 0; | return 0; |
} | } |
if (key_file == NULL) key_file=cert_file; | if (key_file == NULL) key_file=cert_file; |
if (SSL_CTX_use_PrivateKey_file(ctx,key_file,SSL_FILETYPE_PEM) <= 0) | if (SSL_CTX_use_PrivateKey_file(ctx,key_file,SSL_FILETYPE_PEM) <= 0) |
{ | { |
SSLCONTEXT_DEBUG(cerr << "no private key found in " << key_file << endl;) |
PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, |
|
"---> SSL: no private key found in " + String(key_file)); |
|
PEG_METHOD_EXIT(); |
return 0; | return 0; |
} | } |
| |
if (!SSL_CTX_check_private_key(ctx)) | if (!SSL_CTX_check_private_key(ctx)) |
{ | { |
SSLCONTEXT_DEBUG(cerr << "Private and public key do not match\n";) |
PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, |
|
"---> SSL: Private and public key do not match"); |
|
PEG_METHOD_EXIT(); |
return 0; | return 0; |
} | } |
} | } |
|
PEG_METHOD_EXIT(); |
return -1; | return -1; |
} | } |
| |
static int prepareForCallback(int preverifyOk, X509_STORE_CTX *ctx) | static int prepareForCallback(int preverifyOk, X509_STORE_CTX *ctx) |
{ | { |
PEG_METHOD_ENTER(TRC_SSL, "CertificateManager::prepareForCallback()"); |
PEG_METHOD_ENTER(TRC_SSL, "prepareForCallback()"); |
| |
char buf[256]; | char buf[256]; |
X509 *err_cert; | X509 *err_cert; |
|
|
| |
if (!preverifyOk) | if (!preverifyOk) |
{ | { |
SSLCONTEXT_DEBUG(cerr << "---> verify error: num = " << err << ", " |
PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, |
<< X509_verify_cert_error_string(err) << ", " << depth |
"---> SSL: verify error: " + String(X509_verify_cert_error_string(err))); |
<< ", " << buf << endl;) |
|
} | } |
| |
if (!preverifyOk && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) | if (!preverifyOk && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) |
|
|
X509_STORE_CTX_set_error(ctx, verify_error); | X509_STORE_CTX_set_error(ctx, verify_error); |
} | } |
| |
SSLCONTEXT_DEBUG(cerr << "verify return: " << preverifyOk << endl;) |
|
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return(preverifyOk); | return(preverifyOk); |
} | } |
|
|
Boolean isCIMClient) | Boolean isCIMClient) |
throw(SSL_Exception) | throw(SSL_Exception) |
{ | { |
SSLCONTEXT_DEBUG(cout << "Entering SSLContextRep::SSLContextRep()\n";) |
PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()"); |
| |
_certPath = certPath.allocateCString(); | _certPath = certPath.allocateCString(); |
| |
|
|
ArrayDestroyer<char> pRandomFile(randomFile.allocateCString()); | ArrayDestroyer<char> pRandomFile(randomFile.allocateCString()); |
char* randFilename = pRandomFile.getPointer(); | char* randFilename = pRandomFile.getPointer(); |
| |
SSLCONTEXT_DEBUG( cout << "load Rand file: name=" << randFilename << endl; ) |
|
int ret = RAND_load_file(randFilename, -1); | int ret = RAND_load_file(randFilename, -1); |
if ( ret < 0 ) | if ( ret < 0 ) |
{ | { |
SSLCONTEXT_DEBUG( cerr << " RAND_load_file failed, Status="<< ret << endl;) |
PEG_METHOD_EXIT(); |
throw( SSL_Exception("RAND_load_file - failed")); | throw( SSL_Exception("RAND_load_file - failed")); |
} | } |
else |
|
{ |
|
SSLCONTEXT_DEBUG( cerr << " RAND_load_file Status="<< ret << endl;) |
|
} |
|
| |
// | // |
// Will do more seeding | // Will do more seeding |
|
|
int seedRet = RAND_status(); | int seedRet = RAND_status(); |
if ( seedRet == 0 ) | if ( seedRet == 0 ) |
{ | { |
SSLCONTEXT_DEBUG( cerr << " Not enough data , Rand Status="<< seedRet << endl;) |
PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, |
|
"Not enough data , RAND_status = " + seedRet ); |
|
PEG_METHOD_EXIT(); |
throw( SSL_Exception("RAND_seed - Not enough seed data ")); | throw( SSL_Exception("RAND_seed - Not enough seed data ")); |
} | } |
} | } |
else | else |
{ | { |
|
PEG_METHOD_EXIT(); |
throw( SSL_Exception("Random seed file required")); | throw( SSL_Exception("Random seed file required")); |
} | } |
| |
|
|
// | // |
| |
if (!( _SSLContext = SSL_CTX_new(SSLv23_method()) )) | if (!( _SSLContext = SSL_CTX_new(SSLv23_method()) )) |
|
{ |
|
PEG_METHOD_EXIT(); |
throw( SSL_Exception("Could not get SSL CTX")); | throw( SSL_Exception("Could not get SSL CTX")); |
|
} |
|
|
|
#ifdef PEGASUS_OS_HPUX |
|
if (!(SSL_CTX_set_cipher_list(_SSLContext, SSL_TXT_EXP40))) |
|
throw( SSL_Exception("Could not set the cipher list")); |
|
#endif |
| |
// | // |
// set overall SSL Context flags | // set overall SSL Context flags |
|
|
SSL_CTX_set_mode(_SSLContext, SSL_MODE_AUTO_RETRY); | SSL_CTX_set_mode(_SSLContext, SSL_MODE_AUTO_RETRY); |
SSL_CTX_set_options(_SSLContext,SSL_OP_ALL); | SSL_CTX_set_options(_SSLContext,SSL_OP_ALL); |
| |
#ifdef CLIENT_CERTIFY |
// |
|
// Check if the client certificate verification is required |
|
// |
|
ConfigManager* configManager = ConfigManager::getInstance(); |
|
|
|
if (String::equalNoCase( |
|
configManager->getCurrentValue("enableClientCertification"), "true")) |
|
{ |
SSL_CTX_set_verify(_SSLContext, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, | SSL_CTX_set_verify(_SSLContext, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, |
prepareForCallback); | prepareForCallback); |
#else |
} |
|
else |
|
{ |
if (verifyCert != NULL) | if (verifyCert != NULL) |
{ | { |
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); |
} | } |
#endif // end of CLIENT_CERTIFY |
} |
| |
// | // |
// check certificate given to me | // check certificate given to me |
// | // |
| |
if (!cert_verify(_SSLContext, _certPath, _certPath)) | if (!cert_verify(_SSLContext, _certPath, _certPath)) |
|
{ |
|
PEG_METHOD_EXIT(); |
throw( SSL_Exception("Could not get certificate and/or private key")); | throw( SSL_Exception("Could not get certificate and/or private key")); |
|
} |
| |
SSLCONTEXT_DEBUG(cout << "Leaving SSLContextRep::SSLContextRep()\n";) |
PEG_METHOD_EXIT(); |
} | } |
| |
| |
|
|
| |
SSLContextRep::~SSLContextRep() | SSLContextRep::~SSLContextRep() |
{ | { |
SSLCONTEXT_DEBUG(cout << "Entering SSLContextRep::~SSLContextRep()\n";) |
PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()"); |
| |
free(_certPath); | free(_certPath); |
SSL_CTX_free(_SSLContext); | SSL_CTX_free(_SSLContext); |
| |
SSLCONTEXT_DEBUG(cout << "Leaving SSLContextRep::~SSLContextRep()\n";) |
PEG_METHOD_EXIT(); |
} | } |
| |
SSL_CTX * SSLContextRep::getContext() const | SSL_CTX * SSLContextRep::getContext() const |