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

📄 tlsconnection.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 2 页
字号:
#if defined(HAVE_CONFIG_H)
#include "resip/stack/config.hxx"
#endif

#include "resip/stack/TlsConnection.hxx"
#include "resip/stack/Security.hxx"
#include "rutil/Logger.hxx"
#include "resip/stack/Uri.hxx"
#include "rutil/Socket.hxx"

#if defined(USE_SSL)
#include <openssl/e_os2.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/pkcs7.h>
#include <openssl/x509v3.h>
#include <openssl/ssl.h>
#endif

using namespace resip;

#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT

TlsConnection::TlsConnection( const Tuple& tuple, Socket fd, Security* security, 
                              bool server, Data domain,  SecurityTypes::SSLType sslType ,
                              Compression &compression) :
   Connection(tuple, fd, compression),
   mServer(server),
   mSecurity(security),
   mSslType( sslType ),
   mDomain(domain)
{
#if defined(USE_SSL)
   InfoLog (<< "Creating TLS connection for domain " 
            << mDomain 
            << " " << tuple 
            << " on " << fd);

   mSsl = NULL;
   mBio= NULL;
  
   if (mServer)
   {
      DebugLog( << "Trying to form TLS connection - acting as server" );
      if ( mDomain.empty() )
      {
         ErrLog(<< "Tranport was not created with a server domain so can not act as server" ); 
         throw Security::Exception("Trying to act as server but no domain specified",
                                   __FILE__,__LINE__);
      }
   }
   else
   {
      DebugLog( << "Trying to form TLS connection - acting as client" );
   }

   assert( mSecurity );
   SSL_CTX* ctx=NULL;
   if ( mSslType ==  SecurityTypes::SSLv23 )
   {
      ctx = mSecurity->getSslCtx();
   }
   else
   {
      ctx = mSecurity->getTlsCtx();
   }   
   assert(ctx);
   
   mSsl = SSL_new(ctx);
   assert(mSsl);

   if ( mServer )
   {
      assert( mSecurity );

      X509* cert = mSecurity->getDomainCert(mDomain); //mDomainCerts[mDomain];
      if (!cert)
      {
         ErrLog(<< "Don't have certificate for domain " << mDomain );
      }
      
      if( !SSL_use_certificate(mSsl, cert) )
      {
         throw Security::Exception("SSL_use_certificate failed",
                                   __FILE__,__LINE__);
      }
      
      EVP_PKEY* pKey = mSecurity->getDomainKey(mDomain); //mDomainPrivateKeys[mDomain];
      if (!pKey)
      {
         ErrLog(<< "Don't have private key for domain " << mDomain );
      }
      if ( !SSL_use_PrivateKey(mSsl, pKey) )
      {
         throw Security::Exception("SSL_use_PrivateKey failed.",
                                   __FILE__,__LINE__);
      }
   }
   
   mBio = BIO_new_socket(fd,0/*close flag*/);
   assert( mBio );
   
   SSL_set_bio( mSsl, mBio, mBio );

   mTlsState = mServer ? Accepting : Connecting;

#endif // USE_SSL   
}

TlsConnection::~TlsConnection()
{
#if defined(USE_SSL)
   SSL_shutdown(mSsl);
   SSL_free(mSsl);
#endif // USE_SSL   
}


const char*
TlsConnection::fromState(TlsConnection::TlsState s)
{
   switch(s)
   {
      case Handshaking: return "Handshaking"; break;
      case Accepting: return "Accepting"; break;
      case Broken: return "Broken"; break;
      case Connecting: return "Connecting"; break;
      case Up: return "Up"; break;
   }
   return "????";
}

TlsConnection::TlsState
TlsConnection::checkState()
{
#if defined(USE_SSL)
   //DebugLog(<<"state is " << fromTlsState(mTlsState));

   if (mTlsState == Up || mTlsState == Broken)
   {
      return mTlsState;
   }
   
   int ok=0;
   
   ERR_clear_error();
   
   if (mTlsState != Handshaking)
   {
      if (mTlsState == Accepting)
      {
         ok = SSL_accept(mSsl);
      }
      else
      {
         ok = SSL_connect(mSsl);
         //StackLog( << "TLS SSL_connect - state = " << fromTlsState(mTlsState) );
      }

      if ( ok <= 0 )
      {
         int err = SSL_get_error(mSsl,ok);
         char buf[256];
         ERR_error_string_n(err,buf,sizeof(buf));
//          StackLog( << "TLS error in " 
//                    << (char*)( (mTlsState == Accepting) ? (char*)"accept" : (char*)"connect" )
//                    << " ok=" << ok << " err=" << err << " " << buf );
          
         switch (err)
         {
            case SSL_ERROR_WANT_READ:
               //StackLog( << "TLS connection want read" );
               return mTlsState;
            case SSL_ERROR_WANT_WRITE:
               //StackLog( << "TLS connection want write" );
               return mTlsState;
            case SSL_ERROR_WANT_CONNECT:
               //StackLog( << "TLS connection want connect" );
               return mTlsState;
#if  ( OPENSSL_VERSION_NUMBER >= 0x0090702fL )
            case SSL_ERROR_WANT_ACCEPT:
               //StackLog( << "TLS connection want accept" );
               return mTlsState;
#endif
         }
	   
         ErrLog( << "TLS connection failed "
                 << "ok=" << ok << " err=" << err << " " << buf );
         
         switch (err)
         {
            case SSL_ERROR_NONE: 
               ErrLog( <<" (SSL Error none)" );
               break;
            case SSL_ERROR_SSL: 
               ErrLog( <<" (SSL Error ssl)" );
               break;
            case SSL_ERROR_WANT_READ: 
               ErrLog( <<" (SSL Error want read)" ); 
               break;
            case SSL_ERROR_WANT_WRITE: 
               ErrLog( <<" (SSL Error want write)" ); 
               break;
            case SSL_ERROR_WANT_X509_LOOKUP: 
               ErrLog( <<" (SSL Error want x509 lookup)" ); 
               break;
            case SSL_ERROR_SYSCALL: 
               ErrLog( <<" (SSL Error want syscall)" ); 
               ErrLog( <<"Error may be because trying ssl connection to tls server" ); 
               break;
            case SSL_ERROR_WANT_CONNECT: 
               ErrLog( <<" (SSL Error want connect)" ); 
               break;
#if ( OPENSSL_VERSION_NUMBER >= 0x0090702fL )
            case SSL_ERROR_WANT_ACCEPT: 
               ErrLog( <<" (SSL Error want accept)" ); 
               break;
#endif
         }
         while (true)
         {
            const char* file;
            int line;
            
            unsigned long code = ERR_get_error_line(&file,&line);
            if ( code == 0 )
            {
               break;
            }
            
            char buf[256];
            ERR_error_string_n(code,buf,sizeof(buf));
            ErrLog( << buf  );
            ErrLog( << "Error code = " 
                     << code << " file=" << file << " line=" << line );
         }
         
         mTlsState = Broken;
         mBio = 0;
         //.dcm. -- may not be correct
         mFailureReason = TransportFailure::CertValidationFailure;
         ErrLog (<< "Couldn't TLS connect");
         return mTlsState;
      }
      
      InfoLog( << "TLS connected" ); 
      mTlsState = Handshaking;
   }

   InfoLog( << "TLS handshake starting" ); 

   ok = SSL_do_handshake(mSsl);
      
   if ( ok <= 0 )
   {
      int err = SSL_get_error(mSsl,ok);
      char buf[256];
      ERR_error_string_n(err,buf,sizeof(buf));
         
      switch (err)
      {
         case SSL_ERROR_WANT_READ:
            StackLog( << "TLS handshake want read" );
            return mTlsState;
         case SSL_ERROR_WANT_WRITE:
            StackLog( << "TLS handshake want write" );
            return mTlsState;
         default:
            ErrLog( << "TLS handshake failed "
                    << "ok=" << ok << " err=" << err << " " << buf );
            mBio = NULL;
            mTlsState = Broken;
            mFailureReason = TransportFailure::CertValidationFailure;         
            return mTlsState;
      }
   }

   // force peer name to get checked and perhaps cert loaded
   computePeerName();

   //post-connection verification: check that certificate name matches domain name
   if (!mServer)
   {
      bool matches = false;
      for(std::list<Data>::iterator it = mPeerNames.begin(); it != mPeerNames.end(); it++)
      {
         if(isEqualNoCase(*it, who().getTargetDomain()))
         {
             matches=true;
             break;
         }
      }
      if(!matches)
      {
         mTlsState = Broken;
         mBio = 0;
         ErrLog (<< "Certificate name mismatch: trying to connect to <" 
                 << who().getTargetDomain()
                 << "> remote cert domain(s) are <" 
                 << getPeerNamesData() << ">" );
         mFailureReason = TransportFailure::CertNameMismatch;         
         return mTlsState;
      }
   }

   InfoLog( << "TLS handshake done for peer " << getPeerNamesData()); 
   mTlsState = Up;

#endif // USE_SSL   
   return mTlsState;
}

      
int 
TlsConnection::read(char* buf, int count )
{
#if defined(USE_SSL)
   assert( mSsl ); 
   assert( buf );

   switch(checkState())
   {
      case Broken:
         return -1;
         break;
      case Up:
         break;
      default:
         return 0;
         break;
   }

   if (!mBio)
   {
      DebugLog( << "Got TLS read bad bio  " );
      return 0;
   }
      
   if ( !isGood() )
   {
      return -1;
   }

   int bytesRead = SSL_read(mSsl,buf,count);
   StackLog(<< "SSL_read returned " << bytesRead << " bytes [" << Data(Data::Borrow, buf, bytesRead) << "]");

   if (bytesRead > 0 && SSL_pending(mSsl))
   {
      int restBytes = SSL_pending(mSsl);
      char* buffer = getWriteBufferForExtraBytes(restBytes);
      StackLog(<< "reading remaining buffered bytes");
      restBytes = SSL_read(mSsl, buffer, SSL_pending(mSsl));
      StackLog(<< "SSL_read returned  " << restBytes << " bytes [" << Data(Data::Borrow, buffer, restBytes) << "]");

      if (restBytes>0)
      {
         bytesRead += restBytes;
      }
      else
      {
         bytesRead = restBytes;
      }

⌨️ 快捷键说明

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