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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2