OpenSSL support (thanks to Mehmet Bozkurt).
This commit is contained in:
parent
cce1c28bce
commit
bc63892291
7
AUTHORS
7
AUTHORS
@ -2,7 +2,7 @@
|
|||||||
VMIME AUTHOR
|
VMIME AUTHOR
|
||||||
============
|
============
|
||||||
|
|
||||||
Vincent Richard <vincent@vincent-richard.net>
|
Vincent Richard <vincent@vmime.org>
|
||||||
Project owner and creator. VMime was created in 1998, and publicly released
|
Project owner and creator. VMime was created in 1998, and publicly released
|
||||||
under the GNU GPL license in 2003.
|
under the GNU GPL license in 2003.
|
||||||
|
|
||||||
@ -28,9 +28,10 @@ AUTHORS file.
|
|||||||
- Zarafa <http://developer.zarafa.com/VmimePatches>
|
- Zarafa <http://developer.zarafa.com/VmimePatches>
|
||||||
- Bartek Szurgot <vempirelord@wp.pl, http://baszerr.org>
|
- Bartek Szurgot <vempirelord@wp.pl, http://baszerr.org>
|
||||||
- Achim Brandt <http://sourceforge.net/users/a-brandt/>
|
- Achim Brandt <http://sourceforge.net/users/a-brandt/>
|
||||||
|
- Mehmet Bozkurt <mehmet.bozkurt78@gmail.com> (OpenSSL support)
|
||||||
|
|
||||||
Please apologize if I have forgotten someone here. ;) Send me an email
|
Please apologize if I have forgotten someone here. ;) Send me an email
|
||||||
to <vincent@vincent-richard.net> if you want your name to be listed.
|
to <vincent@vmime.org> if you want your name to be listed.
|
||||||
|
|
||||||
See SVN Changelog for full list.
|
See Changelogs for full list.
|
||||||
|
|
||||||
|
@ -448,6 +448,7 @@ ENDIF()
|
|||||||
# SSL/TLS support
|
# SSL/TLS support
|
||||||
|
|
||||||
INCLUDE(FindGnuTLS)
|
INCLUDE(FindGnuTLS)
|
||||||
|
INCLUDE(FindOpenSSL)
|
||||||
|
|
||||||
|
|
||||||
INCLUDE(CheckFunctionExists)
|
INCLUDE(CheckFunctionExists)
|
||||||
@ -457,7 +458,7 @@ CHECK_FUNCTION_EXISTS(gnutls_priority_set_direct VMIME_HAVE_GNUTLS_PRIORITY_FUNC
|
|||||||
|
|
||||||
OPTION(
|
OPTION(
|
||||||
VMIME_HAVE_TLS_SUPPORT
|
VMIME_HAVE_TLS_SUPPORT
|
||||||
"SSL/TLS support (requires GNU TLS library)"
|
"SSL/TLS support (requires either GNU TLS or OpenSSL library)"
|
||||||
ON
|
ON
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -467,6 +468,11 @@ OPTION(
|
|||||||
ON
|
ON
|
||||||
)
|
)
|
||||||
|
|
||||||
|
OPTION(
|
||||||
|
VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
"Use OpenSSL library for SSL/TLS support"
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
|
||||||
IF(VMIME_HAVE_TLS_SUPPORT)
|
IF(VMIME_HAVE_TLS_SUPPORT)
|
||||||
|
|
||||||
@ -492,6 +498,23 @@ IF(VMIME_HAVE_TLS_SUPPORT)
|
|||||||
SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} ${GNUTLS_INCLUDE_DIR}")
|
SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} ${GNUTLS_INCLUDE_DIR}")
|
||||||
SET(VMIME_PKGCONFIG_REQUIRES "${VMIME_PKGCONFIG_REQUIRES} libgnutls")
|
SET(VMIME_PKGCONFIG_REQUIRES "${VMIME_PKGCONFIG_REQUIRES} libgnutls")
|
||||||
|
|
||||||
|
ELSEIF(VMIME_TLS_SUPPORT_LIB_IS_OPENSSL)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
${INCLUDE_DIRECTORIES}
|
||||||
|
${OPENSSL_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(
|
||||||
|
${VMIME_LIBRARY_NAME}
|
||||||
|
${TARGET_LINK_LIBRARIES}
|
||||||
|
${OPENSSL_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} ${OPENSSL_LIBRARIES}")
|
||||||
|
SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} ${OPENSSL_INCLUDE_DIR}")
|
||||||
|
SET(VMIME_PKGCONFIG_REQUIRES "${VMIME_PKGCONFIG_REQUIRES} libopenssl")
|
||||||
|
|
||||||
ELSE()
|
ELSE()
|
||||||
|
|
||||||
MESSAGE(FATAL_ERROR "TLS support is enabled, but no TLS/SSL library was selected/found")
|
MESSAGE(FATAL_ERROR "TLS support is enabled, but no TLS/SSL library was selected/found")
|
||||||
@ -535,8 +558,14 @@ ENDIF()
|
|||||||
# POSIX-specific checks
|
# POSIX-specific checks
|
||||||
|
|
||||||
INCLUDE(CheckFunctionExists)
|
INCLUDE(CheckFunctionExists)
|
||||||
|
INCLUDE(CheckSymbolExists)
|
||||||
|
|
||||||
CHECK_FUNCTION_EXISTS(getaddrinfo VMIME_HAVE_GETADDRINFO)
|
CHECK_FUNCTION_EXISTS(getaddrinfo VMIME_HAVE_GETADDRINFO)
|
||||||
|
|
||||||
|
CHECK_FUNCTION_EXISTS(gettid VMIME_HAVE_GETTID)
|
||||||
|
CHECK_FUNCTION_EXISTS(syscall VMIME_HAVE_SYSCALL)
|
||||||
|
CHECK_SYMBOL_EXISTS(SYS_gettid sys/syscall.h VMIME_HAVE_SYSCALL_GETTID)
|
||||||
|
|
||||||
FIND_PACKAGE(Threads)
|
FIND_PACKAGE(Threads)
|
||||||
FIND_LIBRARY(PTHREAD pthread)
|
FIND_LIBRARY(PTHREAD pthread)
|
||||||
|
|
||||||
|
34
SConstruct
34
SConstruct
@ -137,6 +137,8 @@ libvmime_sources = [
|
|||||||
'utility/stringUtils.cpp', 'utility/stringUtils.hpp',
|
'utility/stringUtils.cpp', 'utility/stringUtils.hpp',
|
||||||
'utility/url.cpp', 'utility/url.hpp',
|
'utility/url.cpp', 'utility/url.hpp',
|
||||||
'utility/urlUtils.cpp', 'utility/urlUtils.hpp',
|
'utility/urlUtils.cpp', 'utility/urlUtils.hpp',
|
||||||
|
'utility/sync/autoLock.hpp',
|
||||||
|
'utility/sync/criticalSection.cpp', 'utility/sync/criticalSection.hpp',
|
||||||
# -- encoder
|
# -- encoder
|
||||||
'utility/encoder/encoder.cpp', 'utility/encoder/encoder.hpp',
|
'utility/encoder/encoder.cpp', 'utility/encoder/encoder.hpp',
|
||||||
'utility/encoder/sevenBitEncoder.cpp', 'utility/encoder/sevenBitEncoder.hpp',
|
'utility/encoder/sevenBitEncoder.cpp', 'utility/encoder/sevenBitEncoder.hpp',
|
||||||
@ -210,12 +212,19 @@ libvmime_messaging_sources = [
|
|||||||
libvmime_net_tls_sources = [
|
libvmime_net_tls_sources = [
|
||||||
'net/tls/TLSSession.cpp', 'net/tls/TLSSession.hpp',
|
'net/tls/TLSSession.cpp', 'net/tls/TLSSession.hpp',
|
||||||
'net/tls/TLSSocket.cpp', 'net/tls/TLSSocket.hpp',
|
'net/tls/TLSSocket.cpp', 'net/tls/TLSSocket.hpp',
|
||||||
|
'net/tls/gnutls/TLSSession_GnuTLS.cpp', 'net/tls/gnutls/TLSSession_GnuTLS.hpp',
|
||||||
|
'net/tls/gnutls/TLSSocket_GnuTLS.cpp', 'net/tls/gnutls/TLSSocket_GnuTLS.hpp',
|
||||||
|
'net/tls/openssl/TLSSession_OpenSSL.cpp', 'net/tls/openssl/TLSSession_OpenSSL.hpp',
|
||||||
|
'net/tls/openssl/TLSSocket_OpenSSL.cpp', 'net/tls/openssl/TLSSocket_OpenSSL.hpp',
|
||||||
|
'net/tls/openssl/OpenSSLInitializer.cpp', 'net/tls/openssl/OpenSSLInitializer.hpp',
|
||||||
'net/tls/TLSSecuredConnectionInfos.cpp', 'net/tls/TLSSecuredConnectionInfos.hpp',
|
'net/tls/TLSSecuredConnectionInfos.cpp', 'net/tls/TLSSecuredConnectionInfos.hpp',
|
||||||
'security/cert/certificateChain.cpp', 'security/cert/certificateChain.hpp',
|
'security/cert/certificateChain.cpp', 'security/cert/certificateChain.hpp',
|
||||||
'security/cert/certificateVerifier.hpp',
|
'security/cert/certificateVerifier.hpp',
|
||||||
'security/cert/defaultCertificateVerifier.cpp', 'security/cert/defaultCertificateVerifier.hpp',
|
'security/cert/defaultCertificateVerifier.cpp', 'security/cert/defaultCertificateVerifier.hpp',
|
||||||
'security/cert/certificate.hpp',
|
'security/cert/certificate.hpp',
|
||||||
'security/cert/X509Certificate.cpp', 'security/cert/X509Certificate.hpp'
|
'security/cert/X509Certificate.cpp', 'security/cert/X509Certificate.hpp',
|
||||||
|
'security/cert/gnutls/X509Certificate_GnuTLS.cpp', 'security/cert/gnutls/X509Certificate_GnuTLS.hpp',
|
||||||
|
'security/cert/openssl/X509Certificate_OpenSSL.cpp', 'security/cert/openssl/X509Certificate_OpenSSL.hpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
libvmime_messaging_proto_sources = [
|
libvmime_messaging_proto_sources = [
|
||||||
@ -282,12 +291,14 @@ libvmime_platforms_sources = {
|
|||||||
'posix':
|
'posix':
|
||||||
[
|
[
|
||||||
'platforms/posix/posixChildProcess.cpp', 'platforms/posix/posixChildProcess.hpp',
|
'platforms/posix/posixChildProcess.cpp', 'platforms/posix/posixChildProcess.hpp',
|
||||||
|
'platforms/posix/posixCriticalSection.cpp', 'platforms/posix/posixCriticalSection.hpp',
|
||||||
'platforms/posix/posixFile.cpp', 'platforms/posix/posixFile.hpp',
|
'platforms/posix/posixFile.cpp', 'platforms/posix/posixFile.hpp',
|
||||||
'platforms/posix/posixHandler.cpp', 'platforms/posix/posixHandler.hpp',
|
'platforms/posix/posixHandler.cpp', 'platforms/posix/posixHandler.hpp',
|
||||||
'platforms/posix/posixSocket.cpp', 'platforms/posix/posixSocket.hpp'
|
'platforms/posix/posixSocket.cpp', 'platforms/posix/posixSocket.hpp'
|
||||||
],
|
],
|
||||||
'windows':
|
'windows':
|
||||||
[
|
[
|
||||||
|
'platforms/windows/windowsCriticalSection.cpp', 'platforms/windows/windowsCriticalSection.hpp',
|
||||||
'platforms/windows/windowsFile.cpp', 'platforms/windows/windowsFile.hpp',
|
'platforms/windows/windowsFile.cpp', 'platforms/windows/windowsFile.hpp',
|
||||||
'platforms/windows/windowsHandler.cpp', 'platforms/windows/windowsHandler.hpp',
|
'platforms/windows/windowsHandler.cpp', 'platforms/windows/windowsHandler.hpp',
|
||||||
'platforms/windows/windowsSocket.cpp', 'platforms/windows/windowsSocket.hpp'
|
'platforms/windows/windowsSocket.cpp', 'platforms/windows/windowsSocket.hpp'
|
||||||
@ -590,6 +601,7 @@ env.Append(CXXFLAGS = ['-Wpointer-arith'])
|
|||||||
env.Append(CXXFLAGS = ['-Wold-style-cast'])
|
env.Append(CXXFLAGS = ['-Wold-style-cast'])
|
||||||
env.Append(CXXFLAGS = ['-Wconversion'])
|
env.Append(CXXFLAGS = ['-Wconversion'])
|
||||||
env.Append(CXXFLAGS = ['-Wcast-align'])
|
env.Append(CXXFLAGS = ['-Wcast-align'])
|
||||||
|
env.Append(CXXFLAGS = ['-Wno-long-long']) # OpenSSL
|
||||||
#env.Append(CXXFLAGS = ['-Wshadow'])
|
#env.Append(CXXFLAGS = ['-Wshadow'])
|
||||||
|
|
||||||
env.Append(TARFLAGS = ['-c'])
|
env.Append(TARFLAGS = ['-c'])
|
||||||
@ -614,6 +626,7 @@ if env['with_sasl'] == 'yes':
|
|||||||
env.ParseConfig('pkg-config --cflags --libs ' + libgsasl_pc)
|
env.ParseConfig('pkg-config --cflags --libs ' + libgsasl_pc)
|
||||||
|
|
||||||
if env['with_tls'] == 'yes':
|
if env['with_tls'] == 'yes':
|
||||||
|
# GnuTLS
|
||||||
libgnutls_pc = string.strip(os.popen("pkg-config --list-all | grep '^libgnutls[ ]' | cut -f 1 -d ' '").read())
|
libgnutls_pc = string.strip(os.popen("pkg-config --list-all | grep '^libgnutls[ ]' | cut -f 1 -d ' '").read())
|
||||||
|
|
||||||
if len(libgnutls_pc) == 0:
|
if len(libgnutls_pc) == 0:
|
||||||
@ -625,6 +638,15 @@ if env['with_tls'] == 'yes':
|
|||||||
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs ' + libgnutls_pc)
|
env.ParseConfig('pkg-config --cflags --libs ' + libgnutls_pc)
|
||||||
|
|
||||||
|
# OpenSSL
|
||||||
|
libopenssl_pc = string.strip(os.popen("pkg-config --list-all | grep '^openssl[ ]' | cut -f 1 -d ' '").read())
|
||||||
|
|
||||||
|
if len(libopenssl_pc) == 0:
|
||||||
|
print "ERROR: OpenSSL development package is not installed\n"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
env.ParseConfig('pkg-config --cflags --libs ' + libopenssl_pc)
|
||||||
|
|
||||||
env.Append(CXXFLAGS = ['-pthread'])
|
env.Append(CXXFLAGS = ['-pthread'])
|
||||||
|
|
||||||
# Generate help text for command line options
|
# Generate help text for command line options
|
||||||
@ -806,6 +828,7 @@ config_hpp.write('// -- TLS/SSL support\n')
|
|||||||
if env['with_tls'] == 'yes':
|
if env['with_tls'] == 'yes':
|
||||||
config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 1\n')
|
config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 1\n')
|
||||||
config_hpp.write('#define VMIME_TLS_SUPPORT_LIB_IS_GNUTLS 1\n')
|
config_hpp.write('#define VMIME_TLS_SUPPORT_LIB_IS_GNUTLS 1\n')
|
||||||
|
config_hpp.write('#define VMIME_TLS_SUPPORT_LIB_IS_OPENSSL 0\n')
|
||||||
config_hpp.write('#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS 1\n')
|
config_hpp.write('#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS 1\n')
|
||||||
else:
|
else:
|
||||||
config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 0\n')
|
config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 0\n')
|
||||||
@ -834,8 +857,13 @@ for platform in libvmime_platforms_sources:
|
|||||||
if not platform in platforms:
|
if not platform in platforms:
|
||||||
config_hpp.write('#define VMIME_PLATFORM_IS_' + string.upper(platform) + ' 0\n')
|
config_hpp.write('#define VMIME_PLATFORM_IS_' + string.upper(platform) + ' 0\n')
|
||||||
|
|
||||||
config_hpp.write('#define VMIME_HAVE_GETADDRINFO 1\n')
|
config_hpp.write("""
|
||||||
config_hpp.write('#define VMIME_HAVE_PTHREAD 1\n')
|
#define VMIME_HAVE_GETADDRINFO 1
|
||||||
|
#define VMIME_HAVE_PTHREAD 1
|
||||||
|
#define VMIME_HAVE_GETTID 0
|
||||||
|
#define VMIME_HAVE_SYSCALL 1
|
||||||
|
#define VMIME_HAVE_SYSCALL_GETTID 1
|
||||||
|
""")
|
||||||
|
|
||||||
config_hpp.write('\n')
|
config_hpp.write('\n')
|
||||||
config_hpp.write('// Miscellaneous flags\n')
|
config_hpp.write('// Miscellaneous flags\n')
|
||||||
|
@ -43,6 +43,7 @@ typedef unsigned @VMIME_32BIT_TYPE@ vmime_uint32;
|
|||||||
// -- TLS/SSL support
|
// -- TLS/SSL support
|
||||||
#cmakedefine01 VMIME_HAVE_TLS_SUPPORT
|
#cmakedefine01 VMIME_HAVE_TLS_SUPPORT
|
||||||
#cmakedefine01 VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#cmakedefine01 VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
#cmakedefine01 VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS @VMIME_HAVE_GNUTLS_PRIORITY_FUNCS@
|
#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS @VMIME_HAVE_GNUTLS_PRIORITY_FUNCS@
|
||||||
// -- Messaging support
|
// -- Messaging support
|
||||||
#cmakedefine01 VMIME_HAVE_MESSAGING_FEATURES
|
#cmakedefine01 VMIME_HAVE_MESSAGING_FEATURES
|
||||||
@ -57,6 +58,9 @@ typedef unsigned @VMIME_32BIT_TYPE@ vmime_uint32;
|
|||||||
#cmakedefine01 VMIME_PLATFORM_IS_WINDOWS
|
#cmakedefine01 VMIME_PLATFORM_IS_WINDOWS
|
||||||
#cmakedefine01 VMIME_HAVE_PTHREAD
|
#cmakedefine01 VMIME_HAVE_PTHREAD
|
||||||
#cmakedefine01 VMIME_HAVE_GETADDRINFO
|
#cmakedefine01 VMIME_HAVE_GETADDRINFO
|
||||||
|
#cmakedefine01 VMIME_HAVE_GETTID
|
||||||
|
#cmakedefine01 VMIME_HAVE_SYSCALL
|
||||||
|
#cmakedefine01 VMIME_HAVE_SYSCALL_GETTID
|
||||||
|
|
||||||
|
|
||||||
#define VMIME_SENDMAIL_PATH "@VMIME_SENDMAIL_PATH@"
|
#define VMIME_SENDMAIL_PATH "@VMIME_SENDMAIL_PATH@"
|
||||||
|
@ -111,7 +111,7 @@ void IMAPConnection::connect()
|
|||||||
if (store->isIMAPS()) // dedicated port/IMAPS
|
if (store->isIMAPS()) // dedicated port/IMAPS
|
||||||
{
|
{
|
||||||
ref <tls::TLSSession> tlsSession =
|
ref <tls::TLSSession> tlsSession =
|
||||||
vmime::create <tls::TLSSession>(store->getCertificateVerifier());
|
tls::TLSSession::create(store->getCertificateVerifier());
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
tlsSession->getSocket(m_socket);
|
tlsSession->getSocket(m_socket);
|
||||||
@ -460,7 +460,7 @@ void IMAPConnection::startTLS()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ref <tls::TLSSession> tlsSession =
|
ref <tls::TLSSession> tlsSession =
|
||||||
vmime::create <tls::TLSSession>(m_store.acquire()->getCertificateVerifier());
|
tls::TLSSession::create(m_store.acquire()->getCertificateVerifier());
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
tlsSession->getSocket(m_socket);
|
tlsSession->getSocket(m_socket);
|
||||||
|
@ -151,7 +151,7 @@ void POP3Store::connect()
|
|||||||
if (m_isPOP3S) // dedicated port/POP3S
|
if (m_isPOP3S) // dedicated port/POP3S
|
||||||
{
|
{
|
||||||
ref <tls::TLSSession> tlsSession =
|
ref <tls::TLSSession> tlsSession =
|
||||||
vmime::create <tls::TLSSession>(getCertificateVerifier());
|
tls::TLSSession::create(getCertificateVerifier());
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
tlsSession->getSocket(m_socket);
|
tlsSession->getSocket(m_socket);
|
||||||
@ -550,7 +550,7 @@ void POP3Store::startTLS()
|
|||||||
throw exceptions::command_error("STLS", response);
|
throw exceptions::command_error("STLS", response);
|
||||||
|
|
||||||
ref <tls::TLSSession> tlsSession =
|
ref <tls::TLSSession> tlsSession =
|
||||||
vmime::create <tls::TLSSession>(getCertificateVerifier());
|
tls::TLSSession::create(getCertificateVerifier());
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
tlsSession->getSocket(m_socket);
|
tlsSession->getSocket(m_socket);
|
||||||
|
@ -114,7 +114,7 @@ void SMTPTransport::connect()
|
|||||||
if (m_isSMTPS) // dedicated port/SMTPS
|
if (m_isSMTPS) // dedicated port/SMTPS
|
||||||
{
|
{
|
||||||
ref <tls::TLSSession> tlsSession =
|
ref <tls::TLSSession> tlsSession =
|
||||||
vmime::create <tls::TLSSession>(getCertificateVerifier());
|
tls::TLSSession::create(getCertificateVerifier());
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
tlsSession->getSocket(m_socket);
|
tlsSession->getSocket(m_socket);
|
||||||
@ -463,7 +463,7 @@ void SMTPTransport::startTLS()
|
|||||||
throw exceptions::command_error("STARTTLS", resp->getText());
|
throw exceptions::command_error("STARTTLS", resp->getText());
|
||||||
|
|
||||||
ref <tls::TLSSession> tlsSession =
|
ref <tls::TLSSession> tlsSession =
|
||||||
vmime::create <tls::TLSSession>(getCertificateVerifier());
|
tls::TLSSession::create(getCertificateVerifier());
|
||||||
|
|
||||||
ref <tls::TLSSocket> tlsSocket =
|
ref <tls::TLSSocket> tlsSocket =
|
||||||
tlsSession->getSocket(m_socket);
|
tlsSession->getSocket(m_socket);
|
||||||
|
@ -24,268 +24,19 @@
|
|||||||
#include "vmime/config.hpp"
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
#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/TLSSession.hpp"
|
#include "vmime/net/tls/TLSSession.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 vmime {
|
||||||
namespace net {
|
namespace net {
|
||||||
namespace tls {
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
#ifndef VMIME_BUILDING_DOC
|
TLSSession::TLSSession()
|
||||||
|
|
||||||
// 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 anonCred;
|
|
||||||
gnutls_certificate_credentials certCred;
|
|
||||||
};
|
|
||||||
|
|
||||||
static TLSGlobal g_gnutlsGlobal;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // VMIME_BUILDING_DOC
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TLSSession::TLSSession(ref <security::cert::certificateVerifier> cv)
|
|
||||||
: m_certVerifier(cv)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
m_gnutlsSession = new gnutls_session;
|
|
||||||
|
|
||||||
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.
|
|
||||||
#if VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
|
|
||||||
gnutls_dh_set_prime_bits(*m_gnutlsSession, 128);
|
|
||||||
|
|
||||||
if ((res = gnutls_priority_set_direct
|
|
||||||
(*m_gnutlsSession, "NORMAL:%SSL3_RECORD_VERSION", NULL)) != 0)
|
|
||||||
{
|
|
||||||
if ((res = gnutls_priority_set_direct
|
|
||||||
(*m_gnutlsSession, "NORMAL", 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::TLSSession(const TLSSession&)
|
|
||||||
: object()
|
|
||||||
{
|
|
||||||
// Not used
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TLSSession::~TLSSession()
|
|
||||||
{
|
|
||||||
if (m_gnutlsSession)
|
|
||||||
{
|
|
||||||
gnutls_deinit(*m_gnutlsSession);
|
|
||||||
|
|
||||||
delete m_gnutlsSession;
|
|
||||||
m_gnutlsSession = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ref <TLSSocket> TLSSession::getSocket(ref <socket> sok)
|
|
||||||
{
|
|
||||||
return vmime::create <TLSSocket>
|
|
||||||
(thisRef().dynamicCast <TLSSession>(), sok);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ref <security::cert::certificateVerifier> TLSSession::getCertificateVerifier()
|
|
||||||
{
|
|
||||||
return m_certVerifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSession::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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -294,5 +45,4 @@ void TLSSession::throwTLSException(const string& fname, const int code)
|
|||||||
} // vmime
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
@ -24,18 +24,10 @@
|
|||||||
#include "vmime/config.hpp"
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
#include <gnutls/gnutls.h>
|
|
||||||
#include <gnutls/x509.h>
|
|
||||||
|
|
||||||
#include "vmime/net/tls/TLSSocket.hpp"
|
#include "vmime/net/tls/TLSSocket.hpp"
|
||||||
#include "vmime/net/tls/TLSSession.hpp"
|
|
||||||
|
|
||||||
#include "vmime/platform.hpp"
|
|
||||||
|
|
||||||
#include "vmime/security/cert/X509Certificate.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace vmime {
|
namespace vmime {
|
||||||
@ -43,375 +35,10 @@ namespace net {
|
|||||||
namespace tls {
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
TLSSocket::TLSSocket(ref <TLSSession> session, ref <socket> sok)
|
|
||||||
: m_session(session), m_wrapped(sok), m_connected(false),
|
|
||||||
m_handshaking(false), m_ex(NULL)
|
|
||||||
{
|
|
||||||
gnutls_transport_set_ptr(*m_session->m_gnutlsSession, this);
|
|
||||||
|
|
||||||
gnutls_transport_set_push_function(*m_session->m_gnutlsSession, gnutlsPushFunc);
|
|
||||||
gnutls_transport_set_pull_function(*m_session->m_gnutlsSession, gnutlsPullFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TLSSocket::~TLSSocket()
|
|
||||||
{
|
|
||||||
if (m_ex)
|
|
||||||
{
|
|
||||||
delete m_ex;
|
|
||||||
m_ex = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
// Don't throw exception in destructor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::connect(const string& address, const port_t port)
|
|
||||||
{
|
|
||||||
m_wrapped->connect(address, port);
|
|
||||||
|
|
||||||
handshake(NULL);
|
|
||||||
|
|
||||||
m_connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::disconnect()
|
|
||||||
{
|
|
||||||
if (m_connected)
|
|
||||||
{
|
|
||||||
gnutls_bye(*m_session->m_gnutlsSession, GNUTLS_SHUT_RDWR);
|
|
||||||
|
|
||||||
m_wrapped->disconnect();
|
|
||||||
|
|
||||||
m_connected = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TLSSocket::isConnected() const
|
|
||||||
{
|
|
||||||
return m_wrapped->isConnected() && m_connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TLSSocket::size_type TLSSocket::getBlockSize() const
|
|
||||||
{
|
|
||||||
return 16384; // 16 KB
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::receive(string& buffer)
|
|
||||||
{
|
|
||||||
const int size = receiveRaw(m_buffer, sizeof(m_buffer));
|
|
||||||
buffer = vmime::string(m_buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::send(const string& buffer)
|
|
||||||
{
|
|
||||||
sendRaw(buffer.data(), buffer.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TLSSocket::size_type TLSSocket::receiveRaw(char* buffer, const size_type count)
|
|
||||||
{
|
|
||||||
const ssize_t ret = gnutls_record_recv
|
|
||||||
(*m_session->m_gnutlsSession,
|
|
||||||
buffer, static_cast <size_t>(count));
|
|
||||||
|
|
||||||
if (m_ex)
|
|
||||||
internalThrow();
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
if (ret == GNUTLS_E_AGAIN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
TLSSession::throwTLSException("gnutls_record_recv", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast <int>(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::sendRaw(const char* buffer, const size_type count)
|
|
||||||
{
|
|
||||||
gnutls_record_send
|
|
||||||
(*m_session->m_gnutlsSession,
|
|
||||||
buffer, static_cast <size_t>(count));
|
|
||||||
|
|
||||||
if (m_ex)
|
|
||||||
internalThrow();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::handshake(ref <timeoutHandler> toHandler)
|
|
||||||
{
|
|
||||||
if (toHandler)
|
|
||||||
toHandler->resetTimeOut();
|
|
||||||
|
|
||||||
// Start handshaking process
|
|
||||||
m_handshaking = true;
|
|
||||||
m_toHandler = toHandler;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
const int ret = gnutls_handshake(*m_session->m_gnutlsSession);
|
|
||||||
|
|
||||||
if (m_ex)
|
|
||||||
internalThrow();
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
if (ret == GNUTLS_E_AGAIN ||
|
|
||||||
ret == GNUTLS_E_INTERRUPTED)
|
|
||||||
{
|
|
||||||
// Non-fatal error
|
|
||||||
platform::getHandler()->wait();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TLSSession::throwTLSException("gnutls_handshake", ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Successful handshake
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
m_handshaking = false;
|
|
||||||
m_toHandler = NULL;
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_handshaking = false;
|
|
||||||
m_toHandler = NULL;
|
|
||||||
|
|
||||||
// Verify server's certificate(s)
|
|
||||||
ref <security::cert::certificateChain> certs = getPeerCertificates();
|
|
||||||
|
|
||||||
if (certs == NULL)
|
|
||||||
throw exceptions::tls_exception("No peer certificate.");
|
|
||||||
|
|
||||||
m_session->getCertificateVerifier()->verify(certs);
|
|
||||||
|
|
||||||
m_connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t TLSSocket::gnutlsPushFunc
|
|
||||||
(gnutls_transport_ptr trspt, const void* data, size_t len)
|
|
||||||
{
|
|
||||||
TLSSocket* sok = reinterpret_cast <TLSSocket*>(trspt);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sok->m_wrapped->sendRaw
|
|
||||||
(reinterpret_cast <const char*>(data), static_cast <int>(len));
|
|
||||||
}
|
|
||||||
catch (exception& e)
|
|
||||||
{
|
|
||||||
// Workaround for bad behaviour when throwing C++ exceptions
|
|
||||||
// from C functions (GNU TLS)
|
|
||||||
sok->m_ex = e.clone();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t TLSSocket::gnutlsPullFunc
|
|
||||||
(gnutls_transport_ptr trspt, void* data, size_t len)
|
|
||||||
{
|
|
||||||
TLSSocket* sok = reinterpret_cast <TLSSocket*>(trspt);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Workaround for cross-platform asynchronous handshaking:
|
|
||||||
// gnutls_handshake() only returns GNUTLS_E_AGAIN if recv()
|
|
||||||
// returns -1 and errno is set to EGAIN...
|
|
||||||
if (sok->m_handshaking)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
const ssize_t ret = static_cast <ssize_t>
|
|
||||||
(sok->m_wrapped->receiveRaw
|
|
||||||
(reinterpret_cast <char*>(data),
|
|
||||||
static_cast <int>(len)));
|
|
||||||
|
|
||||||
if (ret == 0)
|
|
||||||
{
|
|
||||||
// No data available yet
|
|
||||||
platform::getHandler()->wait();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the time-out delay is elapsed
|
|
||||||
if (sok->m_toHandler && sok->m_toHandler->isTimeOut())
|
|
||||||
{
|
|
||||||
if (!sok->m_toHandler->handleTimeOut())
|
|
||||||
throw exceptions::operation_timed_out();
|
|
||||||
|
|
||||||
sok->m_toHandler->resetTimeOut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const ssize_t n = static_cast <ssize_t>
|
|
||||||
(sok->m_wrapped->receiveRaw
|
|
||||||
(reinterpret_cast <char*>(data),
|
|
||||||
static_cast <int>(len)));
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
return GNUTLS_E_AGAIN; // This seems like a hack, really...
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (exception& e)
|
|
||||||
{
|
|
||||||
// Workaround for bad behaviour when throwing C++ exceptions
|
|
||||||
// from C functions (GNU TLS)
|
|
||||||
sok->m_ex = e.clone();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ref <security::cert::certificateChain> TLSSocket::getPeerCertificates() const
|
|
||||||
{
|
|
||||||
unsigned int certCount = 0;
|
|
||||||
const gnutls_datum* rawData = gnutls_certificate_get_peers
|
|
||||||
(*m_session->m_gnutlsSession, &certCount);
|
|
||||||
|
|
||||||
if (rawData == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Try X.509
|
|
||||||
gnutls_x509_crt* x509Certs = new gnutls_x509_crt[certCount];
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < certCount; ++i)
|
|
||||||
{
|
|
||||||
gnutls_x509_crt_init(x509Certs + i);
|
|
||||||
|
|
||||||
int res = gnutls_x509_crt_import(x509Certs[i], rawData + i,
|
|
||||||
GNUTLS_X509_FMT_DER);
|
|
||||||
|
|
||||||
if (res < 0)
|
|
||||||
{
|
|
||||||
// XXX more fine-grained error reporting?
|
|
||||||
delete [] x509Certs;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::vector <ref <security::cert::certificate> > certs;
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
for (unsigned int i = 0 ; i < certCount ; ++i)
|
|
||||||
{
|
|
||||||
size_t dataSize = 0;
|
|
||||||
|
|
||||||
gnutls_x509_crt_export(x509Certs[i],
|
|
||||||
GNUTLS_X509_FMT_DER, NULL, &dataSize);
|
|
||||||
|
|
||||||
std::vector <byte_t> data(dataSize);
|
|
||||||
|
|
||||||
gnutls_x509_crt_export(x509Certs[i],
|
|
||||||
GNUTLS_X509_FMT_DER, &data[0], &dataSize);
|
|
||||||
|
|
||||||
ref <security::cert::X509Certificate> cert =
|
|
||||||
security::cert::X509Certificate::import(&data[0], dataSize);
|
|
||||||
|
|
||||||
if (cert != NULL)
|
|
||||||
certs.push_back(cert);
|
|
||||||
else
|
|
||||||
error = true;
|
|
||||||
|
|
||||||
gnutls_x509_crt_deinit(x509Certs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] x509Certs;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return vmime::create <security::cert::certificateChain>(certs);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] x509Certs;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Following is a workaround for C++ exceptions to pass correctly between
|
|
||||||
// C and C++ calls.
|
|
||||||
//
|
|
||||||
// gnutls_record_recv() calls TLSSocket::gnutlsPullFunc, and exceptions
|
|
||||||
// thrown by the socket can not be caught.
|
|
||||||
|
|
||||||
#ifndef VMIME_BUILDING_DOC
|
|
||||||
|
|
||||||
class TLSSocket_DeleteExWrapper : public object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
TLSSocket_DeleteExWrapper(exception* ex) : m_ex(ex) { }
|
|
||||||
~TLSSocket_DeleteExWrapper() { delete m_ex; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
exception* m_ex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // VMIME_BUILDING_DOC
|
|
||||||
|
|
||||||
|
|
||||||
void TLSSocket::internalThrow()
|
|
||||||
{
|
|
||||||
static std::vector <ref <TLSSocket_DeleteExWrapper> > exToDelete;
|
|
||||||
|
|
||||||
if (m_ex)
|
|
||||||
{
|
|
||||||
// Reset the current exception pointer to prevent the same
|
|
||||||
// exception from being thrown again later
|
|
||||||
exception* ex = m_ex;
|
|
||||||
m_ex = NULL;
|
|
||||||
|
|
||||||
// To avoid memory leaks
|
|
||||||
exToDelete.push_back(vmime::create <TLSSocket_DeleteExWrapper>(ex));
|
|
||||||
|
|
||||||
throw *ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // tls
|
} // tls
|
||||||
} // net
|
} // net
|
||||||
} // vmime
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
304
src/net/tls/gnutls/TLSSession_GnuTLS.cpp
Normal file
304
src/net/tls/gnutls/TLSSession_GnuTLS.cpp
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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/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 anonCred;
|
||||||
|
gnutls_certificate_credentials certCred;
|
||||||
|
};
|
||||||
|
|
||||||
|
static TLSGlobal g_gnutlsGlobal;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <TLSSession> TLSSession::create(ref <security::cert::certificateVerifier> cv)
|
||||||
|
{
|
||||||
|
return vmime::create <TLSSession_GnuTLS>(cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSession_GnuTLS::TLSSession_GnuTLS(ref <security::cert::certificateVerifier> cv)
|
||||||
|
: m_certVerifier(cv)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
m_gnutlsSession = new gnutls_session;
|
||||||
|
|
||||||
|
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.
|
||||||
|
#if HAVE_GNUTLS_PRIORITY_FUNCS
|
||||||
|
gnutls_dh_set_prime_bits(*m_gnutlsSession, 128);
|
||||||
|
|
||||||
|
if ((res = gnutls_priority_set_direct
|
||||||
|
(*m_gnutlsSession, "NORMAL:%SSL3_RECORD_VERSION", NULL)) != 0)
|
||||||
|
{
|
||||||
|
if ((res = gnutls_priority_set_direct
|
||||||
|
(*m_gnutlsSession, "NORMAL", NULL)) != 0)
|
||||||
|
{
|
||||||
|
throwTLSException
|
||||||
|
("gnutls_priority_set_direct", res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !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 // !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()
|
||||||
|
{
|
||||||
|
if (m_gnutlsSession)
|
||||||
|
{
|
||||||
|
gnutls_deinit(*m_gnutlsSession);
|
||||||
|
|
||||||
|
delete m_gnutlsSession;
|
||||||
|
m_gnutlsSession = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <TLSSocket> TLSSession_GnuTLS::getSocket(ref <socket> sok)
|
||||||
|
{
|
||||||
|
return TLSSocket::wrap(thisRef().dynamicCast <TLSSession>(), sok);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <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
|
424
src/net/tls/gnutls/TLSSocket_GnuTLS.cpp
Normal file
424
src/net/tls/gnutls/TLSSocket_GnuTLS.cpp
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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>
|
||||||
|
#include <gnutls/x509.h>
|
||||||
|
|
||||||
|
#include "vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp"
|
||||||
|
#include "vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp"
|
||||||
|
|
||||||
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
|
#include "vmime/security/cert/X509Certificate.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <TLSSocket> TLSSocket::wrap(ref <TLSSession> session, ref <socket> sok)
|
||||||
|
{
|
||||||
|
return vmime::create <TLSSocket_GnuTLS>
|
||||||
|
(session.dynamicCast <TLSSession_GnuTLS>(), sok);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket_GnuTLS::TLSSocket_GnuTLS(ref <TLSSession_GnuTLS> session, ref <socket> sok)
|
||||||
|
: m_session(session), m_wrapped(sok), m_connected(false),
|
||||||
|
m_handshaking(false), m_ex(NULL)
|
||||||
|
{
|
||||||
|
gnutls_transport_set_ptr(*m_session->m_gnutlsSession, this);
|
||||||
|
|
||||||
|
gnutls_transport_set_push_function(*m_session->m_gnutlsSession, gnutlsPushFunc);
|
||||||
|
gnutls_transport_set_pull_function(*m_session->m_gnutlsSession, gnutlsPullFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket_GnuTLS::~TLSSocket_GnuTLS()
|
||||||
|
{
|
||||||
|
if (m_ex)
|
||||||
|
{
|
||||||
|
delete m_ex;
|
||||||
|
m_ex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// Don't throw exception in destructor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::connect(const string& address, const port_t port)
|
||||||
|
{
|
||||||
|
m_wrapped->connect(address, port);
|
||||||
|
|
||||||
|
handshake(NULL);
|
||||||
|
|
||||||
|
m_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::disconnect()
|
||||||
|
{
|
||||||
|
if (m_connected)
|
||||||
|
{
|
||||||
|
gnutls_bye(*m_session->m_gnutlsSession, GNUTLS_SHUT_RDWR);
|
||||||
|
|
||||||
|
m_wrapped->disconnect();
|
||||||
|
|
||||||
|
m_connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TLSSocket_GnuTLS::isConnected() const
|
||||||
|
{
|
||||||
|
return m_wrapped->isConnected() && m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket::size_type TLSSocket_GnuTLS::getBlockSize() const
|
||||||
|
{
|
||||||
|
return 16384; // 16 KB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::receive(string& buffer)
|
||||||
|
{
|
||||||
|
const int size = receiveRaw(m_buffer, sizeof(m_buffer));
|
||||||
|
buffer = vmime::string(m_buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::send(const string& buffer)
|
||||||
|
{
|
||||||
|
sendRaw(buffer.data(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket::size_type TLSSocket_GnuTLS::receiveRaw(char* buffer, const size_type count)
|
||||||
|
{
|
||||||
|
const ssize_t ret = gnutls_record_recv
|
||||||
|
(*m_session->m_gnutlsSession,
|
||||||
|
buffer, static_cast <size_t>(count));
|
||||||
|
|
||||||
|
if (m_ex)
|
||||||
|
internalThrow();
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
if (ret == GNUTLS_E_AGAIN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TLSSession_GnuTLS::throwTLSException("gnutls_record_recv", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast <int>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::sendRaw(const char* buffer, const size_type count)
|
||||||
|
{
|
||||||
|
gnutls_record_send
|
||||||
|
(*m_session->m_gnutlsSession,
|
||||||
|
buffer, static_cast <size_t>(count));
|
||||||
|
|
||||||
|
if (m_ex)
|
||||||
|
internalThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::handshake(ref <timeoutHandler> toHandler)
|
||||||
|
{
|
||||||
|
if (toHandler)
|
||||||
|
toHandler->resetTimeOut();
|
||||||
|
|
||||||
|
// Start handshaking process
|
||||||
|
m_handshaking = true;
|
||||||
|
m_toHandler = toHandler;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const int ret = gnutls_handshake(*m_session->m_gnutlsSession);
|
||||||
|
|
||||||
|
if (m_ex)
|
||||||
|
internalThrow();
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
if (ret == GNUTLS_E_AGAIN ||
|
||||||
|
ret == GNUTLS_E_INTERRUPTED)
|
||||||
|
{
|
||||||
|
// Non-fatal error
|
||||||
|
platform::getHandler()->wait();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Successful handshake
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
m_handshaking = false;
|
||||||
|
m_toHandler = NULL;
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_handshaking = false;
|
||||||
|
m_toHandler = NULL;
|
||||||
|
|
||||||
|
// Verify server's certificate(s)
|
||||||
|
ref <security::cert::certificateChain> certs = getPeerCertificates();
|
||||||
|
|
||||||
|
if (certs == NULL)
|
||||||
|
throw exceptions::tls_exception("No peer certificate.");
|
||||||
|
|
||||||
|
m_session->getCertificateVerifier()->verify(certs);
|
||||||
|
|
||||||
|
m_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t TLSSocket_GnuTLS::gnutlsPushFunc
|
||||||
|
(gnutls_transport_ptr trspt, const void* data, size_t len)
|
||||||
|
{
|
||||||
|
TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sok->m_wrapped->sendRaw
|
||||||
|
(reinterpret_cast <const char*>(data), static_cast <int>(len));
|
||||||
|
}
|
||||||
|
catch (exception& e)
|
||||||
|
{
|
||||||
|
// Workaround for bad behaviour when throwing C++ exceptions
|
||||||
|
// from C functions (GNU TLS)
|
||||||
|
sok->m_ex = e.clone();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t TLSSocket_GnuTLS::gnutlsPullFunc
|
||||||
|
(gnutls_transport_ptr trspt, void* data, size_t len)
|
||||||
|
{
|
||||||
|
TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Workaround for cross-platform asynchronous handshaking:
|
||||||
|
// gnutls_handshake() only returns GNUTLS_E_AGAIN if recv()
|
||||||
|
// returns -1 and errno is set to EGAIN...
|
||||||
|
if (sok->m_handshaking)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const ssize_t ret = static_cast <ssize_t>
|
||||||
|
(sok->m_wrapped->receiveRaw
|
||||||
|
(reinterpret_cast <char*>(data),
|
||||||
|
static_cast <int>(len)));
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
// No data available yet
|
||||||
|
platform::getHandler()->wait();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the time-out delay is elapsed
|
||||||
|
if (sok->m_toHandler && sok->m_toHandler->isTimeOut())
|
||||||
|
{
|
||||||
|
if (!sok->m_toHandler->handleTimeOut())
|
||||||
|
throw exceptions::operation_timed_out();
|
||||||
|
|
||||||
|
sok->m_toHandler->resetTimeOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ssize_t n = static_cast <ssize_t>
|
||||||
|
(sok->m_wrapped->receiveRaw
|
||||||
|
(reinterpret_cast <char*>(data),
|
||||||
|
static_cast <int>(len)));
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return GNUTLS_E_AGAIN; // This seems like a hack, really...
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exception& e)
|
||||||
|
{
|
||||||
|
// Workaround for bad behaviour when throwing C++ exceptions
|
||||||
|
// from C functions (GNU TLS)
|
||||||
|
sok->m_ex = e.clone();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertificates() const
|
||||||
|
{
|
||||||
|
unsigned int certCount = 0;
|
||||||
|
const gnutls_datum* rawData = gnutls_certificate_get_peers
|
||||||
|
(*m_session->m_gnutlsSession, &certCount);
|
||||||
|
|
||||||
|
if (rawData == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Try X.509
|
||||||
|
gnutls_x509_crt* x509Certs = new gnutls_x509_crt[certCount];
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < certCount; ++i)
|
||||||
|
{
|
||||||
|
gnutls_x509_crt_init(x509Certs + i);
|
||||||
|
|
||||||
|
int res = gnutls_x509_crt_import(x509Certs[i], rawData + i,
|
||||||
|
GNUTLS_X509_FMT_DER);
|
||||||
|
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
// XXX more fine-grained error reporting?
|
||||||
|
delete [] x509Certs;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::vector <ref <security::cert::certificate> > certs;
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0 ; i < certCount ; ++i)
|
||||||
|
{
|
||||||
|
size_t dataSize = 0;
|
||||||
|
|
||||||
|
gnutls_x509_crt_export(x509Certs[i],
|
||||||
|
GNUTLS_X509_FMT_DER, NULL, &dataSize);
|
||||||
|
|
||||||
|
std::vector <byte_t> data(dataSize);
|
||||||
|
|
||||||
|
gnutls_x509_crt_export(x509Certs[i],
|
||||||
|
GNUTLS_X509_FMT_DER, &data[0], &dataSize);
|
||||||
|
|
||||||
|
ref <security::cert::X509Certificate> cert =
|
||||||
|
security::cert::X509Certificate::import(&data[0], dataSize);
|
||||||
|
|
||||||
|
if (cert != NULL)
|
||||||
|
certs.push_back(cert);
|
||||||
|
else
|
||||||
|
error = true;
|
||||||
|
|
||||||
|
gnutls_x509_crt_deinit(x509Certs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] x509Certs;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return vmime::create <security::cert::certificateChain>(certs);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] x509Certs;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Following is a workaround for C++ exceptions to pass correctly between
|
||||||
|
// C and C++ calls.
|
||||||
|
//
|
||||||
|
// gnutls_record_recv() calls TLSSocket::gnutlsPullFunc, and exceptions
|
||||||
|
// thrown by the socket can not be caught.
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
class TLSSocket_DeleteExWrapper : public object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TLSSocket_DeleteExWrapper(exception* ex) : m_ex(ex) { }
|
||||||
|
~TLSSocket_DeleteExWrapper() { delete m_ex; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
exception* m_ex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_GnuTLS::internalThrow()
|
||||||
|
{
|
||||||
|
static std::vector <ref <TLSSocket_DeleteExWrapper> > exToDelete;
|
||||||
|
|
||||||
|
if (m_ex)
|
||||||
|
{
|
||||||
|
// Reset the current exception pointer to prevent the same
|
||||||
|
// exception from being thrown again later
|
||||||
|
exception* ex = m_ex;
|
||||||
|
m_ex = NULL;
|
||||||
|
|
||||||
|
// To avoid memory leaks
|
||||||
|
exToDelete.push_back(vmime::create <TLSSocket_DeleteExWrapper>(ex));
|
||||||
|
|
||||||
|
throw *ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
152
src/net/tls/openssl/OpenSSLInitializer.cpp
Executable file
152
src/net/tls/openssl/OpenSSLInitializer.cpp
Executable file
@ -0,0 +1,152 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
|
||||||
|
|
||||||
|
#include "vmime/utility/sync/autoLock.hpp"
|
||||||
|
#include "vmime/utility/sync/criticalSection.hpp"
|
||||||
|
|
||||||
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x0907000L
|
||||||
|
# include <openssl/conf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
ref <vmime::utility::sync::criticalSection >* OpenSSLInitializer::sm_mutexes;
|
||||||
|
int OpenSSLInitializer::sm_initCount(0);
|
||||||
|
|
||||||
|
|
||||||
|
OpenSSLInitializer::OpenSSLInitializer()
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenSSLInitializer::~OpenSSLInitializer()
|
||||||
|
{
|
||||||
|
uninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <vmime::utility::sync::criticalSection> OpenSSLInitializer::getMutex()
|
||||||
|
{
|
||||||
|
static ref <vmime::utility::sync::criticalSection> criticalSection
|
||||||
|
= vmime::platform::getHandler()->createCriticalSection();
|
||||||
|
|
||||||
|
return criticalSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
void OpenSSLInitializer::initialize()
|
||||||
|
{
|
||||||
|
ref <vmime::utility::sync::criticalSection> mutex = getMutex();
|
||||||
|
vmime::utility::sync::autoLock <vmime::utility::sync::criticalSection> lock(mutex);
|
||||||
|
|
||||||
|
if (++sm_initCount == 1)
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x0907000L
|
||||||
|
OPENSSL_config(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SSL_load_error_strings();
|
||||||
|
SSL_library_init();
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
|
unsigned char seed[SEEDSIZE];
|
||||||
|
vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE);
|
||||||
|
RAND_seed(seed, SEEDSIZE);
|
||||||
|
|
||||||
|
int numMutexes = CRYPTO_num_locks();
|
||||||
|
sm_mutexes = new ref <vmime::utility::sync::criticalSection>[numMutexes];
|
||||||
|
|
||||||
|
for (int i = 0 ; i < numMutexes ; ++i)
|
||||||
|
sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection();
|
||||||
|
|
||||||
|
CRYPTO_set_locking_callback(&OpenSSLInitializer::lock);
|
||||||
|
CRYPTO_set_id_callback(&OpenSSLInitializer::id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
void OpenSSLInitializer::uninitialize()
|
||||||
|
{
|
||||||
|
ref <vmime::utility::sync::criticalSection> mutex = getMutex();
|
||||||
|
vmime::utility::sync::autoLock <vmime::utility::sync::criticalSection> lock(mutex);
|
||||||
|
|
||||||
|
if (--sm_initCount == 0)
|
||||||
|
{
|
||||||
|
EVP_cleanup();
|
||||||
|
ERR_free_strings();
|
||||||
|
|
||||||
|
CRYPTO_set_locking_callback(NULL);
|
||||||
|
CRYPTO_set_id_callback(NULL);
|
||||||
|
|
||||||
|
delete [] sm_mutexes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */)
|
||||||
|
{
|
||||||
|
if (mode & CRYPTO_LOCK)
|
||||||
|
sm_mutexes[n]->lock();
|
||||||
|
else
|
||||||
|
sm_mutexes[n]->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
unsigned long OpenSSLInitializer::id()
|
||||||
|
{
|
||||||
|
return vmime::platform::getHandler()->getThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
138
src/net/tls/openssl/TLSSession_OpenSSL.cpp
Executable file
138
src/net/tls/openssl/TLSSession_OpenSSL.cpp
Executable file
@ -0,0 +1,138 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_PTHREAD
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <gcrypt.h>
|
||||||
|
# include <errno.h>
|
||||||
|
#endif // VMIME_HAVE_PTHREAD
|
||||||
|
|
||||||
|
#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp"
|
||||||
|
#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
|
||||||
|
|
||||||
|
#include "vmime/exception.hpp"
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
// Thread-safe OpenSSL initialization
|
||||||
|
static OpenSSLInitializer g_openSSLGlobal;
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <TLSSession> TLSSession::create(ref <security::cert::certificateVerifier> cv)
|
||||||
|
{
|
||||||
|
return vmime::create <TLSSession_OpenSSL>(cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSession_OpenSSL::TLSSession_OpenSSL(ref <vmime::security::cert::certificateVerifier> cv)
|
||||||
|
: m_sslctx(0), m_certVerifier(cv)
|
||||||
|
{
|
||||||
|
m_sslctx = SSL_CTX_new(SSLv23_client_method());
|
||||||
|
SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSession_OpenSSL::TLSSession_OpenSSL(const TLSSession_OpenSSL&)
|
||||||
|
: TLSSession()
|
||||||
|
{
|
||||||
|
// Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSession_OpenSSL::~TLSSession_OpenSSL()
|
||||||
|
{
|
||||||
|
SSL_CTX_free(m_sslctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <TLSSocket> TLSSession_OpenSSL::getSocket(ref <socket> sok)
|
||||||
|
{
|
||||||
|
return TLSSocket::wrap(thisRef().dynamicCast <TLSSession>(), sok);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <security::cert::certificateVerifier> TLSSession_OpenSSL::getCertificateVerifier()
|
||||||
|
{
|
||||||
|
return m_certVerifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile)
|
||||||
|
{
|
||||||
|
if (SSL_CTX_use_PrivateKey_file(m_sslctx, keyfile.c_str(), SSL_FILETYPE_PEM) != 1)
|
||||||
|
{
|
||||||
|
unsigned long errCode = ERR_get_error();
|
||||||
|
char buffer[256];
|
||||||
|
ERR_error_string_n(errCode, buffer, sizeof(buffer));
|
||||||
|
vmime::string sslErr(buffer);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Error loading private key from file " << keyfile;
|
||||||
|
oss << " - msg: " << sslErr;
|
||||||
|
throw exceptions::certificate_exception(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile)
|
||||||
|
{
|
||||||
|
if (SSL_CTX_use_certificate_chain_file(m_sslctx, chainFile.c_str()) != 1)
|
||||||
|
{
|
||||||
|
unsigned long errCode = ERR_get_error();
|
||||||
|
char buffer[256];
|
||||||
|
ERR_error_string_n(errCode, buffer, sizeof(buffer));
|
||||||
|
vmime::string sslErr(buffer);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Error loading certificate from file " << chainFile;
|
||||||
|
oss << " - msg: " << sslErr;
|
||||||
|
throw exceptions::certificate_exception(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SSL_CTX* TLSSession_OpenSSL::getContext() const
|
||||||
|
{
|
||||||
|
return m_sslctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
416
src/net/tls/openssl/TLSSocket_OpenSSL.cpp
Executable file
416
src/net/tls/openssl/TLSSocket_OpenSSL.cpp
Executable file
@ -0,0 +1,416 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
#include "vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp"
|
||||||
|
#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp"
|
||||||
|
|
||||||
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
|
#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <TLSSocket> TLSSocket::wrap(ref <TLSSession> session, ref <socket> sok)
|
||||||
|
{
|
||||||
|
return vmime::create <TLSSocket_OpenSSL>
|
||||||
|
(session.dynamicCast <TLSSession_OpenSSL>(), sok);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket_OpenSSL::TLSSocket_OpenSSL(ref <TLSSession_OpenSSL> session, ref <socket> sok)
|
||||||
|
: m_session(session), m_wrapped(sok), m_connected(false), m_ssl(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket_OpenSSL::~TLSSocket_OpenSSL()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
disconnect();
|
||||||
|
|
||||||
|
if (m_ssl)
|
||||||
|
{
|
||||||
|
SSL_free(m_ssl);
|
||||||
|
m_ssl = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// Don't throw in destructor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::createSSLHandle()
|
||||||
|
{
|
||||||
|
if (m_wrapped->isConnected())
|
||||||
|
{
|
||||||
|
static BIO_METHOD customBIOMethod;
|
||||||
|
::memset(&customBIOMethod, 0, sizeof(customBIOMethod));
|
||||||
|
|
||||||
|
customBIOMethod.type = 100 | BIO_TYPE_SOURCE_SINK;
|
||||||
|
customBIOMethod.name = "vmime::socket glue";
|
||||||
|
customBIOMethod.bwrite = bio_write;
|
||||||
|
customBIOMethod.bread = bio_read;
|
||||||
|
customBIOMethod.bputs = bio_puts;
|
||||||
|
customBIOMethod.bgets = bio_gets;
|
||||||
|
customBIOMethod.ctrl = bio_ctrl;
|
||||||
|
customBIOMethod.create = bio_create;
|
||||||
|
customBIOMethod.destroy = bio_destroy;
|
||||||
|
|
||||||
|
BIO* sockBio = BIO_new(&customBIOMethod);
|
||||||
|
sockBio->ptr = this;
|
||||||
|
|
||||||
|
m_ssl = SSL_new(m_session->getContext());
|
||||||
|
|
||||||
|
if (!m_ssl)
|
||||||
|
{
|
||||||
|
BIO_free(sockBio);
|
||||||
|
throw exceptions::tls_exception("Cannot create SSL object");
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_set_bio(m_ssl, sockBio, sockBio);
|
||||||
|
SSL_set_connect_state(m_ssl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw exceptions::tls_exception("Unconnected socket error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::connect(const string& address, const port_t port)
|
||||||
|
{
|
||||||
|
m_wrapped->connect(address, port);
|
||||||
|
|
||||||
|
createSSLHandle();
|
||||||
|
|
||||||
|
handshake(NULL);
|
||||||
|
|
||||||
|
m_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::disconnect()
|
||||||
|
{
|
||||||
|
if (m_connected)
|
||||||
|
{
|
||||||
|
if (m_ssl)
|
||||||
|
{
|
||||||
|
// Don't shut down the socket more than once.
|
||||||
|
int shutdownState = SSL_get_shutdown(m_ssl);
|
||||||
|
bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN;
|
||||||
|
|
||||||
|
if (!shutdownSent)
|
||||||
|
SSL_shutdown(m_ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_wrapped->disconnect();
|
||||||
|
m_connected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TLSSocket_OpenSSL::isConnected() const
|
||||||
|
{
|
||||||
|
return m_wrapped->isConnected() && m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket::size_type TLSSocket_OpenSSL::getBlockSize() const
|
||||||
|
{
|
||||||
|
return 16384; // 16 KB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::receive(string& buffer)
|
||||||
|
{
|
||||||
|
const int size = receiveRaw(m_buffer, sizeof(m_buffer));
|
||||||
|
buffer = vmime::string(m_buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::send(const string& buffer)
|
||||||
|
{
|
||||||
|
sendRaw(buffer.data(), buffer.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TLSSocket::size_type TLSSocket_OpenSSL::receiveRaw(char* buffer, const size_type count)
|
||||||
|
{
|
||||||
|
int rc = SSL_read(m_ssl, buffer, count);
|
||||||
|
handleError(rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::sendRaw(const char* buffer, const size_type count)
|
||||||
|
{
|
||||||
|
int rc = SSL_write(m_ssl, buffer, count);
|
||||||
|
handleError(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::handshake(ref <timeoutHandler> toHandler)
|
||||||
|
{
|
||||||
|
if (toHandler)
|
||||||
|
toHandler->resetTimeOut();
|
||||||
|
|
||||||
|
// Start handshaking process
|
||||||
|
m_toHandler = toHandler;
|
||||||
|
|
||||||
|
if (!m_ssl)
|
||||||
|
createSSLHandle();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// int ret = SSL_connect(m_ssl);
|
||||||
|
int ret = SSL_do_handshake(m_ssl);
|
||||||
|
handleError(ret);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
SSL_free(m_ssl);
|
||||||
|
m_ssl = 0;
|
||||||
|
m_toHandler = NULL;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_toHandler = NULL;
|
||||||
|
|
||||||
|
// Verify server's certificate(s)
|
||||||
|
ref <security::cert::certificateChain> certs = getPeerCertificates();
|
||||||
|
|
||||||
|
if (certs == NULL)
|
||||||
|
throw exceptions::tls_exception("No peer certificate.");
|
||||||
|
|
||||||
|
m_session->getCertificateVerifier()->verify(certs);
|
||||||
|
|
||||||
|
m_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <security::cert::certificateChain> TLSSocket_OpenSSL::getPeerCertificates() const
|
||||||
|
{
|
||||||
|
STACK_OF(X509)* chain = SSL_get_peer_cert_chain(m_ssl);
|
||||||
|
|
||||||
|
if (chain == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int certCount = sk_X509_num(chain);
|
||||||
|
|
||||||
|
if (certCount == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
std::vector <ref <security::cert::certificate> > certs;
|
||||||
|
|
||||||
|
for (int i = 0; i < certCount && !error; i++)
|
||||||
|
{
|
||||||
|
ref <vmime::security::cert::X509Certificate> cert =
|
||||||
|
vmime::security::cert::X509Certificate_OpenSSL::importInternal(sk_X509_value(chain, i));
|
||||||
|
|
||||||
|
if (cert)
|
||||||
|
certs.push_back(cert);
|
||||||
|
else
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return vmime::create <security::cert::certificateChain>(certs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TLSSocket_OpenSSL::handleError(int rc)
|
||||||
|
{
|
||||||
|
if (rc > 0) return;
|
||||||
|
|
||||||
|
int sslError = SSL_get_error(m_ssl, rc);
|
||||||
|
long lastError = ERR_get_error();
|
||||||
|
|
||||||
|
switch (sslError)
|
||||||
|
{
|
||||||
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
{
|
||||||
|
if (lastError == 0)
|
||||||
|
{
|
||||||
|
if (rc == 0)
|
||||||
|
throw exceptions::tls_exception("SSL connection unexpectedly closed");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vmime::string msg;
|
||||||
|
std::ostringstream oss(msg);
|
||||||
|
oss << "The BIO reported an error: %d" << rc;
|
||||||
|
oss.flush();
|
||||||
|
throw exceptions::tls_exception(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Follwoing errors should not occur
|
||||||
|
// With SSL_MODE_AUTO_RETRY these should not happen
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
// This happens only for BIOs of type BIO_s_connect() or BIO_s_accept()
|
||||||
|
case SSL_ERROR_WANT_CONNECT:
|
||||||
|
case SSL_ERROR_WANT_ACCEPT:
|
||||||
|
// SSL_CTX_set_client_cert_cb related, not used
|
||||||
|
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
default:
|
||||||
|
|
||||||
|
if (lastError == 0)
|
||||||
|
{
|
||||||
|
throw exceptions::tls_exception("Unexpected SSL IO error");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
ERR_error_string_n(lastError, buffer, sizeof(buffer));
|
||||||
|
vmime::string msg(buffer);
|
||||||
|
throw exceptions::tls_exception(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Implementation of custom BIO methods
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len)
|
||||||
|
{
|
||||||
|
if (buf == NULL || len <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(bio->ptr);
|
||||||
|
|
||||||
|
sok->m_wrapped->sendRaw(buf, len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len)
|
||||||
|
{
|
||||||
|
if (buf == NULL || len <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(bio->ptr);
|
||||||
|
|
||||||
|
const int n = sok->m_wrapped->receiveRaw(buf, len);
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
BIO_set_retry_read(bio); // This seems like a hack, really...
|
||||||
|
else
|
||||||
|
BIO_clear_retry_flags(bio);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str)
|
||||||
|
{
|
||||||
|
return bio_write(bio, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
int TLSSocket_OpenSSL::bio_gets(BIO* /* bio */, char* /* buf */, int /* len */)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
long TLSSocket_OpenSSL::bio_ctrl(BIO* /* bio */, int cmd, long /* num */, void* /* ptr */)
|
||||||
|
{
|
||||||
|
if (cmd == BIO_CTRL_FLUSH)
|
||||||
|
{
|
||||||
|
// OpenSSL library needs this
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
int TLSSocket_OpenSSL::bio_create(BIO* bio)
|
||||||
|
{
|
||||||
|
bio->init = 1;
|
||||||
|
bio->num = 0;
|
||||||
|
bio->ptr = NULL;
|
||||||
|
bio->flags = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
int TLSSocket_OpenSSL::bio_destroy(BIO* bio)
|
||||||
|
{
|
||||||
|
if (bio == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bio->ptr = NULL;
|
||||||
|
bio->init = 0;
|
||||||
|
bio->flags = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
67
src/platforms/posix/posixCriticalSection.cpp
Executable file
67
src/platforms/posix/posixCriticalSection.cpp
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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_PLATFORM_IS_POSIX
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/platforms/posix/posixCriticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace platforms {
|
||||||
|
namespace posix {
|
||||||
|
|
||||||
|
|
||||||
|
posixCriticalSection::posixCriticalSection()
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&m_cs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
posixCriticalSection::~posixCriticalSection()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&m_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void posixCriticalSection::lock()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void posixCriticalSection::unlock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&m_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // posix
|
||||||
|
} // platforms
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_PLATFORM_IS_POSIX
|
@ -29,8 +29,10 @@
|
|||||||
|
|
||||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||||
|
|
||||||
#include <time.h>
|
#include "vmime/platforms/posix/posixCriticalSection.hpp"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
@ -39,10 +41,15 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#if VMIME_HAVE_SYSCALL
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#if VMIME_HAVE_PTHREAD
|
#if VMIME_HAVE_PTHREAD
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
@ -217,6 +224,18 @@ unsigned int posixHandler::getProcessId() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int posixHandler::getThreadId() const
|
||||||
|
{
|
||||||
|
#if VMIME_HAVE_GETTID
|
||||||
|
return static_cast <unsigned int>(::gettid());
|
||||||
|
#elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID
|
||||||
|
return static_cast <unsigned int>(::syscall(SYS_gettid));
|
||||||
|
#else
|
||||||
|
#error We have no implementation of getThreadId() for this platform!
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
|
||||||
ref <vmime::net::socketFactory> posixHandler::getSocketFactory()
|
ref <vmime::net::socketFactory> posixHandler::getSocketFactory()
|
||||||
@ -261,6 +280,29 @@ void posixHandler::wait() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void posixHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count)
|
||||||
|
{
|
||||||
|
int fd = open("/dev/urandom", O_RDONLY);
|
||||||
|
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
read(fd, buffer, count);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
else // fallback
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0 ; i < count ; ++i)
|
||||||
|
buffer[i] = static_cast <unsigned char>(rand() % 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <utility::sync::criticalSection> posixHandler::createCriticalSection()
|
||||||
|
{
|
||||||
|
return vmime::create <posixCriticalSection>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // posix
|
} // posix
|
||||||
} // platforms
|
} // platforms
|
||||||
} // vmime
|
} // vmime
|
||||||
|
67
src/platforms/windows/windowsCriticalSection.cpp
Executable file
67
src/platforms/windows/windowsCriticalSection.cpp
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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_PLATFORM_IS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/platforms/windows/windowsCriticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace platforms {
|
||||||
|
namespace windows {
|
||||||
|
|
||||||
|
|
||||||
|
windowsCriticalSection::windowsCriticalSection()
|
||||||
|
{
|
||||||
|
InitializeCriticalSectionAndSpinCount(&m_cs, 0x400);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
windowsCriticalSection::~windowsCriticalSection()
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(&m_cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowsCriticalSection::lock()
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&m_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowsCriticalSection::unlock()
|
||||||
|
{
|
||||||
|
LeaveCriticalSection(&m_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // windows
|
||||||
|
} // platforms
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_PLATFORM_IS_WINDOWS
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include "vmime/platforms/windows/windowsHandler.hpp"
|
#include "vmime/platforms/windows/windowsHandler.hpp"
|
||||||
|
|
||||||
|
#include "vmime/platforms/windows/windowsCriticalSection.hpp"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
@ -239,6 +241,12 @@ unsigned int windowsHandler::getProcessId() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int windowsHandler::getThreadId() cont
|
||||||
|
{
|
||||||
|
return static_cast <unsigned int>(::GetCurrentThreadId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
|
||||||
ref <vmime::net::socketFactory> windowsHandler::getSocketFactory()
|
ref <vmime::net::socketFactory> windowsHandler::getSocketFactory()
|
||||||
@ -272,6 +280,21 @@ void windowsHandler::wait() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void windowsHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count)
|
||||||
|
{
|
||||||
|
HCRYPTPROV cryptProvider = 0;
|
||||||
|
CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
|
||||||
|
CryptGenRandom(cryptProvider, static_cast <unsigned long>(count), static_cast <unsigned char*>(buffer));
|
||||||
|
CryptReleaseContext(cryptProvider, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ref <utility::sync::criticalSection> posixHandler::createCriticalSection()
|
||||||
|
{
|
||||||
|
return vmime::create <windowsCriticalSection>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // posix
|
} // posix
|
||||||
} // platforms
|
} // platforms
|
||||||
} // vmime
|
} // vmime
|
||||||
|
@ -21,240 +21,22 @@
|
|||||||
// the GNU General Public License cover the whole combination.
|
// the GNU General Public License cover the whole combination.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <gnutls/gnutls.h>
|
#include "vmime/config.hpp"
|
||||||
#include <gnutls/x509.h>
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#include "vmime/security/cert/X509Certificate.hpp"
|
#include "vmime/security/cert/X509Certificate.hpp"
|
||||||
|
|
||||||
#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace vmime {
|
namespace vmime {
|
||||||
namespace security {
|
namespace security {
|
||||||
namespace cert {
|
namespace cert {
|
||||||
|
|
||||||
|
|
||||||
#ifndef VMIME_BUILDING_DOC
|
|
||||||
|
|
||||||
struct X509CertificateInternalData
|
|
||||||
{
|
|
||||||
X509CertificateInternalData()
|
|
||||||
{
|
|
||||||
gnutls_x509_crt_init(&cert);
|
|
||||||
}
|
|
||||||
|
|
||||||
~X509CertificateInternalData()
|
|
||||||
{
|
|
||||||
gnutls_x509_crt_deinit(cert);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gnutls_x509_crt cert;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // VMIME_BUILDING_DOC
|
|
||||||
|
|
||||||
|
|
||||||
X509Certificate::X509Certificate()
|
|
||||||
: m_data(new X509CertificateInternalData)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
X509Certificate::X509Certificate(const X509Certificate&)
|
|
||||||
: certificate(), m_data(NULL)
|
|
||||||
{
|
|
||||||
// Not used
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
X509Certificate::~X509Certificate()
|
X509Certificate::~X509Certificate()
|
||||||
{
|
{
|
||||||
delete m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
ref <X509Certificate> X509Certificate::import(utility::inputStream& is)
|
|
||||||
{
|
|
||||||
byteArray bytes;
|
|
||||||
utility::stream::value_type chunk[4096];
|
|
||||||
|
|
||||||
while (!is.eof())
|
|
||||||
{
|
|
||||||
const int len = is.read(chunk, sizeof(chunk));
|
|
||||||
bytes.insert(bytes.end(), chunk, chunk + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return import(&bytes[0], bytes.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
ref <X509Certificate> X509Certificate::import
|
|
||||||
(const byte_t* data, const unsigned int length)
|
|
||||||
{
|
|
||||||
gnutls_datum buffer;
|
|
||||||
buffer.data = const_cast <byte_t*>(data);
|
|
||||||
buffer.size = length;
|
|
||||||
|
|
||||||
// Try DER format
|
|
||||||
ref <X509Certificate> derCert = vmime::create <X509Certificate>();
|
|
||||||
|
|
||||||
if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0)
|
|
||||||
return derCert;
|
|
||||||
|
|
||||||
// Try PEM format
|
|
||||||
ref <X509Certificate> pemCert = vmime::create <X509Certificate>();
|
|
||||||
|
|
||||||
if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0)
|
|
||||||
return pemCert;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void X509Certificate::write
|
|
||||||
(utility::outputStream& os, const Format format) const
|
|
||||||
{
|
|
||||||
size_t dataSize = 0;
|
|
||||||
gnutls_x509_crt_fmt fmt = GNUTLS_X509_FMT_DER;
|
|
||||||
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break;
|
|
||||||
case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gnutls_x509_crt_export(m_data->cert, fmt, NULL, &dataSize);
|
|
||||||
|
|
||||||
std::vector <byte_t> data(dataSize);
|
|
||||||
|
|
||||||
gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize);
|
|
||||||
|
|
||||||
os.write(reinterpret_cast <utility::stream::value_type*>(&data[0]), dataSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const byteArray X509Certificate::getSerialNumber() const
|
|
||||||
{
|
|
||||||
char serial[64];
|
|
||||||
size_t serialSize = sizeof(serial);
|
|
||||||
|
|
||||||
gnutls_x509_crt_get_serial(m_data->cert, serial, &serialSize);
|
|
||||||
|
|
||||||
return byteArray(serial, serial + serialSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool X509Certificate::checkIssuer(ref <const X509Certificate> issuer) const
|
|
||||||
{
|
|
||||||
return (gnutls_x509_crt_check_issuer
|
|
||||||
(m_data->cert, issuer->m_data->cert) >= 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool X509Certificate::verify(ref <const X509Certificate> caCert) const
|
|
||||||
{
|
|
||||||
unsigned int verify = 0;
|
|
||||||
|
|
||||||
const int res = gnutls_x509_crt_verify
|
|
||||||
(m_data->cert, &(caCert->m_data->cert), 1,
|
|
||||||
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
|
|
||||||
&verify);
|
|
||||||
|
|
||||||
return (res == 0 && verify == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const datetime X509Certificate::getActivationDate() const
|
|
||||||
{
|
|
||||||
const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert);
|
|
||||||
return datetime(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const datetime X509Certificate::getExpirationDate() const
|
|
||||||
{
|
|
||||||
const time_t t = gnutls_x509_crt_get_expiration_time(m_data->cert);
|
|
||||||
return datetime(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const byteArray X509Certificate::getFingerprint(const DigestAlgorithm algo) const
|
|
||||||
{
|
|
||||||
gnutls_digest_algorithm galgo;
|
|
||||||
|
|
||||||
switch (algo)
|
|
||||||
{
|
|
||||||
case DIGEST_MD5:
|
|
||||||
|
|
||||||
galgo = GNUTLS_DIG_MD5;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case DIGEST_SHA1:
|
|
||||||
|
|
||||||
galgo = GNUTLS_DIG_SHA;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bufferSize = 0;
|
|
||||||
gnutls_x509_crt_get_fingerprint
|
|
||||||
(m_data->cert, galgo, NULL, &bufferSize);
|
|
||||||
|
|
||||||
std::vector <byte_t> buffer(bufferSize);
|
|
||||||
|
|
||||||
if (gnutls_x509_crt_get_fingerprint
|
|
||||||
(m_data->cert, galgo, &buffer[0], &bufferSize) == 0)
|
|
||||||
{
|
|
||||||
byteArray res;
|
|
||||||
res.insert(res.end(), &buffer[0], &buffer[0] + bufferSize);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return byteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const byteArray X509Certificate::getEncoded() const
|
|
||||||
{
|
|
||||||
byteArray bytes;
|
|
||||||
utility::outputStreamByteArrayAdapter os(bytes);
|
|
||||||
|
|
||||||
write(os, FORMAT_DER);
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const string X509Certificate::getType() const
|
|
||||||
{
|
|
||||||
return "X.509";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int X509Certificate::getVersion() const
|
|
||||||
{
|
|
||||||
return gnutls_x509_crt_get_version(m_data->cert);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool X509Certificate::equals(ref <const certificate> other) const
|
|
||||||
{
|
|
||||||
ref <const X509Certificate> otherX509 =
|
|
||||||
other.dynamicCast <const X509Certificate>();
|
|
||||||
|
|
||||||
if (!otherX509)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const byteArray fp1 = getFingerprint(DIGEST_MD5);
|
|
||||||
const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5);
|
|
||||||
|
|
||||||
return fp1 == fp2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -262,3 +44,5 @@ bool X509Certificate::equals(ref <const certificate> other) const
|
|||||||
} // security
|
} // security
|
||||||
} // vmime
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
278
src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
Normal file
278
src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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>
|
||||||
|
#include <gnutls/x509.h>
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include "vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp"
|
||||||
|
|
||||||
|
#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace security {
|
||||||
|
namespace cert {
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
struct GnuTLSX509CertificateInternalData
|
||||||
|
{
|
||||||
|
GnuTLSX509CertificateInternalData()
|
||||||
|
{
|
||||||
|
gnutls_x509_crt_init(&cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
~GnuTLSX509CertificateInternalData()
|
||||||
|
{
|
||||||
|
gnutls_x509_crt_deinit(cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gnutls_x509_crt cert;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_GnuTLS::X509Certificate_GnuTLS()
|
||||||
|
: m_data(new GnuTLSX509CertificateInternalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_GnuTLS::X509Certificate_GnuTLS(const X509Certificate&)
|
||||||
|
: certificate(), m_data(NULL)
|
||||||
|
{
|
||||||
|
// Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_GnuTLS::~X509Certificate_GnuTLS()
|
||||||
|
{
|
||||||
|
delete m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <X509Certificate> X509Certificate::import(utility::inputStream& is)
|
||||||
|
{
|
||||||
|
byteArray bytes;
|
||||||
|
utility::stream::value_type chunk[4096];
|
||||||
|
|
||||||
|
while (!is.eof())
|
||||||
|
{
|
||||||
|
const int len = is.read(chunk, sizeof(chunk));
|
||||||
|
bytes.insert(bytes.end(), chunk, chunk + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return import(&bytes[0], bytes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <X509Certificate> X509Certificate::import
|
||||||
|
(const byte_t* data, const unsigned int length)
|
||||||
|
{
|
||||||
|
gnutls_datum buffer;
|
||||||
|
buffer.data = const_cast <byte_t*>(data);
|
||||||
|
buffer.size = length;
|
||||||
|
|
||||||
|
// Try DER format
|
||||||
|
ref <X509Certificate> derCert = vmime::create <X509Certificate_GnuTLS>();
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0)
|
||||||
|
return derCert;
|
||||||
|
|
||||||
|
// Try PEM format
|
||||||
|
ref <X509Certificate> pemCert = vmime::create <X509Certificate_GnuTLS>();
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0)
|
||||||
|
return pemCert;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void X509Certificate_GnuTLS::write
|
||||||
|
(utility::outputStream& os, const Format format) const
|
||||||
|
{
|
||||||
|
size_t dataSize = 0;
|
||||||
|
gnutls_x509_crt_fmt fmt = GNUTLS_X509_FMT_DER;
|
||||||
|
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break;
|
||||||
|
case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_x509_crt_export(m_data->cert, fmt, NULL, &dataSize);
|
||||||
|
|
||||||
|
std::vector <byte_t> data(dataSize);
|
||||||
|
|
||||||
|
gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize);
|
||||||
|
|
||||||
|
os.write(reinterpret_cast <utility::stream::value_type*>(&data[0]), dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const byteArray X509Certificate_GnuTLS::getSerialNumber() const
|
||||||
|
{
|
||||||
|
char serial[64];
|
||||||
|
size_t serialSize = sizeof(serial);
|
||||||
|
|
||||||
|
gnutls_x509_crt_get_serial(m_data->cert, serial, &serialSize);
|
||||||
|
|
||||||
|
return byteArray(serial, serial + serialSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X509Certificate_GnuTLS::checkIssuer(ref <const X509Certificate> issuer_) const
|
||||||
|
{
|
||||||
|
ref <const X509Certificate_GnuTLS> issuer =
|
||||||
|
issuer.dynamicCast <const OpenSSLX509Certificate_GnuTLS>();
|
||||||
|
|
||||||
|
return (gnutls_x509_crt_check_issuer
|
||||||
|
(m_data->cert, issuer->m_data->cert) >= 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X509Certificate_GnuTLS::verify(ref <const X509Certificate> caCert_) const
|
||||||
|
{
|
||||||
|
ref <const X509Certificate_GnuTLS> caCert =
|
||||||
|
caCert_.dynamicCast <const X509Certificate_GnuTLS>();
|
||||||
|
|
||||||
|
unsigned int verify = 0;
|
||||||
|
|
||||||
|
const int res = gnutls_x509_crt_verify
|
||||||
|
(m_data->cert, &(caCert->m_data->cert), 1,
|
||||||
|
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
|
||||||
|
&verify);
|
||||||
|
|
||||||
|
return (res == 0 && verify == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime X509Certificate_GnuTLS::getActivationDate() const
|
||||||
|
{
|
||||||
|
const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert);
|
||||||
|
return datetime(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime X509Certificate_GnuTLS::getExpirationDate() const
|
||||||
|
{
|
||||||
|
const time_t t = gnutls_x509_crt_get_expiration_time(m_data->cert);
|
||||||
|
return datetime(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const byteArray X509Certificate_GnuTLS::getFingerprint(const DigestAlgorithm algo) const
|
||||||
|
{
|
||||||
|
gnutls_digest_algorithm galgo;
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case DIGEST_MD5:
|
||||||
|
|
||||||
|
galgo = GNUTLS_DIG_MD5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case DIGEST_SHA1:
|
||||||
|
|
||||||
|
galgo = GNUTLS_DIG_SHA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bufferSize = 0;
|
||||||
|
gnutls_x509_crt_get_fingerprint
|
||||||
|
(m_data->cert, galgo, NULL, &bufferSize);
|
||||||
|
|
||||||
|
std::vector <byte_t> buffer(bufferSize);
|
||||||
|
|
||||||
|
if (gnutls_x509_crt_get_fingerprint
|
||||||
|
(m_data->cert, galgo, &buffer[0], &bufferSize) == 0)
|
||||||
|
{
|
||||||
|
byteArray res;
|
||||||
|
res.insert(res.end(), &buffer[0], &buffer[0] + bufferSize);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return byteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const byteArray X509Certificate_GnuTLS::getEncoded() const
|
||||||
|
{
|
||||||
|
byteArray bytes;
|
||||||
|
utility::outputStreamByteArrayAdapter os(bytes);
|
||||||
|
|
||||||
|
write(os, FORMAT_DER);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string X509Certificate_GnuTLS::getType() const
|
||||||
|
{
|
||||||
|
return "X.509";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int X509Certificate_GnuTLS::getVersion() const
|
||||||
|
{
|
||||||
|
return gnutls_x509_crt_get_version(m_data->cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X509Certificate_GnuTLS::equals(ref <const certificate> other) const
|
||||||
|
{
|
||||||
|
ref <const X509Certificate_GnuTLS> otherX509 =
|
||||||
|
other.dynamicCast <const X509Certificate_GnuTLS>();
|
||||||
|
|
||||||
|
if (!otherX509)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const byteArray fp1 = getFingerprint(DIGEST_MD5);
|
||||||
|
const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5);
|
||||||
|
|
||||||
|
return fp1 == fp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // cert
|
||||||
|
} // security
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
467
src/security/cert/openssl/X509Certificate_OpenSSL.cpp
Executable file
467
src/security/cert/openssl/X509Certificate_OpenSSL.cpp
Executable file
@ -0,0 +1,467 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <ctime>
|
||||||
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp"
|
||||||
|
|
||||||
|
#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
|
||||||
|
|
||||||
|
#include "vmime/exception.hpp"
|
||||||
|
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace security {
|
||||||
|
namespace cert {
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
class monthMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
monthMap()
|
||||||
|
{
|
||||||
|
m_monthMap["jan"] = vmime::datetime::JAN;
|
||||||
|
m_monthMap["feb"] = vmime::datetime::FEB;
|
||||||
|
m_monthMap["mar"] = vmime::datetime::MAR;
|
||||||
|
m_monthMap["apr"] = vmime::datetime::APR;
|
||||||
|
m_monthMap["may"] = vmime::datetime::MAY;
|
||||||
|
m_monthMap["jun"] = vmime::datetime::JUN;
|
||||||
|
m_monthMap["jul"] = vmime::datetime::JUL;
|
||||||
|
m_monthMap["aug"] = vmime::datetime::AUG;
|
||||||
|
m_monthMap["sep"] = vmime::datetime::SEP;
|
||||||
|
m_monthMap["oct"] = vmime::datetime::OCT;
|
||||||
|
m_monthMap["nov"] = vmime::datetime::NOV;
|
||||||
|
m_monthMap["dec"] = vmime::datetime::DEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getMonth(vmime::string mstr)
|
||||||
|
{
|
||||||
|
std::transform(mstr.begin(), mstr.end(), mstr.begin(), ::tolower);
|
||||||
|
|
||||||
|
std::map <vmime::string, vmime::datetime::Months>::const_iterator
|
||||||
|
c_it = m_monthMap.find(mstr);
|
||||||
|
|
||||||
|
if (c_it != m_monthMap.end())
|
||||||
|
return c_it->second;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::map<vmime::string, vmime::datetime::Months> m_monthMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
static monthMap sg_monthMap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct OpenSSLX509CertificateInternalData
|
||||||
|
{
|
||||||
|
OpenSSLX509CertificateInternalData()
|
||||||
|
{
|
||||||
|
cert = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~OpenSSLX509CertificateInternalData()
|
||||||
|
{
|
||||||
|
if (cert)
|
||||||
|
X509_free(cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
X509* cert;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_OpenSSL::X509Certificate_OpenSSL()
|
||||||
|
: m_data(new OpenSSLX509CertificateInternalData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_OpenSSL::X509Certificate_OpenSSL(X509* cert)
|
||||||
|
: m_data(new OpenSSLX509CertificateInternalData)
|
||||||
|
{
|
||||||
|
m_data->cert = X509_dup(cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_OpenSSL::X509Certificate_OpenSSL(const X509Certificate_OpenSSL&)
|
||||||
|
: X509Certificate(), m_data(NULL)
|
||||||
|
{
|
||||||
|
// Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
X509Certificate_OpenSSL::~X509Certificate_OpenSSL()
|
||||||
|
{
|
||||||
|
delete m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <X509Certificate> X509Certificate_OpenSSL::importInternal(X509* cert)
|
||||||
|
{
|
||||||
|
if (cert)
|
||||||
|
return vmime::create <X509Certificate_OpenSSL>(reinterpret_cast <X509 *>(cert));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <X509Certificate> X509Certificate::import(utility::inputStream& is)
|
||||||
|
{
|
||||||
|
byteArray bytes;
|
||||||
|
utility::stream::value_type chunk[4096];
|
||||||
|
|
||||||
|
while (!is.eof())
|
||||||
|
{
|
||||||
|
const int len = is.read(chunk, sizeof(chunk));
|
||||||
|
bytes.insert(bytes.end(), chunk, chunk + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return import(&bytes[0], bytes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
ref <X509Certificate> X509Certificate::import
|
||||||
|
(const byte_t* data, const unsigned int length)
|
||||||
|
{
|
||||||
|
ref <X509Certificate_OpenSSL> cert = vmime::create <X509Certificate_OpenSSL>();
|
||||||
|
|
||||||
|
BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), length);
|
||||||
|
|
||||||
|
if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0))
|
||||||
|
{
|
||||||
|
BIO_vfree(membio);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BIO_vfree(membio);
|
||||||
|
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void X509Certificate_OpenSSL::write
|
||||||
|
(utility::outputStream& os, const Format format) const
|
||||||
|
{
|
||||||
|
BIO* membio = 0;
|
||||||
|
int dataSize = 0;
|
||||||
|
unsigned char* out = 0;
|
||||||
|
|
||||||
|
if (format == FORMAT_DER)
|
||||||
|
{
|
||||||
|
if ((dataSize = i2d_X509(m_data->cert, &out)) < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
os.write(reinterpret_cast <utility::stream::value_type*>(out), dataSize);
|
||||||
|
os.flush();
|
||||||
|
OPENSSL_free(out);
|
||||||
|
}
|
||||||
|
else if (format == FORMAT_PEM)
|
||||||
|
{
|
||||||
|
membio = BIO_new(BIO_s_mem());
|
||||||
|
BIO_set_close(membio, BIO_CLOSE);
|
||||||
|
|
||||||
|
if (!PEM_write_bio_X509(membio, m_data->cert))
|
||||||
|
goto pem_err;
|
||||||
|
|
||||||
|
dataSize = BIO_get_mem_data(membio, &out);
|
||||||
|
os.write(reinterpret_cast <utility::stream::value_type*>(out), dataSize);
|
||||||
|
os.flush();
|
||||||
|
BIO_vfree(membio);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw vmime::exceptions::unsupported_certificate_type("Unknown cert type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return; // #### Early Return ####
|
||||||
|
|
||||||
|
pem_err:
|
||||||
|
{
|
||||||
|
if (membio)
|
||||||
|
BIO_vfree(membio);
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
{
|
||||||
|
char errstr[256];
|
||||||
|
long ec = ERR_get_error();
|
||||||
|
ERR_error_string(ec, errstr);
|
||||||
|
throw vmime::exceptions::certificate_exception(
|
||||||
|
"OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const byteArray X509Certificate_OpenSSL::getSerialNumber() const
|
||||||
|
{
|
||||||
|
ASN1_INTEGER *serial = X509_get_serialNumber(m_data->cert);
|
||||||
|
BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL);
|
||||||
|
int n = BN_num_bytes(bnser);
|
||||||
|
byte_t* outbuf = new byte_t[n];
|
||||||
|
BN_bn2bin(bnser, outbuf);
|
||||||
|
byteArray ser(outbuf, outbuf + n);
|
||||||
|
delete [] outbuf;
|
||||||
|
BN_free(bnser);
|
||||||
|
return ser;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X509Certificate_OpenSSL::checkIssuer(ref <const X509Certificate> cert_) const
|
||||||
|
{
|
||||||
|
ref <const X509Certificate_OpenSSL> cert =
|
||||||
|
cert_.dynamicCast <const X509Certificate_OpenSSL>();
|
||||||
|
|
||||||
|
// Get issuer for this cert
|
||||||
|
BIO *out;
|
||||||
|
unsigned char *issuer;
|
||||||
|
|
||||||
|
out = BIO_new(BIO_s_mem());
|
||||||
|
X509_NAME_print_ex(out, X509_get_issuer_name(m_data->cert), 0, XN_FLAG_RFC2253);
|
||||||
|
int n = BIO_get_mem_data(out, &issuer);
|
||||||
|
vmime::string thisIssuerName((char*)issuer, n);
|
||||||
|
BIO_free(out);
|
||||||
|
|
||||||
|
// Get subject of issuer
|
||||||
|
unsigned char *subject;
|
||||||
|
out = BIO_new(BIO_s_mem());
|
||||||
|
X509_NAME_print_ex(out, X509_get_subject_name(cert->m_data->cert), 0, XN_FLAG_RFC2253);
|
||||||
|
n = BIO_get_mem_data(out, &subject);
|
||||||
|
vmime::string subjOfIssuer((char*)subject, n);
|
||||||
|
BIO_free(out);
|
||||||
|
|
||||||
|
return subjOfIssuer == thisIssuerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X509Certificate_OpenSSL::verify(ref <const X509Certificate> caCert_) const
|
||||||
|
{
|
||||||
|
ref <const X509Certificate_OpenSSL> caCert =
|
||||||
|
caCert_.dynamicCast <const X509Certificate_OpenSSL>();
|
||||||
|
|
||||||
|
|
||||||
|
bool verified = false;
|
||||||
|
bool error = true;
|
||||||
|
|
||||||
|
X509_STORE *store = X509_STORE_new();
|
||||||
|
|
||||||
|
if (store)
|
||||||
|
{
|
||||||
|
X509_STORE_CTX *verifyCtx = X509_STORE_CTX_new();
|
||||||
|
|
||||||
|
if (verifyCtx)
|
||||||
|
{
|
||||||
|
if (X509_STORE_add_cert(store, caCert->m_data->cert))
|
||||||
|
{
|
||||||
|
X509_STORE_CTX_init(verifyCtx, store, m_data->cert, NULL);
|
||||||
|
|
||||||
|
int ret = X509_verify_cert(verifyCtx);
|
||||||
|
|
||||||
|
if (ret == 1)
|
||||||
|
{
|
||||||
|
verified = true;
|
||||||
|
error = false;
|
||||||
|
}
|
||||||
|
else if (ret == 0)
|
||||||
|
{
|
||||||
|
verified = false;
|
||||||
|
error = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//X509_verify_cert_error_string(vrfy_ctx->error)
|
||||||
|
|
||||||
|
X509_STORE_CTX_free(verifyCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_STORE_free(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
return verified && !error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const
|
||||||
|
{
|
||||||
|
char* buffer;
|
||||||
|
BIO* out = BIO_new(BIO_s_mem());
|
||||||
|
BIO_set_close(out, BIO_CLOSE);
|
||||||
|
|
||||||
|
ASN1_TIME* asn1_time = reinterpret_cast<ASN1_TIME*>(time);
|
||||||
|
ASN1_TIME_print(out, asn1_time);
|
||||||
|
|
||||||
|
int sz = BIO_get_mem_data(out, &buffer);
|
||||||
|
char* dest = new char[sz + 1];
|
||||||
|
dest[sz] = 0;
|
||||||
|
memcpy(dest, buffer, sz);
|
||||||
|
vmime::string t(dest);
|
||||||
|
|
||||||
|
BIO_free(out);
|
||||||
|
delete dest;
|
||||||
|
|
||||||
|
if (t.size() > 0)
|
||||||
|
{
|
||||||
|
char month[4] = {0};
|
||||||
|
char zone[4] = {0};
|
||||||
|
int day, hour, minute, second, year;
|
||||||
|
int nrconv = sscanf(t.c_str(), "%s %2d %02d:%02d:%02d %d%s", month, &day, &hour, &minute, &second,&year,zone);
|
||||||
|
|
||||||
|
if (nrconv >= 6)
|
||||||
|
return datetime(year, sg_monthMap.getMonth(vmime::string(month)), day, hour, minute, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let datetime try and parse it
|
||||||
|
return datetime(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime X509Certificate_OpenSSL::getActivationDate() const
|
||||||
|
{
|
||||||
|
return convertX509Date(X509_get_notBefore(m_data->cert));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime X509Certificate_OpenSSL::getExpirationDate() const
|
||||||
|
{
|
||||||
|
return convertX509Date(X509_get_notAfter(m_data->cert));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm algo) const
|
||||||
|
{
|
||||||
|
BIO *out;
|
||||||
|
int j;
|
||||||
|
unsigned int n;
|
||||||
|
const EVP_MD *digest;
|
||||||
|
unsigned char * fingerprint, *result;
|
||||||
|
unsigned char md[EVP_MAX_MD_SIZE];
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case DIGEST_MD5:
|
||||||
|
|
||||||
|
digest = EVP_md5();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case DIGEST_SHA1:
|
||||||
|
|
||||||
|
digest = EVP_sha1();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = BIO_new(BIO_s_mem());
|
||||||
|
BIO_set_close(out, BIO_CLOSE);
|
||||||
|
|
||||||
|
if (X509_digest(m_data->cert, digest, md, &n))
|
||||||
|
{
|
||||||
|
for (j=0; j<(int)n; j++)
|
||||||
|
{
|
||||||
|
BIO_printf (out, "%02X",md[j]);
|
||||||
|
if (j+1 != (int)n) BIO_printf(out, ":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n = BIO_get_mem_data(out, &fingerprint);
|
||||||
|
result = new unsigned char[n];
|
||||||
|
memcpy (result, fingerprint, n);
|
||||||
|
BIO_free(out);
|
||||||
|
|
||||||
|
byteArray res;
|
||||||
|
res.insert(res.end(), &result[0], &result[0] + n);
|
||||||
|
|
||||||
|
delete [] result;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const byteArray X509Certificate_OpenSSL::getEncoded() const
|
||||||
|
{
|
||||||
|
byteArray bytes;
|
||||||
|
utility::outputStreamByteArrayAdapter os(bytes);
|
||||||
|
|
||||||
|
write(os, FORMAT_DER);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string X509Certificate_OpenSSL::getType() const
|
||||||
|
{
|
||||||
|
return "X.509";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int X509Certificate_OpenSSL::getVersion() const
|
||||||
|
{
|
||||||
|
return (int)X509_get_version(m_data->cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool X509Certificate_OpenSSL::equals(ref <const certificate> other) const
|
||||||
|
{
|
||||||
|
ref <const X509Certificate_OpenSSL> otherX509 =
|
||||||
|
other.dynamicCast <const X509Certificate_OpenSSL>();
|
||||||
|
|
||||||
|
if (!otherX509)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const byteArray fp1 = getFingerprint(DIGEST_MD5);
|
||||||
|
const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5);
|
||||||
|
|
||||||
|
return fp1 == fp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // cert
|
||||||
|
} // security
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
44
src/utility/sync/criticalSection.cpp
Executable file
44
src/utility/sync/criticalSection.cpp
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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/utility/sync/criticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace utility {
|
||||||
|
namespace sync {
|
||||||
|
|
||||||
|
|
||||||
|
criticalSection::criticalSection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
criticalSection::~criticalSection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // sync
|
||||||
|
} // utility
|
||||||
|
} // vmime
|
@ -28,7 +28,7 @@
|
|||||||
#include "vmime/config.hpp"
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
#include "vmime/types.hpp"
|
#include "vmime/types.hpp"
|
||||||
@ -47,19 +47,15 @@ namespace tls {
|
|||||||
*/
|
*/
|
||||||
class TLSSession : public object
|
class TLSSession : public object
|
||||||
{
|
{
|
||||||
friend class TLSSocket;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~TLSSession();
|
|
||||||
|
|
||||||
/** Create and initialize a new TLS session.
|
/** Create and initialize a new TLS session.
|
||||||
*
|
*
|
||||||
* @param cv object responsible for verifying certificates
|
* @param cv object responsible for verifying certificates
|
||||||
* sent by the server
|
* sent by the server
|
||||||
* @return a new TLS session
|
* @return a new TLS session
|
||||||
*/
|
*/
|
||||||
TLSSession(ref <security::cert::certificateVerifier> cv);
|
static ref <TLSSession> create(ref <security::cert::certificateVerifier> cv);
|
||||||
|
|
||||||
/** Create a new socket that adds a TLS security layer around
|
/** Create a new socket that adds a TLS security layer around
|
||||||
* an existing socket. You should create only one socket
|
* an existing socket. You should create only one socket
|
||||||
@ -68,27 +64,20 @@ public:
|
|||||||
* @param sok socket to wrap
|
* @param sok socket to wrap
|
||||||
* @return TLS socket wrapper
|
* @return TLS socket wrapper
|
||||||
*/
|
*/
|
||||||
ref <TLSSocket> getSocket(ref <socket> sok);
|
virtual ref <TLSSocket> getSocket(ref <socket> sok) = 0;
|
||||||
|
|
||||||
/** Get the object responsible for verifying certificates when
|
/** Get the object responsible for verifying certificates when
|
||||||
* using secured connections (TLS/SSL).
|
* using secured connections (TLS/SSL).
|
||||||
*/
|
*/
|
||||||
ref <security::cert::certificateVerifier> getCertificateVerifier();
|
virtual ref <security::cert::certificateVerifier> getCertificateVerifier() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
TLSSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
TLSSession(const TLSSession&);
|
TLSSession(const TLSSession&);
|
||||||
|
|
||||||
static void throwTLSException(const string& fname, const int code);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef LIBGNUTLS_VERSION
|
|
||||||
gnutls_session* m_gnutlsSession;
|
|
||||||
#else
|
|
||||||
void* m_gnutlsSession;
|
|
||||||
#endif // LIBGNUTLS_VERSION
|
|
||||||
|
|
||||||
ref <security::cert::certificateVerifier> m_certVerifier;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -97,7 +86,6 @@ private:
|
|||||||
} // vmime
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
#endif // VMIME_NET_TLS_TLSSESSION_HPP_INCLUDED
|
#endif // VMIME_NET_TLS_TLSSESSION_HPP_INCLUDED
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include "vmime/config.hpp"
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
#include "vmime/exception.hpp"
|
#include "vmime/exception.hpp"
|
||||||
@ -51,9 +51,7 @@ class TLSSession;
|
|||||||
*/
|
*/
|
||||||
class TLSSocket : public socket
|
class TLSSocket : public socket
|
||||||
{
|
{
|
||||||
friend class vmime::creator;
|
public:
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/** Create a new socket object that adds a security layer
|
/** Create a new socket object that adds a security layer
|
||||||
* around an existing socket.
|
* around an existing socket.
|
||||||
@ -61,12 +59,7 @@ protected:
|
|||||||
* @param session TLS session
|
* @param session TLS session
|
||||||
* @param sok socket to wrap
|
* @param sok socket to wrap
|
||||||
*/
|
*/
|
||||||
TLSSocket(ref <TLSSession> session, ref <socket> sok);
|
static ref <TLSSocket> wrap(ref <TLSSession> session, ref <socket> sok);
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
~TLSSocket();
|
|
||||||
|
|
||||||
|
|
||||||
/** Starts a TLS handshake on this connection.
|
/** Starts a TLS handshake on this connection.
|
||||||
*
|
*
|
||||||
@ -74,53 +67,14 @@ public:
|
|||||||
* during the negociation process, exceptions::operation_timed_out
|
* during the negociation process, exceptions::operation_timed_out
|
||||||
* if a time-out occurs
|
* if a time-out occurs
|
||||||
*/
|
*/
|
||||||
void handshake(ref <timeoutHandler> toHandler = NULL);
|
virtual void handshake(ref <timeoutHandler> toHandler = NULL) = 0;
|
||||||
|
|
||||||
/** Return the peer's certificate (chain) as sent by the peer.
|
/** Return the peer's certificate (chain) as sent by the peer.
|
||||||
*
|
*
|
||||||
* @return server certificate chain, or NULL if the handshake
|
* @return server certificate chain, or NULL if the handshake
|
||||||
* has not been performed yet
|
* has not been performed yet
|
||||||
*/
|
*/
|
||||||
ref <security::cert::certificateChain> getPeerCertificates() const;
|
virtual ref <security::cert::certificateChain> getPeerCertificates() const = 0;
|
||||||
|
|
||||||
|
|
||||||
// Implementation of 'socket'
|
|
||||||
void connect(const string& address, const port_t port);
|
|
||||||
void disconnect();
|
|
||||||
bool isConnected() const;
|
|
||||||
|
|
||||||
void receive(string& buffer);
|
|
||||||
size_type receiveRaw(char* buffer, const size_type count);
|
|
||||||
|
|
||||||
void send(const string& buffer);
|
|
||||||
void sendRaw(const char* buffer, const size_type count);
|
|
||||||
|
|
||||||
size_type getBlockSize() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void internalThrow();
|
|
||||||
|
|
||||||
#ifdef LIBGNUTLS_VERSION
|
|
||||||
static ssize_t gnutlsPushFunc(gnutls_transport_ptr trspt, const void* data, size_t len);
|
|
||||||
static ssize_t gnutlsPullFunc(gnutls_transport_ptr trspt, void* data, size_t len);
|
|
||||||
#else
|
|
||||||
static int gnutlsPushFunc(void* trspt, const void* data, size_t len);
|
|
||||||
static int gnutlsPullFunc(void* trspt, void* data, size_t len);
|
|
||||||
#endif // LIBGNUTLS_VERSION
|
|
||||||
|
|
||||||
|
|
||||||
ref <TLSSession> m_session;
|
|
||||||
ref <socket> m_wrapped;
|
|
||||||
|
|
||||||
bool m_connected;
|
|
||||||
|
|
||||||
char m_buffer[65536];
|
|
||||||
|
|
||||||
bool m_handshaking;
|
|
||||||
ref <timeoutHandler> m_toHandler;
|
|
||||||
|
|
||||||
exception* m_ex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -129,7 +83,6 @@ private:
|
|||||||
} // vmime
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
#endif // VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED
|
#endif // VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED
|
||||||
|
|
||||||
|
89
vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp
Normal file
89
vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_TLS_TLSSESSION_GNUTLS_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_TLS_TLSSESSION_GNUTLS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/types.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/tls/TLSSession.hpp"
|
||||||
|
#include "vmime/net/tls/TLSSocket.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
class TLSSession_GnuTLS : public TLSSession
|
||||||
|
{
|
||||||
|
friend class TLSSocket_GnuTLS;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TLSSession_GnuTLS(ref <security::cert::certificateVerifier> cv);
|
||||||
|
~TLSSession_GnuTLS();
|
||||||
|
|
||||||
|
|
||||||
|
ref <TLSSocket> getSocket(ref <socket> sok);
|
||||||
|
|
||||||
|
ref <security::cert::certificateVerifier> getCertificateVerifier();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
TLSSession_GnuTLS(const TLSSession_GnuTLS&);
|
||||||
|
|
||||||
|
static void throwTLSException(const string& fname, const int code);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LIBGNUTLS_VERSION
|
||||||
|
gnutls_session* m_gnutlsSession;
|
||||||
|
#else
|
||||||
|
void* m_gnutlsSession;
|
||||||
|
#endif // LIBGNUTLS_VERSION
|
||||||
|
|
||||||
|
ref <security::cert::certificateVerifier> m_certVerifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
#endif // VMIME_NET_TLS_TLSSESSION_GNUTLS_HPP_INCLUDED
|
||||||
|
|
113
vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp
Normal file
113
vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_TLS_TLSSOCKET_GNUTLS_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_TLS_TLSSOCKET_GNUTLS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/tls/TLSSocket.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
class TLSSession;
|
||||||
|
class TLSSession_GnuTLS;
|
||||||
|
|
||||||
|
|
||||||
|
class TLSSocket_GnuTLS : public TLSSocket
|
||||||
|
{
|
||||||
|
friend class vmime::creator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TLSSocket_GnuTLS(ref <TLSSession_GnuTLS> session, ref <socket> sok);
|
||||||
|
~TLSSocket_GnuTLS();
|
||||||
|
|
||||||
|
|
||||||
|
void handshake(ref <timeoutHandler> toHandler = NULL);
|
||||||
|
|
||||||
|
ref <security::cert::certificateChain> getPeerCertificates() const;
|
||||||
|
|
||||||
|
// Implementation of 'socket'
|
||||||
|
void connect(const string& address, const port_t port);
|
||||||
|
void disconnect();
|
||||||
|
bool isConnected() const;
|
||||||
|
|
||||||
|
void receive(string& buffer);
|
||||||
|
size_type receiveRaw(char* buffer, const size_type count);
|
||||||
|
|
||||||
|
void send(const string& buffer);
|
||||||
|
void sendRaw(const char* buffer, const size_type count);
|
||||||
|
|
||||||
|
size_type getBlockSize() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void internalThrow();
|
||||||
|
|
||||||
|
#ifdef LIBGNUTLS_VERSION
|
||||||
|
static ssize_t gnutlsPushFunc(gnutls_transport_ptr trspt, const void* data, size_t len);
|
||||||
|
static ssize_t gnutlsPullFunc(gnutls_transport_ptr trspt, void* data, size_t len);
|
||||||
|
#else
|
||||||
|
static int gnutlsPushFunc(void* trspt, const void* data, size_t len);
|
||||||
|
static int gnutlsPullFunc(void* trspt, void* data, size_t len);
|
||||||
|
#endif // LIBGNUTLS_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
ref <TLSSession_GnuTLS> m_session;
|
||||||
|
ref <socket> m_wrapped;
|
||||||
|
|
||||||
|
bool m_connected;
|
||||||
|
|
||||||
|
char m_buffer[65536];
|
||||||
|
|
||||||
|
bool m_handshaking;
|
||||||
|
ref <timeoutHandler> m_toHandler;
|
||||||
|
|
||||||
|
exception* m_ex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
#endif // VMIME_NET_TLS_TLSSOCKET_GNUTLS_HPP_INCLUDED
|
||||||
|
|
102
vmime/net/tls/openssl/OpenSSLInitializer.hpp
Executable file
102
vmime/net/tls/openssl/OpenSSLInitializer.hpp
Executable file
@ -0,0 +1,102 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_TLS_OPENSSL_OPENSSLINITIALIZER_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_TLS_OPENSSL_OPENSSLINITIALIZER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/utility/sync/criticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
/** Class responsible for setting up OpenSSL
|
||||||
|
*/
|
||||||
|
class OpenSSLInitializer
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Automatically initialize OpenSSL
|
||||||
|
*/
|
||||||
|
OpenSSLInitializer();
|
||||||
|
|
||||||
|
/** Automatically uninitialize OpenSSL
|
||||||
|
*/
|
||||||
|
~OpenSSLInitializer();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Initializes the OpenSSL lib
|
||||||
|
*/
|
||||||
|
static void initialize();
|
||||||
|
|
||||||
|
/** Shutdown the OpenSSL lib
|
||||||
|
*/
|
||||||
|
static void uninitialize();
|
||||||
|
|
||||||
|
|
||||||
|
static ref <vmime::utility::sync::criticalSection> getMutex();
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SEEDSIZE = 256
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// OpenSSL multithreading support
|
||||||
|
static void lock(int mode, int n, const char* file, int line);
|
||||||
|
static unsigned long id();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static ref <vmime::utility::sync::criticalSection >* sm_mutexes;
|
||||||
|
static int sm_initCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
#endif // VMIME_NET_TLS_OPENSSL_OPENSSLINITIALIZER_HPP_INCLUDED
|
||||||
|
|
106
vmime/net/tls/openssl/TLSSession_OpenSSL.hpp
Executable file
106
vmime/net/tls/openssl/TLSSession_OpenSSL.hpp
Executable file
@ -0,0 +1,106 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/types.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/tls/TLSSession.hpp"
|
||||||
|
#include "vmime/net/tls/TLSSocket.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
class TLSSession_OpenSSL : public TLSSession
|
||||||
|
{
|
||||||
|
friend class TLSSocket_OpenSSL;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TLSSession_OpenSSL(const ref <security::cert::certificateVerifier> cv);
|
||||||
|
~TLSSession_OpenSSL();
|
||||||
|
|
||||||
|
|
||||||
|
ref <TLSSocket> getSocket(ref <socket> sok);
|
||||||
|
|
||||||
|
ref <security::cert::certificateVerifier> getCertificateVerifier();
|
||||||
|
|
||||||
|
|
||||||
|
/** Set the private key to use if server requires a client certificate.
|
||||||
|
*
|
||||||
|
* @param keyfile Path to the private key in PEM format
|
||||||
|
* @param passwd_callback If the private key is stored encrypted the
|
||||||
|
*/
|
||||||
|
void usePrivateKeyFile(const vmime::string& keyfile);
|
||||||
|
|
||||||
|
/** Supply the certificate chain to present if requested by
|
||||||
|
* server.
|
||||||
|
*
|
||||||
|
* @param chainFile File in PEM format holding certificate chain
|
||||||
|
*/
|
||||||
|
void useCertificateChainFile(const vmime::string& chainFile);
|
||||||
|
|
||||||
|
/** Get a pointer to the SSL_CTX used for this session.
|
||||||
|
*
|
||||||
|
* @return the SSL_CTX used for all connections created with this session
|
||||||
|
*/
|
||||||
|
SSL_CTX* getContext() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
TLSSession_OpenSSL(const TLSSession_OpenSSL&);
|
||||||
|
|
||||||
|
SSL_CTX* m_sslctx;
|
||||||
|
|
||||||
|
ref <security::cert::certificateVerifier> m_certVerifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
#endif // VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED
|
||||||
|
|
116
vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp
Executable file
116
vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp
Executable file
@ -0,0 +1,116 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_NET_TLS_TLSSOCKET_OPENSSL_HPP_INCLUDED
|
||||||
|
#define VMIME_NET_TLS_TLSSOCKET_OPENSSL_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/net/tls/TLSSocket.hpp"
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace net {
|
||||||
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
class TLSSession;
|
||||||
|
class TLSSession_OpenSSL;
|
||||||
|
|
||||||
|
|
||||||
|
class TLSSocket_OpenSSL : public TLSSocket
|
||||||
|
{
|
||||||
|
friend class vmime::creator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TLSSocket_OpenSSL(ref <TLSSession_OpenSSL> session, ref <socket> sok);
|
||||||
|
~TLSSocket_OpenSSL();
|
||||||
|
|
||||||
|
|
||||||
|
void handshake(ref <timeoutHandler> toHandler = NULL);
|
||||||
|
|
||||||
|
ref <security::cert::certificateChain> getPeerCertificates() const;
|
||||||
|
|
||||||
|
// Implementation of 'socket'
|
||||||
|
void connect(const string& address, const port_t port);
|
||||||
|
void disconnect();
|
||||||
|
bool isConnected() const;
|
||||||
|
|
||||||
|
void receive(string& buffer);
|
||||||
|
size_type receiveRaw(char* buffer, const size_type count);
|
||||||
|
|
||||||
|
void send(const string& buffer);
|
||||||
|
void sendRaw(const char* buffer, const size_type count);
|
||||||
|
|
||||||
|
size_type getBlockSize() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static int bio_write(BIO* bio, const char* buf, int len);
|
||||||
|
static int bio_read(BIO* bio, char* buf, int len);
|
||||||
|
static int bio_puts(BIO* bio, const char* str);
|
||||||
|
static int bio_gets(BIO* bio, char* buf, int len);
|
||||||
|
static long bio_ctrl(BIO* bio, int cmd, long num, void* ptr);
|
||||||
|
static int bio_create(BIO* bio);
|
||||||
|
static int bio_destroy(BIO* bio);
|
||||||
|
|
||||||
|
void createSSLHandle();
|
||||||
|
|
||||||
|
void handleError(int rc);
|
||||||
|
|
||||||
|
ref <TLSSession_OpenSSL> m_session;
|
||||||
|
|
||||||
|
ref <socket> m_wrapped;
|
||||||
|
|
||||||
|
bool m_connected;
|
||||||
|
|
||||||
|
char m_buffer[65536];
|
||||||
|
|
||||||
|
ref <timeoutHandler> m_toHandler;
|
||||||
|
|
||||||
|
SSL* m_ssl;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // tls
|
||||||
|
} // net
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
#endif // VMIME_BUILDING_DOC
|
||||||
|
|
||||||
|
#endif // VMIME_NET_TLS_TLSSOCKET_OPENSSL_HPP_INCLUDED
|
||||||
|
|
@ -40,6 +40,8 @@
|
|||||||
#include "vmime/utility/childProcess.hpp"
|
#include "vmime/utility/childProcess.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "vmime/utility/sync/criticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace vmime
|
namespace vmime
|
||||||
{
|
{
|
||||||
@ -89,6 +91,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual unsigned int getProcessId() const = 0;
|
virtual unsigned int getProcessId() const = 0;
|
||||||
|
|
||||||
|
/** Return an unique identifier for the current thread.
|
||||||
|
* Used for multi-threading synchronization.
|
||||||
|
*
|
||||||
|
* @return current thread id
|
||||||
|
*/
|
||||||
|
virtual unsigned int getThreadId() const = 0;
|
||||||
|
|
||||||
/** Return the charset used on the system.
|
/** Return the charset used on the system.
|
||||||
*
|
*
|
||||||
* @return locale charset
|
* @return locale charset
|
||||||
@ -126,6 +135,16 @@ public:
|
|||||||
virtual ref <utility::childProcessFactory> getChildProcessFactory() = 0;
|
virtual ref <utility::childProcessFactory> getChildProcessFactory() = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Fills a buffer with cryptographically random bytes.
|
||||||
|
*
|
||||||
|
* @param buffer buffer to fill in with random bytes
|
||||||
|
* @param count number of random bytes to write in buffer
|
||||||
|
*/
|
||||||
|
virtual void generateRandomBytes(unsigned char* buffer, const unsigned int count) = 0;
|
||||||
|
|
||||||
|
/** Creates and initializes a critical section.
|
||||||
|
*/
|
||||||
|
virtual ref <utility::sync::criticalSection> createCriticalSection() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
69
vmime/platforms/posix/posixCriticalSection.hpp
Executable file
69
vmime/platforms/posix/posixCriticalSection.hpp
Executable file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
|
||||||
|
#define VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_PLATFORM_IS_POSIX
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/utility/sync/criticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace platforms {
|
||||||
|
namespace posix {
|
||||||
|
|
||||||
|
|
||||||
|
class posixCriticalSection : public utility::sync::criticalSection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
posixCriticalSection();
|
||||||
|
~posixCriticalSection();
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
pthread_mutex_t m_cs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // posix
|
||||||
|
} // platforms
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_PLATFORM_IS_POSIX
|
||||||
|
|
||||||
|
#endif // VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
|
@ -64,6 +64,7 @@ public:
|
|||||||
const vmime::string getHostName() const;
|
const vmime::string getHostName() const;
|
||||||
|
|
||||||
unsigned int getProcessId() const;
|
unsigned int getProcessId() const;
|
||||||
|
unsigned int getThreadId() const;
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
ref <vmime::net::socketFactory> getSocketFactory();
|
ref <vmime::net::socketFactory> getSocketFactory();
|
||||||
@ -77,6 +78,10 @@ public:
|
|||||||
|
|
||||||
void wait() const;
|
void wait() const;
|
||||||
|
|
||||||
|
void generateRandomBytes(unsigned char* buffer, const unsigned int count);
|
||||||
|
|
||||||
|
ref <utility::sync::criticalSection> createCriticalSection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
68
vmime/platforms/windows/windowsCriticalSection.hpp
Executable file
68
vmime/platforms/windows/windowsCriticalSection.hpp
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
|
||||||
|
#define VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_PLATFORM_IS_WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/utility/sync/criticalSection.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace platforms {
|
||||||
|
namespace windows {
|
||||||
|
|
||||||
|
|
||||||
|
class windowsCriticalSection : public utility::sync::criticalSection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
windowsCriticalSection();
|
||||||
|
~windowsCriticalSection();
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
CRITICAL_SECTION m_cs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // windows
|
||||||
|
} // platforms
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_PLATFORM_IS_WINDOWS
|
||||||
|
|
||||||
|
#endif // VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
|
@ -63,6 +63,7 @@ public:
|
|||||||
const vmime::string getHostName() const;
|
const vmime::string getHostName() const;
|
||||||
|
|
||||||
unsigned int getProcessId() const;
|
unsigned int getProcessId() const;
|
||||||
|
unsigned int getThreadId() const;
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
ref <vmime::net::socketFactory> getSocketFactory();
|
ref <vmime::net::socketFactory> getSocketFactory();
|
||||||
@ -76,6 +77,10 @@ public:
|
|||||||
|
|
||||||
void wait() const;
|
void wait() const;
|
||||||
|
|
||||||
|
void generateRandomBytes(unsigned char* buffer, const unsigned int count);
|
||||||
|
|
||||||
|
ref <utility::sync::criticalSection> createCriticalSection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
#define VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
|
#define VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
#include "vmime/security/cert/certificate.hpp"
|
#include "vmime/security/cert/certificate.hpp"
|
||||||
|
|
||||||
#include "vmime/utility/stream.hpp"
|
#include "vmime/utility/stream.hpp"
|
||||||
@ -42,13 +48,6 @@ namespace cert {
|
|||||||
*/
|
*/
|
||||||
class X509Certificate : public certificate
|
class X509Certificate : public certificate
|
||||||
{
|
{
|
||||||
friend class vmime::creator;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
X509Certificate();
|
|
||||||
X509Certificate(const X509Certificate&);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~X509Certificate();
|
~X509Certificate();
|
||||||
@ -90,7 +89,7 @@ public:
|
|||||||
* @param os output stream into which write data
|
* @param os output stream into which write data
|
||||||
* @param format output format
|
* @param format output format
|
||||||
*/
|
*/
|
||||||
void write(utility::outputStream& os, const Format format) const;
|
virtual void write(utility::outputStream& os, const Format format) const = 0;
|
||||||
|
|
||||||
/** Returns the X.509 certificate's serial number. This is obtained
|
/** Returns the X.509 certificate's serial number. This is obtained
|
||||||
* by the X.509 Certificate 'serialNumber' field. Serial is not
|
* by the X.509 Certificate 'serialNumber' field. Serial is not
|
||||||
@ -99,7 +98,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return serial number of this certificate
|
* @return serial number of this certificate
|
||||||
*/
|
*/
|
||||||
const byteArray getSerialNumber() const;
|
virtual const byteArray getSerialNumber() const = 0;
|
||||||
|
|
||||||
/** Checks if this certificate has the given issuer.
|
/** Checks if this certificate has the given issuer.
|
||||||
*
|
*
|
||||||
@ -107,45 +106,34 @@ public:
|
|||||||
* @return true if this certificate was issued by the given issuer,
|
* @return true if this certificate was issued by the given issuer,
|
||||||
* false otherwise
|
* false otherwise
|
||||||
*/
|
*/
|
||||||
bool checkIssuer(ref <const X509Certificate> issuer) const;
|
virtual bool checkIssuer(ref <const X509Certificate> issuer) const = 0;
|
||||||
|
|
||||||
/** Verifies this certificate against a given trusted one.
|
/** Verifies this certificate against a given trusted one.
|
||||||
*
|
*
|
||||||
* @param caCert a certificate that is considered to be trusted one
|
* @param caCert a certificate that is considered to be trusted one
|
||||||
* @return true if the verification succeeded, false otherwise
|
* @return true if the verification succeeded, false otherwise
|
||||||
*/
|
*/
|
||||||
bool verify(ref <const X509Certificate> caCert) const;
|
virtual bool verify(ref <const X509Certificate> caCert) const = 0;
|
||||||
|
|
||||||
/** Gets the expiration date of this certificate. This is the date
|
/** Gets the expiration date of this certificate. This is the date
|
||||||
* at which this certificate will not be valid anymore.
|
* at which this certificate will not be valid anymore.
|
||||||
*
|
*
|
||||||
* @return expiration date of this certificate
|
* @return expiration date of this certificate
|
||||||
*/
|
*/
|
||||||
const datetime getExpirationDate() const;
|
virtual const datetime getExpirationDate() const = 0;
|
||||||
|
|
||||||
/** Gets the activation date of this certificate. This is the date
|
/** Gets the activation date of this certificate. This is the date
|
||||||
* at which this certificate will be valid.
|
* at which this certificate will be valid.
|
||||||
*
|
*
|
||||||
* @return activation date of this certificate
|
* @return activation date of this certificate
|
||||||
*/
|
*/
|
||||||
const datetime getActivationDate() const;
|
virtual const datetime getActivationDate() const = 0;
|
||||||
|
|
||||||
/** Returns the fingerprint of this certificate.
|
/** Returns the fingerprint of this certificate.
|
||||||
*
|
*
|
||||||
* @return the fingerprint of this certificate
|
* @return the fingerprint of this certificate
|
||||||
*/
|
*/
|
||||||
const byteArray getFingerprint(const DigestAlgorithm algo) const;
|
virtual const byteArray getFingerprint(const DigestAlgorithm algo) const = 0;
|
||||||
|
|
||||||
|
|
||||||
// Implementation of 'certificate'
|
|
||||||
const byteArray getEncoded() const;
|
|
||||||
const string getType() const;
|
|
||||||
int getVersion() const;
|
|
||||||
bool equals(ref <const certificate> other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct X509CertificateInternalData* m_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -154,5 +142,7 @@ private:
|
|||||||
} // vmime
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
|
||||||
|
|
||||||
#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
|
#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
|
||||||
|
|
||||||
|
91
vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp
Normal file
91
vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED
|
||||||
|
#define VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/security/cert/X509Certificate.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace security {
|
||||||
|
namespace cert {
|
||||||
|
|
||||||
|
|
||||||
|
class X509Certificate_GnuTLS : public X509Certificate
|
||||||
|
{
|
||||||
|
friend class vmime::creator;
|
||||||
|
friend class X509Certificate;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
X509Certificate_GnuTLS();
|
||||||
|
X509Certificate_GnuTLS(const X509Certificate&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
~X509Certificate_GnuTLS();
|
||||||
|
|
||||||
|
|
||||||
|
void write(utility::outputStream& os, const Format format) const;
|
||||||
|
|
||||||
|
const byteArray getSerialNumber() const;
|
||||||
|
|
||||||
|
bool checkIssuer(ref <const X509Certificate> issuer) const;
|
||||||
|
|
||||||
|
bool verify(ref <const X509Certificate> caCert) const;
|
||||||
|
|
||||||
|
const datetime getExpirationDate() const;
|
||||||
|
const datetime getActivationDate() const;
|
||||||
|
|
||||||
|
const byteArray getFingerprint(const DigestAlgorithm algo) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Implementation of 'certificate'
|
||||||
|
const byteArray getEncoded() const;
|
||||||
|
const string getType() const;
|
||||||
|
int getVersion() const;
|
||||||
|
bool equals(ref <const certificate> other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct GnuTLSX509CertificateInternalData* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // cert
|
||||||
|
} // security
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
|
||||||
|
|
||||||
|
#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED
|
||||||
|
|
104
vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp
Normal file
104
vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED
|
||||||
|
#define VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/config.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/security/cert/X509Certificate.hpp"
|
||||||
|
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace security {
|
||||||
|
namespace cert {
|
||||||
|
|
||||||
|
|
||||||
|
class X509Certificate_OpenSSL : public X509Certificate
|
||||||
|
{
|
||||||
|
friend class vmime::creator;
|
||||||
|
friend class X509Certificate;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
X509Certificate_OpenSSL();
|
||||||
|
X509Certificate_OpenSSL(X509* cert);
|
||||||
|
X509Certificate_OpenSSL(const X509Certificate_OpenSSL&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
~X509Certificate_OpenSSL();
|
||||||
|
|
||||||
|
|
||||||
|
void write(utility::outputStream& os, const Format format) const;
|
||||||
|
|
||||||
|
const byteArray getSerialNumber() const;
|
||||||
|
|
||||||
|
bool checkIssuer(ref <const X509Certificate> issuer) const;
|
||||||
|
|
||||||
|
bool verify(ref <const X509Certificate> caCert) const;
|
||||||
|
|
||||||
|
const datetime getExpirationDate() const;
|
||||||
|
const datetime getActivationDate() const;
|
||||||
|
|
||||||
|
const byteArray getFingerprint(const DigestAlgorithm algo) const;
|
||||||
|
|
||||||
|
|
||||||
|
static ref <X509Certificate> importInternal(X509* cert);
|
||||||
|
|
||||||
|
|
||||||
|
// Implementation of 'certificate'
|
||||||
|
const byteArray getEncoded() const;
|
||||||
|
const string getType() const;
|
||||||
|
int getVersion() const;
|
||||||
|
bool equals(ref <const certificate> other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Internal utility function to convert ASN1_TIME
|
||||||
|
* structs to vmime::datetime
|
||||||
|
*
|
||||||
|
* @param pointer to ASN1_TIME struct to convert
|
||||||
|
*/
|
||||||
|
const datetime convertX509Date(void* time) const;
|
||||||
|
|
||||||
|
struct OpenSSLX509CertificateInternalData* m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // cert
|
||||||
|
} // security
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
|
||||||
|
|
||||||
|
#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED
|
||||||
|
|
66
vmime/utility/sync/autoLock.hpp
Executable file
66
vmime/utility/sync/autoLock.hpp
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED
|
||||||
|
#define VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/base.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace utility {
|
||||||
|
namespace sync {
|
||||||
|
|
||||||
|
|
||||||
|
/** Critical section wrapper class
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
class autoLock : public object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
autoLock(ref <M> mutex)
|
||||||
|
: m_mutex(mutex)
|
||||||
|
{
|
||||||
|
m_mutex->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~autoLock()
|
||||||
|
{
|
||||||
|
m_mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ref <M> m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // sync
|
||||||
|
} // utility
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED
|
65
vmime/utility/sync/criticalSection.hpp
Executable file
65
vmime/utility/sync/criticalSection.hpp
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED
|
||||||
|
#define VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "vmime/base.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime {
|
||||||
|
namespace utility {
|
||||||
|
namespace sync {
|
||||||
|
|
||||||
|
|
||||||
|
/** Critical section class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class criticalSection : public object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~criticalSection();
|
||||||
|
|
||||||
|
/** Enters the critical section.
|
||||||
|
*/
|
||||||
|
virtual void lock() = 0;
|
||||||
|
|
||||||
|
/** Leaves the critical section.
|
||||||
|
*/
|
||||||
|
virtual void unlock() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
criticalSection();
|
||||||
|
criticalSection(criticalSection&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // sync
|
||||||
|
} // utility
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED
|
Loading…
Reference in New Issue
Block a user