diff --git a/include/znc/Csocket.h b/include/znc/Csocket.h index 587884b5..d87d8645 100644 --- a/include/znc/Csocket.h +++ b/include/znc/Csocket.h @@ -603,6 +603,15 @@ public: TLS12 = 6 }; + enum EDisableProtocol + { + EDP_None = 0, //!< disable nothing + EDP_SSLv2 = 1, //!< disable SSL verion 2 + EDP_SSLv3 = 2, //!< disable SSL verion 3 + EDP_TLSv1 = 4, //!< disable TLS verion 1 + EDP_SSL = (EDP_SSLv2|EDP_SSLv3) + }; + enum ECONState { CST_START = 0, @@ -840,6 +849,8 @@ public: void SetSSL( bool b ); #ifdef HAVE_LIBSSL + //! bitwise setter, @see EDisableProtocol + void DisableSSLProtocols( u_int uDisableOpts ) { m_uDisableProtocols = uDisableOpts; } //! Set the cipher type ( openssl cipher [to see ciphers available] ) void SetCipher( const CS_STRING & sCipher ); const CS_STRING & GetCipher() const; @@ -1078,6 +1089,8 @@ private: //! shrink sendbuff by removing m_uSendBufferPos bytes from m_sSend void ShrinkSendBuff(); void IncBuffPos( size_t uBytes ); + //! checks for configured protocol disabling + void CheckDisabledProtocols(); // NOTE! if you add any new members, be sure to add them to Copy() uint16_t m_uPort; @@ -1106,6 +1119,7 @@ private: SSL * m_ssl; SSL_CTX * m_ssl_ctx; uint32_t m_iRequireClientCertFlags; + u_int m_uDisableProtocols; FPCertVerifyCB m_pCerVerifyCB; diff --git a/src/Csocket.cpp b/src/Csocket.cpp index 4e4a3e7b..6443ca87 100644 --- a/src/Csocket.cpp +++ b/src/Csocket.cpp @@ -1341,6 +1341,24 @@ bool Csock::AcceptSSL() return( false ); } +void Csock::CheckDisabledProtocols() +{ +#ifdef HAVE_LIBSSL + if( m_ssl_ctx && m_uDisableProtocols > 0 ) + { + long uCTXOptions = 0; + if( EDP_SSLv2 & m_uDisableProtocols ) + uCTXOptions |= SSL_OP_NO_SSLv2; + if( EDP_SSLv3 & m_uDisableProtocols ) + uCTXOptions |= SSL_OP_NO_SSLv3; + if( EDP_TLSv1 & m_uDisableProtocols ) + uCTXOptions |= SSL_OP_NO_TLSv1; + if( uCTXOptions ) + SSL_CTX_set_options( m_ssl_ctx, uCTXOptions ); + } +#endif /* HAVE_LIBSSL */ +} + bool Csock::SSLClientSetup() { #ifdef HAVE_LIBSSL @@ -1444,6 +1462,8 @@ bool Csock::SSLClientSetup() } } + CheckDisabledProtocols(); + m_ssl = SSL_new( m_ssl_ctx ); if( !m_ssl ) return( false ); @@ -1599,18 +1619,43 @@ bool Csock::SSLServerSetup() ERR_clear_error(); } + // Errors for the following block are non-fatal (ECDHE is nice to have + // but not a requirement) +#if defined( SSL_CTX_set_ecdh_auto ) + // Auto-select sensible curve + if( !SSL_CTX_set_ecdh_auto( m_ssl_ctx , 1 ) ) + ERR_clear_error(); +#elif defined( SSL_CTX_set_tmp_ecdh ) + // Use a standard, widely-supported curve + EC_KEY * ecdh = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 ); + if( ecdh ) + { + if( !SSL_CTX_set_tmp_ecdh( m_ssl_ctx, ecdh ) ) + ERR_clear_error(); + EC_KEY_free( ecdh ); + } + else + ERR_clear_error(); +#endif + if( SSL_CTX_set_cipher_list( m_ssl_ctx, m_sCipherType.c_str() ) <= 0 ) { CS_DEBUG( "Could not assign cipher [" << m_sCipherType << "]" ); return( false ); } + CheckDisabledProtocols(); + // // setup the SSL m_ssl = SSL_new( m_ssl_ctx ); if( !m_ssl ) return( false ); +#if defined( SSL_MODE_SEND_FALLBACK_SCSV ) + SSL_set_mode( m_ssl, SSL_MODE_SEND_FALLBACK_SCSV ); +#endif /* SSL_MODE_SEND_FALLBACK_SCSV */ + // Call for client Verification SSL_set_rfd( m_ssl, ( int )m_iReadSock ); SSL_set_wfd( m_ssl, ( int )m_iWriteSock ); @@ -2761,6 +2806,7 @@ void Csock::Init( const CS_STRING & sHostname, uint16_t uPort, int iTimeout ) m_ssl = NULL; m_ssl_ctx = NULL; m_iRequireClientCertFlags = 0; + m_uDisableProtocols = 0; #endif /* HAVE_LIBSSL */ m_iTcount = 0; m_iReadSock = CS_INVALID_SOCK;