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

Generated on Sun Dec 28 22:10:18 2008 for gloox by  doxygen 1.4.1