(file) Return to SSLContext.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/SSLContext.cpp between version 1.13 and 1.14

version 1.13, 2002/09/20 00:29:19 version 1.14, 2003/03/13 18:41:47
Line 38 
Line 38 
 #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/Common/FileSystem.h>
  
 #include "SSLContext.h" #include "SSLContext.h"
 #include "SSLContextRep.h" #include "SSLContextRep.h"
Line 46 
Line 47 
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
 // switch on if 'server needs certified client'  
 //#define CLIENT_CERTIFY  
   
 // //
 // use the following definitions only if SSL is available // use the following definitions only if SSL is available
 // //
Line 61 
Line 59 
 // ATTN-RK-20020905: This global variable is unsafe with multiple SSL contexts // ATTN-RK-20020905: This global variable is unsafe with multiple SSL contexts
 SSLCertificateVerifyFunction* verify_certificate; SSLCertificateVerifyFunction* verify_certificate;
  
 static int cert_verify(SSL_CTX *ctx, const char *cert_file, const char *key_file)  
 {  
     PEG_METHOD_ENTER(TRC_SSL, "cert_verify()");  
   
     if (cert_file != NULL)  
     {  
         if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <=0)  
         {  
             PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,  
                 "---> SSL: no certificate found in " + String(cert_file));  
             PEG_METHOD_EXIT();  
             return 0;  
         }  
         if (key_file == NULL) key_file=cert_file;  
         if (SSL_CTX_use_PrivateKey_file(ctx,key_file,SSL_FILETYPE_PEM) <= 0)  
         {  
             PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,  
                 "---> SSL: no private key found in " + String(key_file));  
             PEG_METHOD_EXIT();  
             return 0;  
         }  
   
         if (!SSL_CTX_check_private_key(ctx))  
         {  
             PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,  
                 "---> SSL: Private and public key do not match");  
             PEG_METHOD_EXIT();  
             return 0;  
         }  
     }  
     PEG_METHOD_EXIT();  
     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, "prepareForCallback()");     PEG_METHOD_ENTER(TRC_SSL, "prepareForCallback()");
Line 152 
Line 116 
     //     //
     // Call the verify_certificate() callback     // Call the verify_certificate() callback
     //     //
     SSLCertificateInfo certInfo(subjectName, issuerName, depth, err);      SSLCertificateInfo certInfo(subjectName, issuerName, depth, err, preverifyOk);
  
     if (verify_certificate(certInfo))     if (verify_certificate(certInfo))
     {     {
         preverifyOk = 1;         preverifyOk = 1;
     }     }
  
     //delete certInfo;  
   
     // ATTN-NB-03-05102002: Overriding the default verification result, may  
     // need to be changed to make it more generic.  
     if (preverifyOk)  
     {  
         X509_STORE_CTX_set_error(ctx, verify_error);  
     }  
   
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
     return(preverifyOk);     return(preverifyOk);
 } }
Line 180 
Line 135 
 // must enable PEGASUS_SSL_RANDOMFILE flag. // must enable PEGASUS_SSL_RANDOMFILE flag.
 // //
 SSLContextRep::SSLContextRep(const String& certPath, SSLContextRep::SSLContextRep(const String& certPath,
                          const String& certKeyPath,
                        SSLCertificateVerifyFunction* verifyCert,                        SSLCertificateVerifyFunction* verifyCert,
                        const String& randomFile)                        const String& randomFile)
 { {
Line 187 
Line 143 
  
     _certPath = certPath.getCString();     _certPath = certPath.getCString();
  
       _certKeyPath = certKeyPath.getCString();
   
     verify_certificate = verifyCert;     verify_certificate = verifyCert;
  
     //     //
Line 195 
Line 153 
     SSL_load_error_strings();     SSL_load_error_strings();
     SSL_library_init();     SSL_library_init();
  
 #ifdef PEGASUS_SSL_RANDOMFILE      _randomInit(randomFile);
   
       _sslContext = _makeSSLContext();
   
       PEG_METHOD_EXIT();
   }
   
   SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep)
   {
       PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
   
       _certPath = sslContextRep._certPath;
       _certKeyPath = sslContextRep._certKeyPath;
       // ATTN: verify_certificate is set implicitly in global variable
       _randomFile = sslContextRep._randomFile;
       _sslContext = _makeSSLContext();
   
       PEG_METHOD_EXIT();
   }
  
     //     //
     // Initialise OpenSSL 0.9.5 random number generator.  // Destructor
   //
   
   SSLContextRep::~SSLContextRep()
   {
       PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()");
   
       SSL_CTX_free(_sslContext);
   
       PEG_METHOD_EXIT();
   }
   
   //
   // initialize OpenSSL's PRNG
   //
   void SSLContextRep::_randomInit(const String& randomFile)
   {
       PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_randomInit()");
   
       Boolean ret;
       int retVal = 0;
       int seeded = 0;
   
       const int DEV_RANDOM_BYTES = 64;            /* how many bytes to read */
       const String devRandom = "/dev/random";     /* random device name */
       const String devUrandom = "/dev/urandom";   /* pseudo-random device name */
   
   #ifdef PEGASUS_SSL_DEVRANDOM
   
       if ( FileSystem::exists(devRandom) )
       {
           while ( RAND_status() == 0 )
           {
               //
               // Always attempt to seed from good entropy sources, first
               // try /dev/random
               //
               retVal = RAND_load_file(devRandom.getCString(), DEV_RANDOM_BYTES);
               if (retVal < 0)
               {
                   break;
               }
           }
       }
   
       if ( FileSystem::exists(devUrandom) )
       {
           while ( RAND_status() == 0 )
           {
               //
               // If there isn't /dev/random try /dev/urandom
               //
               retVal = RAND_load_file(devUrandom.getCString(), DEV_RANDOM_BYTES);
               if (retVal < 0)
               {
                   break;
               }
           }
       }
   #endif  /* PEGASUS_SSL_DEVRANDOM */
   
   
   #ifdef PEGASUS_SSL_RANDOMFILE
       if ( RAND_status() == 0 )
       {
           //
           // Initialise OpenSSL random number generator.
     //     //
     if ( randomFile == String::EMPTY )     if ( randomFile == String::EMPTY )
     {     {
               PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
                   "Random seed file is required.");
         PEG_METHOD_EXIT();         PEG_METHOD_EXIT();
         throw( SSLException("Random seed file required"));         throw( SSLException("Random seed file required"));
     }     }
  
     int ret = RAND_load_file(randomFile.getCString(), -1);          //
     if ( ret < 0 )          // Try the given random seed file
           //
           ret = FileSystem::exists(randomFile);
           if( ret )
           {
               retVal = RAND_load_file(randomFile.getCString(), -1);
               if ( retVal < 0 )
     {     {
                   PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
                       "Not enough seed data in seed file: " + randomFile);
         PEG_METHOD_EXIT();         PEG_METHOD_EXIT();
         throw( SSLException("RAND_load_file - failed"));                  throw( SSLException("Not enough seed data in random seed file."));
               }
     }     }
  
           if ( RAND_status() == 0 )
           {
     //     //
     // Will do more seeding              // Try to do more seeding
     //     //
     long seedNumber;     long seedNumber;
     srandom((unsigned int)time(NULL)); // Initialize     srandom((unsigned int)time(NULL)); // Initialize
Line 225 
Line 280 
     if ( seedRet == 0 )     if ( seedRet == 0 )
     {     {
         PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,         PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
             "Not enough data , RAND_status = " + seedRet );                      "Not enough seed data in random seed file, RAND_status = " +
                       seedRet );
         PEG_METHOD_EXIT();         PEG_METHOD_EXIT();
         throw( SSLException("RAND_seed - Not enough seed data "));                  throw( SSLException("Not enough seed data in random seed file."));
               }
     }     }
   
 #endif // end of PEGASUS_SSL_RANDOMFILE  
   
     _sslContext = _makeSSLContext();  
   
     PEG_METHOD_EXIT();  
 } }
   #endif  /* PEGASUS_SSL_RANDOMFILE */
  
 SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep)      int  seedRet = RAND_status();
       if ( seedRet == 0 )
 { {
     PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");          PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
               "Not enough seed data , RAND_status = " + seedRet );
     _certPath = sslContextRep._certPath;  
     // ATTN: verify_certificate is set implicitly in global variable  
     _randomFile = sslContextRep._randomFile;  
     _sslContext = _makeSSLContext();  
   
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
           throw( SSLException("Not enough seed data."));
 } }
  
 //  
 // Destructor  
 //  
   
 SSLContextRep::~SSLContextRep()  
 {  
     PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()");  
   
     SSL_CTX_free(_sslContext);  
   
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
 } }
  
Line 278 
Line 317 
         throw( SSLException("Could not get SSL CTX"));         throw( SSLException("Could not get SSL CTX"));
     }     }
  
 #ifdef PEGASUS_OS_HPUX  #ifdef PEGASUS_SSL_WEAKENCRYPTION
     if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40)))     if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40)))
         throw( SSLException("Could not set the cipher list"));         throw( SSLException("Could not set the cipher list"));
 #endif #endif
Line 290 
Line 329 
     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_options(sslContext,SSL_OP_ALL);     SSL_CTX_set_options(sslContext,SSL_OP_ALL);
       SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
  
 #ifdef CLIENT_CERTIFY  
     SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,  
         prepareForCallback);  
 #else  
     if (verify_certificate != NULL)     if (verify_certificate != 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      else
       {
           SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
       }
  
     //     //
     // check certificate given to me      // Check if there is CA certificate file specified. If specified,
       // load the certificates from the file in to the CA trust store.
       //
       if (strncmp(_certPath, "", 1) != 0)
       {
           //
           // load certificates in to trust store
     //     //
  
     if (!cert_verify(sslContext, _certPath, _certPath))          if ((!SSL_CTX_load_verify_locations(sslContext, _certPath, NULL)) ||
               (!SSL_CTX_set_default_verify_paths(sslContext)))
     {     {
         PEG_METHOD_EXIT();         PEG_METHOD_EXIT();
         throw( SSLException("Could not get certificate and/or private key"));              throw( SSLException("Could not load certificates in to trust store."));
           }
       }
   
       //
       // Check if there is a certificate key file (file containing server
       // certificate and private key) specified. If specified, validate the
       // certificate and the private key, and load them.
       //
       if (strncmp(_certKeyPath, "", 1) != 0)
       {
           //
           // load the specified server certificates
           //
   
           if (SSL_CTX_use_certificate_file(sslContext,
               _certKeyPath, SSL_FILETYPE_PEM) <=0)
           {
               PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
                   "---> SSL: no certificate found in " + String(_certKeyPath));
               PEG_METHOD_EXIT();
               throw( SSLException("Could not get server certificate."));
           }
   
           //
           // load given private key and check for validity
           //
   
           if (!_verifyPrivateKey(sslContext, _certKeyPath))
           {
               PEG_METHOD_EXIT();
               throw( SSLException("Could not get private key."));
           }
     }     }
  
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
     return sslContext;     return sslContext;
 } }
  
   Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx, const char *keyFilePath)
   {
       PEG_METHOD_ENTER(TRC_SSL, "_verifyPrivateKey()");
   
       if (SSL_CTX_use_PrivateKey_file(ctx, keyFilePath, SSL_FILETYPE_PEM) <= 0)
       {
           PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
               "---> SSL: no private key found in " + String(keyFilePath));
           PEG_METHOD_EXIT();
           return false;
       }
   
       if (!SSL_CTX_check_private_key(ctx))
       {
           PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
               "---> SSL: Private and public key do not match");
           PEG_METHOD_EXIT();
           return false;
       }
   
       PEG_METHOD_EXIT();
       return true;
   }
   
 SSL_CTX * SSLContextRep::getContext() const SSL_CTX * SSLContextRep::getContext() const
 { {
     return _sslContext;     return _sslContext;
Line 327 
Line 429 
 // //
  
 SSLContextRep::SSLContextRep(const String& certPath, SSLContextRep::SSLContextRep(const String& certPath,
                          const String& certKeyPath,
                        SSLCertificateVerifyFunction* verifyCert,                        SSLCertificateVerifyFunction* verifyCert,
                        const String& randomFile) {}                        const String& randomFile) {}
  
Line 336 
Line 439 
  
 SSL_CTX * SSLContextRep::_makeSSLContext() { return 0; } SSL_CTX * SSLContextRep::_makeSSLContext() { return 0; }
  
   Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx,
                                            const char *keyFilePath) { return false; }
   
 SSL_CTX * SSLContextRep::getContext() const { return 0; } SSL_CTX * SSLContextRep::getContext() const { return 0; }
  
 #endif // end of PEGASUS_HAS_SSL #endif // end of PEGASUS_HAS_SSL
Line 352 
Line 458 
     SSLCertificateVerifyFunction* verifyCert,     SSLCertificateVerifyFunction* verifyCert,
     const String& randomFile)     const String& randomFile)
 { {
     _rep = new SSLContextRep(certPath, verifyCert, randomFile);      _rep = new SSLContextRep(certPath, String::EMPTY, verifyCert, randomFile);
 } }
  
 #ifndef PEGASUS_REMOVE_DEPRECATED #ifndef PEGASUS_REMOVE_DEPRECATED
Line 362 
Line 468 
     const String& randomFile,     const String& randomFile,
     Boolean isCIMClient)     Boolean isCIMClient)
 { {
     _rep = new SSLContextRep(certPath, verifyCert, randomFile);      _rep = new SSLContextRep(certPath, String::EMPTY, verifyCert, randomFile);
 } }
 #endif #endif
  
   SSLContext::SSLContext(
       const String& certPath,
       const String& certKeyPath,
       SSLCertificateVerifyFunction* verifyCert,
       const String& randomFile)
   {
       _rep = new SSLContextRep(certPath, certKeyPath, verifyCert, randomFile);
   }
   
 SSLContext::SSLContext(const SSLContext& sslContext) SSLContext::SSLContext(const SSLContext& sslContext)
 { {
     _rep = new SSLContextRep(*sslContext._rep);     _rep = new SSLContextRep(*sslContext._rep);
Line 403 
Line 518 
     const String subjectName,     const String subjectName,
     const String issuerName,     const String issuerName,
     const int errorDepth,     const int errorDepth,
     const int errorCode)      const int errorCode,
       const int respCode)
 { {
     _rep = new SSLCertificateInfoRep();     _rep = new SSLCertificateInfoRep();
     _rep->subjectName = subjectName;     _rep->subjectName = subjectName;
     _rep->issuerName = issuerName;     _rep->issuerName = issuerName;
     _rep->errorDepth = errorDepth;     _rep->errorDepth = errorDepth;
     _rep->errorCode = errorCode;     _rep->errorCode = errorCode;
     _rep->respCode = 0;      _rep->respCode = respCode;
 } }
  
 SSLCertificateInfo::SSLCertificateInfo( SSLCertificateInfo::SSLCertificateInfo(
Line 454 
Line 570 
     return (_rep->errorCode);     return (_rep->errorCode);
 } }
  
   int SSLCertificateInfo::getResponseCode() const
   {
       return (_rep->respCode);
   }
   
 void SSLCertificateInfo::setResponseCode(const int respCode) void SSLCertificateInfo::setResponseCode(const int respCode)
 { {
     _rep->respCode = respCode;     _rep->respCode = respCode;


Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2