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

   1 kumpf 1.1 //%/////////////////////////////////////////////////////////////////////////////
   2           //
   3 kumpf 1.2 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
   4 kumpf 1.1 // The Open Group, Tivoli Systems
   5           //
   6           // Permission is hereby granted, free of charge, to any person obtaining a copy
   7 kumpf 1.2 // of this software and associated documentation files (the "Software"), to
   8           // deal in the Software without restriction, including without limitation the
   9           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10 kumpf 1.1 // sell copies of the Software, and to permit persons to whom the Software is
  11           // furnished to do so, subject to the following conditions:
  12           // 
  13 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  14 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  15           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  16 kumpf 1.2 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  17           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  19 kumpf 1.1 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  20           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21           //
  22           //==============================================================================
  23           //
  24           // Author: Markus Mueller (sedgewick_de@yahoo.de)
  25           //
  26 kumpf 1.9 // Modified By: Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
  27           //              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
  28 kumpf 1.15 //              Sushma Fernandes,
  29            //                  Hewlett-Packard Company (sushma_fernandes@hp.com)
  30 kumpf 1.1  //
  31            //%/////////////////////////////////////////////////////////////////////////////
  32            
  33            #ifdef PEGASUS_HAS_SSL
  34 mday  1.19 #define OPENSSL_NO_KRB5 1
  35 kumpf 1.1  #include <openssl/err.h>
  36            #include <openssl/ssl.h>
  37            #include <openssl/rand.h>
  38            #else
  39            #define SSL_CTX void
  40            #endif // end of PEGASUS_HAS_SSL
  41            #include <Pegasus/Common/Destroyer.h>
  42            #include <Pegasus/Common/Socket.h>
  43            #include <Pegasus/Common/Tracer.h>
  44 kumpf 1.14 #include <Pegasus/Common/FileSystem.h>
  45 kumpf 1.16 #include <time.h>
  46 humberto 1.18 #include <Pegasus/Common/MessageLoader.h> //l10n
  47 kumpf    1.1  
  48               #include "SSLContext.h"
  49               #include "SSLContextRep.h"
  50               
  51 kumpf    1.16 typedef struct Timestamp 
  52               {
  53                   char year[4];
  54                   char month[2];
  55                   char day[2];
  56                   char hour[2];
  57                   char minutes[2];
  58                   char seconds[2];
  59                   char dot;
  60                   char microSeconds[6];
  61                   char plusOrMinus;
  62                   char utcOffset[3];
  63                   char padding[3];
  64               } Timestamp_t;
  65               
  66 kumpf    1.1  PEGASUS_USING_STD;
  67               
  68               PEGASUS_NAMESPACE_BEGIN
  69               
  70               //
  71               // use the following definitions only if SSL is available
  72               // 
  73 kumpf    1.3  #ifdef PEGASUS_HAS_SSL
  74 kumpf    1.1  
  75               //
  76               // certificate handling routine
  77               //
  78               
  79 kumpf    1.9  // ATTN-RK-20020905: This global variable is unsafe with multiple SSL contexts
  80               SSLCertificateVerifyFunction* verify_certificate;
  81 kumpf    1.1  
  82 kumpf    1.15 // Mutex for SSL locks.
  83               Mutex* SSLContextRep::_sslLocks = 0;
  84               
  85               // Mutex for _countRep.
  86               Mutex SSLContextRep::_countRepMutex;
  87               
  88               // Initialise _count for SSLContextRep objects.
  89               int SSLContextRep::_countRep = 0;
  90               
  91 kumpf    1.16 
  92               //
  93               // Convert ASN1_UTCTIME to CIMDateTime
  94               //
  95               CIMDateTime getDateTime(const ASN1_UTCTIME *utcTime)
  96               {
  97                   struct tm time;
  98                   int offset;
  99                   Timestamp_t timeStamp;
 100                   char tempString[80];
 101                   char plusOrMinus = '+';
 102               
 103                   memset(&time, '\0', sizeof(time));
 104               
 105               #define g2(p) ( ( (p)[0] - '0' ) * 10 + (p)[1] - '0' )
 106               
 107                   time.tm_year = g2(utcTime->data);
 108               
 109                   if(time.tm_year < 50)
 110                   {
 111                       time.tm_year += 100;
 112 kumpf    1.16     }
 113                   time.tm_mon = g2(utcTime->data + 2) - 1;
 114                   time.tm_mday = g2(utcTime->data + 4);
 115                   time.tm_hour = g2(utcTime->data + 6);
 116                   time.tm_min = g2(utcTime->data + 8);
 117                   time.tm_sec = g2(utcTime->data + 10);
 118               
 119                   if(utcTime->data[12] == 'Z')
 120                   {
 121                       offset = 0;
 122                   }
 123                   else
 124                   {
 125                       offset = g2(utcTime->data + 13) * 60 + g2(utcTime->data + 15);
 126                       if(utcTime->data[12] == '-')
 127                       {
 128                           plusOrMinus = '-';
 129                       }
 130                   }
 131               #undef g2
 132               
 133 kumpf    1.16     int year = 1900;
 134                   memset((void *)&timeStamp, 0, sizeof(Timestamp_t));
 135               
 136                   // Format the date.
 137                   sprintf((char *) &timeStamp,"%04d%02d%02d%02d%02d%02d.%06d%04d",
 138                           year + time.tm_year,
 139                           time.tm_mon + 1,  
 140                           time.tm_mday,
 141                           time.tm_hour,
 142                           time.tm_min,
 143                           time.tm_sec,
 144                           0,
 145                           offset);
 146               
 147                   timeStamp.plusOrMinus = plusOrMinus;
 148               
 149                   CIMDateTime dateTime;
 150               
 151                   dateTime.clear();
 152                   strcpy(tempString, (char *)&timeStamp);
 153                   dateTime.set(tempString);
 154 kumpf    1.16 
 155                   return (dateTime);
 156               }
 157               
 158               //
 159               // Callback function that is called by the OpenSSL library. This function
 160               // extracts X509 certficate information and pass that on to client application
 161               // callback function.
 162               //
 163               int prepareForCallback(int preVerifyOk, X509_STORE_CTX *ctx)
 164 kumpf    1.1  {
 165 kumpf    1.3      PEG_METHOD_ENTER(TRC_SSL, "prepareForCallback()");
 166 kumpf    1.1  
 167                   char   buf[256];
 168 kumpf    1.16     X509   *currentCert;
 169                   int    verifyError = X509_V_OK;
 170 kumpf    1.1  
 171 kumpf    1.16     //
 172                   // get the current certificate
 173                   //
 174                   currentCert = X509_STORE_CTX_get_current_cert(ctx);
 175 kumpf    1.1  
 176 kumpf    1.16     //
 177                   // get the default verification error code
 178                   //
 179                   int errorCode = X509_STORE_CTX_get_error(ctx);
 180               
 181                   //
 182                   // get the depth of certificate chain
 183                   //
 184                   int depth = X509_STORE_CTX_get_error_depth(ctx);
 185 kumpf    1.1  
 186                   //FUTURE: Not sure what to do with these...?
 187                   //ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
 188                   //mydata = SSL_get_ex_data(ssl, mydata_index);
 189               
 190 kumpf    1.16     //
 191                   // get the version on the certificate
 192                   //
 193                   long version = X509_get_version(currentCert);
 194 kumpf    1.1  
 195 kumpf    1.16     //
 196                   // get the serial number of the certificate
 197                   //
 198                   long serialNumber = ASN1_INTEGER_get(X509_get_serialNumber(currentCert));
 199               
 200                   //
 201                   // get the validity of the certificate
 202                   //
 203                   CIMDateTime notBefore = getDateTime(X509_get_notBefore(currentCert));
 204               
 205                   CIMDateTime notAfter = getDateTime(X509_get_notAfter(currentCert));
 206               
 207                   //
 208                   // get the subject name on the certificate
 209                   //
 210                   X509_NAME_oneline(X509_get_subject_name(currentCert), buf, 256);
 211                   String subjectName = String(buf);
 212               
 213                   //
 214                   // get the default verification error string 
 215                   //
 216 kumpf    1.16     String errorStr = String(X509_verify_cert_error_string(errorCode));
 217 kumpf    1.1  
 218 kumpf    1.16     //
 219                   // log the error string if the default verification was failed
 220                   //
 221                   if (!preVerifyOk)
 222 kumpf    1.1      {
 223 kumpf    1.3          PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, 
 224 kumpf    1.16             "---> SSL: certificate default verification error: " + errorStr);
 225 kumpf    1.1      }
 226               
 227 kumpf    1.16     //
 228                   // get the issuer name on the certificate
 229                   //
 230                   if (!preVerifyOk && (errorCode == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
 231 kumpf    1.1      {
 232                       X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
 233                   }
 234                   else
 235                   {
 236 kumpf    1.16         X509_NAME_oneline(X509_get_issuer_name(currentCert), buf, 256);
 237 kumpf    1.1      }
 238 kumpf    1.16     String issuerName = String(buf);
 239 kumpf    1.1  
 240                   //
 241 kumpf    1.16     // Call the verify_certificate() application callback
 242 kumpf    1.1      //
 243 kumpf    1.16     SSLCertificateInfo certInfo(subjectName, issuerName, version, serialNumber,
 244                       notBefore, notAfter, depth, errorCode, errorStr, preVerifyOk);
 245 kumpf    1.1  
 246                   if (verify_certificate(certInfo))
 247                   {
 248 kumpf    1.16         verifyError = X509_V_OK;
 249                       preVerifyOk = 1;
 250                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 251                           "--> SSL: verify_certificate() returned X509_V_OK");
 252                   }
 253                   else
 254                   {
 255                       verifyError = certInfo.getErrorCode();
 256                       preVerifyOk = 0;
 257                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 258                           "--> SSL: verify_certificate() returned error %d", verifyError);
 259 kumpf    1.1      }
 260               
 261 kumpf    1.16     //
 262                   // Reset the error. It is logically not required to reset the error code, but
 263                   // openSSL code does not take just the return value on a failed certificate
 264                   // verification.
 265                   //
 266                   X509_STORE_CTX_set_error(ctx, verifyError);
 267               
 268 kumpf    1.1      PEG_METHOD_EXIT();
 269 kumpf    1.16 
 270                   return(preVerifyOk);
 271 kumpf    1.1  }
 272               
 273 kumpf    1.15 //
 274               // Implement OpenSSL locking callback.
 275               //
 276               void pegasus_locking_callback( int 		mode, 
 277                                              int 		type, 
 278                                              const char* 	file, 
 279                                              int 		line)
 280               {
 281                   // Check whether the mode is lock or unlock.
 282               
 283                   if ( mode & CRYPTO_LOCK )
 284                   {
 285                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 286                               "Now locking for %d", pegasus_thread_self());
 287                       SSLContextRep::_sslLocks[type].lock( pegasus_thread_self() );
 288                   }
 289                   else
 290                   {
 291                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 292                               "Now unlocking for %d", pegasus_thread_self());
 293                       SSLContextRep::_sslLocks[type].unlock( );
 294 kumpf    1.15     }
 295               }
 296               
 297               //
 298               // Initialize OpenSSL Locking and id callbacks.
 299               //
 300               void SSLContextRep::init_ssl()
 301               {
 302                    // Allocate Memory for _sslLocks. SSL locks needs to be able to handle
 303                    // up to CRYPTO_num_locks() different mutex locks.
 304                    PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 305                          "Initialized SSL callback.");
 306               
 307                    _sslLocks= new Mutex[CRYPTO_num_locks()];
 308               
 309                    // Set the ID callback. The ID callback returns a thread ID.
 310               
 311                    CRYPTO_set_id_callback((unsigned long (*)())pegasus_thread_self);
 312               
 313                    // Set the locking callback to pegasus_locking_callback.
 314               
 315 kumpf    1.15      CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))pegasus_locking_callback);
 316               
 317               }
 318               
 319               // Free OpenSSL Locking and id callbacks.
 320               void SSLContextRep::free_ssl()
 321               {
 322                   // Cleanup _sslLocks and set locking & id callback to NULL.
 323               
 324                   CRYPTO_set_locking_callback(NULL);
 325                   CRYPTO_set_id_callback     (NULL);
 326                   PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 327                            "Freed SSL callback.");
 328               
 329                   delete []_sslLocks;
 330               }
 331               
 332 kumpf    1.1  
 333               //
 334               // SSL context area
 335               //
 336               // For the OSs that don't have /dev/random device file,
 337               // must enable PEGASUS_SSL_RANDOMFILE flag.
 338               //
 339 kumpf    1.16 SSLContextRep::SSLContextRep(const String& trustPath,
 340                                      const String& certPath,
 341                                      const String& keyPath,
 342 kumpf    1.9                         SSLCertificateVerifyFunction* verifyCert,
 343 kumpf    1.13                        const String& randomFile)
 344 kumpf    1.1  {
 345 kumpf    1.3      PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
 346 kumpf    1.1  
 347 kumpf    1.16     _trustPath = trustPath.getCString();
 348               
 349 kumpf    1.7      _certPath = certPath.getCString();
 350 kumpf    1.1  
 351 kumpf    1.16     _keyPath = keyPath.getCString();
 352 kumpf    1.14 
 353 kumpf    1.1      verify_certificate = verifyCert;
 354               
 355 kumpf    1.15 
 356                   // Initialiaze SSL callbacks and increment the SSLContextRep object _counter.
 357                   _countRepMutex.lock(pegasus_thread_self());
 358               
 359                   try
 360                   {
 361                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 362                               "Value of Countrep in constructor %d", _countRep);
 363                       if ( _countRep == 0 )
 364                       {
 365                           init_ssl();
 366               
 367                           //
 368                           // load SSL library
 369                           //
 370                           Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 371                               "Before calling SSL_load_error_strings %d", pegasus_thread_self());
 372               
 373                           SSL_load_error_strings();
 374               
 375                           Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 376 kumpf    1.15                 "After calling SSL_load_error_strings %d", pegasus_thread_self());
 377               
 378                           Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 379                               "Before calling SSL_library_init %d", pegasus_thread_self());
 380               
 381                           SSL_library_init();
 382               
 383                           Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 384                               "After calling SSL_library_init %d", pegasus_thread_self());
 385               
 386                       } 
 387                   }
 388                   catch(...)
 389                   {
 390                       _countRepMutex.unlock();
 391                       throw;
 392                   }
 393                   _countRep++;
 394                   _countRepMutex.unlock();
 395 kumpf    1.1  
 396 kumpf    1.14     _randomInit(randomFile);
 397 kumpf    1.1  
 398 kumpf    1.9      _sslContext = _makeSSLContext();
 399               
 400                   PEG_METHOD_EXIT();
 401               }
 402               
 403               SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep)
 404               {
 405                   PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
 406               
 407 kumpf    1.16     _trustPath = sslContextRep._trustPath;
 408 kumpf    1.9      _certPath = sslContextRep._certPath;
 409 kumpf    1.16     _keyPath = sslContextRep._keyPath;
 410 kumpf    1.9      // ATTN: verify_certificate is set implicitly in global variable
 411                   _randomFile = sslContextRep._randomFile;
 412 kumpf    1.15 
 413                   // Initialiaze SSL callbacks and increment the SSLContextRep object _counter.
 414                   _countRepMutex.lock(pegasus_thread_self());
 415                   try
 416                   {
 417                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 418                            "Value of Countrep in copy constructor %d", _countRep);
 419                       if ( _countRep == 0 )
 420                       {
 421                           init_ssl();
 422                       } 
 423                   }
 424                   catch(...)
 425                   {
 426                       _countRepMutex.unlock();
 427                       throw;
 428                   }
 429                   _countRep++;
 430                   _countRepMutex.unlock();
 431               
 432 kumpf    1.9      _sslContext = _makeSSLContext();
 433                   PEG_METHOD_EXIT();
 434               }
 435 kumpf    1.11 
 436 kumpf    1.9  //
 437               // Destructor
 438               //
 439               
 440               SSLContextRep::~SSLContextRep()
 441               {
 442                   PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()");
 443               
 444                   SSL_CTX_free(_sslContext);
 445               
 446 kumpf    1.15     // Decrement the SSLContextRep object _counter.
 447                   _countRepMutex.lock(pegasus_thread_self());
 448                   _countRep--;
 449                   // Free SSL locks if no instances of SSLContextRep exist.
 450                   try
 451                   {
 452                       Tracer::trace(TRC_SSL, Tracer::LEVEL4,
 453                               "Value of Countrep in destructor %d", _countRep);
 454                       if ( _countRep == 0 )
 455                       {
 456                           free_ssl();
 457                       }
 458                   }
 459                   catch(...)
 460                   {
 461                       _countRepMutex.unlock();
 462                       throw;
 463                   }
 464                   _countRepMutex.unlock();
 465 kumpf    1.9      PEG_METHOD_EXIT();
 466               }
 467               
 468 kumpf    1.14 //
 469               // initialize OpenSSL's PRNG
 470               //
 471               void SSLContextRep::_randomInit(const String& randomFile)
 472               {
 473                   PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_randomInit()");
 474               
 475                   Boolean ret;
 476                   int retVal = 0;
 477               
 478 kumpf    1.15     const int DEV_RANDOM_BYTES = 64;	        /* how many bytes to read */
 479 kumpf    1.14     const String devRandom = "/dev/random";     /* random device name */
 480                   const String devUrandom = "/dev/urandom";   /* pseudo-random device name */
 481               
 482               #ifdef PEGASUS_SSL_DEVRANDOM
 483               
 484                   if ( FileSystem::exists(devRandom) )
 485                   {
 486                       while ( RAND_status() == 0 )
 487                       {
 488                           //
 489 kumpf    1.15             // Always attempt to seed from good entropy sources, first
 490 kumpf    1.14             // try /dev/random
 491                           //
 492                           retVal = RAND_load_file(devRandom.getCString(), DEV_RANDOM_BYTES);
 493 kumpf    1.15             if (retVal <= 0)
 494 kumpf    1.14             {
 495                               break;
 496                           }
 497                       }
 498                   }
 499               
 500                   if ( FileSystem::exists(devUrandom) )
 501                   {
 502                       while ( RAND_status() == 0 )
 503                       {
 504                           //
 505                           // If there isn't /dev/random try /dev/urandom
 506                           //
 507                           retVal = RAND_load_file(devUrandom.getCString(), DEV_RANDOM_BYTES);
 508 kumpf    1.15             if (retVal <= 0)
 509 kumpf    1.14             {
 510                               break;
 511                           }
 512                       }
 513                   }
 514               #endif  /* PEGASUS_SSL_DEVRANDOM */
 515               
 516               
 517               #ifdef PEGASUS_SSL_RANDOMFILE
 518                   if ( RAND_status() == 0 )
 519                   {
 520                       //
 521                       // Initialise OpenSSL random number generator.
 522                       //
 523                       if ( randomFile == String::EMPTY )
 524                       {
 525                           PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 526                               "Random seed file is required.");
 527                           PEG_METHOD_EXIT();
 528 humberto 1.18             //l10n
 529                           //throw( SSLException("Random seed file required"));
 530                           MessageLoaderParms parms("Common.SSLContext.RANDOM_SEED_FILE_REQUIRED",
 531                           						 "Random seed file required");
 532                           throw( SSLException(parms));						 
 533 kumpf    1.14         }
 534               
 535                       //
 536                       // Try the given random seed file
 537                       //
 538                       ret = FileSystem::exists(randomFile);
 539                       if( ret )
 540                       {
 541 kumpf    1.15             retVal = RAND_load_file(randomFile.getCString(), -1); 
 542 kumpf    1.14             if ( retVal < 0 )
 543                           {
 544                               PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 545                                   "Not enough seed data in seed file: " + randomFile);
 546                               PEG_METHOD_EXIT();
 547 humberto 1.18                 //l10n
 548 humberto 1.22 		// do not put in $0 in default message, but pass in filename for bundle message
 549 humberto 1.18                 //throw( SSLException("Not enough seed data in random seed file."));
 550                               MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA_IN_FILE",
 551 humberto 1.21             						     "Not enough seed data in random seed file.",
 552                           						     randomFile);
 553 humberto 1.18             	throw( SSLException(parms));
 554 kumpf    1.14             }
 555                       }
 556 kumpf    1.16         else
 557                       {
 558                           PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 559                               "seed file - " + randomFile + " does not exist.");
 560                           PEG_METHOD_EXIT();
 561 humberto 1.18             //l10n
 562                           //throw( SSLException("Seed file '" + randomFile + "' does not exist."));
 563                           MessageLoaderParms parms("Common.SSLContext.SEED_FILE_DOES_NOT_EXIST",
 564                           						 "Seed file '$0' does not exist.",
 565                           						 randomFile);
 566                           throw( SSLException(parms));
 567 kumpf    1.16         }
 568 kumpf    1.14 
 569                       if ( RAND_status() == 0 )
 570                       {
 571                           //
 572                           // Try to do more seeding
 573                           //
 574                           long seedNumber;
 575                           srandom((unsigned int)time(NULL)); // Initialize
 576                           seedNumber = random();
 577                           RAND_seed((unsigned char *) &seedNumber, sizeof(seedNumber));
 578               
 579                           int  seedRet = RAND_status();
 580                           if ( seedRet == 0 )
 581                           {
 582                               PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 583 kumpf    1.15                     "Not enough seed data in random seed file, RAND_status = " +
 584                                   seedRet);
 585 kumpf    1.14                 PEG_METHOD_EXIT();
 586 humberto 1.22                 //l10n 485
 587               		// do not put in $0 in default message, but pass in filename for bundle message
 588 humberto 1.18                 //throw( SSLException("Not enough seed data in random seed file."));
 589                               MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA_IN_FILE",
 590 humberto 1.22             						     "Not enough seed data in random seed file.",
 591                           						     randomFile);
 592 humberto 1.18             	throw( SSLException(parms));
 593 kumpf    1.14             }
 594                       }
 595                   }
 596               #endif  /* PEGASUS_SSL_RANDOMFILE */
 597               
 598                   int  seedRet = RAND_status();
 599                   if ( seedRet == 0 )
 600                   {
 601                       PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 602                           "Not enough seed data , RAND_status = " + seedRet );
 603                       PEG_METHOD_EXIT();
 604 humberto 1.18         //l10n
 605                       //throw( SSLException("Not enough seed data."));
 606                       MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA",
 607                           					 "Not enough seed data.");
 608                       throw( SSLException(parms));
 609 kumpf    1.14     }
 610               
 611                   PEG_METHOD_EXIT();
 612               }
 613               
 614 kumpf    1.9  SSL_CTX * SSLContextRep::_makeSSLContext()
 615               {
 616                   PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()");
 617               
 618                   SSL_CTX * sslContext = 0;
 619               
 620 kumpf    1.1      //
 621                   // create SSL Context Area
 622                   //
 623               
 624 kumpf    1.9      if (!( sslContext = SSL_CTX_new(SSLv23_method()) ))
 625 kumpf    1.3      {
 626                       PEG_METHOD_EXIT();
 627 humberto 1.18         //l10n
 628                       //throw( SSLException("Could not get SSL CTX"));
 629                       MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET",
 630 humberto 1.20             					 "Could not get SSL CTX");
 631 humberto 1.18         throw( SSLException(parms));
 632 kumpf    1.3      }
 633               
 634 kumpf    1.14 #ifdef PEGASUS_SSL_WEAKENCRYPTION
 635 humberto 1.18     if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40))){
 636                   	//l10n
 637                       //throw( SSLException("Could not set the cipher list"));
 638                       MessageLoaderParms parms("Common.SSLContext.COULD_NOT_SET_CIPHER_LIST",
 639                           					 "Could not set the cipher list");
 640                       throw( SSLException(parms));
 641                   }
 642 kumpf    1.3  #endif
 643 kumpf    1.1  
 644                   //
 645                   // set overall SSL Context flags
 646                   //
 647               
 648 kumpf    1.9      SSL_CTX_set_quiet_shutdown(sslContext, 1);
 649                   SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);
 650                   SSL_CTX_set_options(sslContext,SSL_OP_ALL);
 651 kumpf    1.14     SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
 652 kumpf    1.1  
 653 kumpf    1.10     if (verify_certificate != NULL)
 654 kumpf    1.1      {
 655 kumpf    1.9          SSL_CTX_set_verify(sslContext, 
 656 kumpf    1.16              SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback);
 657 kumpf    1.1      }
 658 kumpf    1.14     else
 659                   {
 660 kumpf    1.15 	SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
 661 kumpf    1.14     }
 662 kumpf    1.1  
 663                   //
 664 kumpf    1.14     // Check if there is CA certificate file specified. If specified,
 665                   // load the certificates from the file in to the CA trust store.
 666                   //
 667 kumpf    1.16     if (strncmp(_trustPath, "", 1) != 0)
 668 kumpf    1.14     {
 669                       //
 670                       // load certificates in to trust store
 671                       //
 672               
 673 kumpf    1.16         if ((!SSL_CTX_load_verify_locations(sslContext, _trustPath, NULL)) ||
 674 kumpf    1.14             (!SSL_CTX_set_default_verify_paths(sslContext)))
 675                       {
 676                           PEG_METHOD_EXIT();
 677 humberto 1.18             //l10n
 678                           //throw( SSLException("Could not load certificates in to trust store."));
 679                           MessageLoaderParms parms("Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES",
 680                           					     "Could not load certificates in to trust store.");
 681                           throw( SSLException(parms));
 682 kumpf    1.14         }
 683                   }
 684               
 685 kumpf    1.17     Boolean keyLoaded = false;
 686 kumpf    1.1      //
 687 kumpf    1.16     // Check if there is a certificate file (file containing server 
 688                   // certificate) specified. If specified, validate and load the 
 689                   // certificate.
 690 kumpf    1.14     //
 691 kumpf    1.16     if (strncmp(_certPath, "", 1) != 0)
 692 kumpf    1.14     {
 693                       //
 694                       // load the specified server certificates
 695                       //
 696 kumpf    1.1  
 697 kumpf    1.14         if (SSL_CTX_use_certificate_file(sslContext,
 698 kumpf    1.16             _certPath, SSL_FILETYPE_PEM) <=0)
 699 kumpf    1.14         {
 700                           PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 701 kumpf    1.16                 "---> SSL: no certificate found in " + String(_certPath));
 702 kumpf    1.14             PEG_METHOD_EXIT();
 703 humberto 1.18             //l10n
 704                           //throw( SSLException("Could not get server certificate."));
 705                           MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_SERVER_CERTIFICATE",
 706                           					     "Could not get server certificate.");
 707                           throw( SSLException(parms));
 708 kumpf    1.14         }
 709 kumpf    1.17 
 710 kumpf    1.16         //
 711                       // If there is no key file (file containing server
 712 kumpf    1.17         // private key) specified or the specified file does not exist,
 713                       // then try loading the key from the certificate file.
 714 kumpf    1.16         //
 715 kumpf    1.17         if ( strncmp(_keyPath, "", 1) == 0  ||
 716                          !FileSystem::exists(String(_keyPath)) )
 717 kumpf    1.16         {
 718 kumpf    1.17             PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
 719                               "---> SSL: loading key from" + String(_certPath));
 720 kumpf    1.16             //
 721                           // load the private key and check for validity
 722                           //
 723                           if (!_verifyPrivateKey(sslContext, _certPath))
 724                           {
 725                               PEG_METHOD_EXIT();
 726 humberto 1.18                 //l10n
 727                               //throw( SSLException("Could not get private key."));
 728                               MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY",
 729                           					         "Could not get private key.");
 730                           	throw( SSLException(parms));
 731 kumpf    1.16             }
 732 kumpf    1.17             keyLoaded = true;
 733 kumpf    1.16         }
 734                   }
 735 kumpf    1.14 
 736 kumpf    1.16     //
 737 kumpf    1.17     // Check if there is a key file (file containing server
 738                   // private key) specified and the key was not already loaded.
 739                   // If specified, validate and load the key.
 740 kumpf    1.16     //
 741 kumpf    1.17     if (strncmp(_keyPath, "", 1) != 0 && !keyLoaded)
 742 kumpf    1.16     {
 743 kumpf    1.17         PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
 744                           "---> SSL: loading key from" + String(_keyPath));
 745 kumpf    1.14         //
 746                       // load given private key and check for validity
 747                       //
 748 kumpf    1.16         if (!_verifyPrivateKey(sslContext, _keyPath))
 749 kumpf    1.14         {
 750                           PEG_METHOD_EXIT();
 751 humberto 1.18             //l10n
 752                           //throw( SSLException("Could not get private key."));
 753                           MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY",
 754                           					         "Could not get private key.");
 755                           throw( SSLException(parms));
 756 kumpf    1.14         }
 757 kumpf    1.17         keyLoaded = true;
 758 kumpf    1.14     }
 759               
 760                   PEG_METHOD_EXIT();
 761                   return sslContext;
 762               }
 763               
 764 kumpf    1.16 Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx, const char *keyPath)
 765 kumpf    1.14 {
 766                   PEG_METHOD_ENTER(TRC_SSL, "_verifyPrivateKey()");
 767               
 768 kumpf    1.16     if (SSL_CTX_use_PrivateKey_file(ctx, keyPath, SSL_FILETYPE_PEM) <= 0)
 769 kumpf    1.3      {
 770 kumpf    1.14         PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 771 kumpf    1.16             "---> SSL: no private key found in " + String(keyPath));
 772 kumpf    1.3          PEG_METHOD_EXIT();
 773 kumpf    1.14         return false;
 774                   }
 775               
 776                   if (!SSL_CTX_check_private_key(ctx))
 777                   {
 778                       PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
 779                           "---> SSL: Private and public key do not match");
 780                       PEG_METHOD_EXIT();
 781                       return false;
 782 kumpf    1.3      }
 783 kumpf    1.1  
 784 kumpf    1.3      PEG_METHOD_EXIT();
 785 kumpf    1.14     return true;
 786 kumpf    1.1  }
 787               
 788               SSL_CTX * SSLContextRep::getContext() const 
 789               {
 790 kumpf    1.9      return _sslContext;
 791 kumpf    1.1  }
 792               #else 
 793               
 794               //
 795 kumpf    1.9  // these definitions are used if ssl is not available
 796 kumpf    1.1  //
 797               
 798 kumpf    1.16 SSLContextRep::SSLContextRep(const String& trustPath,
 799                                      const String& certPath,
 800                                      const String& keyPath,
 801 kumpf    1.9                         SSLCertificateVerifyFunction* verifyCert,
 802 kumpf    1.13                        const String& randomFile) {}
 803 kumpf    1.1  
 804 kumpf    1.9  SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep) {}
 805               
 806 kumpf    1.1  SSLContextRep::~SSLContextRep() {}
 807               
 808 kumpf    1.9  SSL_CTX * SSLContextRep::_makeSSLContext() { return 0; }
 809               
 810 kumpf    1.14 Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx,
 811 kumpf    1.16                                          const char *keyPath) { return false; }
 812 kumpf    1.14 
 813 kumpf    1.9  SSL_CTX * SSLContextRep::getContext() const { return 0; }
 814 kumpf    1.15 
 815               void SSLContextRep::init_ssl() {}
 816               
 817               void SSLContextRep::free_ssl() {}
 818 kumpf    1.1  
 819               #endif // end of PEGASUS_HAS_SSL
 820               
 821               ///////////////////////////////////////////////////////////////////////////////
 822               //
 823               // SSLContext
 824               //
 825               ///////////////////////////////////////////////////////////////////////////////
 826               
 827               
 828               SSLContext::SSLContext(
 829 kumpf    1.16     const String& trustPath,
 830 kumpf    1.9      SSLCertificateVerifyFunction* verifyCert,
 831 kumpf    1.13     const String& randomFile)
 832               {
 833 kumpf    1.16     _rep = new SSLContextRep(trustPath, String::EMPTY, String::EMPTY,  verifyCert, randomFile);
 834 kumpf    1.13 }
 835               
 836               #ifndef PEGASUS_REMOVE_DEPRECATED
 837               SSLContext::SSLContext(
 838                   const String& certPath,
 839                   SSLCertificateVerifyFunction* verifyCert,
 840 kumpf    1.1      const String& randomFile,
 841 kumpf    1.6      Boolean isCIMClient)
 842 kumpf    1.1  {
 843 kumpf    1.16     _rep = new SSLContextRep(certPath, String::EMPTY, String::EMPTY,  verifyCert, randomFile);
 844               }
 845               
 846               SSLContext::SSLContext(
 847                   const String& certPath,
 848                   const String& certKeyPath,
 849                   SSLCertificateVerifyFunction* verifyCert,
 850                   const String& randomFile)
 851               {
 852                   _rep = new SSLContextRep(certPath, certKeyPath, String::EMPTY, verifyCert, randomFile);
 853 kumpf    1.1  }
 854 kumpf    1.13 #endif
 855 kumpf    1.1  
 856 kumpf    1.14 SSLContext::SSLContext(
 857 kumpf    1.16     const String& trustPath,
 858 kumpf    1.14     const String& certPath,
 859 kumpf    1.16     const String& keyPath,
 860 kumpf    1.14     SSLCertificateVerifyFunction* verifyCert,
 861                   const String& randomFile)
 862               {
 863 kumpf    1.16     _rep = new SSLContextRep(trustPath, certPath, keyPath, verifyCert, randomFile);
 864 kumpf    1.14 }
 865               
 866 kumpf    1.9  SSLContext::SSLContext(const SSLContext& sslContext)
 867               {
 868                   _rep = new SSLContextRep(*sslContext._rep);
 869 kumpf    1.12 }
 870               
 871               // Dummy constructor made private to disallow default construction
 872               SSLContext::SSLContext()
 873               {
 874 kumpf    1.9  }
 875               
 876 kumpf    1.1  SSLContext::~SSLContext() 
 877               {
 878                   delete _rep;
 879               }
 880               
 881               
 882               ///////////////////////////////////////////////////////////////////////////////
 883               //
 884 kumpf    1.9  // SSLCertificateInfo
 885 kumpf    1.1  //
 886               ///////////////////////////////////////////////////////////////////////////////
 887 kumpf    1.16 //
 888               // Certificate validation result codes.
 889               //
 890               const int    SSLCertificateInfo::V_OK                                       = 0;
 891               
 892               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_GET_ISSUER_CERT            = 2;
 893               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_GET_CRL                    = 3;
 894               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE     = 4;
 895               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE      = 5;
 896               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY   = 6;
 897               const int    SSLCertificateInfo::V_ERR_CERT_SIGNATURE_FAILURE               = 7;
 898               const int    SSLCertificateInfo::V_ERR_CRL_SIGNATURE_FAILURE                = 8;
 899               const int    SSLCertificateInfo::V_ERR_CERT_NOT_YET_VALID                   = 9;
 900               const int    SSLCertificateInfo::V_ERR_CERT_HAS_EXPIRED                     = 10;
 901               const int    SSLCertificateInfo::V_ERR_CRL_NOT_YET_VALID                    = 11;
 902               const int    SSLCertificateInfo::V_ERR_CRL_HAS_EXPIRED                      = 12;
 903               const int    SSLCertificateInfo::V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD       = 13;
 904               const int    SSLCertificateInfo::V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD        = 14;
 905               const int    SSLCertificateInfo::V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD       = 15;
 906               const int    SSLCertificateInfo::V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD       = 16;
 907               const int    SSLCertificateInfo::V_ERR_OUT_OF_MEM                           = 17;
 908 kumpf    1.16 const int    SSLCertificateInfo::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT          = 18;
 909               const int    SSLCertificateInfo::V_ERR_SELF_SIGNED_CERT_IN_CHAIN            = 19;
 910               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY    = 20;
 911               const int    SSLCertificateInfo::V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE      = 21;
 912               const int    SSLCertificateInfo::V_ERR_CERT_CHAIN_TOO_LONG                  = 22;
 913               const int    SSLCertificateInfo::V_ERR_CERT_REVOKED                         = 23;
 914               const int    SSLCertificateInfo::V_ERR_INVALID_CA                           = 24;
 915               const int    SSLCertificateInfo::V_ERR_PATH_LENGTH_EXCEEDED                 = 25;
 916               const int    SSLCertificateInfo::V_ERR_INVALID_PURPOSE                      = 26;
 917               const int    SSLCertificateInfo::V_ERR_CERT_UNTRUSTED                       = 27;
 918               const int    SSLCertificateInfo::V_ERR_CERT_REJECTED                        = 28;
 919               const int    SSLCertificateInfo::V_ERR_SUBJECT_ISSUER_MISMATCH              = 29;
 920               const int    SSLCertificateInfo::V_ERR_AKID_SKID_MISMATCH                   = 30;
 921               const int    SSLCertificateInfo::V_ERR_AKID_ISSUER_SERIAL_MISMATCH          = 31;
 922               const int    SSLCertificateInfo::V_ERR_KEYUSAGE_NO_CERTSIGN                 = 32;
 923               
 924               const int    SSLCertificateInfo::V_ERR_APPLICATION_VERIFICATION             = 50;
 925 kumpf    1.1  
 926 kumpf    1.9  class SSLCertificateInfoRep
 927               {
 928               public:
 929 kumpf    1.16     String    subjectName;
 930                   String    issuerName;
 931                   Uint32    depth;
 932                   Uint32    errorCode;
 933                   Uint32    respCode;
 934                   String    errorString;
 935                   Uint32    versionNumber;
 936                   long      serialNumber;
 937                   CIMDateTime    notBefore;
 938                   CIMDateTime    notAfter;
 939 kumpf    1.9  };
 940               
 941               
 942               SSLCertificateInfo::SSLCertificateInfo(
 943 kumpf    1.1      const String subjectName,
 944                   const String issuerName,
 945                   const int errorDepth,
 946 kumpf    1.14     const int errorCode,
 947                   const int respCode)
 948 kumpf    1.1  {
 949 kumpf    1.9      _rep = new SSLCertificateInfoRep();
 950                   _rep->subjectName = subjectName;
 951                   _rep->issuerName = issuerName;
 952 kumpf    1.16     _rep->versionNumber = 0;
 953                   _rep->serialNumber = 0;
 954                   _rep->notBefore = CIMDateTime(String::EMPTY);
 955                   _rep->notAfter = CIMDateTime(String::EMPTY);
 956                   _rep->depth = errorDepth;
 957 kumpf    1.9      _rep->errorCode = errorCode;
 958 kumpf    1.16     _rep->errorString = String::EMPTY;
 959                   _rep->respCode = respCode;
 960               }
 961               
 962               SSLCertificateInfo::SSLCertificateInfo(
 963                   const String subjectName,
 964                   const String issuerName,
 965                   const Uint32 versionNumber,
 966                   const long serialNumber,
 967                   const CIMDateTime notBefore,
 968                   const CIMDateTime notAfter,
 969                   const Uint32 depth,
 970                   const Uint32 errorCode,
 971                   const String errorString,
 972                   const Uint32 respCode)
 973               {
 974                   _rep = new SSLCertificateInfoRep();
 975                   _rep->subjectName = subjectName;
 976                   _rep->issuerName = issuerName;
 977                   _rep->versionNumber = versionNumber;
 978                   _rep->serialNumber = serialNumber;
 979 kumpf    1.16     _rep->notBefore = notBefore;
 980                   _rep->notAfter = notAfter;
 981                   _rep->depth = depth;
 982                   _rep->errorCode = errorCode;
 983                   _rep->errorString = errorString;
 984 kumpf    1.14     _rep->respCode = respCode;
 985 kumpf    1.9  }
 986               
 987               SSLCertificateInfo::SSLCertificateInfo(
 988                   const SSLCertificateInfo& certificateInfo)
 989               {
 990                   _rep = new SSLCertificateInfoRep();
 991                   _rep->subjectName = certificateInfo._rep->subjectName;
 992                   _rep->issuerName = certificateInfo._rep->issuerName;
 993 kumpf    1.16     _rep->versionNumber = certificateInfo._rep->versionNumber;
 994                   _rep->serialNumber = certificateInfo._rep->serialNumber;
 995                   _rep->notBefore = certificateInfo._rep->notBefore;
 996                   _rep->notAfter = certificateInfo._rep->notAfter;
 997                   _rep->depth = certificateInfo._rep->depth;
 998 kumpf    1.9      _rep->errorCode = certificateInfo._rep->errorCode;
 999 kumpf    1.16     _rep->errorString = certificateInfo._rep->errorString;
1000 kumpf    1.9      _rep->respCode = certificateInfo._rep->respCode;
1001 kumpf    1.11 }
1002               
1003               // Dummy constructor made private to disallow default construction
1004               SSLCertificateInfo::SSLCertificateInfo()
1005               {
1006 kumpf    1.1  }
1007               
1008 kumpf    1.9  SSLCertificateInfo::~SSLCertificateInfo()
1009 kumpf    1.1  {
1010 kumpf    1.9      delete _rep;
1011 kumpf    1.1  }
1012               
1013 kumpf    1.9  String SSLCertificateInfo::getSubjectName() const
1014 kumpf    1.1  {
1015 kumpf    1.9      return (_rep->subjectName);
1016 kumpf    1.1  }
1017               
1018 kumpf    1.9  String SSLCertificateInfo::getIssuerName() const
1019 kumpf    1.1  {
1020 kumpf    1.9      return (_rep->issuerName);
1021 kumpf    1.1  }
1022               
1023 kumpf    1.16 Uint32 SSLCertificateInfo::getVersionNumber() const
1024               {
1025                   return (_rep->versionNumber);
1026               }
1027               
1028               long SSLCertificateInfo::getSerialNumber() const
1029 kumpf    1.1  {
1030 kumpf    1.16     return (_rep->serialNumber);
1031 kumpf    1.1  }
1032               
1033 kumpf    1.16 CIMDateTime SSLCertificateInfo::getNotBefore() const
1034               {
1035                   return (_rep->notBefore);
1036               }
1037               
1038               CIMDateTime SSLCertificateInfo::getNotAfter() const 
1039               {
1040                   return (_rep->notAfter);
1041               }
1042               
1043               Uint32 SSLCertificateInfo::getErrorDepth() const
1044               {
1045                   return (_rep->depth);
1046               }
1047               
1048               Uint32 SSLCertificateInfo::getErrorCode()  const
1049 kumpf    1.1  {
1050 kumpf    1.9      return (_rep->errorCode);
1051 kumpf    1.14 }
1052               
1053 kumpf    1.16 void SSLCertificateInfo::setErrorCode(const int errorCode)
1054               {
1055                   _rep->errorCode = errorCode;
1056               }
1057               
1058               String SSLCertificateInfo::getErrorString() const
1059               {
1060                   return (_rep->errorString);
1061               }
1062               
1063               Uint32 SSLCertificateInfo::getResponseCode()  const
1064 kumpf    1.14 {
1065                   return (_rep->respCode);
1066 kumpf    1.1  }
1067               
1068 kumpf    1.9  void SSLCertificateInfo::setResponseCode(const int respCode)
1069 kumpf    1.1  {
1070 kumpf    1.9      _rep->respCode = respCode;
1071 kumpf    1.1  }
1072               
1073               PEGASUS_NAMESPACE_END
1074               

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2