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/openssl.c | |
parent | 1a8c2c902dfa982fd387279dfe99dd270d2ecf89 (diff) | |
download | luaossl-c191551c53211db38976183b821f2df12a0f3b7c.tar.gz luaossl-c191551c53211db38976183b821f2df12a0f3b7c.tar.bz2 luaossl-c191551c53211db38976183b821f2df12a0f3b7c.zip |
early external data API work
Diffstat (limited to 'src/openssl.c')
-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); |