TLS/SSL Tutorial
Back to tutorial list...
Table of content
# TLS/SSL basics
Rebex Secure Mail for .NET contains supports SSL security for
SMTP, IMAP
and POP3 protocols. SSL provides privacy
and data integrity between the client and the server.
Please note that SSL and TLS are different versions of the same protocol - TLS
1.0 is a name for what was supposed to be SSL 3.1. When we use the term "SSL",
we generally mean "SSL or TLS".
back to top...
# Namespaces and assemblies
There are several assemblies you might need to reference in your project to be
able to use all features of Secure Mail for .NET. Rebex.Net.Smtp.dll,
Rebex.Net.Imap.dll or Rebex.Net.Pop3.dll are needed
to access SMTP, IMAP or POP3 functionality and Rebex.Mail.dll makes
it possible to read, write, create or send e-mail messages. All of this is covered in
other tutorials. Rebex.Net.SecureSocket.dll contains
classes used to specify additional SSL parameters or making it possible to
implement advanced functionality. Rebex.Security.dll contains
certificate management classes for working with certificates and certificate
stores.
To gain access to all functionality, import the following namespaces in your
source files.
C#
using Rebex.Net;
using Rebex.Mail;
using Rebex.Mime.Headers;
using Rebex.Security.Certificates;
VB.NET
Imports Rebex.Net
Imports Rebex.Mail
Imports Rebex.Mime.Headers
Imports Rebex.Security.Certificates
back to top...
# Connecting to a mail server using SSL
There are two methods to connect to a secure SMTP/IMAP/POP3 server securely:
1) Explicit SSL protection of the session
Client connects to the server in a usual non-protected way, usually to ports 25, 143 or 110 that
are assigned to the three e-mail protocols. When it is desired to protect the connection
using SSL, an SSL negotiation is initialized, the connection is secured and
all following communication is being protected.
In the following code snippet, initializing a secure SMTP connection is demonstrated.
For the other two protocols, just replace all occurences of "Smtp" with "Imap"
or "Pop3".
C#
// Create an instance of the Smtp class.
Smtp client = new Smtp();
// Connect securely using explicit SSL.
// Use the third argument to specify additional SSL parameters.
client.Connect(hostname, Smtp.DefaultPort, null, SmtpSecurity.Explicit);
// Connection is protected now, we can log in safely.
client.Login(username, password);
VB.NET
' Create an instance of the Smtp class.
Dim client As New Smtp()
' Connect securely using explicit SSL.
' Use the third argument to specify additional SSL parameters.
client.Connect(hostname, Smtp.DefaultPort, Nothing, SmtpSecurity.Explicit)
' Connection is protected now, we can log in safely.
client.Login(username, password)
Explicit protection means that it is possible to secure the connection at any
moment. If you don't know whether you will need the protection on not at the
connection time, you might want to connect using the ordinary unencrypted
protocol and secure the connection later. (Again, this also works for IMAP and POP3.)
C#
Smtp client = new Smtp();
// Connect to the server with no protection.
client.Connect(hostname, Smtp.DefaultPort);
// Upgrade connection to SSL.
// This method also accepts an argument to specify SSL parameters.
client.Secure();
// Connection is protected now, we can log in safely.
client.Login(username, password);
VB.NET
Dim client As New Smtp()
' Connect to the server with no protection.
client.Connect(hostname, Smtp.DefaultPort)
' Upgrade connection to SSL.
' This method also accepts an argument to specify SSL parameters.
client.Secure()
' Connection is protected now, we can log in safely.
client.Login(username, password)
2) Implicit SSL protection of the SMTP/IMAP/POP3 session
Originally, a separate port was assigned to the SSL version of all these three protocols.
These were 465 for SMTP/SSL, 993 for IMAP/SSL and 995 for POP3/SSL.
Upon connection to this port, an SSL negotiation starts immediately
and the control connection is secured. All data connections are also secured implicitly in the
same way. This is similar to the approach used by HTTPS.
This approach is not favored by the IETF and is deprecated. It is supported by
Rebex Secure Mail for interoperability with older servers that are still used a lot,
but it is strongly recommended to use the explicit protection instead whenever possible.
C#
Smtp client = new Smtp();
// Connect securely using implicit SSL.
// Use the third argument to specify additional SSL parameters.
client.Connect(hostname, 465, null, SmtpSecurity.Implicit);
// Connection is protected now, we can log in safely.
client.Login(username, password);
VB.NET
Dim client As New Smtp()
' Connect securely using implicit SSL.
' Use the third argument to specify additional SSL parameters.
client.Connect(hostname, 465, Nothing, SmtpSecurity.Implicit)
' Connection is protected now, we can log in safely.
client.Login(username, password)
back to top...
# Getting information about SSL connection
You can easily get information about the SSL connection using properties of
Smtp.TlsSocket, Imap.TlsSocket or Pop3.TlsSocket. The following code snippet will
demonstrate this for IMAP.
C#
Imap client = new Imap();
// Connect securely using explicit SSL.
client.Connect(hostname, 143, null, ImapSecurity.Explicit);
// The Cipher property contains a lot of
// information about the current cipher
TlsCipher cipher = client.TlsSocket.Cipher;
Console.WriteLine("Protocol: {0}", cipher.Protocol);
Console.WriteLine("Cipher: {0}", cipher.CipherAlgorithm);
Console.WriteLine("Key exchange: {0}", cipher.KeyExchangeAlgorithm);
Console.WriteLine("MAC algorithm: {0}", cipher.MacAlgorithm);
Console.WriteLine("All together: {0}", cipher);
// ServerCertificate property provides access
// to server certificate.
Certificate serverCert = client.TlsSocket.ClientCertificate[0];
Console.WriteLine("Subject: {0}", serverCert.GetSubject());
Console.WriteLine("Issuer: {0}", serverCert.GetIssuer());
VB.NET
Dim client As New Imap()
' Connect securely using explicit SSL.
client.Connect(hostname, 143, Nothing, ImapSecurity.Explicit)
' The Cipher property contains a lot of
' information about the current cipher
Dim cipher As TlsCipher = client.TlsSocket.Cipher
Console.WriteLine("Protocol: {0}", cipher.Protocol)
Console.WriteLine("Cipher: {0}", cipher.CipherAlgorithm)
Console.WriteLine("Key exchange: {0}", cipher.KeyExchangeAlgorithm)
Console.WriteLine("MAC algorithm: {0}", cipher.MacAlgorithm)
Console.WriteLine("All together: {0}", cipher)
' ServerCertificate property provides access
' to server certificate.
Dim serverCert As Certificate = client.TlsSocket.ClientCertificate(0)
Console.WriteLine("Subject: {0}", serverCert.GetSubject())
Console.WriteLine("Issuer: {0}", serverCert.GetIssuer())
back to top...
# Specifying SSL parameters
It is possible to affect many aspects of SSL such us specifying which protocol
versions to use or what cipher suites to allow.
It is a good idea to disable weak cipher suites and only allow the strong
ones.
C#
Pop3 client = new Pop3();
// Create an instance of TlsParameters class and
// specify desired arguments.
TlsParameters par = new TlsParameters();
// Only use suites that are currently considered secure.
par.AllowedSuites = TlsCipherSuite.Secure;
// Allow both SSL 3.0 and TLS 1.0 protocols to be used.
par.Version = TlsVersion.SSL30 | TlsVersion.TLS10;
// You also have to specify the common name of
// the mail server if you provide parameters.
par.CommonName = hostname;
// Connect securely using explicit SSL.
// The third argument refers to the parameters class.
client.Connect(hostname, Pop3.DefaultPort, par, Pop3Security.Explicit);
// Connection is protected now, we can log in safely.
client.Login(username, password);
VB.NET
Dim client As New Pop3
' Create an instance of TlsParameters class and
' specify desired arguments.
Dim par As New TlsParameters()
' Only use suites that are currently considered secure.
par.AllowedSuites = TlsCipherSuite.Secure
' Allow both SSL 3.0 and TLS 1.0 protocols to be used.
par.Version = TlsVersion.SSL30 Or TlsVersion.TLS10
' You also have to specify the common name of
' the mail server if you provide your own parameters.
par.CommonName = hostname
' Connect securely using explicit SSL.
' The third argument refers to the parameters class.
client.Connect(hostname, Pop3.DefaultPort, par, Pop3Security.Explicit)
' Connection is protected now, we can log in safely.
client.Login(username, password)
Specifying the supported set of ciphers one by one is also possible. If you only
accept DSA certificates and AES encryption, you can have that.
C#
// Only use the specified cipher suites.
TlsParameters par = new TlsParameters();
par.AllowedSuites =
TlsCipherSuite.DHE_DSS_WITH_AES_256_CBC_SHA |
TlsCipherSuite.DHE_DSS_WITH_AES_128_CBC_SHA;
VB.NET
' Only use the specified cipher suites.
Dim par As New TlsParameters()
par.AllowedSuites = _
TlsCipherSuite.DHE_DSS_WITH_AES_256_CBC_SHA Or _
TlsCipherSuite.DHE_DSS_WITH_AES_128_CBC_SHA
back to top...
# Validating and examining server certificates
Even though Rebex Secure Mail validates server certificate automatically by
default, it is often desirable to extend this process, for example by adding the
ability to ask the user whether to accept or reject the server certificate. In
other scenarios, you might want to use your own code to decide. This is
possible by implementing a custom certificate validator.
C#
// A custom certificate verifier class.
// Implements ICertificateVerifier interface.
public class CustomVerifier : ICertificateVerifier
{
// This method gets called during the SSL handshake
// process when the certificate chain is received from the server.
public TlsCertificateAcceptance Verify
(TlsSocket socket,
string commonName,
CertificateChain certChain)
{
// Use the built-in validation method to validate the chain.
// It is up to you to use another validation method if needed.
ValidationResult res = certChain.Validate(commonName, 0);
// Accept the certificate if the chain is valid.
if (res.Valid)
return TlsCertificateAcceptance.Accept;
// If the chain is not valid, let's display the certificate
// information and validation status to the user and let
// him decide what to do.
Certificate cert = certChain[0];
//bool shouldAccept = SomeCustomDialog(cert, res.Status);
bool shouldAccept = true;
if (shouldAccept)
return TlsCertificateAcceptance.Accept;
else
return TlsCertificateAcceptance.Other;
}
}
// To make your validator the current validator for
// a POP3 session:
Pop3 client = new Pop3();
// Of course, this works for Smtp or Imap as well!
// Create an instance of TlsParameters class and
// set the certificate verifier to an instance of CustomVerifier.
// You also have to specify the common name of
// the mail server to be passed to your verifier.
TlsParameters par = new TlsParameters();
par.CertificateVerifier = new CustomVerifier();
par.CommonName = hostname;
// Connect securely using explicit SSL.
// The third argument refers to the parameters class.
client.Connect(hostname, Pop3.DefaultPort, par, Pop3Security.Explicit);
// Connection is protected now, we can log in safely.
client.Login(username, password);
VB.NET
' A custom certificate verifier class.
' Implements ICertificateVerifier interface.
Public Class CustomVerifier
Implements Rebex.Net.ICertificateVerifier
' This method gets called during the SSL handshake
' process when the certificate chain is received from the server.
Public Overloads Function Verify _
(ByVal socket As TlsSocket, _
ByVal commonName As String, _
ByVal certChain As CertificateChain) _
As TlsCertificateAcceptance _
Implements ICertificateVerifier.Verify
' Use the built-in validation method to validate the chain.
' It is up to you to use another validation method if needed.
Dim res As ValidationResult = certChain.Validate(commonName, 0)
' Accept the certificate if the chain is valid.
If res.Valid Then
Return TlsCertificateAcceptance.Accept
End If
' If the chain is not valid, let's display the certificate
' information and validation status to the user and let
' him decide what to do.
Dim cert As Certificate = certChain(0)
'Dim shouldAccept As Boolean = SomeCustomDialog(cert, res.Status)
Dim shouldAccept As Boolean = True
If shouldAccept Then
Return TlsCertificateAcceptance.Accept
Else
Return TlsCertificateAcceptance.Other
End If
End Function
End Class
' To make your validator the current validator for
' an POP3 session:
Dim client As New Pop3()
' Of course, this works for Smtp or Imap as well!
' Create an instance of TlsParameters class and
' set the certificate verifier to an instance of CustomVerifier.
' You also have to specify the common name of
' the mail server to be passed to your verifier.
Dim par As New TlsParameters()
par.CertificateVerifier = New CustomVerifier()
par.CommonName = hostname
' Connect securely using explicit SSL.
' The third argument refers to the parameters class.
client.Connect(hostname, Pop3.DefaultPort, par, Pop3Security.Explicit)
' Connection is protected now, we can log in safely.
client.Login(username, password)
There are two verifiers provided by Rebex Secure Mail. The default verifier is
CertificateVerifier.Default and uses CryptoAPI to validate the certificate
chain. There is also CertificateVerifier.AcceptAll verifier that does no
validation and accepts anything - this can be handy while testing, but don't
use it in your production code.
back to top...
# Authenticating the client using a certificate
Mail servers might be configured to request the client to authenticate using its
certificate during SSL negotiation. Client either complies or informs the
server that no it has no suitable certificate available. In the latter case,
the server can optionally refuse to proceed negotiating. Rebex Mail for
.NET makes it possible to select one of the built-in certificate request
handlers or to implement a custom handler if they are not sufficient.
By default, client authentication is disabled - certificate request handler is
set to the built-in CertificateRequestHandler.NoCertificate handler that does
not try to find any certificate and just informs the server that no certificate
is available.
However, client authentication can be enabled easily by using the second
built-in certificate request handler that is able to searches the user's
certificate store for a suitable certificate with a private key, and if one is
found, it is used to authenticate the client:
C#
// We use IMAP in this sample, but you might use SMTP or POP3 as well
Imap client = new Imap();
// Create an instance of TlsParameters class and
// set the certificate request handler to
// CertificateRequestHandler.StoreSearch.
// You also have to specify the common name of
// the mail server if you provide your own parameters.
TlsParameters par = new TlsParameters();
par.CertificateRequestHandler = CertificateRequestHandler.StoreSearch;
par.CommonName = hostname;
// Connect securely using explicit SSL.
// The third argument refers to the parameters class.
client.Connect(hostname, Imap.DefaultPort, par, ImapSecurity.Explicit);
// Connection is protected now, we can log in safely.
// Some servers may not require login if the client
// successfully authenticated itself using a certificate
// known to the server.
client.Login(username, password);
VB.NET
' We use IMAP in this sample, but you might use SMTP or POP3 as well
Dim client As New Imap()
' Create an instance of TlsParameters class and
' set the certificate request handler to
' CertificateRequestHandler.StoreSearch.
' You also have to specify the common name of
' the mail server if you provide your own parameters.
Dim par As New TlsParameters()
par.CertificateRequestHandler = CertificateRequestHandler.StoreSearch
par.CommonName = hostname
' Connect securely using explicit SSL.
' The third argument refers to the parameters class.
client.Connect(hostname, Imap.DefaultPort, par, ImapSecurity.Explicit)
' Connection is protected now, we can log in safely.
' Some servers may not require login if the client
' successfully authenticated itself using a certificate
' known to the server.
client.Login(username, password)
Another built-in certificate request handler is based on certificate chain and makes it possible
to easily authenticate a user using a client certificate stored in a .PFX/.P12 (PKCS#12) file:
C#
// We use IMAP in this sample, but you might use SMTP or POP3 as well
Imap client = new Imap();
// Load a certificate chain from a .PFX/.P12 file
// that contains a certificate and its private key.
CertificateChain certificateChain = CertificateChain.LoadPfx(@"c:\temp\mycert.pfx", "mypass");
// Create an instance of TlsParameters class and
// assing a certificate request handler based on
// the chain loaded from the PFX file.
TlsParameters par = new TlsParameters();
par.CertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(certificateChain);
// Connect securely using explicit SSL.
// The third argument refers to the parameters class.
client.Connect(hostname, Imap.DefaultPort, par, ImapSecurity.Explicit);
// Connection is protected now, we can log in safely.
// Some servers may not require login if the client
// successfully authenticated itself using a certificate
// known to the server.
client.Login(username, password);
VB.NET
' We use IMAP in this sample, but you might use SMTP or POP3 as well
Dim client As New Imap()
' Load a certificate chain from a .PFX/.P12 file
' that contains a certificate and its private key.
Dim certificateChain As CertificateChain = certificateChain.LoadPfx("c:\temp\mycert.pfx", "mypass")
' Create an instance of TlsParameters class and
' assing a certificate request handler based on
' the chain loaded from the PFX file.
Dim par As New TlsParameters()
par.CertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(certificateChain)
' Connect securely using explicit SSL.
' The third argument refers to the parameters class.
client.Connect(hostname, Imap.DefaultPort, par, ImapSecurity.Explicit)
' Connection is protected now, we can log in safely.
' Some servers may not require login if the client
' successfully authenticated itself using a certificate
' known to the server.
client.Login(username, password)
If you need to use another method of selecting a suitable certificate or if a
GUI should be presented to the user to let him select the certificate, a custom
certificate handler is can be used instead. The following sample handler will
load a certificate from a PKCS#12 file as well, but it can be easily modified
to do something else:
C#
// A custom certificate request handler class.
// Implements ICertificateRequestHandler interface.
public class CustomRequestHandler : ICertificateRequestHandler
{
// This method gets called during the SSL handshake
// process if the server requests the client's certificate.
public CertificateChain Request
(TlsSocket socket,
DistinguishedName[] issuers)
{
// Load the certificate with a private key from a PFX file.
string path = "myCertificate.pfx";
Certificate cert = Certificate.LoadPfx(path, "password");
// We actually need a certificate chain, so let's build one.
CertificateChain chain = CertificateChain.BuildFrom(cert);
return chain;
}
}
// To make your request handler the current request handler for
// an IMAP session:
Imap client = new Imap();
// Of course, this works for Smtp or Pop3 as well!
// Create an instance of TlsParameters class and
// set the certificate request handler to an instance
// of CustomVerifier.
// You also have to specify the common name of
// the mail server if you provide your own parameters.
TlsParameters par = new TlsParameters();
par.CertificateRequestHandler = new CustomRequestHandler();
par.CommonName = hostname;
// Connect securely using explicit SSL.
// The third argument refers to the parameters class.
client.Connect(hostname, Imap.DefaultPort, par, ImapSecurity.Explicit);
// Connection is protected now, we can log in safely.
// Some servers may not require login if the client
// successfully authenticated itself using a certificate
// known to the server.
client.Login(username, password);
VB.NET
' A custom certificate request handler class.
' Implements ICertificateRequestHandler interface.
Public Class CustomRequestHandler
Implements ICertificateRequestHandler
' This method gets called during the SSL handshake
' process if the server requests the client's certificate.
Public Overloads Function Request _
(ByVal socket As TlsSocket, _
ByVal issuers() As DistinguishedName) _
As CertificateChain _
Implements ICertificateRequestHandler.Request
' Load the certificate with a private key from a PFX file.
Dim path As String = "myCertificate.pfx"
Dim cert As Certificate = Certificate.LoadPfx(path, "password")
' We actually need a certificate chain, so let's build one.
Dim chain As CertificateChain = CertificateChain.BuildFrom(cert)
Return chain
End Function
End Class
' To make your request handler the current request handler for
' an IMAP session:
Dim client As New Imap()
' Of course, this works for Smtp or Pop3 as well!
' Create an instance of TlsParameters class and
' set the certificate request handler to an instance
' of CustomVerifier.
' You also have to specify the common name of
' the mail server if you provide your own parameters.
Dim par As New TlsParameters()
par.CertificateRequestHandler = New CustomRequestHandler()
par.CommonName = hostname
' Connect securely using explicit SSL.
' The third argument refers to the parameters class.
client.Connect(hostname, Imap.DefaultPort, par, ImapSecurity.Explicit)
' Connection is protected now, we can log in safely.
' Some servers may not require login if the client
' successfully authenticated itself using a certificate
' known to the server.
client.Login(username, password)
Check out the POP3 Browser or IMAP Browser sample source code for
an advanced certificate request handler that presents a GUI to the user and lets him choose the certificate to use.
back to top...
Back to tutorial list...