Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

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

Generated on Sat Mar 22 09:32:20 2008 for gloox by  doxygen 1.4.1