diff --git a/Csocket.cc b/Csocket.cc index d342b69..dd8f269 100644 --- a/Csocket.cc +++ b/Csocket.cc @@ -1044,6 +1044,9 @@ void Csock::Copy( const Csock & cCopy ) m_shostname = cCopy.m_shostname; m_sbuffer = cCopy.m_sbuffer; m_sSockName = cCopy.m_sSockName; + m_pUseKey = cCopy.m_pUseKey; + m_pUseCert = cCopy.m_pUseCert; + m_pUseDHParam = cCopy.m_pUseDHParam; m_sKeyFile = cCopy.m_sKeyFile; m_sDHParamFile = cCopy.m_sDHParamFile; m_sPemFile = cCopy.m_sPemFile; @@ -1570,20 +1573,32 @@ bool Csock::SSLClientSetup() SSL_CTX_set_default_verify_paths( m_ssl_ctx ); - if( !m_sPemFile.empty() ) - { - // are we sending a client cerificate ? - SSL_CTX_set_default_passwd_cb( m_ssl_ctx, _PemPassCB ); - SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, ( void * )this ); + // are we sending a client cerificate ? + SSL_CTX_set_default_passwd_cb( m_ssl_ctx, _PemPassCB ); + SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, ( void * )this ); - // - // set up the CTX + // set up the CTX + if( m_pUseCert && m_pUseKey ) + { + if( SSL_CTX_use_certificate( m_ssl_ctx, m_pUseCert ) <= 0 ) + { + CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); + SSLErrors( __FILE__, __LINE__ ); + } + if( SSL_CTX_use_PrivateKey( m_ssl_ctx, m_pUseKey ) <= 0 ) + { + CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); + SSLErrors( __FILE__, __LINE__ ); + } + } + else if( !m_sPemFile.empty() ) + { if( SSL_CTX_use_certificate_file( m_ssl_ctx, m_sPemFile.c_str() , SSL_FILETYPE_PEM ) <= 0 ) { CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); SSLErrors( __FILE__, __LINE__ ); } - CS_STRING privKeyFile = m_sKeyFile.empty() ? m_sPemFile : m_sKeyFile; + CS_STRING privKeyFile = m_sKeyFile.empty() ? m_sPemFile : m_sKeyFile; if( SSL_CTX_use_PrivateKey_file( m_ssl_ctx, privKeyFile.c_str(), SSL_FILETYPE_PEM ) <= 0 ) { CS_DEBUG( "Error with SSLKey file [" << privKeyFile << "]" ); @@ -1704,64 +1719,98 @@ SSL_CTX * Csock::SetupServerCTX() SSL_CTX_set_default_passwd_cb( pCTX, _PemPassCB ); SSL_CTX_set_default_passwd_cb_userdata( pCTX, ( void * )this ); - if( m_sPemFile.empty() || access( m_sPemFile.c_str(), R_OK ) != 0 ) + if( !m_pUseCert ) { - CS_DEBUG( "Empty, missing, or bad pemfile ... [" << m_sPemFile << "]" ); - SSL_CTX_free( pCTX ); - return( NULL ); + if( m_sPemFile.empty() || access( m_sPemFile.c_str(), R_OK ) != 0 ) + { + CS_DEBUG( "Empty, missing, or bad pemfile ... [" << m_sPemFile << "]" ); + SSL_CTX_free( pCTX ); + return( NULL ); + } + else + { + // + // set up the CTX + if( SSL_CTX_use_certificate_chain_file( pCTX, m_sPemFile.c_str() ) <= 0 ) + { + CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); + SSLErrors( __FILE__, __LINE__ ); + SSL_CTX_free( pCTX ); + return( NULL ); + } + } } - - if( ! m_sKeyFile.empty() && access( m_sKeyFile.c_str(), R_OK ) != 0 ) + else { - CS_DEBUG( "Bad keyfile ... [" << m_sKeyFile << "]" ); - SSL_CTX_free( pCTX ); - return( NULL ); + if( SSL_CTX_use_certificate( pCTX, m_pUseCert ) <= 0 ) + { + CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); + SSLErrors( __FILE__, __LINE__ ); + } } - // - // set up the CTX - if( SSL_CTX_use_certificate_chain_file( pCTX, m_sPemFile.c_str() ) <= 0 ) + + if( !m_pUseKey ) { - CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); - SSLErrors( __FILE__, __LINE__ ); - SSL_CTX_free( pCTX ); - return( NULL ); + if( ! m_sKeyFile.empty() && access( m_sKeyFile.c_str(), R_OK ) != 0 ) + { + CS_DEBUG( "Bad keyfile ... [" << m_sKeyFile << "]" ); + SSL_CTX_free( pCTX ); + return( NULL ); + } + else + { + CS_STRING privKeyFile = m_sKeyFile.empty() ? m_sPemFile : m_sKeyFile; + if( SSL_CTX_use_PrivateKey_file( pCTX, privKeyFile.c_str(), SSL_FILETYPE_PEM ) <= 0 ) + { + CS_DEBUG( "Error with SSLKey file [" << privKeyFile << "]" ); + SSLErrors( __FILE__, __LINE__ ); + SSL_CTX_free( pCTX ); + return( NULL ); + } + } } - - CS_STRING privKeyFile = m_sKeyFile.empty() ? m_sPemFile : m_sKeyFile; - if( SSL_CTX_use_PrivateKey_file( pCTX, privKeyFile.c_str(), SSL_FILETYPE_PEM ) <= 0 ) + else { - CS_DEBUG( "Error with SSLKey file [" << privKeyFile << "]" ); - SSLErrors( __FILE__, __LINE__ ); - SSL_CTX_free( pCTX ); - return( NULL ); + if( SSL_CTX_use_PrivateKey( pCTX, m_pUseKey ) <= 0 ) + { + CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" ); + SSLErrors( __FILE__, __LINE__ ); + } } // check to see if this pem file contains a DH structure for use with DH key exchange // https://github.com/znc/znc/pull/46 - CS_STRING DHParamFile = m_sDHParamFile.empty() ? m_sPemFile : m_sDHParamFile; - FILE *dhParamsFile = fopen( DHParamFile.c_str(), "r" ); - if( !dhParamsFile ) + DH * pDHParam; + if( !m_pUseDHParam ) { - CS_DEBUG( "Error with DHParam file [" << DHParamFile << "]" ); - SSL_CTX_free( pCTX ); - return( NULL ); + CS_STRING sDHParamFile = m_sDHParamFile.empty() ? m_sPemFile : m_sDHParamFile; + FILE *pDHParamsFile = fopen( sDHParamFile.c_str(), "r" ); + if( !pDHParamsFile ) + { + CS_DEBUG( "Error with DHParam file [" << sDHParamFile << "]" ); + SSL_CTX_free( pCTX ); + return( NULL ); + } + pDHParam = PEM_read_DHparams( pDHParamsFile, NULL, NULL, NULL ); + fclose( pDHParamsFile ); } - - DH * dhParams = PEM_read_DHparams( dhParamsFile, NULL, NULL, NULL ); - fclose( dhParamsFile ); - if( dhParams ) + else + { + pDHParam = m_pUseDHParam; + } + if( pDHParam ) { SSL_CTX_set_options( pCTX, SSL_OP_SINGLE_DH_USE ); - if( !SSL_CTX_set_tmp_dh( pCTX, dhParams ) ) + if( !SSL_CTX_set_tmp_dh( pCTX, pDHParam ) ) { CS_DEBUG( "Error setting ephemeral DH parameters from [" << m_sPemFile << "]" ); SSLErrors( __FILE__, __LINE__ ); - DH_free( dhParams ); + DH_free( pDHParam ); SSL_CTX_free( pCTX ); return( NULL ); } - DH_free( dhParams ); + DH_free( pDHParam ); } else { @@ -2549,6 +2598,15 @@ void Csock::SetSSL( bool b ) { m_bUseSSL = b; } void Csock::SetCipher( const CS_STRING & sCipher ) { m_sCipherType = sCipher; } const CS_STRING & Csock::GetCipher() const { return( m_sCipherType ); } +void Csock::SetUseKey( EVP_PKEY * sKeyRaw ) { m_pUseKey = sKeyRaw; } +EVP_PKEY * Csock::GetUseKey() const { return( m_pUseKey ); } + +void Csock::SetUseCert( X509 * sCertRaw ) { m_pUseCert = sCertRaw; } +X509 * Csock::GetUseCert() const { return( m_pUseCert ); } + +void Csock::SetUseDHParam( DH * sDHParamRaw ) { m_pUseDHParam = sDHParamRaw; } +DH * Csock::GetUseDHParam() const { return( m_pUseDHParam ); } + void Csock::SetDHParamLocation( const CS_STRING & sDHParamFile ) { m_sDHParamFile = sDHParamFile; } const CS_STRING & Csock::GetDHParamLocation() const { return( m_sDHParamFile ); } @@ -3069,6 +3127,9 @@ void Csock::Init( const CS_STRING & sHostname, uint16_t uPort, int iTimeout ) m_uDisableProtocols = 0; m_bNoSSLCompression = false; m_bSSLCipherServerPreference = false; + m_pUseCert = NULL; + m_pUseKey = NULL; + m_pUseDHParam = NULL; #endif /* HAVE_LIBSSL */ m_iTcount = 0; m_iReadSock = CS_INVALID_SOCK; @@ -4044,6 +4105,12 @@ void CSocketManager::Select( std::map & mpeSocks ) NewpcSock->SetDHParamLocation( pcSock->GetDHParamLocation() ); NewpcSock->SetKeyLocation( pcSock->GetKeyLocation() ); NewpcSock->SetPemLocation( pcSock->GetPemLocation() ); + NewpcSock->SetPemPass( pcSock->GetPemPass() ); + + NewpcSock->SetUseCert( pcSock->GetUseCert() ); + NewpcSock->SetUseKey( pcSock->GetUseKey() ); + NewpcSock->SetUseDHParam( pcSock->GetUseDHParam() ); + NewpcSock->SetPemPass( pcSock->GetPemPass() ); NewpcSock->SetRequireClientCertFlags( pcSock->GetRequireClientCertFlags() ); bAddSock = NewpcSock->AcceptSSL(); diff --git a/Csocket.h b/Csocket.h index 7b8e969..8ab740a 100644 --- a/Csocket.h +++ b/Csocket.h @@ -876,6 +876,14 @@ class CS_EXPORT Csock : public CSockCommon void SetPemPass( const CS_STRING & sPassword ); const CS_STRING & GetPemPass() const; + //! set raw certificate, keys & dhparam + void SetUseKey( EVP_PKEY * sKeyRaw ); + EVP_PKEY * GetUseKey() const; + void SetUseCert( X509 * sCertRaw ); + X509 * GetUseCert() const; + void SetUseDHParam( DH * sDHParamRaw ); + DH * GetUseDHParam() const; + //! Set the SSL method type void SetSSLMethod( int iMethod ); int GetSSLMethod() const; @@ -1172,6 +1180,9 @@ class CS_EXPORT Csock : public CSockCommon bool m_bUseSSL, m_bIsConnected; bool m_bsslEstablished, m_bEnableReadLine, m_bPauseRead; CS_STRING m_shostname, m_sbuffer, m_sSockName, m_sDHParamFile, m_sKeyFile, m_sPemFile, m_sCipherType, m_sParentName; + X509* m_pUseCert; + EVP_PKEY* m_pUseKey; + DH* m_pUseDHParam; CS_STRING m_sSend, m_sPemPass; ECloseType m_eCloseType; @@ -1264,6 +1275,9 @@ class CS_EXPORT CSConnection #ifdef HAVE_LIBSSL const CS_STRING & GetCipher() const { return( m_sCipher ); } + const X509 * GetUseCert() const { return( m_pUseCert ); } + const EVP_PKEY * GetUseKey() const { return( m_pUseKey ); } + const DH * GetUseDHParam() const { return( m_pUseDHParam ); } const CS_STRING & GetPemLocation() const { return( m_sPemLocation ); } const CS_STRING & GetKeyLocation() const { return( m_sKeyLocation ); } const CS_STRING & GetDHParamLocation() const { return( m_sDHParamLocation ); } @@ -1302,6 +1316,9 @@ class CS_EXPORT CSConnection CSSockAddr::EAFRequire m_iAFrequire; #ifdef HAVE_LIBSSL CS_STRING m_sDHParamLocation, m_sKeyLocation, m_sPemLocation, m_sPemPass, m_sCipher; + X509* m_pUseCert; + EVP_PKEY* m_pUseKey; + DH* m_pUseDHParam; #endif /* HAVE_LIBSSL */ }; @@ -1356,6 +1373,9 @@ class CS_EXPORT CSListener #ifdef HAVE_LIBSSL const CS_STRING & GetCipher() const { return( m_sCipher ); } const CS_STRING & GetDHParamLocation() const { return( m_sDHParamLocation ); } + const EVP_PKEY * GetUseKey() const { return( m_pUseKey ); } + const X509 * GetUseCert() const { return( m_pUseCert ); } + const DH * GetUseDHParam() const { return( m_pUseDHParam ); } const CS_STRING & GetKeyLocation() const { return( m_sKeyLocation ); } const CS_STRING & GetPemLocation() const { return( m_sPemLocation ); } const CS_STRING & GetPemPass() const { return( m_sPemPass ); } @@ -1380,6 +1400,12 @@ class CS_EXPORT CSListener #ifdef HAVE_LIBSSL //! set the cipher strength to use, default is HIGH void SetCipher( const CS_STRING & s ) { m_sCipher = s; } + //! set the raw cert data + void SetUseCert( X509 * s ) { m_pUseCert = s; } + //! set the raw key data + void SetUseKey( EVP_PKEY * s ) { m_pUseKey = s; } + //! set the raw dhparam data + void SetUseDHParam( DH * s ) { m_pUseDHParam = s; } //! set the location of the pemfile void SetPemLocation( const CS_STRING & s ) { m_sPemLocation = s; } //! set the location of the keyfile @@ -1404,6 +1430,9 @@ class CS_EXPORT CSListener #ifdef HAVE_LIBSSL CS_STRING m_sDHParamLocation, m_sKeyLocation, m_sPemLocation, m_sPemPass, m_sCipher; + X509* m_pUseCert; + EVP_PKEY* m_pUseKey; + DH* m_pUseDHParam; uint32_t m_iRequireCertFlags; #endif /* HAVE_LIBSSL */ };