aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ChangeLog4
-rw-r--r--SConstruct171
-rw-r--r--examples/README7
-rw-r--r--examples/example6.cpp118
-rw-r--r--m4/libgnutls.m4160
-rw-r--r--src/exception.cpp54
-rw-r--r--src/net/authHelper.cpp111
-rw-r--r--src/net/builtinServices.inl30
-rw-r--r--src/net/imap/IMAPConnection.cpp112
-rw-r--r--src/net/imap/IMAPSStore.cpp65
-rw-r--r--src/net/imap/IMAPServiceInfos.cpp133
-rw-r--r--src/net/imap/IMAPStore.cpp73
-rw-r--r--src/net/maildir/maildirServiceInfos.cpp64
-rw-r--r--src/net/maildir/maildirStore.cpp42
-rw-r--r--src/net/pop3/POP3SStore.cpp66
-rw-r--r--src/net/pop3/POP3ServiceInfos.cpp139
-rw-r--r--src/net/pop3/POP3Store.cpp191
-rw-r--r--src/net/sendmail/sendmailServiceInfos.cpp65
-rw-r--r--src/net/sendmail/sendmailTransport.cpp41
-rw-r--r--src/net/service.cpp25
-rw-r--r--src/net/serviceInfos.cpp10
-rw-r--r--src/net/smtp/SMTPSTransport.cpp66
-rw-r--r--src/net/smtp/SMTPServiceInfos.cpp136
-rw-r--r--src/net/smtp/SMTPTransport.cpp169
-rw-r--r--src/net/tls/TLSSession.cpp342
-rw-r--r--src/net/tls/TLSSocket.cpp391
-rw-r--r--src/net/tls/X509Certificate.cpp273
-rw-r--r--src/net/tls/certificateChain.cpp (renamed from vmime/net/authHelper.hpp)27
-rw-r--r--src/net/tls/defaultCertificateVerifier.cpp164
-rw-r--r--src/utility/stream.cpp16
-rw-r--r--vmime.doxygen2
-rw-r--r--vmime/exception.hpp67
-rw-r--r--vmime/net/imap/IMAPConnection.hpp4
-rw-r--r--vmime/net/imap/IMAPParser.hpp5
-rw-r--r--vmime/net/imap/IMAPSStore.hpp63
-rw-r--r--vmime/net/imap/IMAPServiceInfos.hpp87
-rw-r--r--vmime/net/imap/IMAPStore.hpp41
-rw-r--r--vmime/net/maildir/maildirServiceInfos.hpp64
-rw-r--r--vmime/net/maildir/maildirStore.hpp19
-rw-r--r--vmime/net/pop3/POP3SStore.hpp63
-rw-r--r--vmime/net/pop3/POP3ServiceInfos.hpp89
-rw-r--r--vmime/net/pop3/POP3Store.hpp43
-rw-r--r--vmime/net/sendmail/sendmailServiceInfos.hpp64
-rw-r--r--vmime/net/sendmail/sendmailTransport.hpp19
-rw-r--r--vmime/net/service.hpp30
-rw-r--r--vmime/net/serviceFactory.hpp18
-rw-r--r--vmime/net/serviceInfos.hpp17
-rw-r--r--vmime/net/smtp/SMTPSTransport.hpp63
-rw-r--r--vmime/net/smtp/SMTPServiceInfos.hpp88
-rw-r--r--vmime/net/smtp/SMTPTransport.hpp41
-rw-r--r--vmime/net/tls/TLSSession.hpp95
-rw-r--r--vmime/net/tls/TLSSocket.hpp125
-rw-r--r--vmime/net/tls/X509Certificate.hpp158
-rw-r--r--vmime/net/tls/certificate.hpp77
-rw-r--r--vmime/net/tls/certificateChain.hpp79
-rw-r--r--vmime/net/tls/certificateVerifier.hpp60
-rw-r--r--vmime/net/tls/defaultCertificateVerifier.hpp88
-rw-r--r--vmime/utility/stream.hpp17
-rw-r--r--vmime/vmime.hpp13
59 files changed, 4275 insertions, 589 deletions
diff --git a/ChangeLog b/ChangeLog
index bcdea3a3..a4775a5c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,10 @@
VERSION 0.7.2cvs
================
+2005-10-03 Vincent Richard <[email protected]>
+
+ * Added TLS/SSL support, using GNU TLS library.
+
2005-09-17 Vincent Richard <[email protected]>
* Added SASL support, based on GNU SASL library. Slightly modified
diff --git a/SConstruct b/SConstruct
index 0f24b6e8..130a3345 100644
--- a/SConstruct
+++ b/SConstruct
@@ -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,46 +211,64 @@ 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/POP3Store.cpp', 'net/pop3/POP3Store.hpp',
- 'net/pop3/POP3Folder.cpp', 'net/pop3/POP3Folder.hpp',
- 'net/pop3/POP3Message.cpp', 'net/pop3/POP3Message.hpp'
+ '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'
]
],
[
'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/IMAPConnection.cpp', 'net/imap/IMAPConnection.hpp',
- 'net/imap/IMAPStore.cpp', 'net/imap/IMAPStore.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/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',
]
],
[
'maildir',
[
- 'net/maildir/maildirStore.cpp', 'net/maildir/maildirStore.hpp',
- 'net/maildir/maildirFolder.cpp', 'net/maildir/maildirFolder.hpp',
- 'net/maildir/maildirMessage.cpp', 'net/maildir/maildirMessage.hpp',
- 'net/maildir/maildirUtils.cpp', 'net/maildir/maildirUtils.hpp'
+ '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',
+ 'net/maildir/maildirUtils.cpp', 'net/maildir/maildirUtils.hpp'
]
],
[
'sendmail',
[
- 'net/sendmail/sendmailTransport.cpp', 'net/sendmail/sendmailTransport.hpp'
+ '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
diff --git a/examples/README b/examples/README
index f741c387..4f58b1fd 100644
--- a/examples/README
+++ b/examples/README
@@ -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/
diff --git a/examples/example6.cpp b/examples/example6.cpp
index 13b85d8c..6dea8e30 100644
--- a/examples/example6.cpp
+++ b/examples/example6.cpp
@@ -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. [email protected]): ";
@@ -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:[email protected], 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();
diff --git a/m4/libgnutls.m4 b/m4/libgnutls.m4
new file mode 100644
index 00000000..99f0aa27
--- /dev/null
+++ b/m4/libgnutls.m4
@@ -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.
diff --git a/src/exception.cpp b/src/exception.cpp
index f2106e89..9620a310 100644
--- a/src/exception.cpp
+++ b/src/exception.cpp
@@ -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
diff --git a/src/net/authHelper.cpp b/src/net/authHelper.cpp
deleted file mode 100644
index e9c217f3..00000000
--- a/src/net/authHelper.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//
-// VMime library (http://www.vmime.org)
-// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
-//
-// 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
diff --git a/src/net/builtinServices.inl b/src/net/builtinServices.inl
index 88578e4b..803371ac 100644
--- a/src/net/builtinServices.inl
+++ b/src/net/builtinServices.inl
@@ -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
diff --git a/src/net/imap/IMAPConnection.cpp b/src/net/imap/IMAPConnection.cpp
index 6d2a4a4e..b0716f45 100644
--- a/src/net/imap/IMAPConnection.cpp
+++ b/src/net/imap/IMAPConnection.cpp
@@ -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())
{
@@ -118,6 +137,47 @@ void IMAPConnection::connect()
}
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
{
authenticate();
@@ -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);
diff --git a/src/net/imap/IMAPSStore.cpp b/src/net/imap/IMAPSStore.cpp
new file mode 100644
index 00000000..ed637c43
--- /dev/null
+++ b/src/net/imap/IMAPSStore.cpp
@@ -0,0 +1,65 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
diff --git a/src/net/imap/IMAPServiceInfos.cpp b/src/net/imap/IMAPServiceInfos.cpp
new file mode 100644
index 00000000..d8164ce1
--- /dev/null
+++ b/src/net/imap/IMAPServiceInfos.cpp
@@ -0,0 +1,133 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/imap/IMAPStore.cpp b/src/net/imap/IMAPStore.cpp
index d4f18e7c..95f96276 100644
--- a/src/net/imap/IMAPStore.cpp
+++ b/src/net/imap/IMAPStore.cpp
@@ -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);
-}
-
-
-const string IMAPStore::_infos::getPropertyPrefix() const
-{
- return "store.imap.";
+ return sm_infos;
}
-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
diff --git a/src/net/maildir/maildirServiceInfos.cpp b/src/net/maildir/maildirServiceInfos.cpp
new file mode 100644
index 00000000..f6487103
--- /dev/null
+++ b/src/net/maildir/maildirServiceInfos.cpp
@@ -0,0 +1,64 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/maildir/maildirStore.cpp b/src/net/maildir/maildirStore.cpp
index bbb95624..d1baf8dd 100644
--- a/src/net/maildir/maildirStore.cpp
+++ b/src/net/maildir/maildirStore.cpp
@@ -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;
}
diff --git a/src/net/pop3/POP3SStore.cpp b/src/net/pop3/POP3SStore.cpp
new file mode 100644
index 00000000..760ddd86
--- /dev/null
+++ b/src/net/pop3/POP3SStore.cpp
@@ -0,0 +1,66 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/pop3/POP3ServiceInfos.cpp b/src/net/pop3/POP3ServiceInfos.cpp
new file mode 100644
index 00000000..52387c5d
--- /dev/null
+++ b/src/net/pop3/POP3ServiceInfos.cpp
@@ -0,0 +1,139 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/pop3/POP3Store.cpp b/src/net/pop3/POP3Store.cpp
index cabd81f0..4f373268 100644
--- a/src/net/pop3/POP3Store.cpp
+++ b/src/net/pop3/POP3Store.cpp
@@ -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();
-
- sendRequest("QUIT");
+ 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;
}
diff --git a/src/net/sendmail/sendmailServiceInfos.cpp b/src/net/sendmail/sendmailServiceInfos.cpp
new file mode 100644
index 00000000..f0f2fa59
--- /dev/null
+++ b/src/net/sendmail/sendmailServiceInfos.cpp
@@ -0,0 +1,65 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/sendmail/sendmailTransport.cpp b/src/net/sendmail/sendmailTransport.cpp
index 4a077465..853f4eec 100644
--- a/src/net/sendmail/sendmailTransport.cpp
+++ b/src/net/sendmail/sendmailTransport.cpp
@@ -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;
}
diff --git a/src/net/service.cpp b/src/net/service.cpp
index acdfb390..35e8aa55 100644
--- a/src/net/service.cpp
+++ b/src/net/service.cpp
@@ -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
diff --git a/src/net/serviceInfos.cpp b/src/net/serviceInfos.cpp
index 68d78c73..306c1ec3 100644
--- a/src/net/serviceInfos.cpp
+++ b/src/net/serviceInfos.cpp
@@ -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
diff --git a/src/net/smtp/SMTPSTransport.cpp b/src/net/smtp/SMTPSTransport.cpp
new file mode 100644
index 00000000..22bf4e4b
--- /dev/null
+++ b/src/net/smtp/SMTPSTransport.cpp
@@ -0,0 +1,66 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/smtp/SMTPServiceInfos.cpp b/src/net/smtp/SMTPServiceInfos.cpp
new file mode 100644
index 00000000..1f0bca6c
--- /dev/null
+++ b/src/net/smtp/SMTPServiceInfos.cpp
@@ -0,0 +1,136 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp
index 1aa15c13..d0c72a13 100644
--- a/src/net/smtp/SMTPTransport.cpp
+++ b/src/net/smtp/SMTPTransport.cpp
@@ -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;
}
diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp
new file mode 100644
index 00000000..fb84714c
--- /dev/null
+++ b/src/net/tls/TLSSession.cpp
@@ -0,0 +1,342 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/tls/TLSSocket.cpp b/src/net/tls/TLSSocket.cpp
new file mode 100644
index 00000000..ebf3214b
--- /dev/null
+++ b/src/net/tls/TLSSocket.cpp
@@ -0,0 +1,391 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/net/tls/X509Certificate.cpp b/src/net/tls/X509Certificate.cpp
new file mode 100644
index 00000000..cfb52a1d
--- /dev/null
+++ b/src/net/tls/X509Certificate.cpp
@@ -0,0 +1,273 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/authHelper.hpp b/src/net/tls/certificateChain.cpp
index 54487fbe..52855cc2 100644
--- a/vmime/net/authHelper.hpp
+++ b/src/net/tls/certificateChain.cpp
@@ -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 {
+
+
+certificateChain::certificateChain(const std::vector <ref <certificate> >& certs)
+ : m_certs(certs)
+{
+}
-void hmac_md5(const string& text, const string& key, string& hexDigest);
+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
diff --git a/src/net/tls/defaultCertificateVerifier.cpp b/src/net/tls/defaultCertificateVerifier.cpp
new file mode 100644
index 00000000..de0c6e45
--- /dev/null
+++ b/src/net/tls/defaultCertificateVerifier.cpp
@@ -0,0 +1,164 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/src/utility/stream.cpp b/src/utility/stream.cpp
index 2941e5f2..04fa3308 100644
--- a/src/utility/stream.cpp
+++ b/src/utility/stream.cpp
@@ -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)
diff --git a/vmime.doxygen b/vmime.doxygen
index 231ea27d..50960e13 100644
--- a/vmime.doxygen
+++ b/vmime.doxygen
@@ -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.
diff --git a/vmime/exception.hpp b/vmime/exception.hpp
index ed104fba..d686ab1f 100644
--- a/vmime/exception.hpp
+++ b/vmime/exception.hpp
@@ -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
diff --git a/vmime/net/imap/IMAPConnection.hpp b/vmime/net/imap/IMAPConnection.hpp
index f51e97e2..f01236f2 100644
--- a/vmime/net/imap/IMAPConnection.hpp
+++ b/vmime/net/imap/IMAPConnection.hpp
@@ -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;
diff --git a/vmime/net/imap/IMAPParser.hpp b/vmime/net/imap/IMAPParser.hpp
index d88fcf6e..5b267ac8 100644
--- a/vmime/net/imap/IMAPParser.hpp
+++ b/vmime/net/imap/IMAPParser.hpp
@@ -94,6 +94,11 @@ public:
return (m_tag);
}
+ void setSocket(weak_ref <socket> sok)
+ {
+ m_socket = sok;
+ }
+
const string lastLine() const
{
diff --git a/vmime/net/imap/IMAPSStore.hpp b/vmime/net/imap/IMAPSStore.hpp
new file mode 100644
index 00000000..a99aff6e
--- /dev/null
+++ b/vmime/net/imap/IMAPSStore.hpp
@@ -0,0 +1,63 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/imap/IMAPServiceInfos.hpp b/vmime/net/imap/IMAPServiceInfos.hpp
new file mode 100644
index 00000000..67ef0980
--- /dev/null
+++ b/vmime/net/imap/IMAPServiceInfos.hpp
@@ -0,0 +1,87 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/imap/IMAPStore.hpp b/vmime/net/imap/IMAPStore.hpp
index 0dd748cc..dcd2099b 100644
--- a/vmime/net/imap/IMAPStore.hpp
+++ b/vmime/net/imap/IMAPStore.hpp
@@ -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;
};
diff --git a/vmime/net/maildir/maildirServiceInfos.hpp b/vmime/net/maildir/maildirServiceInfos.hpp
new file mode 100644
index 00000000..29ef32b9
--- /dev/null
+++ b/vmime/net/maildir/maildirServiceInfos.hpp
@@ -0,0 +1,64 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/maildir/maildirStore.hpp b/vmime/net/maildir/maildirStore.hpp
index 41807336..f2792403 100644
--- a/vmime/net/maildir/maildirStore.hpp
+++ b/vmime/net/maildir/maildirStore.hpp
@@ -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;
};
diff --git a/vmime/net/pop3/POP3SStore.hpp b/vmime/net/pop3/POP3SStore.hpp
new file mode 100644
index 00000000..b1bf08ad
--- /dev/null
+++ b/vmime/net/pop3/POP3SStore.hpp
@@ -0,0 +1,63 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/pop3/POP3ServiceInfos.hpp b/vmime/net/pop3/POP3ServiceInfos.hpp
new file mode 100644
index 00000000..04f14b78
--- /dev/null
+++ b/vmime/net/pop3/POP3ServiceInfos.hpp
@@ -0,0 +1,89 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/pop3/POP3Store.hpp b/vmime/net/pop3/POP3Store.hpp
index 461741f8..b19c9790 100644
--- a/vmime/net/pop3/POP3Store.hpp
+++ b/vmime/net/pop3/POP3Store.hpp
@@ -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;
+ // Service infos
+ static POP3ServiceInfos sm_infos;
};
diff --git a/vmime/net/sendmail/sendmailServiceInfos.hpp b/vmime/net/sendmail/sendmailServiceInfos.hpp
new file mode 100644
index 00000000..7da4b776
--- /dev/null
+++ b/vmime/net/sendmail/sendmailServiceInfos.hpp
@@ -0,0 +1,64 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/sendmail/sendmailTransport.hpp b/vmime/net/sendmail/sendmailTransport.hpp
index 937aaf1e..39f02b8c 100644
--- a/vmime/net/sendmail/sendmailTransport.hpp
+++ b/vmime/net/sendmail/sendmailTransport.hpp
@@ -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;
};
diff --git a/vmime/net/service.hpp b/vmime/net/service.hpp
index c9cc77e4..8025ebd9 100644
--- a/vmime/net/service.hpp
+++ b/vmime/net/service.hpp
@@ -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
+
};
diff --git a/vmime/net/serviceFactory.hpp b/vmime/net/serviceFactory.hpp
index 71c5cb34..9401e310 100644
--- a/vmime/net/serviceFactory.hpp
+++ b/vmime/net/serviceFactory.hpp
@@ -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.
diff --git a/vmime/net/serviceInfos.hpp b/vmime/net/serviceInfos.hpp
index 03fe0a0e..14657b2b 100644
--- a/vmime/net/serviceInfos.hpp
+++ b/vmime/net/serviceInfos.hpp
@@ -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.
*/
diff --git a/vmime/net/smtp/SMTPSTransport.hpp b/vmime/net/smtp/SMTPSTransport.hpp
new file mode 100644
index 00000000..87eba159
--- /dev/null
+++ b/vmime/net/smtp/SMTPSTransport.hpp
@@ -0,0 +1,63 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/smtp/SMTPServiceInfos.hpp b/vmime/net/smtp/SMTPServiceInfos.hpp
new file mode 100644
index 00000000..ac3ae372
--- /dev/null
+++ b/vmime/net/smtp/SMTPServiceInfos.hpp
@@ -0,0 +1,88 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/smtp/SMTPTransport.hpp b/vmime/net/smtp/SMTPTransport.hpp
index ae22af7f..65d8537b 100644
--- a/vmime/net/smtp/SMTPTransport.hpp
+++ b/vmime/net/smtp/SMTPTransport.hpp
@@ -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;
+ // Service infos
+ static SMTPServiceInfos sm_infos;
};
diff --git a/vmime/net/tls/TLSSession.hpp b/vmime/net/tls/TLSSession.hpp
new file mode 100644
index 00000000..e946c102
--- /dev/null
+++ b/vmime/net/tls/TLSSession.hpp
@@ -0,0 +1,95 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/tls/TLSSocket.hpp b/vmime/net/tls/TLSSocket.hpp
new file mode 100644
index 00000000..075a77ef
--- /dev/null
+++ b/vmime/net/tls/TLSSocket.hpp
@@ -0,0 +1,125 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/tls/X509Certificate.hpp b/vmime/net/tls/X509Certificate.hpp
new file mode 100644
index 00000000..5edd4e46
--- /dev/null
+++ b/vmime/net/tls/X509Certificate.hpp
@@ -0,0 +1,158 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/tls/certificate.hpp b/vmime/net/tls/certificate.hpp
new file mode 100644
index 00000000..c070484b
--- /dev/null
+++ b/vmime/net/tls/certificate.hpp
@@ -0,0 +1,77 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/tls/certificateChain.hpp b/vmime/net/tls/certificateChain.hpp
new file mode 100644
index 00000000..332e3f70
--- /dev/null
+++ b/vmime/net/tls/certificateChain.hpp
@@ -0,0 +1,79 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/tls/certificateVerifier.hpp b/vmime/net/tls/certificateVerifier.hpp
new file mode 100644
index 00000000..fd235b48
--- /dev/null
+++ b/vmime/net/tls/certificateVerifier.hpp
@@ -0,0 +1,60 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/net/tls/defaultCertificateVerifier.hpp b/vmime/net/tls/defaultCertificateVerifier.hpp
new file mode 100644
index 00000000..3713fd21
--- /dev/null
+++ b/vmime/net/tls/defaultCertificateVerifier.hpp
@@ -0,0 +1,88 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// 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
+
diff --git a/vmime/utility/stream.hpp b/vmime/utility/stream.hpp
index 4a5bd216..2ebd41c5 100644
--- a/vmime/utility/stream.hpp
+++ b/vmime/utility/stream.hpp
@@ -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.
*/
diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp
index b2245917..c7a0b4f6 100644
--- a/vmime/vmime.hpp
+++ b/vmime/vmime.hpp
@@ -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