0 votes
by (370 points)

I have an issue connecting to a secure IMAP with a client certificate in C# and not sure how to move forward. This is in part a theoretical question as I cannot get access to the server myself for testing.

Using the rebex imap browser a person on-site can access the connection after accepting the certificate from the popup.

Our rebex usage consist of an desktop application used for configuring, but the actual access is from a service application. I have tried to port the rebex code as closely as possible to our application. When trying to connect without the certificate popup code I get "Server certificate was rejected because of an unknown certificate authority", which makes sense, because the certificate popup code is not used.

When I do use that code with the verifier, the error is this "An exception occurred in certificate verifier".

The desktop application and service application are not necessarily running using the same credentials.

How can I move forward to resolving such issue? The version currently used is 2017R3.

Applies to: Rebex Secure Mail

1 Answer

+1 vote
by (147k points)
selected by
 
Best answer

The "Server certificate was rejected because of an unknown certificate authority" indicates that the certificate validation failed because the root certificate authority is not trusted by the Windows account under which the application runs. The recommended solution is to add the server root certification authority certificate into a list of trusted root CAs.

Check out the following blog posts for additional information:
- http://blog.rebex.net/howto-server-certificate-rejected-exception/
- http://blog.rebex.net/introduction-to-public-key-certificates/

Another alternative would be to implement a custom verifier (possibly based on the ImapBrowse one) that replaces certificateChain.Validate call with this:

ValidationResult res = certificateChain.Validate(commonName, ValidationOptions.AllowUnknownCa);

This makes it succeed despite an untrusted root CA. However, in addition to this, you would have to make sure that raw certificate data returned by certificateChain.RootCertificate.GetRawCertData() is actually identical to the proper root certificate. Otherwise, an attacker with access to any device along the way between the client and the server would be able to trick the application into connecting to his own server.

The "An exception occurred in certificate verifier" indicates that an exception occurred inside the custom verifier routine. To determine the cause of that, put the contents of that routine into try/catch block and see which exception gets caught.

by (370 points)
Making it succeed is not an option.

The problem is I cannot just debug, I need to create a setup and have it deploy on the production machine through inaccessible channels. I have no logging at the lowest level, and the point where I can log at this moment is where I get "An exception occurred in certificate verifier", Rebex appears to eat the original exception. Is there a way to turn that off, or see the inner exception?
by (147k points)
Rebex does not eat the original exception when the "An exception occurred in certificate verifier" error occurs. The original exception is available in `TlsException`'s inner exception chain and the most simple way to see it is to call exception's ToString() method on the top exception and view the result. In addition to this, the original exception is logged (at Debug level) into a log, and a log file can be created using `Imap` object's `LogWriter` property (as described at https://www.rebex.net/kb/logging/).
by (370 points)
Must've been looking in the wrong place then. I'll see if I can request a file location to write to and enable this. Not being able to debug this on my own machine is making this very hard to find.
by (370 points)
edited by
On my local debug machine I now get this:

2018-08-21 10:50:53.797 Opening log file.
2018-08-21 10:50:53.798 Using FileLogWriter version 7.0.301.1253.
2018-08-21 10:50:53.800 DEBUG Imap(2)[1] Info: State changed from 'Disconnected' to 'Connecting'.
2018-08-21 10:50:53.800 INFO Imap(2)[1] Info: Connecting to outlook.office365.com:993 using Imap.
2018-08-21 10:50:53.800 INFO Imap(2)[1] Info: Assembly: Rebex.Imap 2017 R3 for .NET 4.0-4.7
2018-08-21 10:50:53.801 DEBUG Imap(2)[1] Info: Platform: Windows 6.2.9200 32-bit; CLR: 4.0.30319.42000
2018-08-21 10:50:53.802 DEBUG Imap(2)[1] Info: Culture: nl; Windows-1252
2018-08-21 10:50:53.803 INFO Imap(2)[1] Info: Connecting to 40.101.80.178.
2018-08-21 10:50:53.803 DEBUG ProxySocket(4)[1] Socket: Connecting to 40.101.80.178:993.
2018-08-21 10:50:53.811 DEBUG Imap(2)[1] Info: Connection succeeded.
2018-08-21 10:50:53.811 DEBUG Imap(2)[1] Info: Upgrading connection to TLS/SSL.
2018-08-21 10:50:53.813 VERBOSE Imap(2)[1] TLS: Sent TLS packet:
[packet omitted]
2018-08-21 10:50:53.815 INFO Imap(2)[1] TLS: State StateChange:Negotiating
2018-08-21 10:50:53.815 DEBUG Imap(2)[1] TLS: HandshakeMessage:ClientHello was sent.
2018-08-21 10:50:53.829 VERBOSE Imap(2)[1] TLS: Received TLS packet:
[packet omitted]
2018-08-21 10:50:53.830 DEBUG Imap(2)[1] TLS: HandshakeMessage:ServerHello was received.
2018-08-21 10:50:53.830 INFO Imap(2)[1] TLS: Using TLS 1.2.
2018-08-21 10:50:53.830 DEBUG Imap(2)[1] TLS: The server supports secure renegotiation.
2018-08-21 10:50:53.830 DEBUG Imap(2)[1] TLS: HandshakeMessage:Certificate was received.
2018-08-21 10:50:53.830 DEBUG Imap(2)[1] TLS: HandshakeMessage:ServerKeyExchange was received.
2018-08-21 10:50:53.830 DEBUG Imap(2)[1] TLS: HandshakeMessage:ServerHelloDone was received.
2018-08-21 10:50:53.830 DEBUG Imap(2)[1] TLS: Verifying server certificate ('CN=outlook.com, O=Microsoft Corporation, L=Redmond, S=Washington, C=US').
2018-08-21 10:50:53.922 DEBUG Imap(2)[1] TLS: Certificate verification failed: System.MissingMethodException: Methode niet gevonden: Rebex.Net.TlsCertificateAcceptance RebexHelper.Verifier.Verify(System.String, Rebex.Security.Certificates.CertificateChain, Boolean).
   bij Sucaba.Taskmanager.ActionLib.ImapConnection.PbV6DCI1Om(Object  , SslCertificateValidationEventArgs  )
   bij Rebex.Net.Imap.JB(SslCertificateValidationEventArgs C)
   bij Rebex.Net.Imap.BJ[C](SQ`1 C, C V)
   bij Rebex.Net.Imap.XijRZqJM4E(SslCertificateValidationEventArgs C)
   bij Rebex.Net.PIG.Verify(TlsSocket socket, String commonName, CertificateChain certificateChain)
   bij Rebex.Net.BXG.EG(String C, CertificateChain V)
2018-08-21 10:50:53.924 DEBUG Imap(2)[1] TLS: Error while processing TLS packet: Rebex.Net.TlsException: An exception occurred in certificate verifier. ---> System.MissingMethodException: Methode niet gevonden: Rebex.Net.TlsCertificateAcceptance RebexHelper.Verifier.Verify(System.String, Rebex.Security.Certificates.CertificateChain, Boolean).
   bij Sucaba.Taskmanager.ActionLib.ImapConnection.PbV6DCI1Om(Object  , SslCertificateValidationEventArgs  )
   bij Rebex.Net.Imap.JB(SslCertificateValidationEventArgs C)
   bij Rebex.Net.Imap.BJ[C](SQ`1 C, C V)
   bij Rebex.Net.Imap.XijRZqJM4E(SslCertificateValidationEventArgs C)
   bij Rebex.Net.PIG.Verify(TlsSocket socket, String commonName, CertificateChain certificateChain)
   bij Rebex.Net.BXG.EG(String C, CertificateChain V)
   --- Einde van intern uitzonderingsstackpad ---
   bij Rebex.Net.BXG.EG(String C, CertificateChain V)
   bij Rebex.Net.BXG.QG(Byte[] C, Int32 V, Int32 Z, LIG N)
   bij Rebex.Net.BXG.HZ(Byte[] C, Int32 V, Int32 Z)
   bij Rebex.Net.JXG.KP(Byte[] C, Int32 V, Int32 Z)
   bij Rebex.Net.JXG.YP()
2018-08-21 10:50:53.924 INFO Imap(2)[1] TLS: Alert Alert:Alert was sent.
2018-08-21 10:50:53.924 INFO Imap(2)[1] TLS: State StateChange:Closed
2018-08-21 10:50:53.924 VERBOSE Imap(2)[1] TLS: Sent TLS packet:
 0000 |15-03-03-00-02-02-50                           | ......P
2018-08-21 10:50:53.924 DEBUG Imap(2)[1] TLS: Closing TLS socket.
2018-08-21 10:50:53.925 DEBUG Imap(2)[1] Info: State changed from 'Connecting' to 'Disconnected'.
2018-08-21 10:50:53.926 ERROR Imap(2)[1] Info: Rebex.Net.TlsException: An exception occurred in certificate verifier. ---> Rebex.Net.TlsException: An exception occurred in certificate verifier. ---> Rebex.Net.TlsException: An exception occurred in certificate verifier. ---> System.MissingMethodException: Methode niet gevonden: Rebex.Net.TlsCertificateAcceptance RebexHelper.Verifier.Verify(System.String, Rebex.Security.Certificates.CertificateChain, Boolean).
   bij Sucaba.Taskmanager.ActionLib.ImapConnection.PbV6DCI1Om(Object  , SslCertificateValidationEventArgs  )
   bij Rebex.Net.Imap.JB(SslCertificateValidationEventArgs C)
   bij Rebex.Net.Imap.BJ[C](SQ`1 C, C V)
   bij Rebex.Net.Imap.XijRZqJM4E(SslCertificateValidationEventArgs C)
   bij Rebex.Net.PIG.Verify(TlsSocket socket, String commonName, CertificateChain certificateChain)
   bij Rebex.Net.BXG.EG(String C, CertificateChain V)
   --- Einde van intern uitzonderingsstackpad ---
   bij Rebex.Net.BXG.EG(String C, CertificateChain V)
   bij Rebex.Net.BXG.QG(Byte[] C, Int32 V, Int32 Z, LIG N)
   bij Rebex.Net.BXG.HZ(Byte[] C, Int32 V, Int32 Z)
   bij Rebex.Net.JXG.KP(Byte[] C, Int32 V, Int32 Z)
   bij Rebex.Net.JXG.YP()
   --- Einde van intern uitzonderingsstackpad ---
   bij Rebex.Net.JXG.YP()
   bij Rebex.Net.JXG.UP()
   bij Rebex.Net.TlsSocket.Negotiate()
   bij Rebex.Net.LEG.NV(TlsParameters C)
   bij Rebex.Net.Imap.CZV(TlsParameters C, Boolean V)
   --- Einde van intern uitzonderingsstackpad ---
   bij Rebex.Net.Imap.CZV(TlsParameters C, Boolean V)
   bij Rebex.Net.Imap.HJ(String C, Int32 V, TlsParameters Z, SslMode N)

Any ideas? Does that mean it cannot find my assembly containing the verifier method? The main project is in VB.NET, the verifier is in a separate C# assembly. After installation this assembly is present in the install folder.
by (370 points)
In addition, this part of the calling code:

Public Class ImapConnection

        Private _rbxImapConnection As New Rebex.Net.Imap
        Private _strConnectionSignature As String = ""

        Public Property IsUserInteractive As Boolean = False

        Public ReadOnly Property Connection As Rebex.Net.Imap
            Get
                Return _rbxImapConnection
            End Get
        End Property

        Public Sub New()

        End Sub

        Public Sub New(blnCertificateCheck As Boolean)

            If blnCertificateCheck

                Dim rebexTempLog As String = My.Computer.FileSystem.SpecialDirectories.Temp.Trim().TrimEnd("\"c) &
                                            "\bpm_rebex_verbose.log"

                _rbxImapConnection.LogWriter = new FileLogWriter(rebexTempLog, LogLevel.Verbose)

                AddHandler _rbxImapConnection.ValidatingCertificate, AddressOf ValidateCertificate
            End If

        End Sub

        Private Sub ValidateCertificate(sender As Object, e As SslCertificateValidationEventArgs)
            
            if e Is Nothing
                Exit Sub
            End If

            if String.IsNullOrEmpty(e.ServerName) OrElse e.CertificateChain Is Nothing
                e.Accept()
                Exit Sub
            End If

            Try
                Dim verifier As Verifier = new Verifier()
                Dim acceptResult As TlsCertificateAcceptance = verifier.Verify(e.ServerName, e.CertificateChain, IsUserInteractive)

                If acceptResult = TlsCertificateAcceptance.Accept
                    e.Accept()
                Else
                    e.Reject(acceptResult)
                End If
            Catch
                e.Accept()
            End Try

        End Sub
by (72.7k points)
Please note, that the error was raised inside your code:

System.MissingMethodException: Methode niet gevonden: Rebex.Net.TlsCertificateAcceptance RebexHelper.Verifier.Verify(System.String, Rebex.Security.Certificates.CertificateChain, Boolean).

Your code looks correct, but the runtime environment cannot find implementation of method verifier.Verify(e.ServerName, e.CertificateChain, IsUserInteractive).

We cannot assist you because it is related to your environment.

Do you have reference to your C# assembly in your VB.NET project?
Look at Menu->Project->ProjName Properties...->References
by (370 points)
Yes. All there, thank you. I'm moving the code out of the assembly to see if that does the trick for now.
...