Providing client's certificate required by server
This topic explains how to authenticate the client using a certificate. IMAP servers might be configured to request the client to authenticate using its certificate during SSL negotiation. The client can either process, or inform the server that it has no suitable certificate.
The example below demonstrates how to use ComponentSoft IMAP library and handle the CertificateRequired event of the ImapClient to find a suitable certificate for the client authentication:
C#:
public void HandleCertificateRequiredEvent()
{
// Create a new instance.
ImapClient client = new ImapClient();
client.CertificateRequired += client_CertificateRequired;
// Connect to the IMAP server.
client.Connect("myserver", 143, SecurityMode.Explicit);
// Authenticate.
client.Authenticate("userName", "password");
// Do something here...
// ...
// Disconnect.
client.Disconnect();
}
void client_CertificateRequired(object sender, ComponentSoft.Security.CertificateRequiredEventArgs e)
{
// Load certificates from the local machine.
X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
my.Open(OpenFlags.ReadOnly);
// Retrieve a list of available certificates.
X509Certificate2Collection certs = my.Certificates;
// If no certificate found, return.
if (certs.Count == 0)
{
e.Certificate = null;
return;
}
// Show all certificates.
Console.WriteLine("Select certificate:");
for (int i = 0; i <= certs.Count; i++)
{
if (i == 0)
{
Console.WriteLine(string.Format("{0}. [Nothing, skip this step]", i));
continue;
}
Console.WriteLine(string.Format("{0}. {1}", i, certs[i - 1].SubjectName.Name));
}
// And ask user to choose an appropriate certificate.
while (true)
{
Console.Write(string.Format("Select certificate [0 - {0}]: ", certs.Count));
int certIndex;
try
{
certIndex = int.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("ERROR: Wrong certificate index input!");
continue;
}
if (certIndex > 0 && certIndex <= certs.Count)
{
e.Certificate = certs[certIndex];
return;
}
if (certIndex == 0)
break;
Console.WriteLine(string.Format("ERROR: You must enter number between 0 and {0}.", certs.Count));
}
}
VB.NET
' Create a new instance.
Dim client As New ImapClient()
AddHandler client.CertificateRequired, AddressOf client_CertificateRequired
' Connect to the IMAP server.
client.Connect("myserver", 143, SecurityMode.Explicit)
' Authenticate.
client.Authenticate("userName", "password")
' Do something here...
' ...
' Disconnect.
client.Disconnect()
End Sub
Private Sub client_CertificateRequired(ByVal sender As Object, ByVal e As ComponentSoft.Security.CertificateRequiredEventArgs)
' Load certificates from the local machine.
Dim my As New X509Store(StoreName.My, StoreLocation.CurrentUser)
my.Open(OpenFlags.ReadOnly)
' Retrieve a list of available certificates.
Dim certs As X509Certificate2Collection = my.Certificates
' If no certificate found, return.
If certs.Count = 0 Then
e.Certificate = Nothing
Return
End If
' Show all certificates.
Console.WriteLine("Select certificate:")
For i As Integer = 0 To certs.Count
If i = 0 Then
Console.WriteLine(String.Format("{0}. [Nothing, skip this step]", i))
Continue For
End If
Console.WriteLine(String.Format("{0}. {1}", i, certs(i - 1).SubjectName.Name))
Next i
' And ask user to choose an appropriate certificate.
Do
Console.Write(String.Format("Select certificate [0 - {0}]: ", certs.Count))
Dim certIndex As Integer
Try
certIndex = Integer.Parse(Console.ReadLine())
Catch
Console.WriteLine("ERROR: Wrong certificate index input!")
Continue Do
End Try
If certIndex > 0 AndAlso certIndex <= certs.Count Then
e.Certificate = certs(certIndex)
Return
End If
If certIndex = 0 Then
Exit Do
End If
Console.WriteLine(String.Format("ERROR: You must enter number between 0 and {0}.", certs.Count))
Loop
End Sub
