diff options
Diffstat (limited to 'src/openssl.c')
| -rw-r--r-- | src/openssl.c | 155 |
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 | |||
| 578 | static 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 | |||
| 641 | static 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 | |||
| 656 | static 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 | |||
| 677 | static 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 */ | ||
| 687 | static 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 | |||
| 696 | static 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 | } | ||
| 738 | epilog: | ||
| 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; | ||
| 747 | sslerr: | ||
| 748 | error = -1; | ||
| 749 | |||
| 750 | goto epilog; | ||
| 751 | syserr: | ||
| 752 | error = errno; | ||
| 753 | |||
| 754 | goto epilog; | ||
| 755 | } /* compat_init() */ | ||
| 756 | |||
| 624 | 757 | ||
| 625 | typedef int auxref_t; | 758 | typedef int auxref_t; |
| 626 | typedef int auxtype_t; | 759 | typedef 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) { |
