Added TLS/SSL support.

This commit is contained in:
Vincent Richard 2005-10-03 21:29:04 +00:00
parent e7ca1d2465
commit 7d2d25da3e
59 changed files with 4275 additions and 589 deletions

View File

@ -2,6 +2,10 @@
VERSION 0.7.2cvs
================
2005-10-03 Vincent Richard <vincent@vincent-richard.net>
* Added TLS/SSL support, using GNU TLS library.
2005-09-17 Vincent Richard <vincent@vincent-richard.net>
* Added SASL support, based on GNU SASL library. Slightly modified

View File

@ -26,33 +26,26 @@ import string
# Version #
#############
# How to increment version number when building a public release?
# ===============================================================
#
# Changing package version number:
#
# * Increment major number if major changes have been made to the library,
# that is, program depending on this library will need to be changed to
# work with the new major release.
#
# * Increment minor number when the changes are upward-compatible: some
# interfaces have been added, but compatibility is maintained for
# existing interfaces.
#
# * Increment micro number when the changes do not add any new interface.
# The changes only apply to the implementation (bug or security fix,
# performance improvement, etc.).
#
# Package version number
packageVersionMajor = 0
packageVersionMinor = 7
packageVersionMicro = 2
# Shared library version number (computed from package version number)
packageAPICurrent = packageVersionMajor + packageVersionMinor
packageAPIRevision = packageVersionMicro
packageAPIAge = packageVersionMinor
# API version number (libtool)
#
# Increment this number only immediately before a public release.
# This is independant from package version number.
#
# See: http://www.gnu.org/software/libtool/manual.html#Libtool-versioning
#
# . Implementation changed (eg. bug/security fix): REVISION++
# . Interfaces added/removed/changed: CURRENT++, REVISION=0
# . Interfaces added (upward-compatible changes): AGE++
# . Interfaces removed: AGE=0
#
packageAPICurrent = 0
packageAPIRevision = 0
packageAPIAge = 0
# Package information
packageName = 'libvmime'
@ -204,7 +197,6 @@ libvmime_examples_sources = [
]
libvmime_messaging_sources = [
'net/authHelper.cpp', 'net/authHelper.hpp',
'net/builtinServices.inl',
'net/events.cpp', 'net/events.hpp',
'net/folder.cpp', 'net/folder.hpp',
@ -219,11 +211,23 @@ libvmime_messaging_sources = [
'net/transport.cpp', 'net/transport.hpp'
]
libvmime_net_tls_sources = [
'net/tls/TLSSession.cpp', 'net/tls/TLSSession.hpp',
'net/tls/TLSSocket.cpp', 'net/tls/TLSSocket.hpp',
'net/tls/certificateChain.cpp', 'net/tls/certificateChain.hpp',
'net/tls/certificateVerifier.hpp',
'net/tls/defaultCertificateVerifier.cpp', 'net/tls/defaultCertificateVerifier.hpp',
'net/tls/certificate.hpp',
'net/tls/X509Certificate.cpp', 'net/tls/X509Certificate.hpp'
]
libvmime_messaging_proto_sources = [
[
'pop3',
[
'net/pop3/POP3ServiceInfos.cpp', 'net/pop3/POP3ServiceInfos.hpp',
'net/pop3/POP3Store.cpp', 'net/pop3/POP3Store.hpp',
'net/pop3/POP3SStore.cpp', 'net/pop3/POP3SStore.hpp',
'net/pop3/POP3Folder.cpp', 'net/pop3/POP3Folder.hpp',
'net/pop3/POP3Message.cpp', 'net/pop3/POP3Message.hpp'
]
@ -231,24 +235,29 @@ libvmime_messaging_proto_sources = [
[
'smtp',
[
'net/smtp/SMTPTransport.cpp', 'net/smtp/SMTPTransport.hpp'
'net/smtp/SMTPServiceInfos.cpp', 'net/smtp/SMTPServiceInfos.hpp',
'net/smtp/SMTPTransport.cpp', 'net/smtp/SMTPTransport.hpp',
'net/smtp/SMTPSTransport.cpp', 'net/smtp/SMTPSTransport.hpp'
]
],
[
'imap',
[
'net/imap/IMAPServiceInfos.cpp', 'net/imap/IMAPServiceInfos.hpp',
'net/imap/IMAPConnection.cpp', 'net/imap/IMAPConnection.hpp',
'net/imap/IMAPStore.cpp', 'net/imap/IMAPStore.hpp',
'net/imap/IMAPSStore.cpp', 'net/imap/IMAPSStore.hpp',
'net/imap/IMAPFolder.cpp', 'net/imap/IMAPFolder.hpp',
'net/imap/IMAPMessage.cpp', 'net/imap/IMAPMessage.hpp',
'net/imap/IMAPTag.cpp', 'net/imap/IMAPTag.hpp',
'net/imap/IMAPUtils.cpp', 'net/imap/IMAPUtils.hpp',
'net/imap/IMAPParser.hpp'
'net/imap/IMAPParser.hpp',
]
],
[
'maildir',
[
'net/maildir/maildirServiceInfos.cpp', 'net/maildir/maildirServiceInfos.hpp',
'net/maildir/maildirStore.cpp', 'net/maildir/maildirStore.hpp',
'net/maildir/maildirFolder.cpp', 'net/maildir/maildirFolder.hpp',
'net/maildir/maildirMessage.cpp', 'net/maildir/maildirMessage.hpp',
@ -258,6 +267,7 @@ libvmime_messaging_proto_sources = [
[
'sendmail',
[
'net/sendmail/sendmailServiceInfos.cpp', 'net/sendmail/sendmailServiceInfos.hpp',
'net/sendmail/sendmailTransport.cpp', 'net/sendmail/sendmailTransport.hpp'
]
]
@ -348,6 +358,7 @@ libvmime_autotools = [
'm4/lib-ld.m4',
'm4/lib-link.m4',
'm4/lib-prefix.m4',
'm4/libgnutls.m4',
'autotools/install-sh',
# 'autotools/mkinstalldirs',
'autotools/missing',
@ -367,7 +378,7 @@ libvmime_autotools = [
'vmime/Makefile.in'
]
libvmime_all_sources = [] + libvmime_sources + libvmime_messaging_sources + libvmime_security_sasl_sources
libvmime_all_sources = [] + libvmime_sources + libvmime_messaging_sources + libvmime_security_sasl_sources + libvmime_net_tls_sources
for i in range(len(libvmime_all_sources)):
f = libvmime_all_sources[i]
@ -481,6 +492,14 @@ opts.AddOptions(
map = { },
ignorecase = 1
),
EnumOption(
'with_tls',
'Enable TLS support (requires GNU TLS library)',
'yes',
allowed_values = ('yes', 'no'),
map = { },
ignorecase = 1
),
(
'sendmail_path',
'Specifies the path to sendmail.',
@ -559,6 +578,8 @@ env.Append(CXXFLAGS = ['-pedantic'])
env.Append(CXXFLAGS = ['-Wpointer-arith'])
env.Append(CXXFLAGS = ['-Wold-style-cast'])
env.Append(CXXFLAGS = ['-Wconversion'])
env.Append(CXXFLAGS = ['-Wcast-align'])
#env.Append(CXXFLAGS = ['-Wshadow'])
env.Append(TARFLAGS = ['-c'])
env.Append(TARFLAGS = ['--bzip2'])
@ -572,7 +593,11 @@ else:
#env.Append(LIBS = ['additional-lib-here'])
env.ParseConfig('pkg-config --cflags --libs libgsasl')
if env['with_sasl'] == 'yes':
env.ParseConfig('pkg-config --cflags --libs libgsasl')
if env['with_tls'] == 'yes':
env.ParseConfig('pkg-config --cflags --libs libgnutls')
# Generate help text for command line options
Help(opts.GenerateHelpText(env))
@ -663,6 +688,7 @@ if env['with_messaging'] == 'yes':
print "File-system support : " + env['with_filesystem']
print "Platform handlers : " + env['with_platforms']
print "SASL support : " + env['with_sasl']
print "TLS/SSL support : " + env['with_tls']
if IsProtocolSupported(messaging_protocols, 'sendmail'):
print "Sendmail path : " + env['sendmail_path']
@ -754,6 +780,12 @@ if env['with_sasl'] == 'yes':
else:
config_hpp.write('#define VMIME_HAVE_SASL_SUPPORT 0\n')
config_hpp.write('// -- TLS/SSL support\n')
if env['with_tls'] == 'yes':
config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 1\n')
else:
config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 0\n')
config_hpp.write('// -- Messaging support\n')
if env['with_messaging'] == 'yes':
config_hpp.write('#define VMIME_HAVE_MESSAGING_FEATURES 1\n')
@ -832,6 +864,11 @@ if env['with_sasl'] == 'yes':
for file in libvmime_security_sasl_sources:
libvmime_sel_sources.append(file)
# -- TLS support
if env['with_tls'] == 'yes':
for file in libvmime_net_tls_sources:
libvmime_sel_sources.append(file)
# -- platform handlers
for platform in platforms:
files = libvmime_platforms_sources[platform]
@ -1010,9 +1047,9 @@ def generateAutotools(target, source, env):
vmime_pc_in.write("Description: " + packageDescription + "\n")
vmime_pc_in.write("Version: @VERSION@\n")
vmime_pc_in.write("Requires: @GSASL_REQUIRED@\n")
vmime_pc_in.write("Libs: -L${libdir} -l@GENERIC_VERSIONED_LIBRARY_NAME@ @GSASL_LIBS@\n")
vmime_pc_in.write("Libs: -L${libdir} -l@GENERIC_VERSIONED_LIBRARY_NAME@ @GSASL_LIBS@ @LIBGNUTLS_LIBS@\n")
#vmime_pc_in.write("Cflags: -I${includedir}/@GENERIC_VERSIONED_LIBRARY_NAME@\n")
vmime_pc_in.write("Cflags: -I${includedir}/\n")
vmime_pc_in.write("Cflags: -I${includedir}/ @LIBGNUTLS_CFLAGS@\n")
vmime_pc_in.close()
# Generate 'Makefile.am'
@ -1123,6 +1160,15 @@ INCLUDES = -I$(top_srcdir) -I$(srcdir) @PKGCONFIG_CFLAGS@ @EXTRA_CFLAGS@
Makefile_am.write(packageVersionedName + "_la_SOURCES += " + buildMakefileFileList(x, 1) + "\n")
Makefile_am.write("endif\n")
# -- TLS support
x = selectFilesFromSuffixNot(libvmime_net_tls_sources, '.hpp')
sourceFiles += x
Makefile_am.write("\n")
Makefile_am.write("if VMIME_HAVE_TLS_SUPPORT\n")
Makefile_am.write(packageVersionedName + "_la_SOURCES += " + buildMakefileFileList(x, 1) + "\n")
Makefile_am.write("endif\n")
# -- platform handlers
for platform in libvmime_platforms_sources:
Makefile_am.write("\n")
@ -1256,6 +1302,9 @@ AC_CHECK_HEADER(gsasl.h,
have_gsasl=no),
have_gsasl=no)
# -- GNU TLS Library (http://www.gnu.org/software/gnutls/)
AM_PATH_LIBGNUTLS(1.2.0, have_gnutls=yes, have_gnutls=no)
# -- global constructors (stolen from 'configure.in' in libsigc++)
AC_MSG_CHECKING([if linker supports global constructors])
cat > mylib.$ac_ext <<EOF
@ -1299,7 +1348,7 @@ if test -x mytest; then
AC_ERROR([
===================================================================
ERROR: This platform lacks support of construction of global
objects in shared librarys.
objects in shared libraries.
See ftp://rtfm.mit.edu/pub/usenet/news.answers/g++-FAQ/plain
for details about this problem. Also for possible solutions
@ -1514,6 +1563,29 @@ fi
AC_SUBST(GSASL_REQUIRED)
AC_SUBST(GSASL_LIBS)
# ** TLS
AC_ARG_ENABLE(tls,
AC_HELP_STRING([--enable-tls], [Enable TLS/SSL support with GNU TLS, default: enabled]),
[case "${enableval}" in
yes) conf_tls=yes ;;
no) conf_tls=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tls) ;;
esac],
[conf_tls=yes])
if test "x$conf_tls" = "xyes"; then
if test "x$have_gnutls" = "xyes"; then
AM_CONDITIONAL(VMIME_HAVE_TLS_SUPPORT, true)
VMIME_HAVE_TLS_SUPPORT=1
else
AC_MSG_ERROR(can't find an usable version of GNU TLS library)
fi
else
AM_CONDITIONAL(VMIME_HAVE_TLS_SUPPORT, false)
VMIME_HAVE_TLS_SUPPORT=0
fi
# ** platform handlers
VMIME_BUILTIN_PLATFORMS=''
@ -1637,8 +1709,8 @@ PKGCONFIG_LIBS=""
AC_SUBST(PKGCONFIG_CFLAGS)
AC_SUBST(PKGCONFIG_LIBS)
EXTRA_CFLAGS="$EXTRA_CFLAGS -D_REENTRANT=1"
EXTRA_LIBS="$GSASL_LIBS"
EXTRA_CFLAGS="$EXTRA_CFLAGS -D_REENTRANT=1 -D_THREAD_SAFE=1 $LIBGNUTLS_CFLAGS"
EXTRA_LIBS="$GSASL_LIBS $LIBGNUTLS_LIBS"
CFLAGS=""
CXXFLAGS=""
@ -1755,6 +1827,8 @@ typedef unsigned ${VMIME_TYPE_INT32} vmime_uint32;
#define VMIME_HAVE_FILESYSTEM_FEATURES 1
// -- SASL support
#define VMIME_HAVE_SASL_SUPPORT ${VMIME_HAVE_SASL_SUPPORT}
// -- TLS support
#define VMIME_HAVE_TLS_SUPPORT ${VMIME_HAVE_TLS_SUPPORT}
// -- Messaging support
#define VMIME_HAVE_MESSAGING_FEATURES ${VMIME_HAVE_MESSAGING_FEATURES}
""")
@ -1809,6 +1883,7 @@ Messaging support : $conf_messaging
File-system support : yes
Platform handlers :$VMIME_BUILTIN_PLATFORMS
SASL support : $conf_sasl
TLS/SSL support : $conf_tls
Please check 'vmime/config.hpp' to ensure the configuration is correct.
])
@ -2081,6 +2156,10 @@ typedef unsigned int vmime_uint32;
#define VMIME_NO_MULTIPLE_INHERITANCE 1
// -- File-system support
#define VMIME_HAVE_FILESYSTEM_FEATURES 1
// -- SASL support
#define VMIME_HAVE_SASL_SUPPORT 1
// -- TLS/SSL support
#define VMIME_HAVE_TLS_SUPPORT 1
// -- Messaging support
#define VMIME_HAVE_MESSAGING_FEATURES 1
// -- Built-in messaging protocols

View File

@ -1,9 +1,12 @@
=========================================
Instructions for compiling VMime examples
=========================================
1) Configure, compile and install vmime library
2) Compile the sample programs with:
$ g++ -o exampleX exampleX.cpp ../libvmime.a ../libvmime-posix.a
$ g++ -o exampleX exampleX.cpp `pkg-config libvmime`
3) For a more complete documentation, please visit:
http://vmime.sourceforge.net/documentation/
http://www.vmime.org/documentation/

View File

@ -59,7 +59,7 @@ class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthen
void setSASLMechanism(vmime::ref <vmime::security::sasl::SASLMechanism> mech)
{
std::cout << "Trying " << mech->getName() << std::endl;
std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl;
defaultSASLAuthenticator::setSASLMechanism(mech);
}
@ -98,6 +98,94 @@ private:
};
#if VMIME_HAVE_TLS_SUPPORT
// Certificate verifier (TLS/SSL)
class interactiveCertificateVerifier : public vmime::net::tls::defaultCertificateVerifier
{
public:
void verify(vmime::ref <vmime::net::tls::certificateChain> chain)
{
try
{
setX509TrustedCerts(m_trustedCerts);
defaultCertificateVerifier::verify(chain);
}
catch (vmime::exceptions::certificate_verification_exception&)
{
// Obtain subject's certificate
vmime::ref <vmime::net::tls::certificate> cert = chain->getAt(0);
std::cout << std::endl;
std::cout << "Server sent a '" << cert->getType() << "'" << " certificate." << std::endl;
std::cout << "Do you want to accept this certificate? (Y/n) ";
std::cout.flush();
std::string answer;
std::getline(std::cin, answer);
if (answer.length() != 0 &&
(answer[0] == 'Y' || answer[0] == 'y'))
{
// Accept it, and remember user's choice for later
if (cert->getType() == "X.509")
{
m_trustedCerts.push_back(cert.dynamicCast
<vmime::net::tls::X509Certificate>());
}
return;
}
throw vmime::exceptions::certificate_verification_exception
("User did not accept the certificate.");
}
}
private:
static std::vector <vmime::ref <vmime::net::tls::X509Certificate> > m_trustedCerts;
};
std::vector <vmime::ref <vmime::net::tls::X509Certificate> >
interactiveCertificateVerifier::m_trustedCerts;
#endif // VMIME_HAVE_TLS_SUPPORT
/** Returns the messaging protocols supported by VMime.
*
* @param type service type (vmime::net::service::TYPE_STORE or
* vmime::net::service::TYPE_TRANSPORT)
*/
static const std::string findAvailableProtocols(const vmime::net::service::Type type)
{
vmime::net::serviceFactory* sf = vmime::net::serviceFactory::getInstance();
std::ostringstream res;
int count = 0;
for (int i = 0 ; i < sf->getServiceCount() ; ++i)
{
const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
if (serv.getType() == type)
{
if (count != 0)
res << ", ";
res << serv.getName();
++count;
}
}
return res.str();
}
// Exception helper
static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
{
@ -244,6 +332,7 @@ static void sendMessage()
{
// Request user to enter an URL
std::cout << "Enter an URL to connect to transport service." << std::endl;
std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl;
std::cout << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl;
std::cout << "> ";
std::cout.flush();
@ -256,9 +345,21 @@ static void sendMessage()
vmime::ref <vmime::net::transport> tr =
g_session->getTransport(url, vmime::create <interactiveAuthenticator>());
#if VMIME_HAVE_TLS_SUPPORT
// Enable TLS support if available
tr->setProperty("connection.tls", true);
// Set the object responsible for verifying certificates, in the
// case a secured connection is used (TLS/SSL)
tr->setCertificateVerifier
(vmime::create <interactiveCertificateVerifier>());
#endif // VMIME_HAVE_TLS_SUPPORT
// You can also set some properties (see example7 to know the properties
// available for each service). For example, for SMTP:
tr->setProperty("options.need-authentication", true);
// tr->setProperty("options.need-authentication", true);
// Information about the mail
std::cout << "Enter email of the expeditor (eg. me@somewhere.com): ";
@ -338,6 +439,7 @@ static void connectStore()
{
// Request user to enter an URL
std::cout << "Enter an URL to connect to store service." << std::endl;
std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl;
std::cout << "(eg. pop3://user:pass@myserver.com, imap://myserver.com:123)" << std::endl;
std::cout << "> ";
std::cout.flush();
@ -357,6 +459,18 @@ static void connectStore()
else
st = g_session->getStore(url);
#if VMIME_HAVE_TLS_SUPPORT
// Enable TLS support if available
st->setProperty("connection.tls", true);
// Set the object responsible for verifying certificates, in the
// case a secured connection is used (TLS/SSL)
st->setCertificateVerifier
(vmime::create <interactiveCertificateVerifier>());
#endif // VMIME_HAVE_TLS_SUPPORT
// Connect to the mail store
st->connect();

160
m4/libgnutls.m4 Normal file
View File

@ -0,0 +1,160 @@
dnl Autoconf macros for libgnutls
dnl $id$
# Modified for LIBGNUTLS -- nmav
# Configure paths for LIBGCRYPT
# Shamelessly stolen from the one of XDELTA by Owen Taylor
# Werner Koch 99-12-09
dnl AM_PATH_LIBGNUTLS([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libgnutls, and define LIBGNUTLS_CFLAGS and LIBGNUTLS_LIBS
dnl
AC_DEFUN([AM_PATH_LIBGNUTLS],
[dnl
dnl Get the cflags and libraries from the libgnutls-config script
dnl
AC_ARG_WITH(libgnutls-prefix,
[ --with-libgnutls-prefix=PFX Prefix where libgnutls is installed (optional)],
libgnutls_config_prefix="$withval", libgnutls_config_prefix="")
if test x$libgnutls_config_prefix != x ; then
if test x${LIBGNUTLS_CONFIG+set} != xset ; then
LIBGNUTLS_CONFIG=$libgnutls_config_prefix/bin/libgnutls-config
fi
fi
AC_PATH_PROG(LIBGNUTLS_CONFIG, libgnutls-config, no)
min_libgnutls_version=ifelse([$1], ,0.1.0,$1)
AC_MSG_CHECKING(for libgnutls - version >= $min_libgnutls_version)
no_libgnutls=""
if test "$LIBGNUTLS_CONFIG" = "no" ; then
no_libgnutls=yes
else
LIBGNUTLS_CFLAGS=`$LIBGNUTLS_CONFIG $libgnutls_config_args --cflags`
LIBGNUTLS_LIBS=`$LIBGNUTLS_CONFIG $libgnutls_config_args --libs`
libgnutls_config_version=`$LIBGNUTLS_CONFIG $libgnutls_config_args --version`
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
LIBS="$LIBS $LIBGNUTLS_LIBS"
dnl
dnl Now check if the installed libgnutls is sufficiently new. Also sanity
dnl checks the results of libgnutls-config to some extent
dnl
rm -f conf.libgnutlstest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnutls/gnutls.h>
int
main ()
{
system ("touch conf.libgnutlstest");
if( strcmp( gnutls_check_version(NULL), "$libgnutls_config_version" ) )
{
printf("\n*** 'libgnutls-config --version' returned %s, but LIBGNUTLS (%s)\n",
"$libgnutls_config_version", gnutls_check_version(NULL) );
printf("*** was found! If libgnutls-config was correct, then it is best\n");
printf("*** to remove the old version of LIBGNUTLS. You may also be able to fix the error\n");
printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
printf("*** required on your system.\n");
printf("*** If libgnutls-config was wrong, set the environment variable LIBGNUTLS_CONFIG\n");
printf("*** to point to the correct copy of libgnutls-config, and remove the file config.cache\n");
printf("*** before re-running configure\n");
}
else if ( strcmp(gnutls_check_version(NULL), LIBGNUTLS_VERSION ) )
{
printf("\n*** LIBGNUTLS header file (version %s) does not match\n", LIBGNUTLS_VERSION);
printf("*** library (version %s)\n", gnutls_check_version(NULL) );
}
else
{
if ( gnutls_check_version( "$min_libgnutls_version" ) )
{
return 0;
}
else
{
printf("no\n*** An old version of LIBGNUTLS (%s) was found.\n",
gnutls_check_version(NULL) );
printf("*** You need a version of LIBGNUTLS newer than %s. The latest version of\n",
"$min_libgnutls_version" );
printf("*** LIBGNUTLS is always available from ftp://gnutls.hellug.gr/pub/gnutls.\n");
printf("*** \n");
printf("*** If you have already installed a sufficiently new version, this error\n");
printf("*** probably means that the wrong copy of the libgnutls-config shell script is\n");
printf("*** being found. The easiest way to fix this is to remove the old version\n");
printf("*** of LIBGNUTLS, but you can also set the LIBGNUTLS_CONFIG environment to point to the\n");
printf("*** correct copy of libgnutls-config. (In this case, you will have to\n");
printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
printf("*** so that the correct libraries are found at run-time))\n");
}
}
return 1;
}
],, no_libgnutls=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
if test "x$no_libgnutls" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
if test -f conf.libgnutlstest ; then
:
else
AC_MSG_RESULT(no)
fi
if test "$LIBGNUTLS_CONFIG" = "no" ; then
echo "*** The libgnutls-config script installed by LIBGNUTLS could not be found"
echo "*** If LIBGNUTLS was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the LIBGNUTLS_CONFIG environment variable to the"
echo "*** full path to libgnutls-config."
else
if test -f conf.libgnutlstest ; then
:
else
echo "*** Could not run libgnutls test program, checking why..."
CFLAGS="$CFLAGS $LIBGNUTLS_CFLAGS"
LIBS="$LIBS $LIBGNUTLS_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnutls/gnutls.h>
], [ return !!gnutls_check_version(NULL); ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding LIBGNUTLS or finding the wrong"
echo "*** version of LIBGNUTLS. If it is not finding LIBGNUTLS, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
echo "***" ],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means LIBGNUTLS was incorrectly installed"
echo "*** or that you have moved LIBGNUTLS since it was installed. In the latter case, you"
echo "*** may want to edit the libgnutls-config script: $LIBGNUTLS_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
LIBGNUTLS_CFLAGS=""
LIBGNUTLS_LIBS=""
ifelse([$3], , :, [$3])
fi
rm -f conf.libgnutlstest
AC_SUBST(LIBGNUTLS_CFLAGS)
AC_SUBST(LIBGNUTLS_LIBS)
])
dnl *-*wedit:notab*-* Please keep this as the last line.

View File

@ -719,6 +719,60 @@ const char* no_auth_information::name() const throw() { return "no_auth_informat
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
//
// tls_exception
//
tls_exception::~tls_exception() throw() {}
tls_exception::tls_exception(const string& what, const exception& other)
: exception(what, other) {}
exception* tls_exception::clone() const { return new tls_exception(*this); }
const char* tls_exception::name() const throw() { return "tls_exception"; }
//
// certificate_exception
//
certificate_exception::~certificate_exception() throw() {}
certificate_exception::certificate_exception(const string& what, const exception& other)
: tls_exception(what, other) {}
exception* certificate_exception::clone() const { return new certificate_exception(*this); }
const char* certificate_exception::name() const throw() { return "certificate_exception"; }
//
// certificate_verification_exception
//
certificate_verification_exception::~certificate_verification_exception() throw() {}
certificate_verification_exception::certificate_verification_exception(const string& what, const exception& other)
: certificate_exception(what, other) {}
exception* certificate_verification_exception::clone() const { return new certificate_verification_exception(*this); }
const char* certificate_verification_exception::name() const throw() { return "certificate_verification_exception"; }
//
// unsupported_certificate_type
//
unsupported_certificate_type::~unsupported_certificate_type() throw() {}
unsupported_certificate_type::unsupported_certificate_type(const string& type, const exception& other)
: certificate_exception("Unsupported certificate type: '" + type + "'", other) {}
exception* unsupported_certificate_type::clone() const { return new unsupported_certificate_type(*this); }
const char* unsupported_certificate_type::name() const throw() { return "unsupported_certificate_type"; }
#endif // VMIME_HAVE_TLS_SUPPORT
} // exceptions

View File

@ -1,111 +0,0 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/authHelper.hpp"
#include "vmime/config.hpp"
#include "vmime/security/digest/messageDigestFactory.hpp"
namespace vmime {
namespace net {
//
// This code is based on the Sample Code published in the Appendix of
// the RFC-2104: "HMAC: Keyed-Hashing for Message Authentication".
//
void hmac_md5(const string& text, const string& key, string& hexDigest)
{
vmime_uint8 digest[16];
unsigned char ipad[65]; // inner padding - key XORd with ipad
unsigned char opad[65]; // outer padding - key XORd with opad
unsigned char tkey[16];
int tkeyLen;
ref <security::digest::messageDigest> md5 =
security::digest::messageDigestFactory::getInstance()->create("md5");
// If key is longer than 64 bytes reset it to key = MD5(key)
if (key.length() > 64)
{
md5->reset();
md5->update(reinterpret_cast <const vmime_uint8*>(key.data()), key.length());
md5->finalize();
std::copy(md5->getDigest(), md5->getDigest() + 16, tkey);
tkeyLen = 16;
}
else
{
std::copy(key.begin(), key.end(), tkey);
tkeyLen = key.length();
}
//
// the HMAC_MD5 transform looks like:
//
// MD5(K XOR opad, MD5(K XOR ipad, text))
//
// where K is an n byte key
// ipad is the byte 0x36 repeated 64 times
//
// opad is the byte 0x5c repeated 64 times
// and text is the data being protected
//
// Start out by storing key in pads
std::fill(ipad, ipad + sizeof(ipad), 0);
std::fill(opad, opad + sizeof(opad), 0);
std::copy(tkey, tkey + tkeyLen, ipad);
std::copy(tkey, tkey + tkeyLen, opad);
// XOR key with ipad and opad values
for (int i = 0 ; i < 64 ; ++i)
{
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
// Perform inner MD5
md5->reset();
md5->update(ipad, 64);
md5->update(text);
md5->finalize();
std::copy(md5->getDigest(), md5->getDigest() + 16, digest);
// Perform outer MD5
md5->reset();
md5->update(opad, 64);
md5->update(digest, 16);
md5->finalize();
//std::copy(outerMD5.hash(), outerMD5.hash() + 16, digest);
hexDigest = md5->getHexDigest();
}
} // net
} // vmime

View File

@ -24,36 +24,52 @@
#ifndef VMIME_BUILDING_DOC
#define REGISTER_SERVICE(p_class, p_name) \
vmime::net::service::initializer <vmime::net::p_class> p_name(#p_name)
#define REGISTER_SERVICE(p_class, p_name, p_type) \
vmime::net::service::initializer <vmime::net::p_class> \
p_name(#p_name, vmime::net::service::p_type)
#if VMIME_BUILTIN_MESSAGING_PROTO_POP3
#include "vmime/net/pop3/POP3Store.hpp"
REGISTER_SERVICE(pop3::POP3Store, pop3);
REGISTER_SERVICE(pop3::POP3Store, pop3, TYPE_STORE);
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/pop3/POP3SStore.hpp"
REGISTER_SERVICE(pop3::POP3SStore, pop3s, TYPE_STORE);
#endif // VMIME_HAVE_TLS_SUPPORT
#endif
#if VMIME_BUILTIN_MESSAGING_PROTO_SMTP
#include "vmime/net/smtp/SMTPTransport.hpp"
REGISTER_SERVICE(smtp::SMTPTransport, smtp);
REGISTER_SERVICE(smtp::SMTPTransport, smtp, TYPE_TRANSPORT);
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/smtp/SMTPSTransport.hpp"
REGISTER_SERVICE(smtp::SMTPSTransport, smtps, TYPE_TRANSPORT);
#endif // VMIME_HAVE_TLS_SUPPORT
#endif
#if VMIME_BUILTIN_MESSAGING_PROTO_IMAP
#include "vmime/net/imap/IMAPStore.hpp"
REGISTER_SERVICE(imap::IMAPStore, imap);
REGISTER_SERVICE(imap::IMAPStore, imap, TYPE_STORE);
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/imap/IMAPSStore.hpp"
REGISTER_SERVICE(imap::IMAPSStore, imaps, TYPE_STORE);
#endif // VMIME_HAVE_TLS_SUPPORT
#endif
#if VMIME_BUILTIN_MESSAGING_PROTO_MAILDIR
#include "vmime/net/maildir/maildirStore.hpp"
REGISTER_SERVICE(maildir::maildirStore, maildir);
REGISTER_SERVICE(maildir::maildirStore, maildir, TYPE_STORE);
#endif
#if VMIME_BUILTIN_MESSAGING_PROTO_SENDMAIL
#include "vmime/net/sendmail/sendmailTransport.hpp"
REGISTER_SERVICE(sendmail::sendmailTransport, sendmail);
REGISTER_SERVICE(sendmail::sendmailTransport, sendmail, TYPE_TRANSPORT);
#endif

View File

@ -29,16 +29,20 @@
#include "vmime/security/sasl/SASLContext.hpp"
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/tls/TLSSession.hpp"
#endif // VMIME_HAVE_TLS_SUPPORT
#include <sstream>
// Helpers for service properties
#define GET_PROPERTY(type, prop) \
(m_store->getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const IMAPStore::_infos&>(m_store->getInfos()).getProperties().prop))
dynamic_cast <const IMAPServiceInfos&>(m_store->getInfos()).getProperties().prop))
#define HAS_PROPERTY(prop) \
(m_store->getInfos().hasProperty(getSession(), \
dynamic_cast <const IMAPStore::_infos&>(m_store->getInfos()).getProperties().prop))
dynamic_cast <const IMAPServiceInfos&>(m_store->getInfos()).getProperties().prop))
namespace vmime {
@ -94,6 +98,20 @@ void IMAPConnection::connect()
getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY));
m_socket = sf->create();
#if VMIME_HAVE_TLS_SUPPORT
if (m_store->isSecuredConnection()) // dedicated port/IMAPS
{
ref <tls::TLSSession> tlsSession =
vmime::create <tls::TLSSession>(m_store->getCertificateVerifier());
ref <tls::TLSSocket> tlsSocket =
tlsSession->getSocket(m_socket);
m_socket = tlsSocket;
}
#endif // VMIME_HAVE_TLS_SUPPORT
m_socket->connect(address, port);
@ -110,6 +128,7 @@ void IMAPConnection::connect()
// --- S: * OK mydomain.org IMAP4rev1 v12.256 server ready
utility::auto_ptr <IMAPParser::greeting> greet(m_parser->readGreeting());
bool needAuth = false;
if (greet->resp_cond_bye())
{
@ -117,6 +136,47 @@ void IMAPConnection::connect()
throw exceptions::connection_greeting_error(m_parser->lastLine());
}
else if (greet->resp_cond_auth()->condition() != IMAPParser::resp_cond_auth::PREAUTH)
{
needAuth = true;
}
#if VMIME_HAVE_TLS_SUPPORT
// Setup secured connection, if requested
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
if (!m_store->isSecuredConnection() && tls) // only if not IMAPS
{
try
{
startTLS();
}
// Non-fatal error
catch (exceptions::command_error&)
{
if (tlsRequired)
{
m_state = STATE_NONE;
throw;
}
else
{
// TLS is not required, so don't bother
}
}
// Fatal error
catch (...)
{
m_state = STATE_NONE;
throw;
}
}
#endif // VMIME_HAVE_TLS_SUPPORT
// Authentication
if (needAuth)
{
try
{
@ -287,17 +347,19 @@ void IMAPConnection::authenticateSASL()
respDataList = resp->continue_req_or_response_data();
string response;
bool hasResponse = false;
for (unsigned int i = 0 ; i < respDataList.size() ; ++i)
{
if (respDataList[i]->continue_req())
{
response = respDataList[i]->continue_req()->resp_text()->text();
hasResponse = true;
break;
}
}
if (response.empty())
if (!hasResponse)
{
cont = false;
continue;
@ -365,6 +427,50 @@ void IMAPConnection::authenticateSASL()
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
void IMAPConnection::startTLS()
{
try
{
send(true, "STARTTLS", true);
utility::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
if (resp->isBad() || resp->response_done()->response_tagged()->
resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
{
throw exceptions::command_error
("STARTTLS", m_parser->lastLine(), "bad response");
}
ref <tls::TLSSession> tlsSession =
vmime::create <tls::TLSSession>(m_store->getCertificateVerifier());
ref <tls::TLSSocket> tlsSocket =
tlsSession->getSocket(m_socket);
tlsSocket->handshake(m_timeoutHandler);
m_socket = tlsSocket;
m_parser->setSocket(m_socket);
}
catch (exceptions::command_error&)
{
// Non-fatal error
throw;
}
catch (exception&)
{
// Fatal error
internalDisconnect();
throw;
}
}
#endif // VMIME_HAVE_TLS_SUPPORT
const std::vector <string> IMAPConnection::getCapabilities()
{
send(true, "CAPABILITY", true);

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/imap/IMAPSStore.hpp"
namespace vmime {
namespace net {
namespace imap {
IMAPSStore::IMAPSStore(ref <session> sess, ref <security::authenticator> auth)
: IMAPStore(sess, auth, true)
{
}
IMAPSStore::~IMAPSStore()
{
}
const string IMAPSStore::getProtocolName() const
{
return "imaps";
}
// Service infos
IMAPServiceInfos IMAPSStore::sm_infos(true);
const serviceInfos& IMAPSStore::getInfosInstance()
{
return sm_infos;
}
const serviceInfos& IMAPSStore::getInfos() const
{
return sm_infos;
}
} // imap
} // net
} // vmime

View File

@ -0,0 +1,133 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/imap/IMAPServiceInfos.hpp"
namespace vmime {
namespace net {
namespace imap {
IMAPServiceInfos::IMAPServiceInfos(const bool imaps)
: m_imaps(imaps)
{
}
const string IMAPServiceInfos::getPropertyPrefix() const
{
if (m_imaps)
return "store.imaps.";
else
return "store.imap.";
}
const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const
{
static props imapProps =
{
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
#if VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::CONNECTION_TLS),
property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
#endif // VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "143"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
static props imapsProps =
{
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
#if VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::CONNECTION_TLS),
property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
#endif // VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "993"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
return m_imaps ? imapsProps : imapProps;
}
const std::vector <serviceInfos::property> IMAPServiceInfos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
list.push_back(p.PROPERTY_OPTIONS_SASL);
list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
list.push_back(p.PROPERTY_AUTH_USERNAME);
list.push_back(p.PROPERTY_AUTH_PASSWORD);
#if VMIME_HAVE_TLS_SUPPORT
if (!m_imaps)
{
list.push_back(p.PROPERTY_CONNECTION_TLS);
list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED);
}
#endif // VMIME_HAVE_TLS_SUPPORT
list.push_back(p.PROPERTY_SERVER_ADDRESS);
list.push_back(p.PROPERTY_SERVER_PORT);
list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY);
list.push_back(p.PROPERTY_TIMEOUT_FACTORY);
return list;
}
} // imap
} // net
} // vmime

View File

@ -32,8 +32,8 @@ namespace net {
namespace imap {
IMAPStore::IMAPStore(ref <session> sess, ref <security::authenticator> auth)
: store(sess, getInfosInstance(), auth), m_connection(NULL)
IMAPStore::IMAPStore(ref <session> sess, ref <security::authenticator> auth, const bool secured)
: store(sess, getInfosInstance(), auth), m_connection(NULL), m_secured(secured)
{
}
@ -91,6 +91,12 @@ const bool IMAPStore::isValidFolderName(const folder::path::component& /* name *
}
const bool IMAPStore::isSecuredConnection() const
{
return m_secured;
}
void IMAPStore::connect()
{
if (isConnected())
@ -189,78 +195,21 @@ const int IMAPStore::getCapabilities() const
// Service infos
IMAPStore::_infos IMAPStore::sm_infos;
IMAPServiceInfos IMAPStore::sm_infos(false);
const serviceInfos& IMAPStore::getInfosInstance()
{
return (sm_infos);
return sm_infos;
}
const serviceInfos& IMAPStore::getInfos() const
{
return (sm_infos);
return sm_infos;
}
const string IMAPStore::_infos::getPropertyPrefix() const
{
return "store.imap.";
}
const IMAPStore::_infos::props& IMAPStore::_infos::getProperties() const
{
static props p =
{
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "143"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
return p;
}
const std::vector <serviceInfos::property> IMAPStore::_infos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
list.push_back(p.PROPERTY_OPTIONS_SASL);
list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
list.push_back(p.PROPERTY_AUTH_USERNAME);
list.push_back(p.PROPERTY_AUTH_PASSWORD);
list.push_back(p.PROPERTY_SERVER_ADDRESS);
list.push_back(p.PROPERTY_SERVER_PORT);
list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY);
list.push_back(p.PROPERTY_TIMEOUT_FACTORY);
return (list);
}
} // imap
} // net
} // vmime

View File

@ -0,0 +1,64 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/maildir/maildirServiceInfos.hpp"
namespace vmime {
namespace net {
namespace maildir {
maildirServiceInfos::maildirServiceInfos()
{
}
const string maildirServiceInfos::getPropertyPrefix() const
{
return "store.maildir.";
}
const maildirServiceInfos::props& maildirServiceInfos::getProperties() const
{
static props maildirProps =
{
property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED)
};
return maildirProps;
}
const std::vector <serviceInfos::property> maildirServiceInfos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
list.push_back(p.PROPERTY_SERVER_ROOTPATH);
return list;
}
} // maildir
} // net
} // vmime

View File

@ -29,9 +29,11 @@
// Helpers for service properties
#define GET_PROPERTY(type, prop) \
(sm_infos.getPropertyValue <type>(getSession(), sm_infos.getProperties().prop))
(getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const maildirServiceInfos&>(getInfos()).getProperties().prop))
#define HAS_PROPERTY(prop) \
(sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop))
(getInfos().hasProperty(getSession(), \
dynamic_cast <const maildirServiceInfos&>(getInfos()).getProperties().prop))
namespace vmime {
@ -205,50 +207,20 @@ const int maildirStore::getCapabilities() const
// Service infos
maildirStore::_infos maildirStore::sm_infos;
maildirServiceInfos maildirStore::sm_infos;
const serviceInfos& maildirStore::getInfosInstance()
{
return (sm_infos);
return sm_infos;
}
const serviceInfos& maildirStore::getInfos() const
{
return (sm_infos);
}
const string maildirStore::_infos::getPropertyPrefix() const
{
return "store.maildir.";
}
const maildirStore::_infos::props& maildirStore::_infos::getProperties() const
{
static props p =
{
property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED)
};
return p;
}
const std::vector <serviceInfos::property> maildirStore::_infos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// Maildir-specific properties
list.push_back(p.PROPERTY_SERVER_ROOTPATH);
return (list);
return sm_infos;
}

View File

@ -0,0 +1,66 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/pop3/POP3SStore.hpp"
namespace vmime {
namespace net {
namespace pop3 {
POP3SStore::POP3SStore(ref <session> sess, ref <security::authenticator> auth)
: POP3Store(sess, auth, true)
{
}
POP3SStore::~POP3SStore()
{
}
const string POP3SStore::getProtocolName() const
{
return "pop3s";
}
// Service infos
POP3ServiceInfos POP3SStore::sm_infos(true);
const serviceInfos& POP3SStore::getInfosInstance()
{
return sm_infos;
}
const serviceInfos& POP3SStore::getInfos() const
{
return sm_infos;
}
} // pop3
} // net
} // vmime

View File

@ -0,0 +1,139 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/pop3/POP3ServiceInfos.hpp"
namespace vmime {
namespace net {
namespace pop3 {
POP3ServiceInfos::POP3ServiceInfos(const bool pop3s)
: m_pop3s(pop3s)
{
}
const string POP3ServiceInfos::getPropertyPrefix() const
{
if (m_pop3s)
return "store.pop3s.";
else
return "store.pop3.";
}
const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const
{
static props pop3Props =
{
// POP3-specific options
property("options.apop", serviceInfos::property::TYPE_BOOL, "true"),
property("options.apop.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
#if VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::CONNECTION_TLS),
property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
#endif // VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "110"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
static props pop3sProps =
{
// POP3-specific options
property("options.apop", serviceInfos::property::TYPE_BOOL, "true"),
property("options.apop.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
#if VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::CONNECTION_TLS),
property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
#endif // VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "995"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
return m_pop3s ? pop3sProps : pop3Props;
}
const std::vector <serviceInfos::property> POP3ServiceInfos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// POP3-specific options
list.push_back(p.PROPERTY_OPTIONS_APOP);
list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK);
#if VMIME_HAVE_SASL_SUPPORT
list.push_back(p.PROPERTY_OPTIONS_SASL);
list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
list.push_back(p.PROPERTY_AUTH_USERNAME);
list.push_back(p.PROPERTY_AUTH_PASSWORD);
#if VMIME_HAVE_TLS_SUPPORT
if (!m_pop3s)
{
list.push_back(p.PROPERTY_CONNECTION_TLS);
list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED);
}
#endif // VMIME_HAVE_TLS_SUPPORT
list.push_back(p.PROPERTY_SERVER_ADDRESS);
list.push_back(p.PROPERTY_SERVER_PORT);
list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY);
list.push_back(p.PROPERTY_TIMEOUT_FACTORY);
return list;
}
} // pop3
} // net
} // vmime

View File

@ -31,14 +31,20 @@
#include "vmime/security/sasl/SASLContext.hpp"
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/tls/TLSSession.hpp"
#endif // VMIME_HAVE_TLS_SUPPORT
#include <algorithm>
// Helpers for service properties
#define GET_PROPERTY(type, prop) \
(sm_infos.getPropertyValue <type>(getSession(), sm_infos.getProperties().prop))
(getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const POP3ServiceInfos&>(getInfos()).getProperties().prop))
#define HAS_PROPERTY(prop) \
(sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop))
(getInfos().hasProperty(getSession(), \
dynamic_cast <const POP3ServiceInfos&>(getInfos()).getProperties().prop))
namespace vmime {
@ -46,9 +52,9 @@ namespace net {
namespace pop3 {
POP3Store::POP3Store(ref <session> sess, ref <security::authenticator> auth)
POP3Store::POP3Store(ref <session> sess, ref <security::authenticator> auth, const bool secured)
: store(sess, getInfosInstance(), auth), m_socket(NULL),
m_authentified(false), m_timeoutHandler(NULL)
m_authentified(false), m_timeoutHandler(NULL), m_secured(secured)
{
}
@ -130,6 +136,20 @@ void POP3Store::connect()
getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY));
m_socket = sf->create();
#if VMIME_HAVE_TLS_SUPPORT
if (m_secured) // dedicated port/POP3S
{
ref <tls::TLSSession> tlsSession =
vmime::create <tls::TLSSession>(getCertificateVerifier());
ref <tls::TLSSocket> tlsSocket =
tlsSession->getSocket(m_socket);
m_socket = tlsSocket;
}
#endif // VMIME_HAVE_TLS_SUPPORT
m_socket->connect(address, port);
// Connection
@ -146,6 +166,39 @@ void POP3Store::connect()
throw exceptions::connection_greeting_error(response);
}
#if VMIME_HAVE_TLS_SUPPORT
// Setup secured connection, if requested
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
if (!m_secured && tls) // only if not POP3S
{
try
{
startTLS();
}
// Non-fatal error
catch (exceptions::command_error&)
{
if (tlsRequired)
{
throw;
}
else
{
// TLS is not required, so don't bother
}
}
// Fatal error
catch (...)
{
throw;
}
}
#endif // VMIME_HAVE_TLS_SUPPORT
// Start authentication process
authenticate(messageId(response));
}
@ -235,6 +288,18 @@ void POP3Store::authenticate(const messageId& randomMID)
internalDisconnect();
throw exceptions::authentication_error(response);
}
// Ensure connection is valid (cf. note above)
try
{
string response2;
sendRequest("NOOP");
readResponse(response2, false);
}
catch (exceptions::socket_exception&)
{
throw exceptions::authentication_error(response);
}
}
}
else
@ -453,6 +518,46 @@ void POP3Store::authenticateSASL()
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
void POP3Store::startTLS()
{
try
{
sendRequest("STLS");
string response;
readResponse(response, false);
if (getResponseCode(response) != RESPONSE_OK)
throw exceptions::command_error("STLS", response);
ref <tls::TLSSession> tlsSession =
vmime::create <tls::TLSSession>(getCertificateVerifier());
ref <tls::TLSSocket> tlsSocket =
tlsSession->getSocket(m_socket);
tlsSocket->handshake(m_timeoutHandler);
m_socket = tlsSocket;
}
catch (exceptions::command_error&)
{
// Non-fatal error
throw;
}
catch (exception&)
{
// Fatal error
internalDisconnect();
throw;
}
}
#endif // VMIME_HAVE_TLS_SUPPORT
const bool POP3Store::isConnected() const
{
return (m_socket && m_socket->isConnected() && m_authentified);
@ -478,8 +583,14 @@ void POP3Store::internalDisconnect()
m_folders.clear();
try
{
sendRequest("QUIT");
}
catch (exception&)
{
// Not important
}
m_socket->disconnect();
m_socket = NULL;
@ -627,6 +738,8 @@ void POP3Store::readResponse(string& buffer, const bool multiLine,
{
if (!m_timeoutHandler->handleTimeOut())
throw exceptions::operation_timed_out();
m_timeoutHandler->resetTimeOut();
}
// Receive data from the socket
@ -844,78 +957,18 @@ const int POP3Store::getCapabilities() const
// Service infos
POP3Store::_infos POP3Store::sm_infos;
POP3ServiceInfos POP3Store::sm_infos(false);
const serviceInfos& POP3Store::getInfosInstance()
{
return (sm_infos);
return sm_infos;
}
const serviceInfos& POP3Store::getInfos() const
{
return (sm_infos);
}
const string POP3Store::_infos::getPropertyPrefix() const
{
return "store.pop3.";
}
const POP3Store::_infos::props& POP3Store::_infos::getProperties() const
{
static props p =
{
// POP3-specific options
property("options.apop", serviceInfos::property::TYPE_BOOL, "true"),
property("options.apop.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "true"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "110"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
return p;
}
const std::vector <serviceInfos::property> POP3Store::_infos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// POP3-specific options
list.push_back(p.PROPERTY_OPTIONS_APOP);
list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK);
#if VMIME_HAVE_SASL_SUPPORT
list.push_back(p.PROPERTY_OPTIONS_SASL);
list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
list.push_back(p.PROPERTY_AUTH_USERNAME);
list.push_back(p.PROPERTY_AUTH_PASSWORD);
list.push_back(p.PROPERTY_SERVER_ADDRESS);
list.push_back(p.PROPERTY_SERVER_PORT);
list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY);
list.push_back(p.PROPERTY_TIMEOUT_FACTORY);
return (list);
return sm_infos;
}

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/sendmail/sendmailServiceInfos.hpp"
namespace vmime {
namespace net {
namespace sendmail {
sendmailServiceInfos::sendmailServiceInfos()
{
}
const string sendmailServiceInfos::getPropertyPrefix() const
{
return "transport.sendmail.";
}
const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const
{
static props sendmailProps =
{
// Path to sendmail (override default)
property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH))
};
return sendmailProps;
}
const std::vector <serviceInfos::property> sendmailServiceInfos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
list.push_back(p.PROPERTY_BINPATH);
return list;
}
} // sendmail
} // net
} // vmime

View File

@ -33,9 +33,11 @@
// Helpers for service properties
#define GET_PROPERTY(type, prop) \
(sm_infos.getPropertyValue <type>(getSession(), sm_infos.getProperties().prop))
(getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const sendmailServiceInfos&>(getInfos()).getProperties().prop))
#define HAS_PROPERTY(prop) \
(sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop))
(getInfos().hasProperty(getSession(), \
dynamic_cast <const sendmailServiceInfos&>(getInfos()).getProperties().prop))
#if VMIME_BUILTIN_PLATFORM_POSIX
@ -177,47 +179,18 @@ void sendmailTransport::internalSend
// Service infos
sendmailTransport::_infos sendmailTransport::sm_infos;
sendmailServiceInfos sendmailTransport::sm_infos;
const serviceInfos& sendmailTransport::getInfosInstance()
{
return (sm_infos);
return sm_infos;
}
const serviceInfos& sendmailTransport::getInfos() const
{
return (sm_infos);
}
const string sendmailTransport::_infos::getPropertyPrefix() const
{
return "transport.sendmail.";
}
const sendmailTransport::_infos::props& sendmailTransport::_infos::getProperties() const
{
static props p =
{
// Path to sendmail (override default)
property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH))
};
return p;
}
const std::vector <serviceInfos::property> sendmailTransport::_infos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
list.push_back(p.PROPERTY_BINPATH);
return (list);
return sm_infos;
}

View File

@ -26,6 +26,10 @@
#include "vmime/security/defaultAuthenticator.hpp"
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/tls/defaultCertificateVerifier.hpp"
#endif // VMIME_HAVE_TLS_SUPPORT
namespace vmime {
namespace net {
@ -45,6 +49,11 @@ service::service(ref <session> sess, const serviceInfos& /* infos */,
<security::defaultAuthenticator>();
#endif // VMIME_HAVE_SASL_SUPPORT
}
#if VMIME_HAVE_TLS_SUPPORT
m_certVerifier = vmime::create <tls::defaultCertificateVerifier>();
#endif // VMIME_HAVE_TLS_SUPPORT
}
@ -83,5 +92,21 @@ void service::setAuthenticator(ref <security::authenticator> auth)
}
#if VMIME_HAVE_TLS_SUPPORT
void service::setCertificateVerifier(ref <tls::certificateVerifier> cv)
{
m_certVerifier = cv;
}
ref <tls::certificateVerifier> service::getCertificateVerifier()
{
return m_certVerifier;
}
#endif // VMIME_HAVE_TLS_SUPPORT
} // net
} // vmime

View File

@ -46,6 +46,16 @@ const serviceInfos::property serviceInfos::property::AUTH_PASSWORD
const serviceInfos::property serviceInfos::property::TIMEOUT_FACTORY
("timeout.factory", serviceInfos::property::TYPE_STRING);
#if VMIME_HAVE_TLS_SUPPORT
const serviceInfos::property serviceInfos::property::CONNECTION_TLS
("connection.tls", serviceInfos::property::TYPE_BOOL, "false");
const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED
("connection.tls.required", serviceInfos::property::TYPE_BOOL, "false");
#endif // VMIME_HAVE_TLS_SUPPORT
// serviceInfos

View File

@ -0,0 +1,66 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/smtp/SMTPSTransport.hpp"
namespace vmime {
namespace net {
namespace smtp {
SMTPSTransport::SMTPSTransport(ref <session> sess, ref <security::authenticator> auth)
: SMTPTransport(sess, auth, true)
{
}
SMTPSTransport::~SMTPSTransport()
{
}
const string SMTPSTransport::getProtocolName() const
{
return "smtps";
}
// Service infos
SMTPServiceInfos SMTPSTransport::sm_infos(true);
const serviceInfos& SMTPSTransport::getInfosInstance()
{
return sm_infos;
}
const serviceInfos& SMTPSTransport::getInfos() const
{
return sm_infos;
}
} // smtp
} // net
} // vmime

View File

@ -0,0 +1,136 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 along
// with this program; if not, write to the Free Software Foundation, Inc., Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
#include "vmime/net/smtp/SMTPServiceInfos.hpp"
namespace vmime {
namespace net {
namespace smtp {
SMTPServiceInfos::SMTPServiceInfos(const bool smtps)
: m_smtps(smtps)
{
}
const string SMTPServiceInfos::getPropertyPrefix() const
{
if (m_smtps)
return "transport.smtps.";
else
return "transport.smtp.";
}
const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const
{
static props smtpProps =
{
// SMTP-specific options
property("options.need-authentication", serviceInfos::property::TYPE_BOOL, "false"),
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "false"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
#if VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::CONNECTION_TLS),
property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
#endif // VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "25"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
static props smtpsProps =
{
// SMTP-specific options
property("options.need-authentication", serviceInfos::property::TYPE_BOOL, "false"),
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "false"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
#if VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::CONNECTION_TLS),
property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
#endif // VMIME_HAVE_TLS_SUPPORT
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "465"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
return m_smtps ? smtpsProps : smtpProps;
}
const std::vector <serviceInfos::property> SMTPServiceInfos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// SMTP-specific options
list.push_back(p.PROPERTY_OPTIONS_NEEDAUTH);
#if VMIME_HAVE_SASL_SUPPORT
list.push_back(p.PROPERTY_OPTIONS_SASL);
list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
list.push_back(p.PROPERTY_AUTH_USERNAME);
list.push_back(p.PROPERTY_AUTH_PASSWORD);
#if VMIME_HAVE_TLS_SUPPORT
if (!m_smtps)
{
list.push_back(p.PROPERTY_CONNECTION_TLS);
list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED);
}
#endif // VMIME_HAVE_TLS_SUPPORT
list.push_back(p.PROPERTY_SERVER_ADDRESS);
list.push_back(p.PROPERTY_SERVER_PORT);
list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY);
list.push_back(p.PROPERTY_TIMEOUT_FACTORY);
return list;
}
} // smtp
} // net
} // vmime

View File

@ -24,8 +24,6 @@
#include "vmime/encoderB64.hpp"
#include "vmime/mailboxList.hpp"
#include "vmime/net/authHelper.hpp"
#include "vmime/utility/filteredStream.hpp"
#include "vmime/utility/stringUtils.hpp"
@ -33,12 +31,18 @@
#include "vmime/security/sasl/SASLContext.hpp"
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/tls/TLSSession.hpp"
#endif // VMIME_HAVE_TLS_SUPPORT
// Helpers for service properties
#define GET_PROPERTY(type, prop) \
(sm_infos.getPropertyValue <type>(getSession(), sm_infos.getProperties().prop))
(getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const SMTPServiceInfos&>(getInfos()).getProperties().prop))
#define HAS_PROPERTY(prop) \
(sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop))
(getInfos().hasProperty(getSession(), \
dynamic_cast <const SMTPServiceInfos&>(getInfos()).getProperties().prop))
namespace vmime {
@ -46,9 +50,10 @@ namespace net {
namespace smtp {
SMTPTransport::SMTPTransport(ref <session> sess, ref <security::authenticator> auth)
SMTPTransport::SMTPTransport(ref <session> sess, ref <security::authenticator> auth, const bool secured)
: transport(sess, getInfosInstance(), auth), m_socket(NULL),
m_authentified(false), m_extendedSMTP(false), m_timeoutHandler(NULL)
m_authentified(false), m_extendedSMTP(false), m_timeoutHandler(NULL),
m_secured(secured)
{
}
@ -97,6 +102,20 @@ void SMTPTransport::connect()
getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY));
m_socket = sf->create();
#if VMIME_HAVE_TLS_SUPPORT
if (m_secured) // dedicated port/SMTPS
{
ref <tls::TLSSession> tlsSession =
vmime::create <tls::TLSSession>(getCertificateVerifier());
ref <tls::TLSSocket> tlsSocket =
tlsSession->getSocket(m_socket);
m_socket = tlsSocket;
}
#endif // VMIME_HAVE_TLS_SUPPORT
m_socket->connect(address, port);
m_responseBuffer.clear();
@ -146,6 +165,39 @@ void SMTPTransport::connect()
m_extendedSMTPResponse = response;
}
#if VMIME_HAVE_TLS_SUPPORT
// Setup secured connection, if requested
const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
&& GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
if (!m_secured && tls) // only if not POP3S
{
try
{
startTLS();
}
// Non-fatal error
catch (exceptions::command_error&)
{
if (tlsRequired)
{
throw;
}
else
{
// TLS is not required, so don't bother
}
}
// Fatal error
catch (...)
{
throw;
}
}
#endif // VMIME_HAVE_TLS_SUPPORT
// Authentication
if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH))
authenticate();
@ -369,6 +421,45 @@ void SMTPTransport::authenticateSASL()
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
void SMTPTransport::startTLS()
{
try
{
sendRequest("STARTTLS");
string response;
if (readAllResponses(response) != 220)
throw exceptions::command_error("STARTTLS", response);
ref <tls::TLSSession> tlsSession =
vmime::create <tls::TLSSession>(getCertificateVerifier());
ref <tls::TLSSocket> tlsSocket =
tlsSession->getSocket(m_socket);
tlsSocket->handshake(m_timeoutHandler);
m_socket = tlsSocket;
}
catch (exceptions::command_error&)
{
// Non-fatal error
throw;
}
catch (exception&)
{
// Fatal error
internalDisconnect();
throw;
}
}
#endif // VMIME_HAVE_TLS_SUPPORT
const bool SMTPTransport::isConnected() const
{
return (m_socket && m_socket->isConnected() && m_authentified);
@ -516,6 +607,8 @@ const string SMTPTransport::readResponseLine()
{
if (!m_timeoutHandler->handleTimeOut())
throw exceptions::operation_timed_out();
m_timeoutHandler->resetTimeOut();
}
// Receive data from the socket
@ -589,76 +682,18 @@ const int SMTPTransport::readAllResponses(string& outText, const bool allText)
// Service infos
SMTPTransport::_infos SMTPTransport::sm_infos;
SMTPServiceInfos SMTPTransport::sm_infos(false);
const serviceInfos& SMTPTransport::getInfosInstance()
{
return (sm_infos);
return sm_infos;
}
const serviceInfos& SMTPTransport::getInfos() const
{
return (sm_infos);
}
const string SMTPTransport::_infos::getPropertyPrefix() const
{
return "transport.smtp.";
}
const SMTPTransport::_infos::props& SMTPTransport::_infos::getProperties() const
{
static props p =
{
// SMTP-specific options
property("options.need-authentication", serviceInfos::property::TYPE_BOOL, "false"),
#if VMIME_HAVE_SASL_SUPPORT
property("options.sasl", serviceInfos::property::TYPE_BOOL, "true"),
property("options.sasl.fallback", serviceInfos::property::TYPE_BOOL, "false"),
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
property(serviceInfos::property::AUTH_USERNAME),
property(serviceInfos::property::AUTH_PASSWORD),
property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
property(serviceInfos::property::SERVER_PORT, "25"),
property(serviceInfos::property::SERVER_SOCKETFACTORY),
property(serviceInfos::property::TIMEOUT_FACTORY)
};
return p;
}
const std::vector <serviceInfos::property> SMTPTransport::_infos::getAvailableProperties() const
{
std::vector <property> list;
const props& p = getProperties();
// SMTP-specific options
list.push_back(p.PROPERTY_OPTIONS_NEEDAUTH);
#if VMIME_HAVE_SASL_SUPPORT
list.push_back(p.PROPERTY_OPTIONS_SASL);
list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
list.push_back(p.PROPERTY_AUTH_USERNAME);
list.push_back(p.PROPERTY_AUTH_PASSWORD);
list.push_back(p.PROPERTY_SERVER_ADDRESS);
list.push_back(p.PROPERTY_SERVER_PORT);
list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY);
list.push_back(p.PROPERTY_TIMEOUT_FACTORY);
return (list);
return sm_infos;
}

342
src/net/tls/TLSSession.cpp Normal file
View File

@ -0,0 +1,342 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 <gnutls/gnutls.h>
#include <gnutls/extra.h>
#include "vmime/net/tls/TLSSession.hpp"
#include "vmime/exception.hpp"
// Enable GnuTLS debugging by defining GNUTLS_DEBUG
//#define GNUTLS_DEBUG 1
#if VMIME_DEBUG && GNUTLS_DEBUG
#include <iostream>
#endif // VMIME_DEBUG && GNUTLS_DEBUG
namespace vmime {
namespace net {
namespace tls {
#ifndef VMIME_BUILDING_DOC
// Initialize GNU TLS library
struct TLSGlobal
{
TLSGlobal()
{
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 <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.
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);
// 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 <tls::certificateVerifier> TLSSession::getCertificateVerifier()
{
return m_certVerifier;
}
void TLSSession::throwTLSException(const string& fname, const int code)
{
string msg = fname + "() returned ";
#define ERROR(x) \
case x: msg += #x; break;
switch (code)
{
ERROR(GNUTLS_E_SUCCESS)
ERROR(GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM)
ERROR(GNUTLS_E_UNKNOWN_CIPHER_TYPE)
ERROR(GNUTLS_E_LARGE_PACKET)
ERROR(GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
ERROR(GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
ERROR(GNUTLS_E_INVALID_SESSION)
ERROR(GNUTLS_E_FATAL_ALERT_RECEIVED)
ERROR(GNUTLS_E_UNEXPECTED_PACKET)
ERROR(GNUTLS_E_WARNING_ALERT_RECEIVED)
ERROR(GNUTLS_E_ERROR_IN_FINISHED_PACKET)
ERROR(GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)
ERROR(GNUTLS_E_UNKNOWN_CIPHER_SUITE)
ERROR(GNUTLS_E_UNWANTED_ALGORITHM)
ERROR(GNUTLS_E_MPI_SCAN_FAILED)
ERROR(GNUTLS_E_DECRYPTION_FAILED)
ERROR(GNUTLS_E_MEMORY_ERROR)
ERROR(GNUTLS_E_DECOMPRESSION_FAILED)
ERROR(GNUTLS_E_COMPRESSION_FAILED)
ERROR(GNUTLS_E_AGAIN)
ERROR(GNUTLS_E_EXPIRED)
ERROR(GNUTLS_E_DB_ERROR)
ERROR(GNUTLS_E_SRP_PWD_ERROR)
ERROR(GNUTLS_E_INSUFFICIENT_CREDENTIALS)
ERROR(GNUTLS_E_HASH_FAILED)
ERROR(GNUTLS_E_BASE64_DECODING_ERROR)
ERROR(GNUTLS_E_MPI_PRINT_FAILED)
ERROR(GNUTLS_E_REHANDSHAKE)
ERROR(GNUTLS_E_GOT_APPLICATION_DATA)
ERROR(GNUTLS_E_RECORD_LIMIT_REACHED)
ERROR(GNUTLS_E_ENCRYPTION_FAILED)
ERROR(GNUTLS_E_PK_ENCRYPTION_FAILED)
ERROR(GNUTLS_E_PK_DECRYPTION_FAILED)
ERROR(GNUTLS_E_PK_SIGN_FAILED)
ERROR(GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION)
ERROR(GNUTLS_E_KEY_USAGE_VIOLATION)
ERROR(GNUTLS_E_NO_CERTIFICATE_FOUND)
ERROR(GNUTLS_E_INVALID_REQUEST)
ERROR(GNUTLS_E_SHORT_MEMORY_BUFFER)
ERROR(GNUTLS_E_INTERRUPTED)
ERROR(GNUTLS_E_PUSH_ERROR)
ERROR(GNUTLS_E_PULL_ERROR)
ERROR(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER)
ERROR(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
ERROR(GNUTLS_E_PKCS1_WRONG_PAD)
ERROR(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION)
ERROR(GNUTLS_E_INTERNAL_ERROR)
ERROR(GNUTLS_E_DH_PRIME_UNACCEPTABLE)
ERROR(GNUTLS_E_FILE_ERROR)
ERROR(GNUTLS_E_TOO_MANY_EMPTY_PACKETS)
ERROR(GNUTLS_E_UNKNOWN_PK_ALGORITHM)
ERROR(GNUTLS_E_INIT_LIBEXTRA)
ERROR(GNUTLS_E_LIBRARY_VERSION_MISMATCH)
ERROR(GNUTLS_E_NO_TEMPORARY_RSA_PARAMS)
ERROR(GNUTLS_E_LZO_INIT_FAILED)
ERROR(GNUTLS_E_NO_COMPRESSION_ALGORITHMS)
ERROR(GNUTLS_E_NO_CIPHER_SUITES)
ERROR(GNUTLS_E_OPENPGP_GETKEY_FAILED)
ERROR(GNUTLS_E_PK_SIG_VERIFY_FAILED)
ERROR(GNUTLS_E_ILLEGAL_SRP_USERNAME)
ERROR(GNUTLS_E_SRP_PWD_PARSING_ERROR)
ERROR(GNUTLS_E_NO_TEMPORARY_DH_PARAMS)
ERROR(GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
ERROR(GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND)
ERROR(GNUTLS_E_ASN1_DER_ERROR)
ERROR(GNUTLS_E_ASN1_VALUE_NOT_FOUND)
ERROR(GNUTLS_E_ASN1_GENERIC_ERROR)
ERROR(GNUTLS_E_ASN1_VALUE_NOT_VALID)
ERROR(GNUTLS_E_ASN1_TAG_ERROR)
ERROR(GNUTLS_E_ASN1_TAG_IMPLICIT)
ERROR(GNUTLS_E_ASN1_TYPE_ANY_ERROR)
ERROR(GNUTLS_E_ASN1_SYNTAX_ERROR)
ERROR(GNUTLS_E_ASN1_DER_OVERFLOW)
ERROR(GNUTLS_E_OPENPGP_TRUSTDB_VERSION_UNSUPPORTED)
ERROR(GNUTLS_E_OPENPGP_UID_REVOKED)
ERROR(GNUTLS_E_CERTIFICATE_ERROR)
//ERROR(GNUTLS_E_X509_CERTIFICATE_ERROR)
ERROR(GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
ERROR(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE)
ERROR(GNUTLS_E_X509_UNKNOWN_SAN)
ERROR(GNUTLS_E_OPENPGP_FINGERPRINT_UNSUPPORTED)
ERROR(GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE)
ERROR(GNUTLS_E_UNKNOWN_HASH_ALGORITHM)
ERROR(GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE)
ERROR(GNUTLS_E_UNKNOWN_PKCS_BAG_TYPE)
ERROR(GNUTLS_E_INVALID_PASSWORD)
ERROR(GNUTLS_E_MAC_VERIFY_FAILED)
ERROR(GNUTLS_E_CONSTRAINT_ERROR)
ERROR(GNUTLS_E_BASE64_ENCODING_ERROR)
ERROR(GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY)
//ERROR(GNUTLS_E_INCOMPATIBLE_CRYPTO_LIBRARY)
ERROR(GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY)
ERROR(GNUTLS_E_OPENPGP_KEYRING_ERROR)
ERROR(GNUTLS_E_X509_UNSUPPORTED_OID)
//ERROR(GNUTLS_E_RANDOM_FAILED)
ERROR(GNUTLS_E_UNIMPLEMENTED_FEATURE)
default:
msg += "unknown error";
break;
}
#undef ERROR
throw exceptions::tls_exception(msg);
}
} // tls
} // net
} // vmime

391
src/net/tls/TLSSocket.cpp Normal file
View File

@ -0,0 +1,391 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "vmime/net/tls/TLSSocket.hpp"
#include "vmime/net/tls/TLSSession.hpp"
#include "vmime/platformDependant.hpp"
#include "vmime/net/tls/X509Certificate.hpp"
namespace vmime {
namespace net {
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()
{
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;
}
}
const bool TLSSocket::isConnected() const
{
return m_wrapped->isConnected() && m_connected;
}
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());
}
const int TLSSocket::receiveRaw(char* buffer, const int 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 int 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
platformDependant::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 <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
platformDependant::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 <certificateChain> TLSSocket::getPeerCertificates()
{
unsigned int certCount = 0;
const gnutls_datum* rawData = gnutls_certificate_get_peers
(*m_session->m_gnutlsSession, &certCount);
// Try X.509
gnutls_x509_crt* x509Certs = new gnutls_x509_crt[certCount];
unsigned int count = certCount;
int res = gnutls_x509_crt_list_import
(x509Certs, &count, rawData, GNUTLS_X509_FMT_PEM, 0);
if (res <= 0)
{
count = certCount;
res = gnutls_x509_crt_list_import
(x509Certs, &count, rawData, GNUTLS_X509_FMT_DER, 0);
}
if (res >= 1)
{
std::vector <ref <certificate> > certs;
bool error = false;
count = static_cast <unsigned int>(res);
for (unsigned int i = 0 ; i < count ; ++i)
{
size_t dataSize = 0;
gnutls_x509_crt_export(x509Certs[i],
GNUTLS_X509_FMT_DER, NULL, &dataSize);
byte* data = new byte[dataSize];
gnutls_x509_crt_export(x509Certs[i],
GNUTLS_X509_FMT_DER, data, &dataSize);
ref <X509Certificate> cert =
X509Certificate::import(data, dataSize);
if (cert != NULL)
certs.push_back(cert);
else
error = true;
delete [] data;
gnutls_x509_crt_deinit(x509Certs[i]);
}
delete [] x509Certs;
if (error)
return NULL;
return vmime::create <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 not catched.
#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)
{
// To avoid memory leaks
exToDelete.push_back(vmime::create <TLSSocket_DeleteExWrapper>(m_ex));
throw *m_ex;
}
}
} // tls
} // net
} // vmime

View File

@ -0,0 +1,273 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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 <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <ctime>
#include "vmime/net/tls/X509Certificate.hpp"
namespace vmime {
namespace net {
namespace tls {
#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()
{
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* data, const unsigned int length)
{
ref <X509Certificate> cert = vmime::create <X509Certificate>();
gnutls_datum buffer;
buffer.data = const_cast <byte*>(data);
buffer.size = length;
// Try DER format
if (gnutls_x509_crt_import(cert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0)
return cert;
// Try PEM format
if (gnutls_x509_crt_import(cert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0)
return cert;
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);
byte* data = new byte[dataSize];
gnutls_x509_crt_export(m_data->cert, fmt, data, &dataSize);
try
{
os.write(reinterpret_cast <utility::stream::value_type*>(data), dataSize);
}
catch (...)
{
delete [] data;
throw;
}
}
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);
}
const bool X509Certificate::checkIssuer
(ref <const X509Certificate> issuer) const
{
return (gnutls_x509_crt_check_issuer
(m_data->cert, issuer->m_data->cert) >= 1);
}
const 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);
byte* buffer = new byte[bufferSize];
if (gnutls_x509_crt_get_fingerprint
(m_data->cert, galgo, buffer, &bufferSize) == 0)
{
byteArray res;
res.insert(res.end(), buffer, buffer + bufferSize);
delete [] buffer;
return res;
}
delete [] buffer;
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";
}
const int X509Certificate::getVersion() const
{
return gnutls_x509_crt_get_version(m_data->cert);
}
const 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;
}
} // tls
} // net
} // vmime

View File

@ -21,22 +21,33 @@
// the GNU General Public License cover the whole combination.
//
#ifndef VMIME_NET_AUTHHELPER_HPP_INCLUDED
#define VMIME_NET_AUTHHELPER_HPP_INCLUDED
#include "vmime/types.hpp"
#include "vmime/net/tls/certificateChain.hpp"
namespace vmime {
namespace net {
namespace tls {
void hmac_md5(const string& text, const string& key, string& hexDigest);
certificateChain::certificateChain(const std::vector <ref <certificate> >& certs)
: m_certs(certs)
{
}
const unsigned int certificateChain::getCount() const
{
return static_cast <unsigned int>(m_certs.size());
}
ref <certificate> certificateChain::getAt(const unsigned int index)
{
return m_certs[index];
}
} // tls
} // net
} // vmime
#endif // VMIME_NET_AUTHHELPER_HPP_INCLUDED

View File

@ -0,0 +1,164 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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/net/tls/defaultCertificateVerifier.hpp"
#include "vmime/net/tls/X509Certificate.hpp"
#include "vmime/exception.hpp"
namespace vmime {
namespace net {
namespace tls {
defaultCertificateVerifier::defaultCertificateVerifier()
{
}
defaultCertificateVerifier::~defaultCertificateVerifier()
{
}
defaultCertificateVerifier::defaultCertificateVerifier(const defaultCertificateVerifier&)
: certificateVerifier()
{
// Not used
}
void defaultCertificateVerifier::verify(ref <certificateChain> chain)
{
if (chain->getCount() == 0)
return;
const string type = chain->getAt(0)->getType();
if (type == "X.509")
verifyX509(chain);
else
throw exceptions::unsupported_certificate_type(type);
}
void defaultCertificateVerifier::verifyX509(ref <certificateChain> chain)
{
// For every certificate in the chain, verify that the certificate
// has been issued by the next certificate in the chain
if (chain->getCount() >= 2)
{
for (unsigned int i = 0 ; i < chain->getCount() - 1 ; ++i)
{
ref <X509Certificate> cert =
chain->getAt(i).dynamicCast <X509Certificate>();
ref <X509Certificate> next =
chain->getAt(i + 1).dynamicCast <X509Certificate>();
if (!cert->checkIssuer(next))
{
throw exceptions::certificate_verification_exception
("Subject/issuer verification failed.");
}
}
}
// For every certificate in the chain, verify that the certificate
// is valid at the current time
const datetime now = datetime::now();
for (unsigned int i = 0 ; i < chain->getCount() ; ++i)
{
ref <X509Certificate> cert =
chain->getAt(i).dynamicCast <X509Certificate>();
const datetime begin = cert->getActivationDate();
const datetime end = cert->getExpirationDate();
if (now < begin || now > end)
{
throw exceptions::certificate_verification_exception
("Validity date check failed.");
}
}
// Check whether the certificate can be trusted
// -- First, verify that the the last certificate in the chain was
// -- issued by a third-party that we trust
ref <X509Certificate> lastCert =
chain->getAt(chain->getCount() - 1).dynamicCast <X509Certificate>();
bool trusted = false;
for (unsigned int i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i)
{
ref <X509Certificate> rootCa = m_x509RootCAs[i];
if (lastCert->verify(rootCa))
trusted = true;
}
// -- Next, if the issuer certificate cannot be verified against
// -- root CAs, compare the subject's certificate against the
// -- trusted certificates
ref <X509Certificate> firstCert =
chain->getAt(0).dynamicCast <X509Certificate>();
for (unsigned int i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i)
{
ref <X509Certificate> cert = m_x509TrustedCerts[i];
if (firstCert->equals(cert))
trusted = true;
}
if (!trusted)
{
throw exceptions::certificate_verification_exception
("Cannot verify certificate against trusted certificates.");
}
}
void defaultCertificateVerifier::setX509RootCAs
(const std::vector <ref <X509Certificate> >& caCerts)
{
m_x509RootCAs = caCerts;
}
void defaultCertificateVerifier::setX509TrustedCerts
(const std::vector <ref <X509Certificate> >& trustedCerts)
{
m_x509TrustedCerts = trustedCerts;
}
} // tls
} // net
} // vmime

View File

@ -117,6 +117,22 @@ void outputStreamStringAdapter::write(const value_type* const data, const size_t
// outputStreamByteArrayAdapter
outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array)
: m_array(array)
{
m_array.clear();
}
void outputStreamByteArrayAdapter::write(const value_type* const data, const size_type count)
{
m_array.insert(m_array.end(), data, data + count);
}
// inputStreamAdapter
inputStreamAdapter::inputStreamAdapter(std::istream& is)

View File

@ -842,7 +842,7 @@ INCLUDE_FILE_PATTERNS =
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed.
PREDEFINED = VMIME_BUILDING_DOC
PREDEFINED = VMIME_BUILDING_DOC VMIME_HAVE_SASL_SUPPORT VMIME_HAVE_TLS_SUPPORT
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.

View File

@ -77,11 +77,15 @@ public:
*/
virtual const char* name() const throw();
/** Clone this object.
*
* @return a new copy of this object
*/
virtual exception* clone() const;
protected:
static const exception NO_EXCEPTION;
virtual exception* clone() const;
};
@ -818,7 +822,7 @@ public:
#if VMIME_HAVE_SASL_SUPPORT
/** Base class for exceptions throw by SASL module.
/** Base class for exceptions thrown by SASL module.
*/
class sasl_exception : public vmime::exception
@ -866,6 +870,63 @@ public:
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
/** Base class for exceptions thrown by TLS module.
*/
class tls_exception : public vmime::exception
{
public:
tls_exception(const string& what, const exception& other = NO_EXCEPTION);
~tls_exception() throw();
exception* clone() const;
const char* name() const throw();
};
class certificate_exception : public tls_exception
{
public:
certificate_exception(const string& what, const exception& other = NO_EXCEPTION);
~certificate_exception() throw();
exception* clone() const;
const char* name() const throw();
};
class certificate_verification_exception : public certificate_exception
{
public:
certificate_verification_exception(const string& what, const exception& other = NO_EXCEPTION);
~certificate_verification_exception() throw ();
exception* clone() const;
const char* name() const throw ();
};
class unsupported_certificate_type : public certificate_exception
{
public:
unsupported_certificate_type(const string& type, const exception& other = NO_EXCEPTION);
~unsupported_certificate_type() throw ();
exception* clone() const;
const char* name() const throw ();
};
#endif // VMIME_HAVE_TLS_SUPPORT
} // exceptions

View File

@ -99,6 +99,10 @@ private:
void authenticateSASL();
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
void startTLS();
#endif // VMIME_HAVE_TLS_SUPPORT
weak_ref <IMAPStore> m_store;

View File

@ -94,6 +94,11 @@ public:
return (m_tag);
}
void setSocket(weak_ref <socket> sok)
{
m_socket = sok;
}
const string lastLine() const
{

View File

@ -0,0 +1,63 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_IMAP_IMAPSSTORE_HPP_INCLUDED
#define VMIME_NET_IMAP_IMAPSSTORE_HPP_INCLUDED
#include "vmime/net/imap/IMAPStore.hpp"
namespace vmime {
namespace net {
namespace imap {
/** IMAPS store service.
*/
class IMAPSStore : public IMAPStore
{
public:
IMAPSStore(ref <session> sess, ref <security::authenticator> auth);
~IMAPSStore();
const string getProtocolName() const;
static const serviceInfos& getInfosInstance();
const serviceInfos& getInfos() const;
private:
static IMAPServiceInfos sm_infos;
};
} // imap
} // net
} // vmime
#endif // VMIME_NET_IMAP_IMAPSSTORE_HPP_INCLUDED

View File

@ -0,0 +1,87 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_IMAP_IMAPSERVICEINFOS_HPP_INCLUDED
#define VMIME_NET_IMAP_IMAPSERVICEINFOS_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/net/serviceInfos.hpp"
namespace vmime {
namespace net {
namespace imap {
/** Information about IMAP service.
*/
class IMAPServiceInfos : public serviceInfos
{
public:
IMAPServiceInfos(const bool imaps);
struct props
{
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
serviceInfos::property PROPERTY_OPTIONS_SASL;
serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
serviceInfos::property PROPERTY_AUTH_USERNAME;
serviceInfos::property PROPERTY_AUTH_PASSWORD;
#if VMIME_HAVE_TLS_SUPPORT
serviceInfos::property PROPERTY_CONNECTION_TLS;
serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED;
#endif // VMIME_HAVE_TLS_SUPPORT
serviceInfos::property PROPERTY_SERVER_ADDRESS;
serviceInfos::property PROPERTY_SERVER_PORT;
serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY;
serviceInfos::property PROPERTY_TIMEOUT_FACTORY;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
private:
const bool m_imaps;
};
} // imap
} // net
} // vmime
#endif // VMIME_NET_IMAP_IMAPSERVICEINFOS_HPP_INCLUDED

View File

@ -31,7 +31,7 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/folder.hpp"
#include <ostream>
#include "vmime/net/imap/IMAPServiceInfos.hpp"
namespace vmime {
@ -56,7 +56,7 @@ class IMAPStore : public store
public:
IMAPStore(ref <session> sess, ref <security::authenticator> auth);
IMAPStore(ref <session> sess, ref <security::authenticator> auth, const bool secured = false);
~IMAPStore();
const string getProtocolName() const;
@ -78,7 +78,9 @@ public:
const int getCapabilities() const;
private:
const bool isSecuredConnection() const;
protected:
// Connection
ref <IMAPConnection> m_connection;
@ -93,39 +95,10 @@ private:
std::list <IMAPFolder*> m_folders;
bool m_secured; // Use IMAPS
// Service infos
class _infos : public serviceInfos
{
public:
struct props
{
// IMAP-specific options
#if VMIME_HAVE_SASL_SUPPORT
serviceInfos::property PROPERTY_OPTIONS_SASL;
serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
serviceInfos::property PROPERTY_AUTH_USERNAME;
serviceInfos::property PROPERTY_AUTH_PASSWORD;
serviceInfos::property PROPERTY_SERVER_ADDRESS;
serviceInfos::property PROPERTY_SERVER_PORT;
serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY;
serviceInfos::property PROPERTY_TIMEOUT_FACTORY;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
static _infos sm_infos;
static IMAPServiceInfos sm_infos;
};

View File

@ -0,0 +1,64 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
#define VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/net/serviceInfos.hpp"
namespace vmime {
namespace net {
namespace maildir {
/** Information about maildir service.
*/
class maildirServiceInfos : public serviceInfos
{
public:
maildirServiceInfos();
struct props
{
serviceInfos::property PROPERTY_SERVER_ROOTPATH;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
} // maildir
} // net
} // vmime
#endif // VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED

View File

@ -31,6 +31,8 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/folder.hpp"
#include "vmime/net/maildir/maildirServiceInfos.hpp"
#include "vmime/utility/file.hpp"
#include <ostream>
@ -91,22 +93,7 @@ private:
// Service infos
class _infos : public serviceInfos
{
public:
struct props
{
serviceInfos::property PROPERTY_SERVER_ROOTPATH;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
static _infos sm_infos;
static maildirServiceInfos sm_infos;
};

View File

@ -0,0 +1,63 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_POP3_POP3SSTORE_HPP_INCLUDED
#define VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED
#include "vmime/net/pop3/POP3Store.hpp"
namespace vmime {
namespace net {
namespace pop3 {
/** POP3S store service.
*/
class POP3SStore : public POP3Store
{
public:
POP3SStore(ref <session> sess, ref <security::authenticator> auth);
~POP3SStore();
const string getProtocolName() const;
static const serviceInfos& getInfosInstance();
const serviceInfos& getInfos() const;
private:
static POP3ServiceInfos sm_infos;
};
} // pop3
} // net
} // vmime
#endif // VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED

View File

@ -0,0 +1,89 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_POP3_POP3SERVICEINFOS_HPP_INCLUDED
#define VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/net/serviceInfos.hpp"
namespace vmime {
namespace net {
namespace pop3 {
/** Information about POP3 service.
*/
class POP3ServiceInfos : public serviceInfos
{
public:
POP3ServiceInfos(const bool pop3s);
struct props
{
// POP3-specific options
serviceInfos::property PROPERTY_OPTIONS_APOP;
serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK;
#if VMIME_HAVE_SASL_SUPPORT
serviceInfos::property PROPERTY_OPTIONS_SASL;
serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
serviceInfos::property PROPERTY_AUTH_USERNAME;
serviceInfos::property PROPERTY_AUTH_PASSWORD;
#if VMIME_HAVE_TLS_SUPPORT
serviceInfos::property PROPERTY_CONNECTION_TLS;
serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED;
#endif // VMIME_HAVE_TLS_SUPPORT
serviceInfos::property PROPERTY_SERVER_ADDRESS;
serviceInfos::property PROPERTY_SERVER_PORT;
serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY;
serviceInfos::property PROPERTY_TIMEOUT_FACTORY;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
private:
const bool m_pop3s;
};
} // pop3
} // net
} // vmime
#endif // VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED

View File

@ -31,6 +31,8 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/pop3/POP3ServiceInfos.hpp"
#include "vmime/utility/stream.hpp"
@ -52,7 +54,7 @@ class POP3Store : public store
public:
POP3Store(ref <session> sess, ref <security::authenticator> auth);
POP3Store(ref <session> sess, ref <security::authenticator> auth, const bool secured = false);
~POP3Store();
const string getProtocolName() const;
@ -88,6 +90,10 @@ private:
void authenticateSASL();
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
void startTLS();
#endif // VMIME_HAVE_TLS_SUPPORT
const std::vector <string> getCapabilities();
static const bool isSuccessResponse(const string& buffer);
@ -116,40 +122,11 @@ private:
ref <timeoutHandler> m_timeoutHandler;
bool m_secured;
// Service infos
class _infos : public serviceInfos
{
public:
struct props
{
// POP3-specific options
serviceInfos::property PROPERTY_OPTIONS_APOP;
serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK;
#if VMIME_HAVE_SASL_SUPPORT
serviceInfos::property PROPERTY_OPTIONS_SASL;
serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
serviceInfos::property PROPERTY_AUTH_USERNAME;
serviceInfos::property PROPERTY_AUTH_PASSWORD;
serviceInfos::property PROPERTY_SERVER_ADDRESS;
serviceInfos::property PROPERTY_SERVER_PORT;
serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY;
serviceInfos::property PROPERTY_TIMEOUT_FACTORY;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
static _infos sm_infos;
static POP3ServiceInfos sm_infos;
};

View File

@ -0,0 +1,64 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_SENDMAIL_SENDMAILSERVICEINFOS_HPP_INCLUDED
#define VMIME_NET_SENDMAIL_SENDMAILSERVICEINFOS_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/net/serviceInfos.hpp"
namespace vmime {
namespace net {
namespace sendmail {
/** Information about sendmail service.
*/
class sendmailServiceInfos : public serviceInfos
{
public:
sendmailServiceInfos();
struct props
{
serviceInfos::property PROPERTY_BINPATH;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
} // sendmail
} // net
} // vmime
#endif // VMIME_NET_SENDMAIL_SENDMAILSERVICEINFOS_HPP_INCLUDED

View File

@ -31,6 +31,8 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/sendmail/sendmailServiceInfos.hpp"
#if VMIME_BUILTIN_PLATFORM_POSIX
@ -77,22 +79,7 @@ private:
// Service infos
class _infos : public serviceInfos
{
public:
struct props
{
serviceInfos::property PROPERTY_BINPATH;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
static _infos sm_infos;
static sendmailServiceInfos sm_infos;
};

View File

@ -25,6 +25,7 @@
#define VMIME_NET_SERVICE_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/types.hpp"
#include "vmime/net/session.hpp"
@ -32,6 +33,10 @@
#include "vmime/net/serviceFactory.hpp"
#include "vmime/net/serviceInfos.hpp"
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/tls/certificateVerifier.hpp"
#endif // VMIME_HAVE_TLS_SUPPORT
#include "vmime/utility/progressionListener.hpp"
@ -52,7 +57,7 @@ public:
virtual ~service();
// Possible service types
/** Possible service types. */
enum Type
{
TYPE_STORE = 0, /**< The service is a message store. */
@ -127,6 +132,20 @@ public:
*/
void setAuthenticator(ref <security::authenticator> auth);
#if VMIME_HAVE_TLS_SUPPORT
/** Set the object responsible for verifying certificates when
* using secured connections (TLS/SSL).
*/
void setCertificateVerifier(ref <tls::certificateVerifier> cv);
/** Get the object responsible for verifying certificates when
* using secured connections (TLS/SSL).
*/
ref <tls::certificateVerifier> getCertificateVerifier();
#endif // VMIME_HAVE_TLS_SUPPORT
/** Set a property for this service (service prefix is added automatically).
*
* WARNING: this sets the property on the session object, so all service
@ -148,10 +167,10 @@ public:
{
public:
initializer(const string& protocol)
initializer(const string& protocol, const Type type)
{
serviceFactory::getInstance()->
template registerServiceByProtocol <S>(protocol);
template registerServiceByProtocol <S>(protocol, type);
}
};
#endif // VMIME_BUILDING_DOC
@ -160,6 +179,11 @@ private:
ref <session> m_session;
ref <security::authenticator> m_auth;
#if VMIME_HAVE_TLS_SUPPORT
ref <tls::certificateVerifier> m_certVerifier;
#endif // VMIME_HAVE_TLS_SUPPORT
};

View File

@ -45,8 +45,8 @@ namespace vmime {
namespace net {
class service;
class session;
class service;
/** A factory to create 'service' objects for a specified protocol.
@ -78,6 +78,7 @@ public:
(ref <session> sess,
ref <security::authenticator> auth) const = 0;
virtual const int getType() const = 0;
virtual const string& getName() const = 0;
virtual const serviceInfos& getInfos() const = 0;
};
@ -92,8 +93,8 @@ private:
protected:
registeredServiceImpl(const string& name)
: m_name(name), m_servInfos(S::getInfosInstance())
registeredServiceImpl(const string& name, const int type)
: m_type(type), m_name(name), m_servInfos(S::getInfosInstance())
{
}
@ -116,8 +117,14 @@ private:
return (m_name);
}
const int getType() const
{
return (m_type);
}
private:
const int m_type;
const string m_name;
const serviceInfos& m_servInfos;
};
@ -129,12 +136,13 @@ public:
/** Register a new service by its protocol name.
*
* @param protocol protocol name
* @param type service type
*/
template <class S>
void registerServiceByProtocol(const string& protocol)
void registerServiceByProtocol(const string& protocol, const int type)
{
const string name = utility::stringUtils::toLower(protocol);
m_services.push_back(vmime::create <registeredServiceImpl <S> >(name));
m_services.push_back(vmime::create <registeredServiceImpl <S> >(name, type));
}
/** Create a new service instance from a protocol name.

View File

@ -95,6 +95,23 @@ public:
* no time-out handler is used. */
static const property TIMEOUT_FACTORY;
#if VMIME_HAVE_TLS_SUPPORT
/** The common property 'connection.tls': this is used to
* start a secured connection if it is supported by the
* server (STARTTLS extension).
*/
static const property CONNECTION_TLS;
/** The common property 'connection.tls.required' should be
* set to 'true' to make the connection process fail if the
* server can't start a secured connection (no effect if
* 'connection.tls' is not set to 'true').
*/
static const property CONNECTION_TLS_REQUIRED;
#endif // VMIME_HAVE_TLS_SUPPORT
/** Value types.
*/

View File

@ -0,0 +1,63 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_SMTP_SMTPSSTORE_HPP_INCLUDED
#define VMIME_NET_SMTP_SMTPSSTORE_HPP_INCLUDED
#include "vmime/net/smtp/SMTPTransport.hpp"
namespace vmime {
namespace net {
namespace smtp {
/** SMTPS transport service.
*/
class SMTPSTransport : public SMTPTransport
{
public:
SMTPSTransport(ref <session> sess, ref <security::authenticator> auth);
~SMTPSTransport();
const string getProtocolName() const;
static const serviceInfos& getInfosInstance();
const serviceInfos& getInfos() const;
private:
static SMTPServiceInfos sm_infos;
};
} // smtp
} // net
} // vmime
#endif // VMIME_NET_SMTP_SMTPSSTORE_HPP_INCLUDED

View File

@ -0,0 +1,88 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_SMTP_SMTPSERVICEINFOS_HPP_INCLUDED
#define VMIME_NET_SMTP_SMTPSERVICEINFOS_HPP_INCLUDED
#include "vmime/config.hpp"
#include "vmime/net/serviceInfos.hpp"
namespace vmime {
namespace net {
namespace smtp {
/** Information about SMTP service.
*/
class SMTPServiceInfos : public serviceInfos
{
public:
SMTPServiceInfos(const bool smtps);
struct props
{
// SMTP-specific options
serviceInfos::property PROPERTY_OPTIONS_NEEDAUTH;
#if VMIME_HAVE_SASL_SUPPORT
serviceInfos::property PROPERTY_OPTIONS_SASL;
serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
serviceInfos::property PROPERTY_AUTH_USERNAME;
serviceInfos::property PROPERTY_AUTH_PASSWORD;
#if VMIME_HAVE_TLS_SUPPORT
serviceInfos::property PROPERTY_CONNECTION_TLS;
serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED;
#endif // VMIME_HAVE_TLS_SUPPORT
serviceInfos::property PROPERTY_SERVER_ADDRESS;
serviceInfos::property PROPERTY_SERVER_PORT;
serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY;
serviceInfos::property PROPERTY_TIMEOUT_FACTORY;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
private:
const bool m_smtps;
};
} // smtp
} // net
} // vmime
#endif // VMIME_NET_SMTP_SMTPSERVICEINFOS_HPP_INCLUDED

View File

@ -31,6 +31,8 @@
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/smtp/SMTPServiceInfos.hpp"
namespace vmime {
namespace net {
@ -44,7 +46,7 @@ class SMTPTransport : public transport
{
public:
SMTPTransport(ref <session> sess, ref <security::authenticator> auth);
SMTPTransport(ref <session> sess, ref <security::authenticator> auth, const bool secured = false);
~SMTPTransport();
const string getProtocolName() const;
@ -77,6 +79,9 @@ private:
void authenticateSASL();
#endif // VMIME_HAVE_SASL_SUPPORT
#if VMIME_HAVE_TLS_SUPPORT
void startTLS();
#endif // VMIME_HAVE_TLS_SUPPORT
ref <socket> m_socket;
bool m_authentified;
@ -89,39 +94,11 @@ private:
ref <timeoutHandler> m_timeoutHandler;
bool m_secured;
// Service infos
class _infos : public serviceInfos
{
public:
struct props
{
// SMTP-specific options
serviceInfos::property PROPERTY_OPTIONS_NEEDAUTH;
#if VMIME_HAVE_SASL_SUPPORT
serviceInfos::property PROPERTY_OPTIONS_SASL;
serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
#endif // VMIME_HAVE_SASL_SUPPORT
// Common properties
serviceInfos::property PROPERTY_AUTH_USERNAME;
serviceInfos::property PROPERTY_AUTH_PASSWORD;
serviceInfos::property PROPERTY_SERVER_ADDRESS;
serviceInfos::property PROPERTY_SERVER_PORT;
serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY;
serviceInfos::property PROPERTY_TIMEOUT_FACTORY;
};
const props& getProperties() const;
const string getPropertyPrefix() const;
const std::vector <serviceInfos::property> getAvailableProperties() const;
};
static _infos sm_infos;
static SMTPServiceInfos sm_infos;
};

View File

@ -0,0 +1,95 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_HPP_INCLUDED
#define VMIME_NET_TLS_TLSSESSION_HPP_INCLUDED
#include "vmime/types.hpp"
#include "vmime/net/tls/TLSSocket.hpp"
#include "vmime/net/tls/certificateVerifier.hpp"
namespace vmime {
namespace net {
namespace tls {
/** Describe a TLS connection between a client and a server.
*/
class TLSSession : public object
{
friend class TLSSocket;
public:
~TLSSession();
/** Create and initialize a new TLS session.
*
* @param cv object responsible for verifying certificates
* sent by the server
* @return a new TLS session
*/
TLSSession(ref <certificateVerifier> cv);
/** Create a new socket that adds a TLS security layer around
* an existing socket. You should create only one socket
* per session.
*
* @param sok socket to wrap
* @return TLS socket wrapper
*/
ref <TLSSocket> getSocket(ref <socket> sok);
/** Get the object responsible for verifying certificates when
* using secured connections (TLS/SSL).
*/
ref <tls::certificateVerifier> getCertificateVerifier();
private:
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 <certificateVerifier> m_certVerifier;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_TLSSESSION_HPP_INCLUDED

125
vmime/net/tls/TLSSocket.hpp Normal file
View File

@ -0,0 +1,125 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_HPP_INCLUDED
#define VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED
#include "vmime/exception.hpp"
#include "vmime/net/socket.hpp"
#include "vmime/net/timeoutHandler.hpp"
#include "vmime/net/tls/certificateChain.hpp"
namespace vmime {
namespace net {
namespace tls {
class TLSSession;
/** Add a TLS security layer to an existing socket.
*/
class TLSSocket : public socket
{
friend class vmime::creator;
protected:
/** Create a new socket object that adds a security layer
* around an existing socket.
*
* @param session TLS session
* @param sok socket to wrap
*/
TLSSocket(ref <TLSSession> session, ref <socket> sok);
public:
~TLSSocket();
/** Starts a TLS handshake on this connection.
*
* @throw exceptions::tls_exception if a fatal error occurs
* during the negociation process, exceptions::operation_timed_out
* if a time-out occurs
*/
void handshake(ref <timeoutHandler> toHandler = NULL);
/** Return the peer's certificate (chain) as sent by the peer.
*
* @return server certificate chain, or NULL if the handshake
* has not been performed yet
*/
ref <certificateChain> getPeerCertificates();
// Implementation of 'socket'
void connect(const string& address, const port_t port);
void disconnect();
const bool isConnected() const;
void receive(string& buffer);
const int receiveRaw(char* buffer, const int count);
void send(const string& buffer);
void sendRaw(const char* buffer, const int count);
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 ssize_t gnutlsPushFunc(void* trspt, const void* data, size_t len);
static ssize_t 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;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED

View File

@ -0,0 +1,158 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_X509CERTIFICATE_HPP_INCLUDED
#define VMIME_NET_TLS_X509CERTIFICATE_HPP_INCLUDED
#include "vmime/net/tls/certificate.hpp"
#include "vmime/utility/stream.hpp"
#include "vmime/base.hpp"
#include "vmime/dateTime.hpp"
namespace vmime {
namespace net {
namespace tls {
/** Identity certificate based on X.509 standard.
*/
class X509Certificate : public certificate
{
friend class vmime::creator;
protected:
X509Certificate();
X509Certificate(const X509Certificate&);
public:
~X509Certificate();
/** Supported encodings for X.509 certificates. */
enum Format
{
FORMAT_DER, /**< DER encoding */
FORMAT_PEM /**< PEM encoding */
};
/** Supported digest algorithms (used for fingerprint). */
enum DigestAlgorithm
{
DIGEST_MD5, /**< MD5 digest */
DIGEST_SHA1 /**< SHA1 digest */
};
/** Imports a DER or PEM encoded X.509 certificate.
*
* @param is input stream to read data from
* @return a X.509 certificate, or NULL if the given data does not
* represent a valid certificate
*/
static ref <X509Certificate> import(utility::inputStream& is);
/** Imports a DER or PEM encoded X.509 certificate.
*
* @param data points to raw data
* @param length size of data
* @return a X.509 certificate, or NULL if the given data does not
* represent a valid certificate
*/
static ref <X509Certificate> import(const byte* data, const unsigned int length);
/** Exports this X.509 certificate to the specified format.
*
* @param os output stream into which write data
* @param format output format
*/
void write(utility::outputStream& os, const Format format) const;
/** Returns the X.509 certificate's serial number. This is obtained
* by the X.509 Certificate 'serialNumber' field. Serial is not
* always a 32 or 64bit number. Some CAs use large serial numbers,
* thus it may be wise to handle it as something opaque.
*
* @return serial number of this certificate
*/
const byteArray getSerialNumber() const;
/** Checks if this certificate has the given issuer.
*
* @param issuer certificate of a possible issuer
* @return true if this certificate was issued by the given issuer,
* false otherwise
*/
const bool checkIssuer(ref <const X509Certificate> issuer) const;
/** Verifies this certificate against a given trusted one.
*
* @param caCert a certificate that is considered to be trusted one
* @return true if the verification succeeded, false otherwise
*/
const bool verify(ref <const X509Certificate> caCert) const;
/** Gets the expiration date of this certificate. This is the date
* at which this certificate will not be valid anymore.
*
* @return expiration date of this certificate
*/
const datetime getExpirationDate() const;
/** Gets the activation date of this certificate. This is the date
* at which this certificate will be valid.
*
* @return activation date of this certificate
*/
const datetime getActivationDate() const;
/** Returns the fingerprint of this certificate.
*
* @return the fingerprint of this certificate
*/
const byteArray getFingerprint(const DigestAlgorithm algo) const;
// Implementation of 'certificate'
const byteArray getEncoded() const;
const string getType() const;
const int getVersion() const;
const bool equals(ref <const certificate> other) const;
private:
class X509CertificateInternalData* m_data;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_X509CERTIFICATE_HPP_INCLUDED

View File

@ -0,0 +1,77 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_CERTIFICATE_HPP_INCLUDED
#define VMIME_NET_TLS_CERTIFICATE_HPP_INCLUDED
#include "vmime/types.hpp"
namespace vmime {
namespace net {
namespace tls {
/** Identity certificate for a peer.
*/
class certificate : public object
{
public:
/** Returns the encoded form of this certificate (for example,
* X.509 certificates are encoded as ASN.1 DER).
*
* @return the encoded form of this certificate
*/
virtual const byteArray getEncoded() const = 0;
/** Return the type of this certificate.
*
* @return the type of this certificate
*/
virtual const string getType() const = 0;
/** Return the version of this certificate.
*
* @return the version of this certificate
*/
virtual const int getVersion() const = 0;
/** Checks if two certificates are the same.
*
* @param other certificate to compare with
* @return true if the two certificates are the same,
* false otherwise
*/
virtual const bool equals(ref <const certificate> other) const = 0;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_CERTIFICATE_HPP_INCLUDED

View File

@ -0,0 +1,79 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_CERTIFICATECHAIN_HPP_INCLUDED
#define VMIME_NET_TLS_CERTIFICATECHAIN_HPP_INCLUDED
#include "vmime/types.hpp"
#include "vmime/net/tls/certificate.hpp"
namespace vmime {
namespace net {
namespace tls {
/** An ordered list of certificates, from the subject certificate to
* the issuer certificate.
*/
class certificateChain : public object
{
public:
/** Construct a new certificateChain object given an ordered list
* of certificates.
*
* @param certs chain of certificates
*/
certificateChain(const std::vector <ref <certificate> >& certs);
/** Return the number of certificates in the chain.
*
* @return number of certificates in the chain
*/
const unsigned int getCount() const;
/** Return the certificate at the specified position. 0 is the
* subject certificate, 1 is the issuer's certificate, 2 is
* the issuer's issuer, etc.
*
* @param index position at which to retrieve certificate
* @return certificate at the specified position
*/
ref <certificate> getAt(const unsigned int index);
protected:
std::vector <ref <certificate> > m_certs;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_CERTIFICATECHAIN_HPP_INCLUDED

View File

@ -0,0 +1,60 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_CERTIFICATEVERIFIER_HPP_INCLUDED
#define VMIME_NET_TLS_CERTIFICATEVERIFIER_HPP_INCLUDED
#include "vmime/types.hpp"
#include "vmime/net/tls/certificateChain.hpp"
namespace vmime {
namespace net {
namespace tls {
/** Verify that a certificate path issued by a server can be trusted.
*/
class certificateVerifier : public object
{
public:
/** Verify that the specified certificate chain is trusted.
*
* @param chain certificate chain
* @throw exceptions::certificate_verification_exception if one
* or more certificates can not be trusted
*/
virtual void verify(ref <certificateChain> chain) = 0;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_CERTIFICATEVERIFIER_HPP_INCLUDED

View File

@ -0,0 +1,88 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 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 2 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_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED
#define VMIME_NET_TLS_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED
#include "vmime/net/tls/certificateVerifier.hpp"
namespace vmime {
namespace net {
namespace tls {
class X509Certificate;
/** Default implementation for certificate verification.
*/
class defaultCertificateVerifier : public certificateVerifier
{
private:
defaultCertificateVerifier(const defaultCertificateVerifier&);
public:
defaultCertificateVerifier();
~defaultCertificateVerifier();
/** Sets a list of X.509 certificates that are trusted.
*
* @param trustedCerts list of trusted certificates
*/
void setX509TrustedCerts(const std::vector <ref <X509Certificate> >& trustedCerts);
/** Sets the X.509 root CAs used for certificate verification.
*
* @param caCerts list of root CAs
*/
void setX509RootCAs(const std::vector <ref <X509Certificate> >& caCerts);
// Implementation of 'certificateVerifier'
void verify(ref <certificateChain> chain);
private:
/** Verify a chain of X.509 certificates.
*
* @param chain list of X.509 certificates
*/
void verifyX509(ref <certificateChain> chain);
std::vector <ref <X509Certificate> > m_x509RootCAs;
std::vector <ref <X509Certificate> > m_x509TrustedCerts;
};
} // tls
} // net
} // vmime
#endif // VMIME_NET_TLS_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED

View File

@ -229,6 +229,23 @@ private:
};
/** An adapter class for byte array output.
*/
class outputStreamByteArrayAdapter : public outputStream
{
public:
outputStreamByteArrayAdapter(byteArray& array);
void write(const value_type* const data, const size_type count);
private:
byteArray m_array;
};
/** An adapter class for C++ standard input streams.
*/

View File

@ -119,5 +119,18 @@
#include "vmime/net/message.hpp"
#endif // VMIME_HAVE_MESSAGING_FEATURES
// Net/TLS
#if VMIME_HAVE_TLS_SUPPORT
#include "vmime/net/tls/certificate.hpp"
#include "vmime/net/tls/certificateChain.hpp"
#include "vmime/net/tls/certificateVerifier.hpp"
#include "vmime/net/tls/X509Certificate.hpp"
#include "vmime/net/tls/defaultCertificateVerifier.hpp"
#include "vmime/net/tls/TLSSession.hpp"
#endif // VMIME_HAVE_TLS_SUPPORT
#endif // VMIME_INCLUDED