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 | |
| 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
| -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); |
