>Synopsis: X509_STORE_free does not obey reference count
>Category: library
>Description:
The X509_STORE_free routine does not decrement and check the
reference count, even though it's initialized properly in
X509_STORE_new. This has been fixed in OpenSSL 1.0.2, but not yet in
libressl.
Ruby's OpenSSL bindings, as well as my own Lua OpenSSL bindings
(luaossl), partially workaround this bug by installing an external
application data hook on the SSL_CTX object and nulling the
cert_store member. This depends on the coincidental ordering of
freeing ex_data before the X509_STORE object in SSL_CTX_free, and
doesn't work if other application code uses SSL_CTX_set_cert_store.
>How-To-Repeat:
OpenSSL and libressl also lack SSL_CTX_set1_cert_store. Instead,
language bindings explicitly increment the reference count on an
X509_STORE object when using SSL_CTX_set_cert_store. But as
described above this isn't enough.
#include <assert.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
int main(void) {
X509_STORE *store;
SSL_CTX *ctx;
SSL_library_init();
store = X509_STORE_new();
ctx = SSL_CTX_new(TLSv1_method());
SSL_CTX_set_cert_store(ctx, store);
assert(store->references == 1);
CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
SSL_CTX_free(ctx);
X509_STORE_free(store); /* <-- double-free */
return 0;
}
>Fix:
Add the following near the top of X509_STORE_free, defined
in x509_lu.c:
i = CRYPTO_add(&vfy->references, -1, CRYPTO_LOCK_X509_STORE);
if (i > 0)
return;