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; }