tlsgnutlsbase.cpp

00001 /*
00002   Copyright (c) 2005-2008 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
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

Generated on Fri Oct 10 15:26:12 2008 for gloox by  doxygen 1.5.6