How to use SSL_CERT_FILE for OpenSSL Windows (OpenSSL 1.0.1c)

前端 未结 1 1565
自闭症患者
自闭症患者 2021-01-13 22:29

How (if at all) can one define a single trusted certificate file for OpenSSL on Windows (Win-7, OpenSSL 1.0.1c) using the SSL_CERT_FILE environment variable?

Variou

相关标签:
1条回答
  • 2021-01-13 22:57

    How (if at all) can one define a single trusted certificate file for OpenSSL

    The CAFile is simply a concatenation of self-signed certificates that you trust and want to use. If you only want to trust one, then there should only be one in the CA File.

    I prefer the PEM encoding because its easier to inspect with a text editor (-----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----). For example, here's the ca-bundle.pem from Startcom (http://www.startssl.com/certs/):

    Image of Startcom's ca-bundle.pem file

    So, to create one, just use cat and redirections (or copy and paste):

    # Empty my-ca-file.pem
    echo "" > my-ca-file.pem
    # Add Startcom certs
    cat startcom-ca-bundle.pem >> my-ca-file.pem
    # Add others as desired
    ...
    

    Various research led me to download the December '12 version of Mozilla's trusted certificates in PEM format...

    Well, that's one of the lists you can use. When you use Mozilla's list, you are saying "I trust Mozilla to do the right thing". Keep in mind Mozilla rewarded Trustwave's bad behavior when Trustwave was caught intercepting SSL/TLS traffic. Even though Trustwave violated at least two inclusion policies, Mozilla continued to include them because Trustwave promised never to do it again. See Remove Trustwave Certificate(s) from trusted root certificates for details.

    If you don't trust Mozilla's judgement, then you can use OpenSSL's built-in list at /usr/lib/ssl/certs/ca-certificates.crt, use another list (most major vendors have them), or build your own.

    Using a different vendor's list is usually the equivalent of trading the devil you know for the devil you don't know. For example, Apple has a list they use that you can inspect at iOS: List of available trusted root certificates (iOS 7). But Apple's list has lots of problems: http://seclists.org/fulldisclosure/2013/Sep/186 and http://seclists.org/fulldisclosure/2013/Sep/184.

    I would recommend building your own list or pinning certificates. Pinning certificates or public keys is better because it neutralizes the systemic problems in SSL/TLS that allowed Trustwave to do what they did. See OWASP's Certificate and Public Key Pinning for details.


    ... on Windows (Win-7, OpenSSL 1.0.1c) using the SSL_CERT_FILE environment variable?

    I don't know how to do it through environmental variables because I don't use them. But there should be no difference between Linux/Unix/OSX/Windows (except, perhaps, the handling of long file names and spaces).

    Looking at the OpenSSL sources, you have the following in cryptlib.h:

    #define X509_CERT_FILE_EVP       "SSL_CERT_FILE"
    

    x509_def.c uses X509_CERT_FILE_EVP:

    const char *X509_get_default_cert_file_env(void)
        { return(X509_CERT_FILE_EVP); }
    

    X509_get_default_cert_file_env is used in by_file.c in by_file_ctrl:

    ...
    switch (cmd)
    {
        case X509_L_FILE_LOAD:
            if (argl == X509_FILETYPE_DEFAULT)
            {
                file = (char *)getenv(X509_get_default_cert_file_env());
                if (file)
                    ok = (X509_load_cert_crl_file(ctx,file,
                                                  X509_FILETYPE_PEM) != 0);
    
                else
                    ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
                                                  X509_FILETYPE_PEM) != 0);
    
                if (!ok)
                {
                    X509err(X509_F_BY_FILE_CTRL,X509_R_LOADING_DEFAULTS);
                }
            }
            else
            {
                if(argl == X509_FILETYPE_PEM)
                    ok = (X509_load_cert_crl_file(ctx,argp,
                                                  X509_FILETYPE_PEM) != 0);
                else
                    ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0);
            }
            break;
    }
    return(ok);
    

    So, a concatenation of PEM formats is preferred (required?) when using SSL_CERT_FILE.

    Finally, be sure the SSL_CERT_FILE is not being overridden by a configuration file setting. See OpenSSL config(5) for details.


    It seems like an arduous process to manually extract each certificate and put it in its own file with a hash link pointing at it.

    I don't believe you need to rehash when using SSL_CERT_FILE, -CAfile, or SSL_CTX_load_verify_locations.

    I've never rehashed when using -CAfile or SSL_CTX_load_verify_locations, and everything has worked fine. When things break, it usually because (1) the root certificate is not present or trusted; or (2) an intermediate certificate is not present.

    For item (2) above, you need the server to send all the required certificates to build the chain. Otherwise, a client won't know where to look to find a missing intermediate certificate. Is a well known problem in PKI called the "Which Directory" problem (the client does not know which X500 directory to search for the missing certificate).


    Related, here's how to use them in OpenSSL's s_client. This actually works because pagepeeker.com uses StartCom, and it will fail if you omit the -CAfile option:

    $ echo "GET / HTTP\1.1" | openssl s_client -connect api.pagepeeker.com:443 -CAfile startcom-ca-bundle.pem
    CONNECTED(00000003)
    depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Certification Authority
    verify error:num=19:self signed certificate in certificate chain
    verify return:0
    ---
    Certificate chain
     0 s:/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu@gmail.com
       i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
     1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
       i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
     2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
       i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
    ---
    Server certificate
    -----BEGIN CERTIFICATE-----
    MIIGZTCCBU2gAwIBAgIDCJkoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
    TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
    ...
    

    And related code when doing C programming. This is part of the code I use to setup a SSL/TLS connection (in addition to public key pinning):

    int ret = 0;
    unsigned long ssl_err = 0;
    SSL_CTX* ctx = NULL;
    
    do
    {
        ret = SSL_library_init();
        ssl_err = ERR_get_error();
        if(!(1 == ret))
        {
            display_error("SSL_library_init", ssl_err);
            break; /* failed */
        }
    
        /* SSLv23_method() is 'everything' */
        const SSL_METHOD* method = SSLv23_method();
        ssl_err = ERR_get_error();
        if(!(NULL != method))
        {
            display_error("SSLv23_method", ssl_err);
            break; /* failed */
        }
    
        /* http://www.openssl.org/docs/ssl/ctx_new.html */
        ctx = SSL_CTX_new(method);
        ssl_err = ERR_get_error();
        if(!(ctx != NULL))
        {
            display_error("SSL_CTX_new", ssl_err);
            break; /* failed */
        }
    
        /* Enable standard certificate validation and our callback */
        /* https://www.openssl.org/docs/ssl/ctx_set_verify.html */
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, my_verify_cb);
        /* Cannot fail ??? */
    
        /* Remove most egregious */
        const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
        long old_opts = SSL_CTX_set_options(ctx, flags);
        UNUSED(old_opts);
    
        /* http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html */
        ret = SSL_CTX_load_verify_locations(ctx, "startcom-ca-bundle.pem", NULL);
        ssl_err = ERR_get_error();
        if(!(1 == ret))
            display_warning("SSL_CTX_load_verify_locations", ssl_err);
    
    } while(0);
    
    // Use context
    return ctx;
    

    Its OK if SSL_CTX_load_verify_locations fails. It means you won't trust anything, so you fail closed or shut.

    0 讨论(0)
提交回复
热议问题