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