tlsgnutlsbase.cpp

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

Generated on Sat Nov 10 08:50:27 2007 for gloox by  doxygen 1.5.3-20071008