gloox  0.9.9.12
tlsgnutlsbase.cpp
1 /*
2  Copyright (c) 2005-2008 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 
15 #include "tlsgnutlsbase.h"
16 
17 #ifdef HAVE_GNUTLS
18 
19 #include <errno.h>
20 
21 #include <cstdlib>
22 #include <cstring>
23 
24 namespace gloox
25 {
26 
27  GnuTLSBase::GnuTLSBase( TLSHandler *th, const std::string& server )
28  : TLSBase( th, server ), m_session( new gnutls_session_t ), m_buf( 0 ), m_bufsize( 17000 )
29  {
30  m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
31  }
32 
34  {
35  free( m_buf );
36  m_buf = 0;
37  cleanup();
38  delete m_session;
39  gnutls_global_deinit();
40  }
41 
42  bool GnuTLSBase::encrypt( const std::string& data )
43  {
44  if( !m_secure )
45  {
46  handshake();
47  return true;
48  }
49 
50  int ret = 0;
51  std::string::size_type sum = 0;
52  do
53  {
54  ret = gnutls_record_send( *m_session, data.c_str() + sum, data.length() - sum );
55  sum += ret;
56  }
57  while( ( ret == GNUTLS_E_AGAIN ) || ( ret == GNUTLS_E_INTERRUPTED ) || sum < data.length() );
58  return true;
59  }
60 
61  int GnuTLSBase::decrypt( const std::string& data )
62  {
63  m_recvBuffer += data;
64 
65  if( !m_secure )
66  {
67  handshake();
68  return data.length();
69  }
70 
71  int sum = 0;
72  int ret = 0;
73  do
74  {
75  ret = gnutls_record_recv( *m_session, m_buf, m_bufsize );
76 
77  if( ret > 0 && m_handler )
78  {
79  m_handler->handleDecryptedData( this, std::string( m_buf, ret ) );
80  sum += ret;
81  }
82  }
83  while( ret > 0 );
84 
85  return sum;
86  }
87 
89  {
90  TLSHandler* handler = m_handler;
91  m_handler = 0;
92  gnutls_bye( *m_session, GNUTLS_SHUT_RDWR );
93  gnutls_db_remove_session( *m_session );
94  gnutls_credentials_clear( *m_session );
95  if( m_secure )
96  gnutls_deinit( *m_session );
97 
98  m_secure = false;
99  m_valid = false;
100  delete m_session;
101  m_session = 0;
102  m_session = new gnutls_session_t;
103  m_handler = handler;
104  }
105 
107  {
108  if( !m_handler )
109  return false;
110 
111  int ret = gnutls_handshake( *m_session );
112  if( ret < 0 && gnutls_error_is_fatal( ret ) )
113  {
114  gnutls_perror( ret );
115  gnutls_db_remove_session( *m_session );
116  gnutls_deinit( *m_session );
117  m_valid = false;
118 
119  m_handler->handleHandshakeResult( this, false, m_certInfo );
120  return false;
121  }
122  else if( ret == GNUTLS_E_AGAIN )
123  {
124  return true;
125  }
126 
127  m_secure = true;
128 
129  getCertInfo();
130 
131  m_handler->handleHandshakeResult( this, true, m_certInfo );
132  return true;
133  }
134 
135  ssize_t GnuTLSBase::pullFunc( void *data, size_t len )
136  {
137  ssize_t cpy = ( len > m_recvBuffer.length() ) ? ( m_recvBuffer.length() ) : ( len );
138  if( cpy > 0 )
139  {
140  memcpy( data, (const void*)m_recvBuffer.c_str(), cpy );
141  m_recvBuffer.erase( 0, cpy );
142  return cpy;
143  }
144  else
145  {
146  errno = EAGAIN;
147  return GNUTLS_E_AGAIN;
148  }
149  }
150 
151  ssize_t GnuTLSBase::pullFunc( gnutls_transport_ptr_t ptr, void *data, size_t len )
152  {
153  return static_cast<GnuTLSBase*>( ptr )->pullFunc( data, len );
154  }
155 
156  ssize_t GnuTLSBase::pushFunc( const void *data, size_t len )
157  {
158  if( m_handler )
159  m_handler->handleEncryptedData( this, std::string( (const char*)data, len ) );
160 
161  return len;
162  }
163 
164  ssize_t GnuTLSBase::pushFunc( gnutls_transport_ptr_t ptr, const void *data, size_t len )
165  {
166  return static_cast<GnuTLSBase*>( ptr )->pushFunc( data, len );
167  }
168 
169 }
170 
171 #endif // HAVE_GNUTLS