summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorwilliam <william@25thandclement.com>2015-04-09 20:53:43 -0700
committerwilliam <william@25thandclement.com>2015-04-09 20:53:43 -0700
commit55da052192e151ee055e62a378d6ebdbdcbe5087 (patch)
treeddc306d844f2bad8cc43cc6f800f05fc20e23134 /src
parentc191551c53211db38976183b821f2df12a0f3b7c (diff)
downloadluaossl-55da052192e151ee055e62a378d6ebdbdcbe5087.tar.gz
luaossl-55da052192e151ee055e62a378d6ebdbdcbe5087.tar.bz2
luaossl-55da052192e151ee055e62a378d6ebdbdcbe5087.zip
refactor and fixup some interfaces, and begin to flesh out ALPN selection callback
Diffstat (limited to 'src')
-rw-r--r--src/openssl.c187
1 files changed, 148 insertions, 39 deletions
diff --git a/src/openssl.c b/src/openssl.c
index 4e0b898..3465922 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -424,6 +424,24 @@ static void checkprotos(luaL_Buffer *B, lua_State *L, int index) {
424 } 424 }
425} /* checkprotos() */ 425} /* checkprotos() */
426 426
427static void pushprotos(lua_State *L, const unsigned char *p, size_t n) {
428 const unsigned char *pe = &p[n];
429 int i = 0;
430
431 lua_newtable(L);
432
433 while (p < pe) {
434 n = *p++;
435
436 if ((size_t)(pe - p) < n)
437 luaL_error(L, "corrupt ALPN protocol list (%zu > %zu)", n, (size_t)(pe - p));
438
439 lua_pushlstring(L, (const void *)p, n);
440 lua_rawseti(L, -2, ++i);
441 p += n;
442 }
443} /* pushprotos() */
444
427 445
428static _Bool getfield(lua_State *L, int index, const char *k) { 446static _Bool getfield(lua_State *L, int index, const char *k) {
429 lua_getfield(L, index, k); 447 lua_getfield(L, index, k);
@@ -604,15 +622,44 @@ static void *compat_EVP_PKEY_get0(EVP_PKEY *key) {
604#endif 622#endif
605 623
606 624
625typedef int auxref_t;
626typedef int auxtype_t;
627
628static void auxL_unref(lua_State *L, auxref_t *ref) {
629 luaL_unref(L, LUA_REGISTRYINDEX, *ref);
630 *ref = LUA_NOREF;
631} /* auxL_unref() */
632
633static void auxL_ref(lua_State *L, int index, auxref_t *ref) {
634 auxL_unref(L, ref);
635 lua_pushvalue(L, index);
636 *ref = luaL_ref(L, LUA_REGISTRYINDEX);
637} /* auxL_ref() */
638
639static auxtype_t auxL_getref(lua_State *L, auxref_t ref) {
640 if (ref == LUA_NOREF || ref == LUA_REFNIL) {
641 lua_pushnil(L);
642 } else {
643 lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
644 }
645
646 return lua_type(L, -1);
647} /* auxL_getref() */
648
649
607struct ex_state { 650struct ex_state {
608 lua_State *mainthread; 651 lua_State *L;
609 LIST_HEAD(, ex_data) data; 652 LIST_HEAD(, ex_data) data;
610}; /* struct ex_state */ 653}; /* struct ex_state */
611 654
655#ifndef EX_DATA_MAXARGS
656#define EX_DATA_MAXARGS 4
657#endif
658
612struct ex_data { 659struct ex_data {
613 struct ex_state *state; 660 struct ex_state *state;
614 int refs; 661 int refs;
615 int arg[4]; 662 auxref_t arg[EX_DATA_MAXARGS];
616 LIST_ENTRY(ex_data) le; 663 LIST_ENTRY(ex_data) le;
617}; /* struct ex_data */ 664}; /* struct ex_data */
618 665
@@ -621,40 +668,47 @@ enum {
621}; 668};
622 669
623static struct ex_type { 670static struct ex_type {
624 int class_index; 671 int class_index; /* OpenSSL object type identifier */
625 int index; 672 int index; /* OpenSSL-allocated external data identifier */
626 void *(*get_ex_data)(); 673 void *(*get_ex_data)();
627 int (*set_ex_data)(); 674 int (*set_ex_data)();
628} ex_type[] = { 675} 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 }, 676 [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data },
630}; 677};
631 678
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) { 679static int ex_ondup(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; 680 struct ex_data **data = from_d;
634 681
635 if (*data) 682 if (*data)
636 (*data)->refs++; 683 (*data)->refs++;
637 684
638 return 1; 685 return 1;
639} /* ex_data_dup() */ 686} /* ex_ondup() */
640 687
641static void ex_data_free(void *parent NOTUSED, void *_data, CRYPTO_EX_DATA *ad NOTUSED, int idx NOTUSED, long argl NOTUSED, void *argp NOTUSED) { 688static void ex_onfree(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; 689 struct ex_data *data = _data;
643 690
644 if (!data || --data->refs > 0) 691 if (!data || --data->refs > 0)
645 return; 692 return;
646 693
647 if (data->state) 694 if (data->state) {
695 int i;
696
697 for (i = 0; i < (int)countof(data->arg); i++) {
698 auxL_unref(data->state->L, &data->arg[i]);
699 }
700
648 LIST_REMOVE(data, le); 701 LIST_REMOVE(data, le);
702 }
649 703
650 free(data); 704 free(data);
651} /* ex_data_free() */ 705} /* ex_onfree() */
652 706
653static int ex_initonce(void) { 707static int ex_initonce(void) {
654 struct ex_type *type; 708 struct ex_type *type;
655 709
656 for (type = ex_type; type < endof(ex_type); type++) { 710 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))) 711 if (-1 == (type->index = CRYPTO_get_ex_new_index(type->class_index, 0, NULL, NULL, &ex_ondup, &ex_onfree)))
658 return -1; 712 return -1;
659 }; 713 };
660 714
@@ -676,22 +730,27 @@ static int ex__gc(lua_State *L) {
676 return 0; 730 return 0;
677} /* ex__gc() */ 731} /* ex__gc() */
678 732
679static void ex_init(lua_State *L) { 733static void ex_newstate(lua_State *L) {
680 struct ex_state *state; 734 struct ex_state *state;
681 struct lua_State *thr; 735 struct lua_State *thr;
682 736
683 state = prepudata(L, sizeof *state, NULL, &ex__gc); 737 state = prepudata(L, sizeof *state, NULL, &ex__gc);
684 LIST_INIT(&state->data); 738 LIST_INIT(&state->data);
685 739
740 /*
741 * XXX: Don't reuse mainthread because if an error occurs in a
742 * callback Lua might longjmp across the OpenSSL call stack.
743 * Instead, we'll install our own panic handlers.
744 */
686#if defined LUA_RIDX_MAINTHREAD 745#if defined LUA_RIDX_MAINTHREAD
687 lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); 746 lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD);
688 state->mainthread = lua_tothread(L, -1); 747 state->L = lua_tothread(L, -1);
689 lua_pop(L, 1); 748 lua_pop(L, 1);
690#else 749#else
691 lua_pushvalue(L, -1); 750 lua_pushvalue(L, -1);
692 thr = lua_newthread(L); 751 thr = lua_newthread(L);
693 lua_settable(L, LUA_REGISTRYINDEX); 752 lua_settable(L, LUA_REGISTRYINDEX);
694 state->mainthread = thr; 753 state->L = thr;
695#endif 754#endif
696 755
697 lua_pushcfunction(L, &ex__gc); 756 lua_pushcfunction(L, &ex__gc);
@@ -699,9 +758,9 @@ static void ex_init(lua_State *L) {
699 lua_settable(L, LUA_REGISTRYINDEX); 758 lua_settable(L, LUA_REGISTRYINDEX);
700 759
701 lua_pop(L, 1); 760 lua_pop(L, 1);
702} /* ex_init() */ 761} /* ex_newstate() */
703 762
704static struct ex_state *ex_get(lua_State *L) { 763static struct ex_state *ex_getstate(lua_State *L) {
705 struct ex_state *state; 764 struct ex_state *state;
706 765
707 lua_pushcfunction(L, &ex__gc); 766 lua_pushcfunction(L, &ex__gc);
@@ -712,12 +771,12 @@ static struct ex_state *ex_get(lua_State *L) {
712 lua_pop(L, 1); 771 lua_pop(L, 1);
713 772
714 return state; 773 return state;
715} /* ex_get() */ 774} /* ex_getstate() */
716 775
717static int ex_data_get(lua_State **L, int _type, void *obj) { 776static size_t ex_getdata(lua_State **L, int _type, void *obj) {
718 struct ex_type *type = &ex_type[_type]; 777 struct ex_type *type = &ex_type[_type];
719 struct ex_data *data; 778 struct ex_data *data;
720 int i; 779 size_t i;
721 780
722 if (!(data = type->get_ex_data(obj, type->index))) 781 if (!(data = type->get_ex_data(obj, type->index)))
723 return 0; 782 return 0;
@@ -725,28 +784,31 @@ static int ex_data_get(lua_State **L, int _type, void *obj) {
725 return 0; 784 return 0;
726 785
727 if (!*L) 786 if (!*L)
728 *L = data->state->mainthread; 787 *L = data->state->L;
788
789 if (!lua_checkstack(*L, countof(data->arg)))
790 return 0;
729 791
730 for (i = 0; i < (int)countof(data->arg); i++) { 792 for (i = 0; i < countof(data->arg) && data->arg[i] != LUA_NOREF; i++) {
731 lua_rawgeti(*L, LUA_REGISTRYINDEX, data->arg[i]); 793 lua_rawgeti(*L, LUA_REGISTRYINDEX, data->arg[i]);
732 } 794 }
733 795
734 return i; 796 return i;
735} /* ex_data_get() */ 797} /* ex_getdata() */
736 798
737static int ex_data_set(lua_State *L, int _type, void *obj, int n) { 799/* returns 0 on success, otherwise error (>0 == errno, -1 == OpenSSL error) */
800static int ex_setdata(lua_State *L, int _type, void *obj, size_t n) {
738 struct ex_type *type = &ex_type[_type]; 801 struct ex_type *type = &ex_type[_type];
739 struct ex_state *state; 802 struct ex_state *state;
740 struct ex_data *data; 803 struct ex_data *data;
741 int i, j; 804 size_t i, j;
742 805
743 if ((data = type->get_ex_data(obj, type->index)) && data->state) { 806 if ((data = type->get_ex_data(obj, type->index)) && data->state) {
744 for (i = 0; i < (int)countof(data->arg); i++) { 807 for (i = 0; i < countof(data->arg); i++) {
745 luaL_unref(L, LUA_REGISTRYINDEX, data->arg[i]); 808 auxL_unref(L, &data->arg[i]);
746 data->arg[i] = LUA_NOREF;
747 } 809 }
748 } else { 810 } else {
749 state = ex_get(L); 811 state = ex_getstate(L);
750 812
751 if (!(data = malloc(sizeof *data))) 813 if (!(data = malloc(sizeof *data)))
752 return errno; 814 return errno;
@@ -756,20 +818,19 @@ static int ex_data_set(lua_State *L, int _type, void *obj, int n) {
756 818
757 data->state = state; 819 data->state = state;
758 data->refs = 1; 820 data->refs = 1;
759 for (i = 0; i < (int)countof(data->arg); i++) 821 for (i = 0; i < countof(data->arg); i++)
760 data->arg[i] = LUA_NOREF; 822 data->arg[i] = LUA_NOREF;
761 LIST_INSERT_HEAD(&state->data, data, le); 823 LIST_INSERT_HEAD(&state->data, data, le);
762 } 824 }
763 825
764 for (i = n, j = 0; i > 0 && j < (int)countof(data->arg); i--, j++) { 826 for (i = n, j = 0; i > 0 && j < countof(data->arg); i--, j++) {
765 lua_pushvalue(L, -i); 827 auxL_ref(L, -(int)i, &data->arg[j]);
766 data->arg[j] = luaL_ref(L, LUA_REGISTRYINDEX);
767 } 828 }
768 829
769 lua_pop(L, n); 830 lua_pop(L, n);
770 831
771 return 0; 832 return 0;
772} /* ex_data_set() */ 833} /* ex_setdata() */
773 834
774static void initall(lua_State *L); 835static void initall(lua_State *L);
775 836
@@ -4800,13 +4861,44 @@ static int sx_setAlpnProtos(lua_State *L) {
4800#endif 4861#endif
4801 4862
4802#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB 4863#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) { 4864static SSL *ssl_push(lua_State *, SSL *);
4865
4866static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) {
4867 SSL_CTX *ctx = _ctx;
4804 lua_State *L = NULL; 4868 lua_State *L = NULL;
4805 int n; 4869 size_t n;
4870 int top, status;
4806 4871
4807 n = ex_data_get(&L, EX_SSL_CTX_ALPN_SELECT_CB, ssl); 4872 if (0 == (n = ex_getdata(&L, EX_SSL_CTX_ALPN_SELECT_CB, ctx)))
4873 return SSL_TLSEXT_ERR_ALERT_FATAL;
4808 4874
4809 return 0; 4875 top = lua_gettop(L) - n;
4876
4877 /* TODO: Install temporary panic handler to catch OOM errors */
4878
4879 /* pass the SSL object as first argument */
4880 ssl_push(L, ssl);
4881 pushprotos(L, in, inlen);
4882
4883 /* TODO: lua_rotate ssl and protocols table into position. */
4884
4885 if (LUA_OK != (status = lua_pcall(L, 2 + (n - 1), 1, 0)))
4886 goto fatal;
4887
4888 /* TODO: check return value */
4889 (void)out; (void)outlen;
4890
4891 lua_settop(L, top);
4892
4893 return SSL_TLSEXT_ERR_OK;
4894fatal:
4895 lua_settop(L, top);
4896
4897 return SSL_TLSEXT_ERR_ALERT_FATAL;
4898noack:
4899 lua_settop(L, top);
4900
4901 return SSL_TLSEXT_ERR_NOACK;
4810} /* sx_setAlpnSelect_cb() */ 4902} /* sx_setAlpnSelect_cb() */
4811 4903
4812static int sx_setAlpnSelect(lua_State *L) { 4904static int sx_setAlpnSelect(lua_State *L) {
@@ -4815,9 +4907,17 @@ static int sx_setAlpnSelect(lua_State *L) {
4815 int error; 4907 int error;
4816 4908
4817 luaL_checktype(L, 2, LUA_TFUNCTION); 4909 luaL_checktype(L, 2, LUA_TFUNCTION);
4818 error = ex_data_set(L, EX_SSL_CTX_ALPN_SELECT_CB, ctx, 1); 4910 if ((error = ex_setdata(L, EX_SSL_CTX_ALPN_SELECT_CB, ctx, 1))) {
4911 if (error > 0) {
4912 return luaL_error(L, "unable to set ALPN protocol selection callback: %s", xstrerror(error));
4913 } else if (!ERR_peek_error()) {
4914 return luaL_error(L, "unable to set ALPN protocol selection callback: Unknown internal error");
4915 } else {
4916 return throwssl(L, "ssl.context:setAlpnSelect");
4917 }
4918 }
4819 4919
4820 SSL_CTX_set_alpn_select_cb(ctx, &sx_setAlpnSelect_cb, NULL); 4920 SSL_CTX_set_alpn_select_cb(ctx, &sx_setAlpnSelect_cb, ctx);
4821 4921
4822 lua_pushboolean(L, 1); 4922 lua_pushboolean(L, 1);
4823 4923
@@ -4936,6 +5036,15 @@ int luaopen__openssl_ssl_context(lua_State *L) {
4936 * 5036 *
4937 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 5037 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4938 5038
5039static SSL *ssl_push(lua_State *L, SSL *ssl) {
5040 SSL **ud = prepsimple(L, SSL_CLASS);
5041
5042 CRYPTO_add(&(ssl)->references, 1, CRYPTO_LOCK_SSL);
5043 *ud = ssl;
5044
5045 return *ud;
5046} /* ssl_push() */
5047
4939static int ssl_new(lua_State *L) { 5048static int ssl_new(lua_State *L) {
4940 lua_pushnil(L); 5049 lua_pushnil(L);
4941 5050
@@ -6168,7 +6277,7 @@ static void initall(lua_State *L) {
6168 6277
6169 pthread_mutex_unlock(&mutex); 6278 pthread_mutex_unlock(&mutex);
6170 6279
6171 ex_init(L); 6280 ex_newstate(L);
6172 6281
6173 addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable); 6282 addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable);
6174 addclass(L, PKEY_CLASS, pk_methods, pk_metatable); 6283 addclass(L, PKEY_CLASS, pk_methods, pk_metatable);