summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwilliam <william@25thandclement.com>2015-04-16 21:00:58 -0700
committerwilliam <william@25thandclement.com>2015-04-16 21:00:58 -0700
commit8dbe7e424adcfcf0bec4c8573b874d733c5b2a66 (patch)
tree9a074c0ca8f2347752b9c8564f4da383e5cb80fd
parent55da052192e151ee055e62a378d6ebdbdcbe5087 (diff)
downloadluaossl-8dbe7e424adcfcf0bec4c8573b874d733c5b2a66.tar.gz
luaossl-8dbe7e424adcfcf0bec4c8573b874d733c5b2a66.tar.bz2
luaossl-8dbe7e424adcfcf0bec4c8573b874d733c5b2a66.zip
add fix for issue #17
-rw-r--r--src/openssl.c155
1 files changed, 148 insertions, 7 deletions
diff --git a/src/openssl.c b/src/openssl.c
index 3465922..163ba7f 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -33,7 +33,9 @@
33#include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */ 33#include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */
34#include <time.h> /* struct tm time_t strptime(3) time(2) */ 34#include <time.h> /* struct tm time_t strptime(3) time(2) */
35#include <ctype.h> /* tolower(3) */ 35#include <ctype.h> /* tolower(3) */
36#include <signal.h> /* sig_atomic_t */
36#include <errno.h> /* ENOMEM errno */ 37#include <errno.h> /* ENOMEM errno */
38#include <assert.h> /* assert */
37 39
38#include <sys/types.h> /* ssize_t pid_t */ 40#include <sys/types.h> /* ssize_t pid_t */
39#if !defined __sun && !defined _AIX 41#if !defined __sun && !defined _AIX
@@ -44,16 +46,11 @@
44#include <sys/socket.h> /* AF_INET AF_INET6 */ 46#include <sys/socket.h> /* AF_INET AF_INET6 */
45#include <sys/resource.h> /* RUSAGE_SELF struct rusage getrusage(2) */ 47#include <sys/resource.h> /* RUSAGE_SELF struct rusage getrusage(2) */
46#include <sys/utsname.h> /* struct utsname uname(3) */ 48#include <sys/utsname.h> /* struct utsname uname(3) */
47
48#include <fcntl.h> /* O_RDONLY O_CLOEXEC open(2) */ 49#include <fcntl.h> /* O_RDONLY O_CLOEXEC open(2) */
49
50#include <unistd.h> /* close(2) getpid(2) */ 50#include <unistd.h> /* close(2) getpid(2) */
51
52#include <netinet/in.h> /* struct in_addr struct in6_addr */ 51#include <netinet/in.h> /* struct in_addr struct in6_addr */
53#include <arpa/inet.h> /* inet_pton(3) */ 52#include <arpa/inet.h> /* inet_pton(3) */
54
55#include <pthread.h> /* pthread_mutex_init(3) pthread_mutex_lock(3) pthread_mutex_unlock(3) */ 53#include <pthread.h> /* pthread_mutex_init(3) pthread_mutex_lock(3) pthread_mutex_unlock(3) */
56
57#include <dlfcn.h> /* dladdr(3) dlopen(3) */ 54#include <dlfcn.h> /* dladdr(3) dlopen(3) */
58 55
59#if __APPLE__ 56#if __APPLE__
@@ -576,6 +573,22 @@ static void lib_setintegers(lua_State *L, const integer_Reg *l) {
576} /* lib_setintegers() */ 573} /* lib_setintegers() */
577 574
578 575
576#define COMPAT_X509_STORE_FREE_BUG 0x01
577
578static struct {
579 int flags;
580
581 int SSL_CTX_ex_index;
582 void (*X509_STORE_free)(X509_STORE *);
583
584 struct {
585 X509_STORE *store;
586 } tmp;
587} compat = {
588 .flags = 0,
589 .SSL_CTX_ex_index = -1,
590 .X509_STORE_free = &X509_STORE_free,
591};
579 592
580#if !HAVE_EVP_PKEY_base_id 593#if !HAVE_EVP_PKEY_base_id
581#define EVP_PKEY_base_id(key) compat_EVP_PKEY_base_id((key)) 594#define EVP_PKEY_base_id(key) compat_EVP_PKEY_base_id((key))
@@ -621,6 +634,126 @@ static void *compat_EVP_PKEY_get0(EVP_PKEY *key) {
621} /* compat_EVP_PKEY_get0() */ 634} /* compat_EVP_PKEY_get0() */
622#endif 635#endif
623 636
637/* X509_STORE_free in OpenSSL versions < 1.0.2 doesn't obey reference count */
638#define X509_STORE_free(store) \
639 (compat.X509_STORE_free)((store))
640
641static void compat_X509_STORE_free(X509_STORE *store) {
642 int i;
643
644 i = CRYPTO_add(&store->references, -1, CRYPTO_LOCK_X509_STORE);
645
646 if (i > 0)
647 return;
648
649 (X509_STORE_free)(store);
650} /* compat_X509_STORE_free() */
651
652#if !HAVE_SSL_CTX_set1_cert_store
653#define SSL_CTX_set1_cert_store(ctx, store) \
654 compat_SSL_CTX_set1_cert_store((ctx), (store))
655
656static void compat_SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store) {
657 int n;
658
659 /*
660 * This isn't thead-safe, but using X509_STORE or SSL_CTX objects
661 * from different threads isn't safe generally.
662 */
663 if (ctx->cert_store) {
664 X509_STORE_free(ctx->cert_store);
665 ctx->cert_store = NULL;
666 }
667
668 n = store->references;
669
670 SSL_CTX_set_cert_store(ctx, store);
671
672 if (n == store->references)
673 CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
674} /* compat_SSL_CTX_set1_cert_store() */
675#endif
676
677static void compat_SSL_CTX_onfree(void *_ctx, void *data NOTUSED, CRYPTO_EX_DATA *ad NOTUSED, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) {
678 SSL_CTX *ctx = _ctx;
679
680 if (ctx->cert_store) {
681 X509_STORE_free(ctx->cert_store);
682 ctx->cert_store = NULL;
683 }
684} /* compat_SSL_CTX_onfree() */
685
686/* helper routine to determine if X509_STORE_free obeys reference count */
687static void compat_init_X509_STORE_onfree(void *store, void *data NOTUSED, CRYPTO_EX_DATA *ad NOTUSED, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) {
688 /* unfortunately there's no way to remove a handler */
689 if (store != compat.tmp.store)
690 return;
691
692 /* signal that we were freed by nulling our reference */
693 compat.tmp.store = NULL;
694} /* compat_init_X509_STORE_onfree() */
695
696static int compat_init(void) {
697 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
698 static volatile sig_atomic_t done;
699 int error;
700
701 if ((error = pthread_mutex_lock(&mutex)))
702 return error;
703
704 if (!done) {
705 /*
706 * Test if X509_STORE_free obeys reference counts.
707 */
708 if (-1 == CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, 0, NULL, NULL, NULL, &compat_init_X509_STORE_onfree))
709 goto sslerr;
710
711 if (!(compat.tmp.store = X509_STORE_new()))
712 goto sslerr;
713
714 CRYPTO_add(&compat.tmp.store->references, 1, CRYPTO_LOCK_X509_STORE);
715 X509_STORE_free(compat.tmp.store);
716
717 if (compat.tmp.store) {
718 X509_STORE_free(compat.tmp.store);
719 assert(compat.tmp.store == NULL);
720 compat.tmp.store = NULL;
721 } else {
722 /*
723 * If X509_STORE_free does NOT obey reference
724 * counts, then make sure that our fixed version is
725 * called on SSL_CTX destruction. Note that this
726 * won't fix code which doesn't properly obey the
727 * reference counts when setting the cert_store
728 * member.
729 */
730 if (-1 == CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, 0, NULL, NULL, NULL, &compat_SSL_CTX_onfree))
731 goto sslerr;
732
733 compat.flags |= COMPAT_X509_STORE_FREE_BUG;
734 }
735
736 done = 1;
737 }
738epilog:
739 if (compat.tmp.store) {
740 X509_STORE_free(compat.tmp.store);
741 compat.tmp.store = NULL;
742 }
743
744 pthread_mutex_unlock(&mutex);
745
746 return 0;
747sslerr:
748 error = -1;
749
750 goto epilog;
751syserr:
752 error = errno;
753
754 goto epilog;
755} /* compat_init() */
756
624 757
625typedef int auxref_t; 758typedef int auxref_t;
626typedef int auxtype_t; 759typedef int auxtype_t;
@@ -4699,8 +4832,7 @@ static int sx_setStore(lua_State *L) {
4699 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); 4832 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
4700 X509_STORE *store = checksimple(L, 2, X509_STORE_CLASS); 4833 X509_STORE *store = checksimple(L, 2, X509_STORE_CLASS);
4701 4834
4702 SSL_CTX_set_cert_store(ctx, store); 4835 SSL_CTX_set1_cert_store(ctx, store);
4703 CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
4704 4836
4705 lua_pushboolean(L, 1); 4837 lua_pushboolean(L, 1);
4706 4838
@@ -6251,6 +6383,15 @@ static void initall(lua_State *L) {
6251 } 6383 }
6252 } 6384 }
6253 6385
6386 /* TODO: Move down to after SSL_load_error_strings */
6387 if ((error = compat_init())) {
6388 if (error == -1) {
6389 throwssl(L, "openssl.init");
6390 } else {
6391 luaL_error(L, "openssl.init: %s", xstrerror(error));
6392 }
6393 }
6394
6254 pthread_mutex_lock(&mutex); 6395 pthread_mutex_lock(&mutex);
6255 6396
6256 if (!initssl) { 6397 if (!initssl) {