diff options
| author | william <william@25thandclement.com> | 2015-03-09 10:15:49 -0700 |
|---|---|---|
| committer | william <william@25thandclement.com> | 2015-03-09 10:15:49 -0700 |
| commit | c191551c53211db38976183b821f2df12a0f3b7c (patch) | |
| tree | b1d67ab18ece86421bb03626bdd2a57676ef24e0 /src | |
| parent | 1a8c2c902dfa982fd387279dfe99dd270d2ecf89 (diff) | |
| download | luaossl-c191551c53211db38976183b821f2df12a0f3b7c.tar.gz luaossl-c191551c53211db38976183b821f2df12a0f3b7c.tar.bz2 luaossl-c191551c53211db38976183b821f2df12a0f3b7c.zip | |
early external data API work
Diffstat (limited to 'src')
| -rw-r--r-- | src/openssl.c | 232 |
1 files changed, 229 insertions, 3 deletions
diff --git a/src/openssl.c b/src/openssl.c index c1b5436..4e0b898 100644 --- a/src/openssl.c +++ b/src/openssl.c | |||
| @@ -87,6 +87,10 @@ | |||
| 87 | #define HAVE_SSL_CTX_SET_ALPN_PROTOS (OPENSSL_VERSION_NUMBER >= 0x1000200fL) | 87 | #define HAVE_SSL_CTX_SET_ALPN_PROTOS (OPENSSL_VERSION_NUMBER >= 0x1000200fL) |
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | #ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB | ||
| 91 | #define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS | ||
| 92 | #endif | ||
| 93 | |||
| 90 | #ifndef HAVE_SSL_SET_ALPN_PROTOS | 94 | #ifndef HAVE_SSL_SET_ALPN_PROTOS |
| 91 | #define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS | 95 | #define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS |
| 92 | #endif | 96 | #endif |
| @@ -99,6 +103,25 @@ | |||
| 99 | #define STRERROR_R_CHAR_P (defined __GLIBC__ && (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) | 103 | #define STRERROR_R_CHAR_P (defined __GLIBC__ && (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) |
| 100 | #endif | 104 | #endif |
| 101 | 105 | ||
| 106 | #ifndef LIST_HEAD | ||
| 107 | #define LIST_HEAD(name, type) struct name { struct type *lh_first; } | ||
| 108 | #define LIST_ENTRY(type) struct { struct type *le_next, **le_prev; } | ||
| 109 | #define LIST_INIT(head) do { LIST_FIRST((head)) = NULL; } while (0) | ||
| 110 | #define LIST_FIRST(head) ((head)->lh_first) | ||
| 111 | #define LIST_NEXT(elm, field) ((elm)->field.le_next) | ||
| 112 | #define LIST_REMOVE(elm, field) do { \ | ||
| 113 | if (LIST_NEXT((elm), field) != NULL) \ | ||
| 114 | LIST_NEXT((elm), field)->field.le_prev = (elm)->field.le_prev; \ | ||
| 115 | *(elm)->field.le_prev = LIST_NEXT((elm), field); \ | ||
| 116 | } while (0) | ||
| 117 | #define LIST_INSERT_HEAD(head, elm, field) do { | ||
| 118 | if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ | ||
| 119 | LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \ | ||
| 120 | LIST_FIRST((head)) = (elm); \ | ||
| 121 | (elm)->field.le_prev = &LIST_FIRST((head)); \ | ||
| 122 | } while (0) | ||
| 123 | #endif | ||
| 124 | |||
| 102 | #define BIGNUM_CLASS "BIGNUM*" | 125 | #define BIGNUM_CLASS "BIGNUM*" |
| 103 | #define PKEY_CLASS "EVP_PKEY*" | 126 | #define PKEY_CLASS "EVP_PKEY*" |
| 104 | #define X509_NAME_CLASS "X509_NAME*" | 127 | #define X509_NAME_CLASS "X509_NAME*" |
| @@ -581,6 +604,173 @@ static void *compat_EVP_PKEY_get0(EVP_PKEY *key) { | |||
| 581 | #endif | 604 | #endif |
| 582 | 605 | ||
| 583 | 606 | ||
| 607 | struct ex_state { | ||
| 608 | lua_State *mainthread; | ||
| 609 | LIST_HEAD(, ex_data) data; | ||
| 610 | }; /* struct ex_state */ | ||
| 611 | |||
| 612 | struct ex_data { | ||
| 613 | struct ex_state *state; | ||
| 614 | int refs; | ||
| 615 | int arg[4]; | ||
| 616 | LIST_ENTRY(ex_data) le; | ||
| 617 | }; /* struct ex_data */ | ||
| 618 | |||
| 619 | enum { | ||
| 620 | EX_SSL_CTX_ALPN_SELECT_CB, | ||
| 621 | }; | ||
| 622 | |||
| 623 | static struct ex_type { | ||
| 624 | int class_index; | ||
| 625 | int index; | ||
| 626 | void *(*get_ex_data)(); | ||
| 627 | int (*set_ex_data)(); | ||
| 628 | } ex_type[] = { | ||
| 629 | [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data }, | ||
| 630 | }; | ||
| 631 | |||
| 632 | static int ex_data_dup(CRYPTO_EX_DATA *to NOTUSED, CRYPTO_EX_DATA *from NOTUSED, void *from_d, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { | ||
| 633 | struct ex_data **data = from_d; | ||
| 634 | |||
| 635 | if (*data) | ||
| 636 | (*data)->refs++; | ||
| 637 | |||
| 638 | return 1; | ||
| 639 | } /* ex_data_dup() */ | ||
| 640 | |||
| 641 | static void ex_data_free(void *parent NOTUSED, void *_data, CRYPTO_EX_DATA *ad NOTUSED, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { | ||
| 642 | struct ex_data *data = _data; | ||
| 643 | |||
| 644 | if (!data || --data->refs > 0) | ||
| 645 | return; | ||
| 646 | |||
| 647 | if (data->state) | ||
| 648 | LIST_REMOVE(data, le); | ||
| 649 | |||
| 650 | free(data); | ||
| 651 | } /* ex_data_free() */ | ||
| 652 | |||
| 653 | static int ex_initonce(void) { | ||
| 654 | struct ex_type *type; | ||
| 655 | |||
| 656 | for (type = ex_type; type < endof(ex_type); type++) { | ||
| 657 | if (-1 == (type->index = CRYPTO_get_ex_new_index(type->class_index, 0, NULL, NULL, &ex_data_dup, &ex_data_free))) | ||
| 658 | return -1; | ||
| 659 | }; | ||
| 660 | |||
| 661 | return 0; | ||
| 662 | } /* ex_initonce() */ | ||
| 663 | |||
| 664 | static int ex__gc(lua_State *L) { | ||
| 665 | struct ex_state *state = lua_touserdata(L, 1); | ||
| 666 | struct ex_data *data; | ||
| 667 | |||
| 668 | if (!state) | ||
| 669 | return 0; | ||
| 670 | |||
| 671 | /* invalidate back references to Lua state */ | ||
| 672 | for (data = LIST_FIRST(&state->data); data; data = LIST_NEXT(data, le)) { | ||
| 673 | data->state = NULL; | ||
| 674 | } | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | } /* ex__gc() */ | ||
| 678 | |||
| 679 | static void ex_init(lua_State *L) { | ||
| 680 | struct ex_state *state; | ||
| 681 | struct lua_State *thr; | ||
| 682 | |||
| 683 | state = prepudata(L, sizeof *state, NULL, &ex__gc); | ||
| 684 | LIST_INIT(&state->data); | ||
| 685 | |||
| 686 | #if defined LUA_RIDX_MAINTHREAD | ||
| 687 | lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); | ||
| 688 | state->mainthread = lua_tothread(L, -1); | ||
| 689 | lua_pop(L, 1); | ||
| 690 | #else | ||
| 691 | lua_pushvalue(L, -1); | ||
| 692 | thr = lua_newthread(L); | ||
| 693 | lua_settable(L, LUA_REGISTRYINDEX); | ||
| 694 | state->mainthread = thr; | ||
| 695 | #endif | ||
| 696 | |||
| 697 | lua_pushcfunction(L, &ex__gc); | ||
| 698 | lua_pushvalue(L, -2); | ||
| 699 | lua_settable(L, LUA_REGISTRYINDEX); | ||
| 700 | |||
| 701 | lua_pop(L, 1); | ||
| 702 | } /* ex_init() */ | ||
| 703 | |||
| 704 | static struct ex_state *ex_get(lua_State *L) { | ||
| 705 | struct ex_state *state; | ||
| 706 | |||
| 707 | lua_pushcfunction(L, &ex__gc); | ||
| 708 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
| 709 | |||
| 710 | luaL_checktype(L, -1, LUA_TUSERDATA); | ||
| 711 | state = lua_touserdata(L, -1); | ||
| 712 | lua_pop(L, 1); | ||
| 713 | |||
| 714 | return state; | ||
| 715 | } /* ex_get() */ | ||
| 716 | |||
| 717 | static int ex_data_get(lua_State **L, int _type, void *obj) { | ||
| 718 | struct ex_type *type = &ex_type[_type]; | ||
| 719 | struct ex_data *data; | ||
| 720 | int i; | ||
| 721 | |||
| 722 | if (!(data = type->get_ex_data(obj, type->index))) | ||
| 723 | return 0; | ||
| 724 | if (!data->state) | ||
| 725 | return 0; | ||
| 726 | |||
| 727 | if (!*L) | ||
| 728 | *L = data->state->mainthread; | ||
| 729 | |||
| 730 | for (i = 0; i < (int)countof(data->arg); i++) { | ||
| 731 | lua_rawgeti(*L, LUA_REGISTRYINDEX, data->arg[i]); | ||
| 732 | } | ||
| 733 | |||
| 734 | return i; | ||
| 735 | } /* ex_data_get() */ | ||
| 736 | |||
| 737 | static int ex_data_set(lua_State *L, int _type, void *obj, int n) { | ||
| 738 | struct ex_type *type = &ex_type[_type]; | ||
| 739 | struct ex_state *state; | ||
| 740 | struct ex_data *data; | ||
| 741 | int i, j; | ||
| 742 | |||
| 743 | if ((data = type->get_ex_data(obj, type->index)) && data->state) { | ||
| 744 | for (i = 0; i < (int)countof(data->arg); i++) { | ||
| 745 | luaL_unref(L, LUA_REGISTRYINDEX, data->arg[i]); | ||
| 746 | data->arg[i] = LUA_NOREF; | ||
| 747 | } | ||
| 748 | } else { | ||
| 749 | state = ex_get(L); | ||
| 750 | |||
| 751 | if (!(data = malloc(sizeof *data))) | ||
| 752 | return errno; | ||
| 753 | |||
| 754 | if (!type->set_ex_data(obj, type->index, data)) | ||
| 755 | return -1; | ||
| 756 | |||
| 757 | data->state = state; | ||
| 758 | data->refs = 1; | ||
| 759 | for (i = 0; i < (int)countof(data->arg); i++) | ||
| 760 | data->arg[i] = LUA_NOREF; | ||
| 761 | LIST_INSERT_HEAD(&state->data, data, le); | ||
| 762 | } | ||
| 763 | |||
| 764 | for (i = n, j = 0; i > 0 && j < (int)countof(data->arg); i--, j++) { | ||
| 765 | lua_pushvalue(L, -i); | ||
| 766 | data->arg[j] = luaL_ref(L, LUA_REGISTRYINDEX); | ||
| 767 | } | ||
| 768 | |||
| 769 | lua_pop(L, n); | ||
| 770 | |||
| 771 | return 0; | ||
| 772 | } /* ex_data_set() */ | ||
| 773 | |||
| 584 | static void initall(lua_State *L); | 774 | static void initall(lua_State *L); |
| 585 | 775 | ||
| 586 | 776 | ||
| @@ -4609,6 +4799,32 @@ static int sx_setAlpnProtos(lua_State *L) { | |||
| 4609 | } /* sx_setAlpnProtos() */ | 4799 | } /* sx_setAlpnProtos() */ |
| 4610 | #endif | 4800 | #endif |
| 4611 | 4801 | ||
| 4802 | #if HAVE_SSL_CTX_SET_ALPN_SELECT_CB | ||
| 4803 | static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { | ||
| 4804 | lua_State *L = NULL; | ||
| 4805 | int n; | ||
| 4806 | |||
| 4807 | n = ex_data_get(&L, EX_SSL_CTX_ALPN_SELECT_CB, ssl); | ||
| 4808 | |||
| 4809 | return 0; | ||
| 4810 | } /* sx_setAlpnSelect_cb() */ | ||
| 4811 | |||
| 4812 | static int sx_setAlpnSelect(lua_State *L) { | ||
| 4813 | SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); | ||
| 4814 | struct ex_data *data; | ||
| 4815 | int error; | ||
| 4816 | |||
| 4817 | luaL_checktype(L, 2, LUA_TFUNCTION); | ||
| 4818 | error = ex_data_set(L, EX_SSL_CTX_ALPN_SELECT_CB, ctx, 1); | ||
| 4819 | |||
| 4820 | SSL_CTX_set_alpn_select_cb(ctx, &sx_setAlpnSelect_cb, NULL); | ||
| 4821 | |||
| 4822 | lua_pushboolean(L, 1); | ||
| 4823 | |||
| 4824 | return 1; | ||
| 4825 | } /* sx_setAlpnSelect() */ | ||
| 4826 | #endif | ||
| 4827 | |||
| 4612 | 4828 | ||
| 4613 | static int sx__gc(lua_State *L) { | 4829 | static int sx__gc(lua_State *L) { |
| 4614 | SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); | 4830 | SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); |
| @@ -5803,7 +6019,7 @@ int luaopen__openssl_des(lua_State *L) { | |||
| 5803 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 6019 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 5804 | 6020 | ||
| 5805 | #ifndef HAVE_DLADDR | 6021 | #ifndef HAVE_DLADDR |
| 5806 | #define HAVE_DLADDR (!defined _AIX) | 6022 | #define HAVE_DLADDR (!defined _AIX) /* TODO: https://root.cern.ch/drupal/content/aix-and-dladdr */ |
| 5807 | #endif | 6023 | #endif |
| 5808 | 6024 | ||
| 5809 | static struct { | 6025 | static struct { |
| @@ -5847,8 +6063,8 @@ static unsigned long mt_gettid(void) { | |||
| 5847 | return _lwp_self(); | 6063 | return _lwp_self(); |
| 5848 | #else | 6064 | #else |
| 5849 | /* | 6065 | /* |
| 5850 | * pthread_t is an integer on Solaris and Linux, and a unique pointer | 6066 | * pthread_t is an integer on Solaris and Linux, an unsigned integer |
| 5851 | * on OpenBSD. | 6067 | * on AIX, and a unique pointer on OpenBSD. |
| 5852 | */ | 6068 | */ |
| 5853 | return (unsigned long)pthread_self(); | 6069 | return (unsigned long)pthread_self(); |
| 5854 | #endif | 6070 | #endif |
| @@ -5940,10 +6156,20 @@ static void initall(lua_State *L) { | |||
| 5940 | * already been configured. | 6156 | * already been configured. |
| 5941 | */ | 6157 | */ |
| 5942 | OPENSSL_config(NULL); | 6158 | OPENSSL_config(NULL); |
| 6159 | |||
| 6160 | if ((error = ex_initonce())) { | ||
| 6161 | if (error == -1) { | ||
| 6162 | throwssl(L, "openssl.init"); | ||
| 6163 | } else { | ||
| 6164 | luaL_error(L, "openssl.init: %s", xstrerror(error)); | ||
| 6165 | } | ||
| 6166 | } | ||
| 5943 | } | 6167 | } |
| 5944 | 6168 | ||
| 5945 | pthread_mutex_unlock(&mutex); | 6169 | pthread_mutex_unlock(&mutex); |
| 5946 | 6170 | ||
| 6171 | ex_init(L); | ||
| 6172 | |||
| 5947 | addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable); | 6173 | addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable); |
| 5948 | addclass(L, PKEY_CLASS, pk_methods, pk_metatable); | 6174 | addclass(L, PKEY_CLASS, pk_methods, pk_metatable); |
| 5949 | addclass(L, X509_NAME_CLASS, xn_methods, xn_metatable); | 6175 | addclass(L, X509_NAME_CLASS, xn_methods, xn_metatable); |
