diff options
author | william <william@25thandclement.com> | 2015-03-05 14:57:45 -0800 |
---|---|---|
committer | william <william@25thandclement.com> | 2015-03-05 14:57:45 -0800 |
commit | afeb65d5c21019132a9b7759f864f19e0ad0df43 (patch) | |
tree | 06e6842ba6444d1765a344800163d09f5e5c30be | |
parent | fe19dfb57495c54c16edbeb52eae64b01404364f (diff) | |
download | luaossl-afeb65d5c21019132a9b7759f864f19e0ad0df43.tar.gz luaossl-afeb65d5c21019132a9b7759f864f19e0ad0df43.tar.bz2 luaossl-afeb65d5c21019132a9b7759f864f19e0ad0df43.zip |
add openssl.ssl:setAlpnProtos
-rw-r--r-- | src/openssl.c | 106 |
1 files changed, 83 insertions, 23 deletions
diff --git a/src/openssl.c b/src/openssl.c index 2dee037..773930b 100644 --- a/src/openssl.c +++ b/src/openssl.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #ifndef LUAOSSL_H | 26 | #ifndef LUAOSSL_H |
27 | #define LUAOSSL_H | 27 | #define LUAOSSL_H |
28 | 28 | ||
29 | #include <limits.h> /* INT_MAX INT_MIN */ | 29 | #include <limits.h> /* INT_MAX INT_MIN UCHAR_MAX */ |
30 | #include <stdint.h> /* uintptr_t */ | 30 | #include <stdint.h> /* uintptr_t */ |
31 | #include <string.h> /* memset(3) strerror_r(3) */ | 31 | #include <string.h> /* memset(3) strerror_r(3) */ |
32 | #include <strings.h> /* strcasecmp(3) */ | 32 | #include <strings.h> /* strcasecmp(3) */ |
@@ -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_SET_ALPN_PROTOS | ||
91 | #define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS | ||
92 | #endif | ||
93 | |||
90 | #ifndef HAVE_SSL_GET0_ALPN_SELECTED | 94 | #ifndef HAVE_SSL_GET0_ALPN_SELECTED |
91 | #define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS | 95 | #define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS |
92 | #endif | 96 | #endif |
@@ -346,6 +350,45 @@ static int optencoding(lua_State *L, int index, const char *def, int allow) { | |||
346 | } /* optencoding() */ | 350 | } /* optencoding() */ |
347 | 351 | ||
348 | 352 | ||
353 | static _Bool rawgeti(lua_State *L, int index, int n) { | ||
354 | lua_rawgeti(L, index, n); | ||
355 | |||
356 | if (lua_isnil(L, -1)) { | ||
357 | lua_pop(L, 1); | ||
358 | |||
359 | return 0; | ||
360 | } else { | ||
361 | return 1; | ||
362 | } | ||
363 | } /* rawgeti() */ | ||
364 | |||
365 | |||
366 | /* check ALPN protocols and add to buffer of length-prefixed strings */ | ||
367 | static void checkprotos(luaL_Buffer *B, lua_State *L, int index) { | ||
368 | int n; | ||
369 | |||
370 | luaL_checktype(L, index, LUA_TTABLE); | ||
371 | |||
372 | for (n = 1; rawgeti(L, index, n); n++) { | ||
373 | const char *tmp; | ||
374 | size_t len; | ||
375 | |||
376 | switch (lua_type(L, -1)) { | ||
377 | case LUA_TSTRING: | ||
378 | break; | ||
379 | default: | ||
380 | luaL_argerror(L, index, "array of strings expected"); | ||
381 | } | ||
382 | |||
383 | tmp = luaL_checklstring(L, -1, &len); | ||
384 | luaL_argcheck(L, len > 0 && len <= UCHAR_MAX, index, "proto string length invalid"); | ||
385 | luaL_addchar(B, (unsigned char)len); | ||
386 | luaL_addlstring(B, tmp, len); | ||
387 | lua_pop(L, 1); | ||
388 | } | ||
389 | } /* checkprotos() */ | ||
390 | |||
391 | |||
349 | static _Bool getfield(lua_State *L, int index, const char *k) { | 392 | static _Bool getfield(lua_State *L, int index, const char *k) { |
350 | lua_getfield(L, index, k); | 393 | lua_getfield(L, index, k); |
351 | 394 | ||
@@ -4524,34 +4567,16 @@ static int sx_setEphemeralKey(lua_State *L) { | |||
4524 | return 1; | 4567 | return 1; |
4525 | } /* sx_setEphemeralKey() */ | 4568 | } /* sx_setEphemeralKey() */ |
4526 | 4569 | ||
4570 | |||
4527 | #if HAVE_SSL_CTX_SET_ALPN_PROTOS | 4571 | #if HAVE_SSL_CTX_SET_ALPN_PROTOS |
4528 | static int sx_setAlpnProtos(lua_State *L) { | 4572 | static int sx_setAlpnProtos(lua_State *L) { |
4529 | SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); | 4573 | SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); |
4574 | luaL_Buffer B; | ||
4530 | size_t len; | 4575 | size_t len; |
4531 | const char *tmp; | 4576 | const char *tmp; |
4532 | unsigned protos_len = 0; | ||
4533 | luaL_Buffer B; | ||
4534 | luaL_checktype(L, 2, LUA_TTABLE); | ||
4535 | luaL_buffinit(L, &B); | ||
4536 | 4577 | ||
4537 | while (1) { | 4578 | luaL_buffinit(L, &B); |
4538 | protos_len++; | 4579 | checkprotos(&B, L, 2); |
4539 | lua_rawgeti(L, 2, protos_len); | ||
4540 | switch (lua_type(L, -1)) { | ||
4541 | case LUA_TNIL: | ||
4542 | goto done; | ||
4543 | case LUA_TSTRING: | ||
4544 | break; | ||
4545 | default: | ||
4546 | return luaL_argerror(L, 2, "array of strings expected"); | ||
4547 | } | ||
4548 | tmp = luaL_checklstring(L, -1, &len); | ||
4549 | luaL_argcheck(L, len > 0 && len <= UCHAR_MAX, 2, "proto string length invalid"); | ||
4550 | luaL_addchar(&B, (unsigned char)len); | ||
4551 | luaL_addlstring(&B, tmp, len); | ||
4552 | lua_pop(L, 1); | ||
4553 | } | ||
4554 | done: | ||
4555 | luaL_pushresult(&B); | 4580 | luaL_pushresult(&B); |
4556 | tmp = lua_tolstring(L, -1, &len); | 4581 | tmp = lua_tolstring(L, -1, &len); |
4557 | 4582 | ||
@@ -4571,6 +4596,7 @@ done: | |||
4571 | } /* sx_setAlpnProtos() */ | 4596 | } /* sx_setAlpnProtos() */ |
4572 | #endif | 4597 | #endif |
4573 | 4598 | ||
4599 | |||
4574 | static int sx__gc(lua_State *L) { | 4600 | static int sx__gc(lua_State *L) { |
4575 | SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); | 4601 | SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); |
4576 | 4602 | ||
@@ -4847,6 +4873,7 @@ static int ssl_getClientVersion(lua_State *L) { | |||
4847 | return 1; | 4873 | return 1; |
4848 | } /* ssl_getClientVersion() */ | 4874 | } /* ssl_getClientVersion() */ |
4849 | 4875 | ||
4876 | |||
4850 | #if HAVE_SSL_GET0_ALPN_SELECTED | 4877 | #if HAVE_SSL_GET0_ALPN_SELECTED |
4851 | static int ssl_getAlpnSelected(lua_State *L) { | 4878 | static int ssl_getAlpnSelected(lua_State *L) { |
4852 | SSL *ssl = checksimple(L, 1, SSL_CLASS); | 4879 | SSL *ssl = checksimple(L, 1, SSL_CLASS); |
@@ -4862,6 +4889,36 @@ static int ssl_getAlpnSelected(lua_State *L) { | |||
4862 | } /* ssl_getAlpnSelected() */ | 4889 | } /* ssl_getAlpnSelected() */ |
4863 | #endif | 4890 | #endif |
4864 | 4891 | ||
4892 | |||
4893 | #if HAVE_SSL_SET_ALPN_PROTOS | ||
4894 | static int ssl_setAlpnProtos(lua_State *L) { | ||
4895 | SSL *ssl = checksimple(L, 1, SSL_CLASS); | ||
4896 | luaL_Buffer B; | ||
4897 | size_t len; | ||
4898 | const char *tmp; | ||
4899 | |||
4900 | luaL_buffinit(L, &B); | ||
4901 | checkprotos(&B, L, 2); | ||
4902 | luaL_pushresult(&B); | ||
4903 | tmp = lua_tolstring(L, -1, &len); | ||
4904 | |||
4905 | /* OpenSSL 1.0.2 doesn't update the error stack on failure. */ | ||
4906 | ERR_clear_error(); | ||
4907 | if (0 != SSL_set_alpn_protos(ssl, (const unsigned char*)tmp, len)) { | ||
4908 | if (!ERR_peek_error()) { | ||
4909 | return luaL_error(L, "unable to set ALPN protocols: %s", xstrerror(ENOMEM)); | ||
4910 | } else { | ||
4911 | return throwssl(L, "ssl:setAlpnProtos"); | ||
4912 | } | ||
4913 | } | ||
4914 | |||
4915 | lua_pushboolean(L, 1); | ||
4916 | |||
4917 | return 1; | ||
4918 | } /* ssl_setAlpnProtos() */ | ||
4919 | #endif | ||
4920 | |||
4921 | |||
4865 | static int ssl__gc(lua_State *L) { | 4922 | static int ssl__gc(lua_State *L) { |
4866 | SSL **ud = luaL_checkudata(L, 1, SSL_CLASS); | 4923 | SSL **ud = luaL_checkudata(L, 1, SSL_CLASS); |
4867 | 4924 | ||
@@ -4888,6 +4945,9 @@ static const luaL_Reg ssl_methods[] = { | |||
4888 | #if HAVE_SSL_GET0_ALPN_SELECTED | 4945 | #if HAVE_SSL_GET0_ALPN_SELECTED |
4889 | { "getAlpnSelected", &ssl_getAlpnSelected }, | 4946 | { "getAlpnSelected", &ssl_getAlpnSelected }, |
4890 | #endif | 4947 | #endif |
4948 | #if HAVE_SSL_SET_ALPN_PROTOS | ||
4949 | { "setAlpnProtos", &ssl_setAlpnProtos }, | ||
4950 | #endif | ||
4891 | { NULL, NULL }, | 4951 | { NULL, NULL }, |
4892 | }; | 4952 | }; |
4893 | 4953 | ||