15 #include "tlsopensslbase.h"
24 #include <openssl/err.h>
25 #include <openssl/x509v3.h>
27 #ifndef OPENSSL_NO_COMP
28 #include <openssl/comp.h>
37 :
TLSBase( th, server ), m_ssl( 0 ), m_ctx( 0 ), m_buf( 0 ), m_bufsize( 17000 )
39 m_buf =
static_cast<char*
>( calloc( m_bufsize + 1,
sizeof(
char ) ) );
46 SSL_CTX_free( m_ctx );
47 SSL_shutdown( m_ssl );
54 const std::string& clientCerts,
57 #if defined OPENSSL_VERSION_NUMBER && ( OPENSSL_VERSION_NUMBER < 0x10100000 )
62 #ifndef OPENSSL_NO_COMP
63 SSL_COMP_add_compression_method( 193, COMP_zlib() );
66 OpenSSL_add_all_algorithms();
74 if( !SSL_CTX_set_cipher_list( m_ctx,
"HIGH:MEDIUM:AES:@STRENGTH" ) )
77 m_ssl = SSL_new( m_ctx );
81 if( !BIO_new_bio_pair( &m_ibio, 0, &m_nbio, 0 ) )
84 SSL_set_bio( m_ssl, m_ibio, m_ibio );
85 SSL_set_mode( m_ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE );
87 ERR_load_crypto_strings();
88 SSL_load_error_strings();
107 doTLSOperation( TLSWrite );
113 m_recvBuffer += data;
121 doTLSOperation( TLSRead );
129 if( m_cacerts.empty() )
130 SSL_CTX_set_default_verify_paths( m_ctx );
132 StringList::const_iterator it = m_cacerts.begin();
133 for( ; it != m_cacerts.end(); ++it )
134 SSL_CTX_load_verify_locations( m_ctx, (*it).c_str(), 0 );
139 m_clientKey = clientKey;
140 m_clientCerts = clientCerts;
142 if( !m_clientKey.empty() && !m_clientCerts.empty() )
144 if( SSL_CTX_use_certificate_chain_file( m_ctx, m_clientCerts.c_str() ) != 1 )
148 if( SSL_CTX_use_RSAPrivateKey_file( m_ctx, m_clientKey.c_str(), SSL_FILETYPE_PEM ) != 1 )
154 if ( SSL_CTX_check_private_key( m_ctx ) != 1 )
171 void OpenSSLBase::doTLSOperation( TLSOperation op )
177 bool onceAgain =
false;
184 ret = handshakeFunction();
187 ret = SSL_write( m_ssl, m_sendBuffer.c_str(),
static_cast<int>( m_sendBuffer.length() ) );
190 ret = SSL_read( m_ssl, m_buf, m_bufsize );
194 switch( SSL_get_error( m_ssl, ret ) )
196 case SSL_ERROR_WANT_READ:
197 case SSL_ERROR_WANT_WRITE:
201 if( op == TLSHandshake )
203 else if( op == TLSWrite )
204 m_sendBuffer.erase( 0, ret );
205 else if( op == TLSRead )
215 if( !onceAgain && !m_recvBuffer.length() )
220 while( ( ( onceAgain || m_recvBuffer.length() ) && ( !m_secure || op == TLSRead ) )
221 || ( ( op == TLSWrite ) && ( ret > 0 ) ));
224 int OpenSSLBase::ASN1Time2UnixTime( ASN1_TIME* time )
227 const char* str =
reinterpret_cast<const char*
>( time->data );
230 memset( &t, 0,
sizeof(t) );
232 if( time->type == V_ASN1_UTCTIME )
234 t.tm_year = ( str[i++] -
'0' ) * 10;
235 t.tm_year += ( str[i++] -
'0' );
240 else if( time->type == V_ASN1_GENERALIZEDTIME )
242 t.tm_year = ( str[i++] -
'0' ) * 1000;
243 t.tm_year += ( str[i++] -
'0' ) * 100;
244 t.tm_year += ( str[i++] -
'0' ) * 10;
245 t.tm_year += ( str[i++] -
'0' );
249 t.tm_mon = ( str[i++] -
'0' ) * 10;
250 t.tm_mon += ( str[i++] -
'0' ) - 1;
251 t.tm_mday = ( str[i++] -
'0' ) * 10;
252 t.tm_mday += ( str[i++] -
'0' );
253 t.tm_hour = ( str[i++] -
'0' ) * 10;
254 t.tm_hour += ( str[i++] -
'0' );
255 t.tm_min = ( str[i++] -
'0' ) * 10;
256 t.tm_min += ( str[i++] -
'0' );
257 t.tm_sec = ( str[i++] -
'0' ) * 10;
258 t.tm_sec += ( str[i++] -
'0' );
260 return static_cast<int>( mktime( &t ) );
263 #if defined OPENSSL_VERSION_NUMBER && ( OPENSSL_VERSION_NUMBER < 0x10100000 )
264 int SSL_SESSION_get_protocol_version(
const SSL_SESSION* s )
266 return s->ssl_version;
273 doTLSOperation( TLSHandshake );
278 long res = SSL_get_verify_result( m_ssl );
279 if( res != X509_V_OK )
284 X509* peer = SSL_get_peer_certificate( m_ssl );
288 X509_NAME_get_text_by_NID( X509_get_issuer_name( peer ), NID_commonName, peer_CN,
sizeof( peer_CN ) );
289 m_certInfo.
issuer = peer_CN;
290 X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName, peer_CN,
sizeof( peer_CN ) );
291 m_certInfo.
server = peer_CN;
292 m_certInfo.
date_from = ASN1Time2UnixTime( X509_get_notBefore( peer ) );
293 m_certInfo.
date_to = ASN1Time2UnixTime( X509_get_notAfter( peer ) );
294 std::string p( peer_CN );
295 std::transform( p.begin(), p.end(), p.begin(), tolower );
297 #if defined OPENSSL_VERSION_NUMBER && ( OPENSSL_VERSION_NUMBER >= 0x10002000 )
298 res = X509_check_host( peer, p.c_str(), p.length(), X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS, 0 );
306 if( ASN1_UTCTIME_cmp_time_t( X509_get_notBefore( peer ), time( 0 ) ) != -1 )
309 if( ASN1_UTCTIME_cmp_time_t( X509_get_notAfter( peer ), time( 0 ) ) != 1 )
320 tmp = SSL_get_cipher_name( m_ssl );
324 SSL_SESSION* sess = SSL_get_session( m_ssl );
327 switch( SSL_SESSION_get_protocol_version( sess ) )
342 m_certInfo.
protocol =
"Unknown TLS version";
347 tmp = SSL_COMP_get_name( SSL_get_current_compression( m_ssl ) );
357 void OpenSSLBase::pushFunc()
364 while( ( wantwrite = BIO_pending( m_nbio ) ) > 0 )
366 if( wantwrite > m_bufsize )
367 wantwrite = m_bufsize;
372 frombio = BIO_read( m_nbio, m_buf, wantwrite );
378 while( ( wantread = BIO_ctrl_get_read_request( m_nbio ) ) > 0 )
380 if( wantread > m_recvBuffer.length() )
381 wantread = m_recvBuffer.length();
386 tobio = BIO_write( m_nbio, m_recvBuffer.c_str(),
static_cast<int>( wantread ) );
387 m_recvBuffer.erase( 0, tobio );
virtual bool encrypt(const std::string &data)
virtual void setCACerts(const StringList &cacerts)
virtual void setClientCert(const std::string &clientKey, const std::string &clientCerts)
virtual bool init(const std::string &clientKey=EmptyString, const std::string &clientCerts=EmptyString, const StringList &cacerts=StringList())
OpenSSLBase(TLSHandler *th, const std::string &server=EmptyString)
virtual int decrypt(const std::string &data)
An abstract base class for TLS implementations.
An interface that allows for interacting with TLS implementations derived from TLSBase.
virtual void handleDecryptedData(const TLSBase *base, const std::string &data)=0
virtual void handleEncryptedData(const TLSBase *base, const std::string &data)=0
virtual void handleHandshakeResult(const TLSBase *base, bool success, CertInfo &certinfo)=0
The namespace for the gloox library.
std::list< std::string > StringList