diff options
author | william <william@25thandclement.com> | 2015-04-09 20:53:43 -0700 |
---|---|---|
committer | william <william@25thandclement.com> | 2015-04-09 20:53:43 -0700 |
commit | 55da052192e151ee055e62a378d6ebdbdcbe5087 (patch) | |
tree | ddc306d844f2bad8cc43cc6f800f05fc20e23134 /src | |
parent | c191551c53211db38976183b821f2df12a0f3b7c (diff) | |
download | luaossl-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.c | 187 |
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 | ||
427 | static 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 | ||
428 | static _Bool getfield(lua_State *L, int index, const char *k) { | 446 | static _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 | ||
625 | typedef int auxref_t; | ||
626 | typedef int auxtype_t; | ||
627 | |||
628 | static void auxL_unref(lua_State *L, auxref_t *ref) { | ||
629 | luaL_unref(L, LUA_REGISTRYINDEX, *ref); | ||
630 | *ref = LUA_NOREF; | ||
631 | } /* auxL_unref() */ | ||
632 | |||
633 | static 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 | |||
639 | static 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 | |||
607 | struct ex_state { | 650 | struct 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 | |||
612 | struct ex_data { | 659 | struct 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 | ||
623 | static struct ex_type { | 670 | static 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 | ||
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) { | 679 | static 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 | ||
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) { | 688 | static 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 | ||
653 | static int ex_initonce(void) { | 707 | static 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 | ||
679 | static void ex_init(lua_State *L) { | 733 | static 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 | ||
704 | static struct ex_state *ex_get(lua_State *L) { | 763 | static 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 | ||
717 | static int ex_data_get(lua_State **L, int _type, void *obj) { | 776 | static 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 | ||
737 | static 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) */ |
800 | static 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 | ||
774 | static void initall(lua_State *L); | 835 | static 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 |
4803 | static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { | 4864 | static SSL *ssl_push(lua_State *, SSL *); |
4865 | |||
4866 | static 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; | ||
4894 | fatal: | ||
4895 | lua_settop(L, top); | ||
4896 | |||
4897 | return SSL_TLSEXT_ERR_ALERT_FATAL; | ||
4898 | noack: | ||
4899 | lua_settop(L, top); | ||
4900 | |||
4901 | return SSL_TLSEXT_ERR_NOACK; | ||
4810 | } /* sx_setAlpnSelect_cb() */ | 4902 | } /* sx_setAlpnSelect_cb() */ |
4811 | 4903 | ||
4812 | static int sx_setAlpnSelect(lua_State *L) { | 4904 | static 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 | ||
5039 | static 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 | |||
4939 | static int ssl_new(lua_State *L) { | 5048 | static 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); |