aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp')
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp313
1 files changed, 313 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp b/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp
new file mode 100644
index 0000000..8586537
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp
@@ -0,0 +1,313 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include <gnutls/gnutls.h>
+#if GNUTLS_VERSION_NUMBER < 0x030000
+#include <gnutls/extra.h>
+#endif
+
+
+// Dependency on gcrypt is not needed since GNU TLS version 2.12.
+// See here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638651
+#if GNUTLS_VERSION_NUMBER <= 0x020b00
+# define VMIME_GNUTLS_NEEDS_GCRYPT 1
+#endif
+
+#if VMIME_HAVE_PTHREAD
+# include <pthread.h>
+# if VMIME_GNUTLS_NEEDS_GCRYPT
+# include <gcrypt.h>
+# endif
+# include <errno.h>
+#endif // VMIME_HAVE_PTHREAD
+
+#include "vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp"
+#include "vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp"
+#include "vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp"
+
+#include "vmime/exception.hpp"
+
+
+// Enable GnuTLS debugging by defining GNUTLS_DEBUG
+//#define GNUTLS_DEBUG 1
+
+
+#include <sstream>
+#include <iomanip>
+
+#if VMIME_DEBUG && GNUTLS_DEBUG
+ #include <iostream>
+#endif // VMIME_DEBUG && GNUTLS_DEBUG
+
+
+#if VMIME_HAVE_PTHREAD && VMIME_GNUTLS_NEEDS_GCRYPT && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
+extern "C"
+{
+ GCRY_THREAD_OPTION_PTHREAD_IMPL;
+}
+#endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+#ifndef VMIME_BUILDING_DOC
+
+// Initialize GNU TLS library
+struct TLSGlobal {
+
+ TLSGlobal() {
+
+#if VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
+ #if VMIME_GNUTLS_NEEDS_GCRYPT
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ #endif // VMIME_GNUTLS_NEEDS_GCRYPT
+#endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL
+
+ gnutls_global_init();
+ //gnutls_global_init_extra();
+
+#if VMIME_DEBUG && GNUTLS_DEBUG
+ gnutls_global_set_log_function(TLSLogFunc);
+ gnutls_global_set_log_level(10);
+#endif // VMIME_DEBUG && GNUTLS_DEBUG
+
+ gnutls_anon_allocate_client_credentials(&anonCred);
+ gnutls_certificate_allocate_credentials(&certCred);
+ }
+
+ ~TLSGlobal() {
+
+ gnutls_anon_free_client_credentials(anonCred);
+ gnutls_certificate_free_credentials(certCred);
+
+ gnutls_global_deinit();
+ }
+
+#if VMIME_DEBUG && GNUTLS_DEBUG
+
+ static void TLSLogFunc(int level, const char *str) {
+
+ std::cerr << "GNUTLS: [" << level << "] " << str << std::endl;
+ }
+
+#endif // VMIME_DEBUG && GNUTLS_DEBUG
+
+
+ gnutls_anon_client_credentials_t anonCred;
+ gnutls_certificate_credentials_t certCred;
+};
+
+static TLSGlobal g_gnutlsGlobal;
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+
+// static
+shared_ptr <TLSSession> TLSSession::create(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+) {
+
+ return make_shared <TLSSession_GnuTLS>(cv, props);
+}
+
+
+TLSSession_GnuTLS::TLSSession_GnuTLS(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+)
+ : m_certVerifier(cv),
+ m_props(props) {
+
+ int res;
+
+ m_gnutlsSession = new gnutls_session_t;
+
+ if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) {
+ throw std::bad_alloc();
+ }
+
+ // Sets some default priority on the ciphers, key exchange methods,
+ // macs and compression methods.
+#ifdef VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+ gnutls_dh_set_prime_bits(*m_gnutlsSession, 128);
+
+ if ((res = gnutls_priority_set_direct
+ (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) {
+
+ throwTLSException("gnutls_priority_set_direct", res);
+ }
+
+#else // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+
+ gnutls_set_default_priority(*m_gnutlsSession);
+
+ // Sets the priority on the certificate types supported by gnutls.
+ // Priority is higher for types specified before others. After
+ // specifying the types you want, you must append a 0.
+ const int certTypePriority[] = { GNUTLS_CRT_X509, 0 };
+
+ res = gnutls_certificate_type_set_priority(*m_gnutlsSession, certTypePriority);
+
+ if (res < 0) {
+ throwTLSException("gnutls_certificate_type_set_priority", res);
+ }
+
+ // Sets the priority on the protocol types
+ const int protoPriority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
+
+ res = gnutls_protocol_set_priority(*m_gnutlsSession, protoPriority);
+
+ if (res < 0) {
+ throwTLSException("gnutls_certificate_type_set_priority", res);
+ }
+
+ // Priority on the ciphers
+ const int cipherPriority[] = {
+ GNUTLS_CIPHER_ARCFOUR_128,
+ GNUTLS_CIPHER_3DES_CBC,
+ GNUTLS_CIPHER_AES_128_CBC,
+ GNUTLS_CIPHER_AES_256_CBC,
+ GNUTLS_CIPHER_ARCFOUR_40,
+ GNUTLS_CIPHER_RC2_40_CBC,
+ GNUTLS_CIPHER_DES_CBC,
+ 0
+ };
+
+ gnutls_cipher_set_priority(*m_gnutlsSession, cipherPriority);
+
+ // Priority on MACs
+ const int macPriority[] = {
+ GNUTLS_MAC_SHA,
+ GNUTLS_MAC_MD5,
+ 0
+ };
+
+ gnutls_mac_set_priority(*m_gnutlsSession, macPriority);
+
+ // Priority on key exchange methods
+ const int kxPriority[] = {
+ GNUTLS_KX_RSA,
+ GNUTLS_KX_DHE_DSS,
+ GNUTLS_KX_DHE_RSA,
+ GNUTLS_KX_ANON_DH,
+ GNUTLS_KX_SRP,
+ GNUTLS_KX_RSA_EXPORT,
+ GNUTLS_KX_SRP_RSA,
+ GNUTLS_KX_SRP_DSS,
+ 0
+ };
+
+ gnutls_kx_set_priority(*m_gnutlsSession, kxPriority);
+
+ // Priority on compression methods
+ const int compressionPriority[] = {
+ GNUTLS_COMP_ZLIB,
+ //GNUTLS_COMP_LZO,
+ GNUTLS_COMP_NULL,
+ 0
+ };
+
+ gnutls_compression_set_priority(*m_gnutlsSession, compressionPriority);
+
+#endif // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+
+ // Initialize credentials
+ gnutls_credentials_set(
+ *m_gnutlsSession, GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred
+ );
+
+ gnutls_credentials_set(
+ *m_gnutlsSession, GNUTLS_CRD_CERTIFICATE, g_gnutlsGlobal.certCred
+ );
+}
+
+
+TLSSession_GnuTLS::TLSSession_GnuTLS(const TLSSession_GnuTLS&)
+ : TLSSession() {
+
+ // Not used
+}
+
+
+TLSSession_GnuTLS::~TLSSession_GnuTLS() {
+
+ try {
+
+ if (m_gnutlsSession) {
+
+ gnutls_deinit(*m_gnutlsSession);
+
+ delete m_gnutlsSession;
+ m_gnutlsSession = NULL;
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+shared_ptr <TLSSocket> TLSSession_GnuTLS::getSocket(const shared_ptr <socket>& sok) {
+
+ return TLSSocket::wrap(dynamicCast <TLSSession>(shared_from_this()), sok);
+}
+
+
+shared_ptr <security::cert::certificateVerifier> TLSSession_GnuTLS::getCertificateVerifier() {
+
+ return m_certVerifier;
+}
+
+
+void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) {
+
+ std::ostringstream msg;
+
+ msg << fname + "() returned code ";
+ msg << std::hex << code;
+ msg << ": ";
+ msg << gnutls_strerror(code);
+
+ throw exceptions::tls_exception(msg.str());
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS