I am attaching a small utility which does all possible checks we can do.

On 05/10/2013 12:01 AM, Alex Rousskov wrote:
> On 05/09/2013 01:10 PM, Tsantilas Christos wrote:
>> On 05/09/2013 05:50 PM, Alex Rousskov wrote:
>> I can reporoduce the bug with the following simple program:
>>
>> int main(int argc, char *argv[])
>> {
>>     SSLeay_add_ssl_algorithms();
>>     SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
>>     SSL *ssl = SSL_new(sslContext);
>>     X509 * cert =  SSL_get_certificate(ssl);
>>     return 0;
>> }
>>
>> This program crashes inside a function called by SSL_get_certificate.
>> I suppose we can check if the program exited normally or not, to decide
>> if the openSSL SDK is OK or have the bug.
> 
> That sounds like a good idea to me. I would extend that test code to
> also include code to test that our workaround compiles. Here is a sketch:
> 
> int main() {
>     ...
>     X509 *cert1 = workaroundCode(...);
>     X509 *cert2 = directCode(...); // may crash!
>     return cert1 == cert2 ? 0 : 1;
> }
> 
> I assume that both cert1 and cert2 will be nil in your test case when
> everything works correctly, but that does not matter.

Well checking with null certificates maybe is not enough good to detect
problems. The SSL and SSL_CTX structures used here mostly uninitialized
so it is possible to get a wrong field which is just zeroed.

But maybe we can add in the check program a hard coded certificate. I am
using it in the check toll I am attaching.
Then to check if the workaround code works required the following:
    const char *certTxt = "-----BEGIN CERTIFICATE----\n" .....;

    SSLeay_add_ssl_algorithms();
    BIO *certBio = BIO_new(BIO_s_mem());
    BIO_puts(certBio, certTxt);
    X509 * cert = NULL;
    PEM_read_bio_X509(certBio, &cert, 0, 0));
    SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
    SSL_CTX_use_certificate(sslContext, cert));
    X509 ***pCert = (X509 ***)sslContext->cert;
    X509 *sslCtxCert = pCert && *pCert ? **pCert : NULL;
    return (sslCtxCert != cert ? 1 : 0);


> 
> Then, we can use one of the following two strategies:
> 
> Conservative (work around the bug if possible and clearly necessary):
>   If the test compiles but crashes, enable workaround.
>   Otherwise, disable workaround.
> 
> Midway (work around the bug if necessary or if work around works):
>   If the test compiles but crashes, enable workaround.
>   If the test compiles and returns 0, enable workaround.
>   Otherwise, disable workaround.
> 
> Aggressive (work around the bug if possible):
>   If the test compiles, enable workaround.
>   Otherwise, disable workaround.
> 
> 
> I think we should use either the Midway or the Aggressive approach to
> accommodate more cases, but I am not sure. What do you think?

I think the best is the aggressive with some additions:

- Check if the workaround work, using a code similar to the above.
- If not work try to use SSL object and SSL_get_certificate function. If
this one crashes, disable SSL bumping (only here needed).

We can implement it using two scripts/checks as Amos suggest.

> 
> 
> If it is easy, we could also allow folks to define the corresponding
> decision macro manually, when building Squid, so that they can overwrite
> our automation when needed (e.g., when compiling Squid for use with a
> different OpenSSL version). I do not think we need to make that choice
> an explicit ./configure option though.
> 
> 
> Thank you,
> 
> Alex.
> 
> 

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>

const char *certTxt = "-----BEGIN CERTIFICATE-----\n"\
"MIICMTCCAZoCCQD+KQjThaQoEDANBgkqhkiG9w0BAQUFADBdMQswCQYDVQQGEwJV\n"\
"UzETMBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UEBwwETm9uZTEOMAwGA1UECgwF\n"\
"U3F1aWQxCzAJBgNVBAsMAml0MQ0wCwYDVQQDDARub25lMB4XDTEzMDUxMDE0MjUz\n"\
"N1oXDTE0MDUxMDE0MjUzN1owXTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUt\n"\
"U3RhdGUxDTALBgNVBAcMBE5vbmUxDjAMBgNVBAoMBVNxdWlkMQswCQYDVQQLDAJp\n"\
"dDENMAsGA1UEAwwEbm9uZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtSz4\n"\
"dQExZQ8mseCr9fwYD3OsIE7p0QvEb8QVQlrLeJ3nqalUb415cg+eyVn1ZAPU52si\n"\
"VebNlKRhIilZfyiwSEuxyyvfmcAVbAMjhwjAuPod8LtQneF9qbxRa4OjytQ1+v7h\n"\
"GFMmZECLvwF5+UUXgPPbFhcBd9gu32YdWs8ADJMCAwEAATANBgkqhkiG9w0BAQUF\n"\
"AAOBgQAqxsFSwhSJkolHtOev4jlk2JqpLcUHq6IpVbfpou7YM2Ca5sSKMf9/mjoY\n"\
"kRyhg6TX/1ymde1V1tA80DjIZYiF/m4YLwsSJVV2hE4lja/e8CvBLzeTSPe3S0rH\n"\
"cWcRnuH9ts0PRPUD0NxZejib4F8m7hI2emm5d56xizvYooZzzg==\n"\
"-----END CERTIFICATE-----";

int main(int argc, char *argv[])
{
    // SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();
    BIO *certBio = BIO_new(BIO_s_mem());
    BIO_puts(certBio, certTxt);

    X509 * cert = NULL;
    if (!PEM_read_bio_X509(certBio, &cert, 0, 0)) {
        fprintf(stderr, "Error building certificate\n");
        return -1;
    }

    SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
    if (!sslContext) {
        fprintf(stderr, "Error creating ssl context\n");
        return -1;
    }

    if (!SSL_CTX_use_certificate(sslContext, cert)) {
        fprintf(stderr, "Error attaching certificate to ssl context\n");
        return -1;
    }


    X509 ***pCert = (X509 ***)sslContext->cert;
    X509 *sslCtxCert = pCert && *pCert ? **pCert : NULL;      
    if (sslCtxCert != cert)  {
        fprintf(stderr, "Geting certificate dicectly from SSL_CTX object failed!\n");
        return 1;
    }


    SSL *ssl = SSL_new(sslContext);
    if (!ssl) {
        fprintf(stderr, "Error creating ssl object\n");
        return -1;
    }

    X509 * sslCert =  SSL_get_certificate(ssl);
    if (sslCert != cert) {
        fprintf(stderr, "SSL_get_certificate failed!\n");
        return 1;
    }

    pCert = (X509 ***)ssl->cert;
    sslCert = pCert && *pCert ? **pCert : NULL; 
    if (sslCert != cert)  {
        fprintf(stderr, "Geting certificate dicectly from ssl object failed!\n");
        return 1;
    }
   
    return 0;
}

Reply via email to