summaryrefslogtreecommitdiff
path: root/src/openssl.c
diff options
context:
space:
mode:
authorwilliam <william@25thandclement.com>2015-03-09 10:15:49 -0700
committerwilliam <william@25thandclement.com>2015-03-09 10:15:49 -0700
commitc191551c53211db38976183b821f2df12a0f3b7c (patch)
treeb1d67ab18ece86421bb03626bdd2a57676ef24e0 /src/openssl.c
parent1a8c2c902dfa982fd387279dfe99dd270d2ecf89 (diff)
downloadluaossl-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.c232
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
607struct ex_state {
608 lua_State *mainthread;
609 LIST_HEAD(, ex_data) data;
610}; /* struct ex_state */
611
612struct 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
619enum {
620 EX_SSL_CTX_ALPN_SELECT_CB,
621};
622
623static 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
632static 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
641static 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
653static 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
664static 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
679static 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
704static 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
717static 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
737static 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
584static void initall(lua_State *L); 774static 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
4803static 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
4812static 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
4613static int sx__gc(lua_State *L) { 4829static 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
5809static struct { 6025static 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);