⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 security.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
      }
      BaseSecurity*  mutable_this = const_cast<BaseSecurity*>(this);
      mutable_this->addCertPEM(type, aor, certPEM, false);
   }
   catch (...)
   {
      return   false;
   }

   assert(  certs.find(aor) != certs.end() );
   
   return   true;
}


void
BaseSecurity::removeCert (PEMType type, const Data& aor)
{
   assert( !aor.empty() );
   X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);

   X509Map::iterator iter = certs.find(aor);
   if (iter != certs.end())
   {
      X509_free(iter->second);
      certs.erase(iter);

      onRemovePEM(aor, type);
   } 

   assert(  certs.find(aor) == certs.end() );
}


Data
BaseSecurity::getCertDER (PEMType type, const Data& key) const
{
   assert( !key.empty() );

   if (hasCert(type, key) == false)
   {
      ErrLog(<< "Could find certificate for '" << key << "'");
      throw BaseSecurity::Exception("Could not find certificate", __FILE__,__LINE__);
   }

   X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
   BaseSecurity::X509Map::iterator where = certs.find(key);
   if (where == certs.end())
   {
      // not supposed to happen,
      // hasCert() should have inserted a value into certs
      // or we should have throwed.
      assert(0);
   }

   //assert(0); // the code following this has no hope of working 
   
   X509* x = where->second;
   unsigned char* buffer=0;
   int len = i2d_X509(x, &buffer);

   // !kh!
   // Although len == 0 is not an error, I am not sure what quite to do.
   // Asserting for now.
   assert(len != 0);
   if(len < 0)
   {
      ErrLog(<< "Could encode certificate of '" << key << "' to DER form");
      throw BaseSecurity::Exception("Could encode certificate to DER form", __FILE__,__LINE__);
   }
   return   Data(Data::Take, (char*)buffer, len);
}


void 
BaseSecurity::addPrivateKeyPKEY(PEMType type, 
                                const Data& name, 
                                EVP_PKEY* pKey, 
                                bool write) const 
{ 
   PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? 
                                 mDomainPrivateKeys : mUserPrivateKeys);

   /*
   // make a copy of the the key 
   assert( EVP_PKEY_type(pKey->type) == EVP_PKEY_RSA );
   RSA* rsa = EVP_PKEY_get1_RSA(pKey);
   assert( rsa );
   EVP_PKEY* nKey = EVP_PKEY_new();
   assert( nKey );
   EVP_PKEY_set1_RSA(nKey, rsa);
   */
   
   //privateKeys.insert(std::make_pair(name, nKey));
   privateKeys.insert(std::make_pair(name, pKey));
      
   if (write)
   {
      // figure out a passPhrase to encrypt with 
      char* kstr=NULL;
      int klen=0;
      if (type != DomainPrivateKey)
      {
         PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name);
         if(iter != mUserPassPhrases.end())
         {
            kstr = (char*)iter->second.c_str(); 
            klen = iter->second.size();
         }
      }

      BIO *bio = BIO_new(BIO_s_mem());
      assert(bio);
      try
      {
         assert( EVP_des_ede3_cbc() );
         const EVP_CIPHER* cipher = EVP_des_ede3_cbc();
         if (kstr == NULL )
         {
            cipher = NULL;
         }
#if 0 // TODO - need to figure out what format to write in 
         int ret = PEM_write_bio_PrivateKey(bio, pKey, cipher, 
                                            (unsigned char*)kstr, klen,
                                            NULL, NULL);
#else
         int ret = PEM_write_bio_PKCS8PrivateKey(bio, pKey, cipher, 
                                                 kstr, klen,
                                                 NULL, NULL);
#endif
         assert(ret);
         
         BIO_flush(bio);
         char* p = 0;
         size_t len = BIO_get_mem_data(bio,&p);
         assert(p);
         assert(len);
         Data  pem(Data::Borrow, p, len);
         onWritePEM(name, type, pem );
      }
      catch(...)
      {
         BIO_free(bio);
         throw;
      }
      BIO_free(bio);
   }
}


void
BaseSecurity::addPrivateKeyDER( PEMType type,
                                const Data& name,
                                const Data& privateKeyDER,
                                bool write ) const
{
   assert( !name.empty() );
   assert( !privateKeyDER.empty() );

   char* passPhrase = 0;
   if (type != DomainPrivateKey)
   {
      PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name);
      if(iter != mUserPassPhrases.end())
      {
         passPhrase = const_cast<char*>(iter->second.c_str());
      }
   }
   
   BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyDER.c_str()), -1);
   if ( !in )
   {
      ErrLog(<< "Could create BIO buffer from '" << privateKeyDER << "'");
      throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
   }
   
   try
   {

      EVP_PKEY* privateKey;
      if (d2i_PKCS8PrivateKey_bio(in, &privateKey, 0, passPhrase) == 0)
      {
         ErrLog(<< "Could not read private key from <" << privateKeyDER << ">" );
         throw Exception("Could not read private key ", __FILE__,__LINE__);
      }
      
      addPrivateKeyPKEY(type,name,privateKey,write);
   }
   catch(...)
   {
      BIO_free(in);
      throw;
   }
   
   BIO_free(in);
}


void
BaseSecurity::addPrivateKeyPEM( PEMType type,
                                const Data& name,
                                const Data& privateKeyPEM,
                                bool write ) const 
{
   assert( !name.empty() );
   assert( !privateKeyPEM.empty() );

   BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyPEM.c_str()), -1);
   if ( !in )
   {
      ErrLog(<< "Could create BIO buffer from '" << privateKeyPEM << "'");
      throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
   }
   
   char* passPhrase = 0;
   try
   {
      if (type == UserPrivateKey)
      {
         PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name);
         if(iter != mUserPassPhrases.end())
         {
            passPhrase = const_cast<char*>(iter->second.c_str());
         }
      }
      
      EVP_PKEY* privateKey=0;
      if ( ( privateKey = PEM_read_bio_PrivateKey(in, NULL, 0, passPhrase)) == NULL)
      {
         ErrLog(<< "Could not read private key from <" << privateKeyPEM << ">" );
         throw Exception("Could not read private key ", __FILE__,__LINE__);
      }
      
      addPrivateKeyPKEY(type,name,privateKey,write);
   }
   catch(...)
   {
      BIO_free(in);
      throw;
   }

   BIO_free(in);
}


bool
BaseSecurity::hasPrivateKey( PEMType type,
                             const Data& key ) const
{
   assert( !key.empty() );

   PrivateKeyMap& privateKeys = (type == DomainPrivateKey 
                                 ? mDomainPrivateKeys : mUserPrivateKeys);

   PrivateKeyMap::const_iterator where = privateKeys.find(key);
   if (where != privateKeys.end())
   {
      return true;
   }
   
   Data privateKeyPEM;
   try
   {
      onReadPEM(key, type, privateKeyPEM);
      BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this);
      mutable_this->addPrivateKeyPEM(type, key, privateKeyPEM, false);
   }
   catch(...)
   {
      return   false;
   }

   return   true;
}


Data
BaseSecurity::getPrivateKeyPEM( PEMType type,
                                const Data& key) const
{
   assert( !key.empty() );

   if ( !hasPrivateKey(type, key) )
   {
      ErrLog(<< "Could find private key for '" << key << "'");
      throw Exception("Could not find private key", __FILE__,__LINE__);
   }

   PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);

   PrivateKeyMap::const_iterator where = privateKeys.find(key);
   char* p = 0;
   if (type != DomainPrivateKey)
   {
      PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
      if (iter != mUserPassPhrases.end())
      {
         p = const_cast<char*>(iter->second.c_str());
      }
   }

   assert(0); // TODO - following code has no hope of working 
    
   // !kh!
   // creates a read/write BIO buffer.
   BIO *out = BIO_new(BIO_s_mem());
   assert(out);
   EVP_PKEY* pk = where->second;
   assert(pk);

   // write pk to out using key phrase p, with no cipher.
   int ret = PEM_write_bio_PrivateKey(out, pk, 0, 0, 0, 0, p);  // paraters
                                                                // are in the wrong order
   assert(ret == 1);

   // get content in BIO buffer to our buffer.
   // hand our buffer to a Data object.
   BIO_flush(out);
   char* buf = 0;
   int len = BIO_get_mem_data(out, &buf);
   Data retVal(Data::Borrow, buf, len);

   BIO_free(out);

   return retVal;
}


Data
BaseSecurity::getPrivateKeyDER( PEMType type,
                                const Data& key) const
{
   assert( !key.empty() );

   if ( !hasPrivateKey(type, key) )
   {
      ErrLog(<< "Could find private key for '" << key << "'");
      throw Exception("Could not find private key", __FILE__,__LINE__);
   }

   PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);

   PrivateKeyMap::const_iterator where = privateKeys.find(key);
   char* p = 0;
   if (type != DomainPrivateKey)
   {
      PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
      if(iter != mUserPassPhrases.end())
      {
         p = const_cast<char*>(iter->second.c_str());
      }
   }

   assert(0); // TODO - following code has no hope of working 
    
   // !kh!
   // creates a read/write BIO buffer.
   BIO *out = BIO_new(BIO_s_mem());
   assert(out);
   EVP_PKEY* pk = where->second;
   assert(pk);

   // write pk to out using key phrase p, with no cipher.
   int ret = i2d_PKCS8PrivateKey_bio(out, pk, 0, 0, 0, 0, p);
   assert(ret == 1);

   // get content in BIO buffer to our buffer.
   // hand our buffer to a Data object.
   BIO_flush(out);
   char* buf = 0;
   int len = BIO_get_mem_data(out, &buf);
   Data retVal(Data::Borrow, buf, len);

   BIO_free(out);
   
   return retVal;
}


void
BaseSecurity::removePrivateKey(PEMType type, const Data& key)
{
   assert( !key.empty() );

   PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);

   assert( !key.empty() );
   PrivateKeyMap::iterator iter = privateKeys.find(key);
   if (iter != privateKeys.end())
   {
      EVP_PKEY_free(iter->second);
      privateKeys.erase(iter);

      onRemovePEM(key, type);
   }
}


Security::Exception::Exception(const Data& msg, const Data& file, const int line)
:  BaseException(msg,file,line)
{
}


BaseSecurity::BaseSecurity (const CipherList& cipherSuite) :
   mTlsCtx(0),
   mSslCtx(0),
   mRootTlsCerts(0),                    
   mRootSslCerts(0)
{ 
   DebugLog(<< "BaseSecurity::BaseSecurity");
   
   int ret;
   initialize(); 
   
   mRootTlsCerts = X509_STORE_new();
   mRootSslCerts = X509_STORE_new();
   assert(mRootTlsCerts && mRootSslCerts);

   mTlsCtx = SSL_CTX_new( TLSv1_method() );
   if (!mTlsCtx)
   {
      ErrLog(<< "SSL_CTX_new failed, dumping OpenSSL error stack:");
      while (ERR_peek_error())
      {
         char errBuf[120];
         ERR_error_string(ERR_get_error(), errBuf);
         ErrLog(<< "OpenSSL error stack: " << errBuf);
      }
   }
   assert(mTlsCtx);

   SSL_CTX_set_cert_store(mTlsCtx, mRootTlsCerts);
   SSL_CTX_set_verify(mTlsCtx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verifyCallback);
   ret = SSL_CTX_set_cipher_list(mTlsCtx, cipherSuite.cipherList().c_str());
   assert(ret);
   
   mSslCtx = SSL_CTX_new( SSLv23_method() );
   assert(mSslCtx);
   SSL_CTX_set_cert_store(mSslCtx, mRootSslCerts);
   SSL_CTX_set_verify(mSslCtx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verifyCallback);
   ret = SSL_CTX_set_cipher_list(mSslCtx,cipherSuite.cipherList().c_str());
   assert(ret);
}


template<class T, class Func> 
void clearMap(T& m, Func& clearFunc)
{
   for (typename T::iterator it = m.begin(); it != m.end(); it++)
   {
      clearFunc(it->second);
   }
   m.clear();
}
         
BaseSecurity::~BaseSecurity ()
{
   DebugLog(<< "BaseSecurity::~BaseSecurity");

   // cleanup certificates
   clearMap(mDomainCerts, X509_free);
   clearMap(mUserCerts, X509_free);

   // cleanup private keys
   clearMap(mDomainPrivateKeys, EVP_PKEY_free);
   clearMap(mUserPrivateKeys, EVP_PKEY_free);

/*
// !abr! This intentional memory leak appears to be unnecessary. Derek to verify.
// !dcm! - still crashses...I think if there were no certs to load. 

   // sailesh@counterpath.com : this code leaks memory but it's necessary on
   // mac and windows. if we don't have this code then SSL_CTX_new( TLSv1_method() )
   // returns NULL when BaseSecurity::BaseSecurity() is called the second time.
   X509_STORE_free(mRootTlsCerts);
   X509_STORE_free(mRootSslCerts);
*/

   // cleanup SSL_CTXes

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -