Archived

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

IceSSL: Is it possible to avoid installing intermediate CAs on the client side?

Greeting.

When a server is using a certificate that has two or more CAs (for example, one root CA and one intermediate CA), is it possible to get the client side to trust the server certificate while having only the root CA (and not the intermediate CA) installed on the certificate store?

I think this means the server side needs to send the full certificate chain, and not only the leaf certificate,

I know there are configurations available for Apache to do something like that: https://stackoverflow.com/questions/30344893/how-to-force-apache-2-2-to-send-the-full-certificate-chain

Our goal is to make the client configuration simpler, meaning only one CA (the root one) would need to be installed on the client side even if the server is using a certificate signed by multiple CAs.

Thanks,
Fábio Moreira

Comments

  • xdm
    xdm La Coruña, Spain

    Hi Fabio,

    You can include the intermediate certificates with the server certificate and IceSSL will provide them to the peer.

    Cheers,
    Jose

  • Hi Jose.

    Just for clarification, this means that if I supply the intermediate CAs using IceSSL.CAs on the server side then it should provide them to the peer, correct?

    Is there any other way to provide those intermediate certificates? For example, on Windows, if I add those intermediate certificates to the Windows Certificate Store on the server side, will the server also provide them to the peer, even if I don't set the IceSSL.CAs property?

    Thanks for the help,
    Fábio

  • xdm
    xdm La Coruña, Spain

    Hi Fabio,

    This is unrelated to Server CA configuration, it is related to the server certificate file that you set using IceSSL.CertFile or IceSSL.FindCert if this certificate contains the certificate chain, it will be sent during SSL handshake.

    Cheers,
    Jose

  • Hi Jose,

    Got it. I created a certificate chain that looks like this: rootCA - intermediateCA - serverCertificate.

    I exported it as a .pfx file and configured the server to use it using IceSSL.CertFile.

    On the client side I can confirm that all 3 certificates are being received. I can see all of them on the certificate chain that is received on the certificate verifier.

    However, I was expecting the "verified" boolean that is available on the certificate verifier callback to be true, because I have the rootCA in my certificate store on the client side.

    I had to add the intermediateCA to the certificate store on the client side so the verified boolean would become true.

    What we wanted to accomplish was to limit the distribution of CAs to the client machines to the rootCA. However, as it is right now, we will also have to distribute the intermediate CAs, even if we set the sender to send the full certificate chain. Otherwise the verified boolean will be false and we will have to fail the certificate verification process.

    Is there any way to get around that? Basically, is there a way to have the client side trust the server certificate if the server sends the full chain and the client only has the rootCA installed?

    Thanks again!
    Fábio

  • xdm
    xdm La Coruña, Spain

    However, I was expecting the "verified" boolean that is available on the certificate verifier callback to be true, because I have the rootCA in my certificate store on the client side.

    I would expect "verified" to be true here, we have a test for a setup similar to this in IceSSL test suite

    https://github.com/zeroc-ice/ice/blob/910308ad17ba6ba1f5e5609fe6dc19b9c6de81ef/cpp/test/IceSSL/configuration/AllTests.cpp#L1734-L1759

    The certificates of the test are:

    server: https://github.com/zeroc-ice/ice/blob/3.7/cpp/test/IceSSL/certs/s_rsa_cai2.p12
    root CA: https://github.com/zeroc-ice/ice/blob/3.7/cpp/test/IceSSL/certs/cacert1.pem

    Maybe verified is false because of a different error?

    Do you have a test certificate that I can use to check this, you can upload it here or sent it to support?

    can you also check if you got the same problem with the test certificates?

  • Hi Jose.

    It seems your certificate chain looks like this: RootCA - ServerCertificate.

    This configuration works fine for me, as long as the root CA is installed on the client side.

    What I was expecting to work was a chain that looks like this: RootCA - IntermediateCA - ServerCertificate. I was expecting to get "verified" to be true without having to install IntermediateCA on the client side. I only have RootCA installed.

    I did configure the server to send the full certificate chain. I also set CheckCertName to false, to make sure that does not influence on the result. As soon as I add the IntermediateCA to the "Intermediate Certification Authorities" windows store I get "verified = true".

    I attached a zip file with the certificates I have been using for testing. I configured the server to use "serverCertificateWithFullChain.pfx". On the client side, I set CheckCertNames to false and install rootCA in "Trusted Root Certification Authorities".

    I get "verified = false". As soon as I add intermediateCA to the trust store on the client side I get "verified = true".

    Thanks,
    Fábio

  • I am also using ICE version 3.7.2. Not sure if it makes a difference.

  • xdm
    xdm La Coruña, Spain

    It seems your certificate chain looks like this: RootCA - ServerCertificate.

    Did you check s_rsa_cai2.p12

    If you look at the test I linked above it checks the chain length is 4, that would not pass if it was RootCA - ServerCertificate.

    I am also using ICE version 3.7.2. Not sure if it makes a difference.

    This shouldn't make any difference

    I attached a zip file with the certificates I have been using for testing

    I would check with your certs

  • xdm
    xdm La Coruña, Spain

    Hi Fabio,

    After review our test, the test imports the certificates in the user store before sending, did you try importing the intermediate certificates into the server intermediate certificate store?

  • The server I'm currently testing is Linux based, so I'm not using a certificate store on the server side, but I can try a windows server one too.

  • FabioMoreira
    edited June 2021

    Hi Jose.

    I got it working by looking at your certificate.

    I changed the certificate chain I'm using on the server from:
    RootCA - IntermediateCA - ServerCertificate

    to

    IntermediateCA - ServerCertificate

    So I just removed the rootCA from the server certificate chain and now I get verified = true, even without installing IntermediateCA on the client.

    Is it supposed to fail if you have the RootCA on the server side chain? I have no idea.

    Anyways, I'm glad it works. We can instruct our customers to set a chain on the server side that contains all the intermediate CAs (but not the rootCA) plus their server certificate and it should be enough so they don't have to distribute their intermediate CAs.

    Thanks a lot for the help.

    Fábio

  • xdm
    xdm La Coruña, Spain

    Hi Fábio,

    Glad you get things working

    Is it supposed to fail if you have the RootCA on the server side chain? I have no idea.

    Not sure if this should result in a failure, it might depend on the SSL implementation, I think that is why we don't include it.

    I can try a windows server one too.

    I was checking Windows and SCHannel only sends the intermediates if they are present in the certificate store, you will have to add that to the server configuration requirements on Windows.

  • Hi again, Jose.

    Unfortunately I had misconfigured my server certificate file, so instead of having intermediateCA + ServerCert I had rootCA + intermediateCA.

    I redid all tests using windows based client and servers and the result is that I can't get verified to be true unless the intermediateCA is available on the client side. Here is what I tried:

    On Server Side:
    1 - File Based certificate with only ServerCertificate
    2 - File Based certificate with IntermediateCA + ServerCertificate
    3 - File Based certificate with RootCA + IntermediateCA + ServerCertificate
    4 - Store based certificate. Used FindCert to select ServerCertificate. IntermediateCA and RootCA were also available on the Store.

    On the Client Side:
    5 - File Based CA with only RootCA
    6 - File Based CA with RootCA + IntermediateCA
    7 - Store based CA. Only RootCA added to the store
    8 - Store based CA. Both RootCA and IntemediateCA added to the store

    It doesn't matter what I do on the sender side. On the client side I can only get the number of certificates to be 3 and the verified boolean to be true if the IntermediateCA is available (so options 6 or 8).

    I tried to use the certificates you provided, however, s_rsa_cai2.p12 is password protected and I can't import it.

    I'm attaching zip file with the certificates I used. On the Server Side, if I set the Server to use intermediateAndSender.pfx and on the client side I install root-ca.crt (file based or store), then I only get one certificate on the certificate verification callback and verified is true. As soon as I install the intermediate.crt on the client side everything works.

  • I did some extra tests connecting from OpenSSL and I am able to perform the connection using only the root certificate on the client side:

    openssl s_client -showcerts -connect 192.168.0.14:42966 -CAfile /c/Users/moreifab/certificates/root-ca.crt

    The server is using a store based certificate. The output of the command above shows that the Server is actually sending both the ServerCertificate and the IntermediateCertificate.

    The output also shows the connection is ok: "Verify return code: 0 (ok)"

    If I don't pass the -CAfile parameter, I get the expected error: "Verify return code: 20 (unable to get local issuer certificate)".

    So with openSSL, I am able to connect to a server without installing the intermediate certificate on the client machine.

    With IceSSL, I am currently unable to do the same. I always have to install the intermediate certificate (file or store) on the client machine.

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

    Hi Fábio,

    I was able to reproduce the issue using s_rsa_cai2.p12 and Windows client, our test worked because the intermediates are imported in the user store.

    The problem is how IceSSL SChannel implementation builds the client chain, it only provides the end cert to the CertGetCertificateChain API, I have a fix that will be included in 3.7.6

    diff --git a/cpp/src/IceSSL/SChannelTransceiverI.cpp b/cpp/src/IceSSL/SChannelTransceiverI.cpp
    index 26e84923d8..d28d9035ea 100644
    --- a/cpp/src/IceSSL/SChannelTransceiverI.cpp
    +++ b/cpp/src/IceSSL/SChannelTransceiverI.cpp
    @@ -765,7 +765,7 @@ SChannel::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal:
    
             string trustError;
             PCCERT_CHAIN_CONTEXT certChain;
    -        if(!CertGetCertificateChain(_engine->chainEngine(), cert, 0, 0, &chainP,
    +        if(!CertGetCertificateChain(_engine->chainEngine(), cert, 0, cert->hCertStore, &chainP,
                                         CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, 0, &certChain))
             {
                 CertFreeCertificateContext(cert);
    

    And I also verified that the Windows server only sends the chain if the intermediates are found in the certificate store.

    BTW for debugging the chain sent by the server you can use openssl command:

    openssl s_client -connect 192.168.1.100:10001 -showcerts
    
  • Hi Jose,

    Thanks for looking into it.

    I was going to mention that maybe your tests worked because you are running the client and server on the same machine, so the certificates you install for the server will be accessible by the client.

    I have just verified that the connection from a MacOS client works fine. I only need to install the root CA on the client side, not the intermediate one.

    I am in the process of verifying our Linux client, but I suspect it will work fine as well.

    As you mentioned, it looks like an issue restricted to the Windows verification process.

    Do you have a commit hash with this fix? The next version of our product will be using Ice 3.7.5 but we are interested in including this patch, if it is simple enough and it can be applied on top of 3.7.5.

    Thanks again.

  • xdm
    xdm La Coruña, Spain

    Hi Fabio,

    See f6396c9c77e9fc4a72200c98c324c7c477a0cbcb https://github.com/zeroc-ice/ice/commit/f6396c9c77e9fc4a72200c98c324c7c477a0cbcb

    Cheers,
    Jose