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