Archived

This forum has been archived. Please start a new discussion on GitHub.

IceSSL: Additional failure info accessible from the low level SSL engine?

2

Comments

  • xdm
    xdm La Coruña, Spain

    To be clear, will we also face this issue too with the CheckTrust step? I'm actually not even sure what that is -- our cerificate verifier doesn't deal with anything trust related today.

    IceSSL has a TrustManager that can be configured throw properties and yes you will face the same issue if the trust manager rejects a connection the verifier will not be called

  • Hi Jose,
    We had a meeting today to discuss our certificate verification strategy. We are planning on supplementing our own certificate verification with the error code(s) we get back from getTrustError(). Just a few more clarification questions around this;
    1) I understand that the getTrustError() more or less just relays the lower level SSL/engine errors to us. We're hoping that it helps us find the harder ones (e.g. Revocation) that we don't deal with . I assume there's no guarantee of order? Do you know if it starts verificate at the root cert and works its way down the chain, or vice versa?
    2) In our certificate verifier, we get the connection object that provides the chain and other information . There's a verified flag. If that is true, then all low level checks have passed, along with any other IceSSL parameter checks too. Correct? And the chain we get - can we safely assume that everything in that chain has passed all low level verification checks? An incomplete chain would mean that the Ice verification failed and did not include a cert that caused the failure, correct?
    3) If we get an incomplete chain, in your opinion, is that a fatal error that we should not allow a connection to proceed? What about a chain that's just missing the root CA ? Obviously a signing failure on a given cert should be fatal as it would be assumed a 3rd party modified.

    Our goal here is to present cert failures to a customer, and allow them to proceed with a connection for "warning" type ones (e.g. hostname mismatch), but deny continuing for "failure" types.

    Thanks again
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    1) I understand that the getTrustError() more or less just relays the lower level SSL/engine errors to us. We're hoping that it helps us find the harder ones (e.g. Revocation) that we don't deal with . I assume there's no guarantee of order? Do you know if it starts verificate at the root cert and works its way down the chain, or vice versa?

    This depends on the engine, in general, I think first the chain is built and trust is checked, then other checks follow (extensions, validity, ...) for OpenSSL this documented in detail in https://www.openssl.org/docs/man1.1.1/man1/openssl-verify.html see "VERIFY OPERATION" in the linked doc

    2) In our certificate verifier, we get the connection object that provides the chain and other information . There's a verified flag. If that is true, then all low level checks have passed, along with any other IceSSL parameter checks too. Correct? And the chain we get - can we safely assume that everything in that chain has passed all low level verification checks? An incomplete chain would mean that the Ice verification failed and did not include a cert that caused the failure, correct?

    if IceSSL::ConnectionInfo::verified is set to true, all checks passed, that is correct. If the SSL engine cannot build the complete chain this would be reported as an error, verified would be false and TrustError would be PartialChain.

    3) If we get an incomplete chain, in your opinion, is that a fatal error that we should not allow a connection to proceed? What about a chain that's just missing the root CA ? Obviously a signing failure on a given cert should be fatal as it would be assumed a 3rd party modified.

    If the root is missing, you cannot verify the chain this results in TrustError::UntrustedRoot, the root CA is required to verify the signature of the previous CA in the chain which is either the peer cert or an intermediary CA, I would never trust a partial chain as you cannot verify the last cert in this partial chain

  • Hi Jose,
    In the certificate verifier callback, there doesn't seem to be any way to obbain the actual hostname/IP address provided for the connection in the first place. I examined the ConnectionInfoPtr class and all the members, and did not see a reference to that. We've been using some ugly logic all along to try to determine which connection a particular cert verifier callback refers to -- since our app can support many connections at once. Do you know of a way we can obtain this information from within the verifier callback directly?
    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    ConnectionInfo uses composition to provide info about the different transports, you can get the IPConnectionInfo by checking the underlying ConnectionInfo, something like:

    shared_ptr<IPConnectionInfo>
    getIPConnectionInfo(const shared_ptr<ConnectionInfo>& info)
    {
        for(shared_ptr<ConnectionInfo> p = info; p; p = p->underlying)
        {
            auto ipInfo = dynamic_pointer_cast<IPConnectionInfo>(p);
            if(ipInfo)
            {
                return ipInfo;
            }
        }
        return nullptr;
    }
    

    IPConnectionInfo is a local class defined in Slice see https://github.com/zeroc-ice/ice/blob/aa9ebdb49eda8392a86bcc49c509cb8f15f67f6b/slice/Ice/Connection.ice#L426 remoteAddress will contain the resolved address to which the connection was made.

  • Hi Jose,
    We do use that IPConnectionInfo to get the IP address currently. The issue is that we don't know the actual hostname (in case a user typed a hostname rather than an IP address). So we have to do some ugly logic to make the association from hostname to IP address. Does Ice have the actual hostname that was presented to it in the connection in addition to the resolved IP address?
    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    The actual hostname is currently not available with the connection info object passed to the verifier, the hostname is part of the Endpoint used to create the connection and IceSSL uses the name for IceSSL.CheckCertName.

    Do you need this only on the client side? one option would be to add a host field to the ExtendedConnectionInfo object and a getHost method to retrieve it, would this help?

  • Hi Jose,
    Yes, we only need this on the client side. Adding an ExtendedConnectionInfo object and a getHost() method would most certainly help!! Since we're planning to adopt a 3.7.5 + Patch already for your changes for getTrustError(), this would be easy for us to pick up.

    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    I would add this, should be pretty simple as the SSL plugin already has this info.

  • xdm
    xdm La Coruña, Spain

    Open a PR with these changes in https://github.com/zeroc-ice/ice/pull/1277

  • xdm
    xdm La Coruña, Spain

    Changes are now in 3.7 https://github.com/zeroc-ice/ice/commit/e2ea3eec1f9056f25859be26685fe612a7d0804b

    You can use IceSSL::getHost(info) with an IceSSL::ConnectionInfo object to get the hostname that was used to create the connection.

    Cheers,
    Jose

  • You're the best!! I'll test those out now.

    A question came up from another guy on our team. Does Ice for Windows support TLS 1.3?

    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    For Windows if you are using SChannel implementation it depends on the Windows version I think it is supported with recent versions of Windows 10 and Windows Server, if you use OpenSSL it depends on the OpenSSL version I think 1.3 was added with 1.1.1.

    Regarding Ice it will be able to use TLS 1.3 if the SSL engines support it.

  • Jose,
    The getHost() change works like a champ. Thanks again for the super-fast turnaround.

    Jeremy

  • Hi Jose,
    Getting around now to testing the other platforms other than Windows. Linux is not working as we would expect. When the certificate verifier callback occurs for a self-signed certificate, we are getting an Invalid Time error on the call to getTrustError(). When we examine the times reported back by getNotAfter() and getNotBefore(), they are ok. Windows and Mac seem to be ok here. I've attached a .zip of our sender cert (in .p12 format) .
    Thanks!

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    I tested Windows and Linux and get InvalidTime in both, looking at the certificate is not yet valid, Valid From on MMC windows reports ‎Monday, ‎June ‎21, ‎2021 1:10:53 AM

    This matches the value return by getNotBefore Mon Jun 21 01:10:53 2021

    Maybe I missing something but seems like the certificate is not yet valid.

  • Hi Jose,
    Sorry to waste your time. Indeed I had a different version of our cert generator that was intentionally making them invalid installed. I didn't pay close enough attention to that before reaching out to you. I thought it had been working on Windows but I realized I was testing my CA signed cert path. All is good, thanks again!
    Jeremy

  • Hi Jose,
    We're verifying Mac Ice 3.7 changes now. We've configured a system to have a root CA that by default is untrusted in the store. On a colleagues system, when the connection is initiated, getTrustError() comes back as 12, which is InvalidPurpose. On my system with the exact same certs, getTrustError() comes back with UntrustedRoot, which is what I would have expected. I'm unclear as to why we would see that difference. And I wasn't expecting Ice to be doing certificate purpose validation anyway, I didn't think it would have the context of the use to make that validation. Any ideas on that? I think ultimately we can survive with it, but just wanted to know if it was something we were doing wrong.
    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    In recent versions of macOS the certificate requirements are tighter, related to a link I posted earlier in this thread https://support.apple.com/en-us/HT210176

    Here the context is if you are authenticating a client or a server, as they have different requirements for trusted certificates. Are you and your colleague using different macOS versions for these tests?

  • Yes, I'm on Catalina and he's on Big Sur. I read that link but it didn't seem to have anything about the certificate purpose. And it seems the new restrictions came about as of Catalina (10.15). Maybe there's additional stuff happening on Big Sur now. I'll have to update and do some reasearch then. Thanks!

  • xdm
    xdm La Coruña, Spain

    For Ice we updated IceSSL test certificates with Catalina, to include "Server Authentication" in "Enhanced key Usage". We didn't need any updates to the certificates for Big Sur release, I would expect Catalina and Big Sur to be the same.

  • Hi Jose,
    We've observed on Mac that when we use a file based CA it fails. We think this is due to the fact that by default Mac now does not trust the root CAs. You have to explicitly trust them in the store. There's no way to do that (that we know of) with a file based CA. The Ice documentation indicates this should work. Is this a known issue, or are we doing something wrong?
    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    Can you clarify the client and server IceSSL configuration for this test?

    Cheers,
    Jose

  • Hi Jose.

    Let me know if you want to discuss this issue in a different thread and I will create one.

    Here is the MacOS issue we are facing:

    1 - Create a certificate chain that only has a rootCA and a server certificate. This is to make things simple and we don't have to worry about intermediateCAs.

    2 - Configure the Server to use the server certificate

    3 - On the MacOS client side (using BigSur here), configure the client to use a file based CA. This means setting the IceSSL.CAs. For example: IceSSL.CAs=/home/myUser/certificates/myCA.pem

    4 - Configure CheckCertName to be false, so we don't have to worry about name checking. This means setting IceSSL.CheckCertName=0

    5 - Attempt a connection from the client to the server and check the "verified" boolean. It should return true, but it returns false instead.

    6 - As soon as you add the RootCA to the Keychain and change the trust setting to "Always Trust", it starts working. However, our goal is to use a file based CA here. This configuration should not depend on what is in the MacOS Keychain.

    I'm attaching the certificates I used for testing.

    Thanks,
    Fábio

  • xdm
    xdm La Coruña, Spain
    edited June 2021

    Hi Fábio,

    I'm able to reproduce the issue using your test certificate, but it is not totally clear to me what is the problem.

    This doesn't happen with ZeroC demo certificates https://github.com/zeroc-ice/ice-demos/tree/3.7/certs

    When I use your server certificate and configure the client with IceSSL.CAs=myCA.pem I get

    src/IceSSL/SecureTransportTransceiverI.cpp:221: ::Ice::SecurityException:
    security exception:
    IceSSL: certificate verification failure:
    the supplied certificate cannot be used for the specified purpose
    

    One difference between your server test certificate and ours is that yours doesn't include "Enhanced Key Usage" Server Authentication, I got the impression that setting "Always Trust" is bypassing this check.

  • Hi Jose.

    I guess this is a SecureTransport issue then. It may be that they enforce the Server Authentication usage, unlike OpenSSL and SChannel.

    I will generate new certificates and redo the test.

    Thanks for the help.

    Fábio

  • Hi Jose.

    I have updated my server certificate to include the "Enhanced Key Usage" Server Authentication, but I'm still getting "verified = false". I did not change the RootCA (myCA.pem).

    During the connection process, I can see this log message from Ice: **IceSSL: ignoring certificate verification failure: Trust denied
    **

    On your tests, are you sure that the CA file is not available in the MacOS Keychain? If we are using IceSSL.CAs then there shouldn't be a need to have them on the Keychain as well.

    I will try to reproduce the issue with your certificates. I will configure the Server to use "server.p12" and the client to use "cacert.pem".

  • xdm
    xdm La Coruña, Spain
    edited June 2021

    Hi Fábio,

    I just checked your server certificate and I don't see the extended key usage extension

    openssl x509 -in server.pem -text -noout
    
    Certificate:
        Data:
            Version: 1 (0x0)
            Serial Number: 15299577704694843659 (0xd45304dc9dd2890b)
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=BR, ST=RS, L=Porto Alegre, O=Certificate Testers LTD, CN=RootCA for Testing/emailAddress=fabio.moreira@hp.com
            Validity
                Not Before: Jun 24 15:03:53 2021 GMT
                Not After : Sep 27 15:03:53 2023 GMT
            Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=MacOSSenderTest
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    Public-Key: (2048 bit)
                    Modulus:
                        00:98:13:fb:2e:56:c3:66:49:0d:42:eb:79:40:1e:
                        3a:4a:15:35:73:58:cb:14:1d:99:cd:fb:16:24:aa:
                        7a:51:90:dc:ea:5b:dd:8d:39:a8:85:c0:e2:a3:7a:
                        54:0b:05:c6:22:41:6c:b4:24:a3:1a:fd:f2:8b:f8:
                        65:ad:35:a6:59:fc:be:87:49:bc:0c:05:2e:82:ea:
                        f1:dc:99:67:be:96:15:8a:1c:f9:53:f6:96:22:d6:
                        a5:37:87:65:cc:ce:68:13:ba:c9:d9:7d:58:e7:2f:
                        a8:b9:bd:3d:eb:90:6f:52:76:57:dd:33:35:22:fb:
                        c0:28:ee:ea:b8:c2:3b:5b:fa:81:05:c6:51:65:aa:
                        9f:8d:21:8b:47:70:7a:35:4b:de:dc:40:8e:ff:af:
                        37:98:3b:6f:cf:fb:55:ec:a2:33:a4:b3:41:46:77:
                        75:7f:e7:36:96:75:0a:e6:27:f7:78:f2:df:2c:96:
                        7a:34:14:97:59:79:00:db:9f:5a:9f:89:ce:13:21:
                        85:e4:25:3e:b5:e2:27:e4:9e:40:a0:1f:31:9a:6b:
                        4a:08:a3:a6:62:66:51:60:9b:e7:8a:b6:09:d5:b5:
                        1f:54:dc:e0:f3:8e:4d:3c:ae:ef:bc:4e:a2:d9:18:
                        3c:a5:58:e2:c7:c8:88:8b:20:58:5e:2a:11:f3:24:
                        ae:f9
                    Exponent: 65537 (0x10001)
        Signature Algorithm: sha256WithRSAEncryption
             72:02:1d:db:96:3f:10:ca:81:ff:04:04:2c:99:a8:d1:41:8d:
             37:9e:5f:e1:20:bf:9a:60:f3:c0:b8:51:f3:96:a6:15:10:a2:
             a0:30:42:36:a2:50:32:07:6d:b0:d3:f1:d3:4f:bb:0e:be:f9:
             5c:8e:cd:02:02:c9:a1:f8:90:20:bd:0a:ff:9d:1e:55:9e:56:
             e1:87:f4:2b:6c:49:9b:aa:91:0c:54:2b:37:a5:cc:a1:e3:5f:
             83:a7:a4:65:42:88:5e:8b:04:3c:bf:31:35:b2:53:8f:47:24:
             a9:97:ff:6b:db:ab:57:c9:0c:69:49:fa:c1:5d:eb:e9:c8:2b:
             0e:9b:53:d7:bb:b9:ef:9c:a4:43:5a:7a:53:88:6f:16:89:7a:
             97:77:68:d9:d2:2e:7d:e5:b4:f2:62:1d:bb:2c:8a:70:4e:d4:
             4d:19:a8:a2:8c:72:2a:ff:75:99:ce:3d:14:26:6f:de:c5:79:
             80:33:e5:86:64:33:84:8a:5f:2f:b6:24:ce:db:5b:7b:3d:bd:
             b7:3d:e9:28:6b:6e:b3:bf:88:68:0e:8f:da:62:26:c6:25:5d:
             48:ca:e5:b2:bc:a8:96:fa:32:52:28:8d:79:ed:a1:84:f4:ee:
             d6:75:1d:db:b1:63:02:df:7d:ec:6e:03:8b:2d:45:47:00:6e:
             40:3b:46:6d
    

    If the extension was present you would see

    X509v3 Extended Key Usage:
                    TLS Web Server Authentication, TLS Web Client Authentication
    

    I find it odd this new cert doesn't include any extensions, your previous server certificate included some extensions but now all are gone.

  • Hi Jose.

    I imported the my.new.sender.pfx file into my windows certificate store and I can see the extended key usage. Maybe it was an issue with exporting it to pem?

    I generated the certificates again in any case. I also created a .pem file for the server, based on the .crt file.

  • Hi Jose.

    The new certificates I created seem to be working now. I'm getting verified = true on the MacOS client, using a file based CA.

    It is possible that I made some mistake while converting the crt certificate to the pfx format.