📄 tlsconnection.cxx
字号:
#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>#endifusing namespace resip;#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORTTlsConnection::TlsConnection( Transport* transport, const Tuple& tuple, Socket fd, Security* security, bool server, Data domain, SecurityTypes::SSLType sslType , Compression &compression) : Connection(transport,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::TlsStateTlsConnection::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; mFailureReason = TransportFailure::Failure; 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; ensureWritable(); #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; } } if (bytesRead <= 0) { int err = SSL_get_error(mSsl,bytesRead); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: case SSL_ERROR_NONE: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -