Archived

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

OpenSSL default certificate directory when IceSSL.UsePlatformCA property is used.

I’m attempting to validate certificates on Ubuntu 20.04 using the IceSSL.UsePlatformCAs property using C++. It’s worth noting that I’m using a different distribution of openSSL 1.1.1f, rather than the system distribution.

Even when I copy the PEM certificate file into the directory that OpenSSL should be using by default (/usr/lib/ssl/certs on Ubuntu, as far as I can tell) and configure and run update-ca-certificates, it fails to validate the certificate. As far as I can tell, no errors are logged, even with a variety of Ice logging settings turned on.

However, when I set the SSL_CERT_DIR or SSL_CERT_FILE environment variables (i.e. running SSL_CERT_DIR=/usr/lib/ssl/certs my_program) with my PEM certificate file present in that directory or at that file, Ice successfully validates the cert.

My desired behavior is for Ice to use OpenSSL’s default certificate directory (or some other reasonable default) for certificate validation when I set UsePlatformCAs, without me needing to set any environment variables. How can I accomplish this? Is there extra openSSL init code I need to run? Would I need to use the system’s openSSL version instead?

If that isn’t possible, is there a way to find out where Ice is looking?

Comments

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    Was your OpenSSL distribution build to use /usr/lib/ssl/certs, or maybe your build is using another directory? what is the output of openssl version -a.

    The fact that it works when you set the environment variables seems to indicate that the default settings are not what you expect.

  • (This is actually my question--Jeremy just posted it for me while I waited for my account to be approved).

    openssl version -a fails with a symbol lookup error on one of the pieces of information it requests, likely because of how we built it. However, here's the output of openssl version with all the flags that do work (all of them except -o):

    ./openssl version -v -b -f -p -d -e
    OpenSSL 1.1.1g  21 Apr 2020 (Library: OpenSSL 1.1.1f  31 Mar 2020)
    built on: Mon Mar 22 11:37:17 2021 UTC
    platform: debian-amd64
    compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-Juj39H/openssl-1.1.1f=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
    OPENSSLDIR: "/usr/lib/ssl"
    ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
    

    This is the same OPENSSLDIR that the distro's OpenSSL reports.

  • xdm
    xdm La Coruña, Spain

    did you install you CA certificate in /usr/share/ca-certificates and added it to /etc/ca-certificates.conf before using update-ca-certificates?
    `

  • xdm
    xdm La Coruña, Spain

    I just tested with the hello demo and this seems to work, here is what I did

    Copy the demo CA certificate to /usr/share/ca-certificates/zeroc/cacert.pem

    Add an entry in /etc/ca-certificates.conf with zeroc/cacert.pem

    Run update-ca-certificates

    in config.client remove IceSSL.CAs=cacert.pem and add IceSSL.UsePlatformCAs=1

    I tested it with OpenSSL 1.1.1f and Ubuntu 20.10

  • It does work with the system Ice and OpenSSL libraries; it seems to be ours that is the problem. I'm looking into other approaches now, thank you for your help.

  • xdm
    xdm La Coruña, Spain

    did you try installing your version in a different location, it can be a problem with having two versions that are not binary compatible install with the same prefix, this is mentioned in the OpenSSL docs https://wiki.openssl.org/index.php/Compilation_and_Installation#PREFIX_and_OPENSSLDIR

  • Yes, our prefix and openssldir are set, and we have a different prefix from the system installation.

  • xdm
    xdm La Coruña, Spain

    According to the openssl output you posted before you are using the same as the system default for your builds.

    OPENSSLDIR: "/usr/lib/ssl"
    ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
    
  • That is true, but the function call X509_get_default_cert_dir_env (which OpenSSL is using) doesn't produce the correct value when compiled and run with our openssl version. It instead looks in the directory where it was compiled.

  • Hi Jose,
    A related question on this topic.
    We're trying to understand if there's any way to have Ice on Linux package up the sender certificate + intermediates other than creating a PFX that has it all combined. Linux has the concept of a certificate store, albeit more primitive than Windows. It would seem that we could do something with IceSSL.CAs or IceSSL.UsePlatformCAs to make Ice gather intermediates up from the store too. It does this just fine on Windows. I tested by installing a intermediate.crt in my Linux system (Centos7) and setting IceSSL.UsePlatformCAs to 1, and it didn't work. But maybe that's not what that property is intended for.
    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    You can put the keychain with the server certificate in a PEM file, IceSSL.CertFile should point to this file and then separately specify the key file using IceSSL.KeyFile

    IceSSL.CertFile=server_cert_pub.pem
    IceSSL.KeyFile=server_key.pem
    

    Seem for example the PEM encoded certificate we use to test this

    https://github.com/zeroc-ice/ice/blob/3.7/cpp/test/IceSSL/certs/s_rsa_cai2_pub.pem
    https://github.com/zeroc-ice/ice/blob/3.7/cpp/test/IceSSL/certs/s_rsa_cai2_priv.pem

    In case you want to test with these certificates, the password is "password".

    The property IceSSL.KeyFile was deprecated in 3.7 but still works, I think we should actually undeprecate it as it is handy for this use case, I will open an issue to discuss it with my colleagues.

    IceSSL.CAs and IceSSL.UsePlatformCAs are unrelated to this.

    Cheers,
    Jose

  • Jose,
    We're already doing something similar today with the IceSSL.CertFile property. We can create a .PFX that has the sender cert and key, plus the intermediate chain all combined. We don't need the IceSSL.KeyFile property. This does work fine for us on Linux. I think you answered our question though... IceSSL.CAs and IceSSL.UsePlatformCAs do not work on sender side. Basically, you're saying there's no way to put intermediate CAs in the Linux stores like you can on Windows, and have them sent when the receiver established a connection. If that's not correct let me know.
    Thanks
    Jeremy

  • xdm
    xdm La Coruña, Spain

    Hi Jeremy,

    I was mistaken aboutIceSSL.UsePlatformCAs not affecting this, after reviewing the OpenSSL docs I found this

    https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_add_extra_chain_cert.html

    If no chain is specified, the library will try to complete the chain from the available CA certificates in the trusted CA > storage, see SSL_CTX_load_verify_locations(3).

    IceSSL calls SSL_CTX_set_default_verify_paths when IceSSL.UsePlatformCAs is set, keep in mind that this setting is ignored if IceSSL.CAs is defined.

    I did a quick test on Ubuntu with OpenSSL 1.1.1g and seems to work fine

    Added the intermediary certs to /etc/ca-certificates.conf

    zeroc/CA2.crt
    zeroc/CA1.crt
    

    And copied them to /usr/share/ca-certificates/zeroc/

    Run update-ca-certificates to update the store

    Then I run hello demo server with this configuration

    Ice.Plugin.IceSSL=IceSSL:createIceSSL
    IceSSL.CertFile=server_pub.pem
    IceSSL.KeyFile=server_priv.pem
    IceSSL.UsePlatformCAs=1
    IceSSL.Password=password
    

    server_pub.pem has just the leaf certificate.

    In a separate machine I check the chain is send by using the following openssl command

    openssl s_client -showcerts -connect 192.168.1.143:10001