tlsgnutlsbase.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "tlsgnutlsbase.h"
00016
00017 #ifdef HAVE_GNUTLS
00018
00019 #include <errno.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022
00023 #include <cstdlib>
00024 #include <cstring>
00025
00026 namespace gloox
00027 {
00028
00029 GnuTLSBase::GnuTLSBase( TLSHandler* th, const std::string& server )
00030 : TLSBase( th, server ), m_session( new gnutls_session_t ), m_buf( 0 ), m_bufsize( 17000 )
00031 {
00032 m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
00033 }
00034
00035 GnuTLSBase::~GnuTLSBase()
00036 {
00037 free( m_buf );
00038 m_buf = 0;
00039 cleanup();
00040 delete m_session;
00041
00042
00043
00044
00045 }
00046
00047 bool GnuTLSBase::encrypt( const std::string& data )
00048 {
00049 if( !m_secure )
00050 {
00051 handshake();
00052 return true;
00053 }
00054
00055 ssize_t ret = 0;
00056 std::string::size_type sum = 0;
00057 do
00058 {
00059 ret = gnutls_record_send( *m_session, data.c_str() + sum, data.length() - sum );
00060 sum += ret;
00061 }
00062 while( ( ret == GNUTLS_E_AGAIN ) || ( ret == GNUTLS_E_INTERRUPTED ) || sum < data.length() );
00063 return true;
00064 }
00065
00066 int GnuTLSBase::decrypt( const std::string& data )
00067 {
00068 m_recvBuffer += data;
00069
00070 if( !m_secure )
00071 {
00072 handshake();
00073 return static_cast<int>( data.length() );
00074 }
00075
00076 int sum = 0;
00077 int ret = 0;
00078 do
00079 {
00080 ret = static_cast<int>( gnutls_record_recv( *m_session, m_buf, m_bufsize ) );
00081
00082 if( ret > 0 && m_handler )
00083 {
00084 m_handler->handleDecryptedData( this, std::string( m_buf, ret ) );
00085 sum += ret;
00086 }
00087 }
00088 while( ret > 0 );
00089
00090 return sum;
00091 }
00092
00093 void GnuTLSBase::cleanup()
00094 {
00095 if( !m_mutex.trylock() )
00096 return;
00097
00098 TLSHandler* handler = m_handler;
00099 m_handler = 0;
00100 gnutls_bye( *m_session, GNUTLS_SHUT_RDWR );
00101 gnutls_db_remove_session( *m_session );
00102 gnutls_credentials_clear( *m_session );
00103 if( m_secure )
00104 gnutls_deinit( *m_session );
00105
00106 m_secure = false;
00107 m_valid = false;
00108 delete m_session;
00109 m_session = 0;
00110 m_session = new gnutls_session_t;
00111 m_handler = handler;
00112
00113 m_mutex.unlock();
00114 }
00115
00116 bool GnuTLSBase::handshake()
00117 {
00118 if( !m_handler )
00119 return false;
00120
00121 int ret = gnutls_handshake( *m_session );
00122 if( ret < 0 && gnutls_error_is_fatal( ret ) )
00123 {
00124 gnutls_perror( ret );
00125 gnutls_db_remove_session( *m_session );
00126 gnutls_deinit( *m_session );
00127 m_valid = false;
00128
00129 m_handler->handleHandshakeResult( this, false, m_certInfo );
00130 return false;
00131 }
00132 else if( ret == GNUTLS_E_AGAIN )
00133 {
00134 return true;
00135 }
00136
00137 m_secure = true;
00138
00139 getCertInfo();
00140
00141 m_handler->handleHandshakeResult( this, true, m_certInfo );
00142 return true;
00143 }
00144
00145 ssize_t GnuTLSBase::pullFunc( void* data, size_t len )
00146 {
00147 ssize_t cpy = ( len > m_recvBuffer.length() ) ? ( m_recvBuffer.length() ) : ( len );
00148 if( cpy > 0 )
00149 {
00150 memcpy( data, (const void*)m_recvBuffer.c_str(), cpy );
00151 m_recvBuffer.erase( 0, cpy );
00152 return cpy;
00153 }
00154 else
00155 {
00156 errno = EAGAIN;
00157 return GNUTLS_E_AGAIN;
00158 }
00159 }
00160
00161 ssize_t GnuTLSBase::pullFunc( gnutls_transport_ptr_t ptr, void* data, size_t len )
00162 {
00163 return static_cast<GnuTLSBase*>( ptr )->pullFunc( data, len );
00164 }
00165
00166 ssize_t GnuTLSBase::pushFunc( const void* data, size_t len )
00167 {
00168 if( m_handler )
00169 m_handler->handleEncryptedData( this, std::string( (const char*)data, len ) );
00170
00171 return len;
00172 }
00173
00174 ssize_t GnuTLSBase::pushFunc( gnutls_transport_ptr_t ptr, const void* data, size_t len )
00175 {
00176 return static_cast<GnuTLSBase*>( ptr )->pushFunc( data, len );
00177 }
00178
00179 }
00180
00181 #endif // HAVE_GNUTLS