00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "tlsopenssl.h"
00016
00017 #ifdef HAVE_OPENSSL
00018
00019 #include <algorithm>
00020 #include <cctype>
00021 #include <ctime>
00022 #include <cstdlib>
00023
00024 namespace gloox
00025 {
00026
00027 OpenSSL::OpenSSL( TLSHandler* th, const std::string& server )
00028 : TLSBase( th, server ), m_ssl( 0 ), m_ctx( 0 ), m_buf( 0 ), m_bufsize( 17000 )
00029 {
00030 m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
00031 }
00032
00033 bool OpenSSL::init()
00034 {
00035 if( m_initLib )
00036 SSL_library_init();
00037
00038 SSL_COMP_add_compression_method( 1, COMP_zlib() );
00039
00040 m_ctx = SSL_CTX_new( TLSv1_client_method() );
00041 if( !m_ctx )
00042 return false;
00043
00044 if( !SSL_CTX_set_cipher_list( m_ctx, "HIGH:MEDIUM:AES:@STRENGTH" ) )
00045 return false;
00046
00047 m_ssl = SSL_new( m_ctx );
00048 SSL_set_connect_state( m_ssl );
00049
00050 if( !BIO_new_bio_pair( &m_ibio, 0, &m_nbio, 0 ) )
00051 return false;
00052
00053 SSL_set_bio( m_ssl, m_ibio, m_ibio );
00054 SSL_set_mode( m_ssl, SSL_MODE_AUTO_RETRY );
00055
00056 m_valid = true;
00057 return true;
00058 }
00059
00060 OpenSSL::~OpenSSL()
00061 {
00062 m_handler = 0;
00063 free( m_buf );
00064 SSL_CTX_free( m_ctx );
00065 SSL_shutdown( m_ssl );
00066 SSL_free( m_ssl );
00067 BIO_free( m_nbio );
00068 cleanup();
00069 }
00070
00071 bool OpenSSL::encrypt( const std::string& data )
00072 {
00073 m_sendBuffer += data;
00074
00075 if( !m_secure )
00076 {
00077 handshake();
00078 return 0;
00079 }
00080
00081 doTLSOperation( TLSWrite );
00082 return true;
00083 }
00084
00085 int OpenSSL::decrypt( const std::string& data )
00086 {
00087 m_recvBuffer += data;
00088
00089 if( !m_secure )
00090 {
00091 handshake();
00092 return 0;
00093 }
00094
00095 doTLSOperation( TLSRead );
00096 return true;
00097 }
00098
00099 void OpenSSL::setCACerts( const StringList& cacerts )
00100 {
00101 m_cacerts = cacerts;
00102
00103 StringList::const_iterator it = m_cacerts.begin();
00104 for( ; it != m_cacerts.end(); ++it )
00105 SSL_CTX_load_verify_locations( m_ctx, (*it).c_str(), 0 );
00106 }
00107
00108 void OpenSSL::setClientCert( const std::string& clientKey, const std::string& clientCerts )
00109 {
00110 m_clientKey = clientKey;
00111 m_clientCerts = clientCerts;
00112
00113 if( !m_clientKey.empty() && !m_clientCerts.empty() )
00114 {
00115 SSL_CTX_use_certificate_chain_file( m_ctx, m_clientCerts.c_str() );
00116 SSL_CTX_use_PrivateKey_file( m_ctx, m_clientKey.c_str(), SSL_FILETYPE_PEM );
00117 }
00118 }
00119
00120 void OpenSSL::cleanup()
00121 {
00122 m_secure = false;
00123 m_valid = false;
00124 }
00125
00126 void OpenSSL::doTLSOperation( TLSOperation op )
00127 {
00128 if( !m_handler )
00129 return;
00130
00131 int ret = 0;
00132 bool onceAgain = false;
00133
00134 do
00135 {
00136 switch( op )
00137 {
00138 case TLSHandshake:
00139 ret = SSL_connect( m_ssl );
00140 break;
00141 case TLSWrite:
00142 ret = SSL_write( m_ssl, m_sendBuffer.c_str(), m_sendBuffer.length() );
00143 break;
00144 case TLSRead:
00145 ret = SSL_read( m_ssl, m_buf, m_bufsize );
00146 break;
00147 }
00148
00149 switch( SSL_get_error( m_ssl, ret ) )
00150 {
00151 case SSL_ERROR_WANT_READ:
00152 case SSL_ERROR_WANT_WRITE:
00153 pushFunc();
00154 break;
00155 case SSL_ERROR_NONE:
00156 if( op == TLSHandshake )
00157 m_secure = true;
00158 else if( op == TLSWrite )
00159 m_sendBuffer.erase( 0, ret );
00160 else if( op == TLSRead )
00161 m_handler->handleDecryptedData( this, std::string( m_buf, ret ) );
00162 pushFunc();
00163 break;
00164 default:
00165 if( !m_secure )
00166 m_handler->handleHandshakeResult( this, false, m_certInfo );
00167 return;
00168 break;
00169 }
00170 if( !onceAgain && !m_recvBuffer.length() )
00171 onceAgain = true;
00172 else if( onceAgain )
00173 onceAgain = false;
00174 }
00175 while( ( onceAgain || m_recvBuffer.length() ) && ( !m_secure || op == TLSRead ) );
00176 }
00177
00178 int OpenSSL::openSSLTime2UnixTime( const char* time_string )
00179 {
00180 char tstring[19];
00181
00182
00183 int m = 0;
00184 for( int n = 0; n < 12; n += 2 )
00185 {
00186 tstring[m] = time_string[n];
00187 tstring[m + 1] = time_string[n + 1];
00188 tstring[m + 2] = 0;
00189 m += 3;
00190 }
00191
00192
00193 tm time_st;
00194 time_st.tm_year = ( atoi( &tstring[3 * 0] ) >= 70 ) ? atoi( &tstring[3 * 0] )
00195 : atoi( &tstring[3 * 0] ) + 100;
00196 time_st.tm_mon = atoi( &tstring[3 * 1] ) - 1;
00197 time_st.tm_mday = atoi( &tstring[3 * 2] );
00198 time_st.tm_hour = atoi( &tstring[3 * 3] );
00199 time_st.tm_min = atoi( &tstring[3 * 4] );
00200 time_st.tm_sec = atoi( &tstring[3 * 5] );
00201
00202 time_t unixt = mktime( &time_st );
00203 return unixt;
00204 }
00205
00206 bool OpenSSL::handshake()
00207 {
00208
00209 doTLSOperation( TLSHandshake );
00210
00211 if( !m_secure )
00212 return true;
00213
00214 int res = SSL_get_verify_result( m_ssl );
00215 if( res != X509_V_OK )
00216 m_certInfo.status = CertInvalid;
00217 else
00218 m_certInfo.status = CertOk;
00219
00220 X509* peer = SSL_get_peer_certificate( m_ssl );
00221 if( peer )
00222 {
00223 char peer_CN[256];
00224 X509_NAME_get_text_by_NID( X509_get_issuer_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
00225 m_certInfo.issuer = peer_CN;
00226 X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
00227 m_certInfo.server = peer_CN;
00228 m_certInfo.date_from = openSSLTime2UnixTime( (char*) (peer->cert_info->validity->notBefore->data) );
00229 m_certInfo.date_to = openSSLTime2UnixTime( (char*) (peer->cert_info->validity->notAfter->data) );
00230 std::string p( peer_CN );
00231 std::transform( p.begin(), p.end(), p.begin(), tolower );
00232 if( p != m_server )
00233 m_certInfo.status |= CertWrongPeer;
00234
00235 if( ASN1_UTCTIME_cmp_time_t( X509_get_notBefore( peer ), time( 0 ) ) != -1 )
00236 m_certInfo.status |= CertNotActive;
00237
00238 if( ASN1_UTCTIME_cmp_time_t( X509_get_notAfter( peer ), time( 0 ) ) != 1 )
00239 m_certInfo.status |= CertExpired;
00240 }
00241 else
00242 {
00243 m_certInfo.status = CertInvalid;
00244 }
00245
00246 const char* tmp;
00247 tmp = SSL_get_cipher_name( m_ssl );
00248 if( tmp )
00249 m_certInfo.cipher = tmp;
00250
00251 tmp = SSL_get_cipher_version( m_ssl );
00252 if( tmp )
00253 m_certInfo.protocol = tmp;
00254
00255 m_valid = true;
00256
00257 m_handler->handleHandshakeResult( this, true, m_certInfo );
00258 return true;
00259 }
00260
00261 void OpenSSL::pushFunc()
00262 {
00263 int wantwrite;
00264 size_t wantread;
00265 int frombio;
00266 int tobio;
00267
00268 while( ( wantwrite = BIO_ctrl_pending( m_nbio ) ) > 0 )
00269 {
00270 if( wantwrite > m_bufsize )
00271 wantwrite = m_bufsize;
00272
00273 if( !wantwrite )
00274 break;
00275
00276 frombio = BIO_read( m_nbio, m_buf, wantwrite );
00277
00278 if( m_handler )
00279 m_handler->handleEncryptedData( this, std::string( m_buf, frombio ) );
00280 }
00281
00282 while( ( wantread = BIO_ctrl_get_read_request( m_nbio ) ) > 0 )
00283 {
00284 if( wantread > m_recvBuffer.length() )
00285 wantread = m_recvBuffer.length();
00286
00287 if( !wantread )
00288 break;
00289
00290 tobio = BIO_write( m_nbio, m_recvBuffer.c_str(), wantread );
00291 m_recvBuffer.erase( 0, tobio );
00292 }
00293 }
00294
00295 }
00296
00297 #endif // HAVE_OPENSSL