summaryrefslogtreecommitdiff
path: root/src/openssl.c
diff options
context:
space:
mode:
authorwilliam <william@25thandclement.com>2015-04-17 19:09:28 -0700
committerwilliam <william@25thandclement.com>2015-04-17 19:09:28 -0700
commit23eafb649ad3e5a8fec499986ecafc453901548a (patch)
treed328968585ca59e2e2936cfa969a6bf3dd841362 /src/openssl.c
parent551ef0b4d84767eaf0c9a88b7a297f19052218e1 (diff)
downloadluaossl-23eafb649ad3e5a8fec499986ecafc453901548a.tar.gz
luaossl-23eafb649ad3e5a8fec499986ecafc453901548a.tar.bz2
luaossl-23eafb649ad3e5a8fec499986ecafc453901548a.zip
finish setAlpnSelect
Diffstat (limited to 'src/openssl.c')
-rw-r--r--src/openssl.c74
1 files changed, 56 insertions, 18 deletions
diff --git a/src/openssl.c b/src/openssl.c
index 5872197..77cec55 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -30,7 +30,7 @@
30#include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */ 30#include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */
31#include <time.h> /* struct tm time_t strptime(3) time(2) */ 31#include <time.h> /* struct tm time_t strptime(3) time(2) */
32#include <ctype.h> /* tolower(3) */ 32#include <ctype.h> /* tolower(3) */
33#include <errno.h> /* ENOMEM ENOTSUP errno */ 33#include <errno.h> /* ENOMEM ENOTSUP EOVERFLOW errno */
34#include <assert.h> /* assert */ 34#include <assert.h> /* assert */
35 35
36#include <sys/types.h> /* ssize_t pid_t */ 36#include <sys/types.h> /* ssize_t pid_t */
@@ -881,7 +881,7 @@ struct ex_state {
881}; /* struct ex_state */ 881}; /* struct ex_state */
882 882
883#ifndef EX_DATA_MAXARGS 883#ifndef EX_DATA_MAXARGS
884#define EX_DATA_MAXARGS 4 884#define EX_DATA_MAXARGS 8
885#endif 885#endif
886 886
887struct ex_data { 887struct ex_data {
@@ -1058,6 +1058,9 @@ static int ex_setdata(lua_State *L, int _type, void *obj, size_t n) {
1058 struct ex_data *data; 1058 struct ex_data *data;
1059 size_t i, j; 1059 size_t i, j;
1060 1060
1061 if (n > countof(data->arg))
1062 return EOVERFLOW;
1063
1061 if ((data = type->get_ex_data(obj, type->index)) && data->state) { 1064 if ((data = type->get_ex_data(obj, type->index)) && data->state) {
1062 for (i = 0; i < countof(data->arg); i++) { 1065 for (i = 0; i < countof(data->arg); i++) {
1063 auxL_unref(L, &data->arg[i]); 1066 auxL_unref(L, &data->arg[i]);
@@ -1069,7 +1072,7 @@ static int ex_setdata(lua_State *L, int _type, void *obj, size_t n) {
1069 return errno; 1072 return errno;
1070 1073
1071 if (!type->set_ex_data(obj, type->index, data)) 1074 if (!type->set_ex_data(obj, type->index, data))
1072 return -1; 1075 return auxL_EOPENSSL;
1073 1076
1074 data->state = state; 1077 data->state = state;
1075 data->refs = 1; 1078 data->refs = 1;
@@ -5139,37 +5142,64 @@ static SSL *ssl_push(lua_State *, SSL *);
5139static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) { 5142static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) {
5140 SSL_CTX *ctx = _ctx; 5143 SSL_CTX *ctx = _ctx;
5141 lua_State *L = NULL; 5144 lua_State *L = NULL;
5142 size_t n; 5145 size_t n, protolen, tmpsiz;
5143 int top, status; 5146 int otop, status;
5147 const void *proto;
5148 void *tmpbuf;
5144 5149
5145 if (0 == (n = ex_getdata(&L, EX_SSL_CTX_ALPN_SELECT_CB, ctx))) 5150 *out = NULL;
5151 *outlen = 0;
5152
5153 /* always expect function (1st) and return string buffer (Nth) */
5154 if ((n = ex_getdata(&L, EX_SSL_CTX_ALPN_SELECT_CB, ctx)) < 2)
5146 return SSL_TLSEXT_ERR_ALERT_FATAL; 5155 return SSL_TLSEXT_ERR_ALERT_FATAL;
5147 5156
5148 top = lua_gettop(L) - n; 5157 otop = lua_gettop(L) - n;
5149 5158
5150 /* TODO: Install temporary panic handler to catch OOM errors */ 5159 /* TODO: Install temporary panic handler to catch OOM errors */
5151 5160
5152 /* pass the SSL object as first argument */ 5161 /* pass SSL object as 1st argument */
5153 ssl_push(L, ssl); 5162 ssl_push(L, ssl);
5163 lua_insert(L, otop + 3);
5164
5165 /* pass table of protocol names as 2nd argument */
5154 pushprotos(L, in, inlen); 5166 pushprotos(L, in, inlen);
5167 lua_insert(L, otop + 4);
5168
5169 if (LUA_OK != (status = lua_pcall(L, 2 + (n - 2), 1, 0)))
5170 goto fatal;
5171
5172 /* did we get a string result? */
5173 if (!(proto = lua_tolstring(L, -1, &protolen)))
5174 goto noack;
5175
5176 /* will it fit in our return buffer? */
5177 if (!(tmpbuf = lua_touserdata(L, otop + 1)))
5178 goto fatal;
5155 5179
5156 /* TODO: lua_rotate ssl and protocols table into position. */ 5180 tmpsiz = lua_rawlen(L, otop + 1);
5157 5181
5158 if (LUA_OK != (status = lua_pcall(L, 2 + (n - 1), 1, 0))) 5182 if (protolen > tmpsiz)
5159 goto fatal; 5183 goto fatal;
5160 5184
5161 /* TODO: check return value */ 5185 memcpy(tmpbuf, proto, protolen);
5162 (void)out; (void)outlen; 5186
5187 /*
5188 * NB: Our return buffer is anchored using the luaL_ref API, so even
5189 * once we pop the stack it will remain valid.
5190 */
5191 *out = tmpbuf;
5192 *outlen = protolen;
5163 5193
5164 lua_settop(L, top); 5194 lua_settop(L, otop);
5165 5195
5166 return SSL_TLSEXT_ERR_OK; 5196 return SSL_TLSEXT_ERR_OK;
5167fatal: 5197fatal:
5168 lua_settop(L, top); 5198 lua_settop(L, otop);
5169 5199
5170 return SSL_TLSEXT_ERR_ALERT_FATAL; 5200 return SSL_TLSEXT_ERR_ALERT_FATAL;
5171noack: 5201noack:
5172 lua_settop(L, top); 5202 lua_settop(L, otop);
5173 5203
5174 return SSL_TLSEXT_ERR_NOACK; 5204 return SSL_TLSEXT_ERR_NOACK;
5175} /* sx_setAlpnSelect_cb() */ 5205} /* sx_setAlpnSelect_cb() */
@@ -5180,13 +5210,18 @@ static int sx_setAlpnSelect(lua_State *L) {
5180 int error; 5210 int error;
5181 5211
5182 luaL_checktype(L, 2, LUA_TFUNCTION); 5212 luaL_checktype(L, 2, LUA_TFUNCTION);
5183 if ((error = ex_setdata(L, EX_SSL_CTX_ALPN_SELECT_CB, ctx, 1))) { 5213
5214 /* allocate space to store the selected protocol in our callback */
5215 lua_newuserdata(L, UCHAR_MAX);
5216 lua_insert(L, 2);
5217
5218 if ((error = ex_setdata(L, EX_SSL_CTX_ALPN_SELECT_CB, ctx, lua_gettop(L) - 1))) {
5184 if (error > 0) { 5219 if (error > 0) {
5185 return luaL_error(L, "unable to set ALPN protocol selection callback: %s", aux_strerror(error)); 5220 return luaL_error(L, "unable to set ALPN protocol selection callback: %s", aux_strerror(error));
5186 } else if (!ERR_peek_error()) { 5221 } else if (error == auxL_EOPENSSL && !ERR_peek_error()) {
5187 return luaL_error(L, "unable to set ALPN protocol selection callback: Unknown internal error"); 5222 return luaL_error(L, "unable to set ALPN protocol selection callback: Unknown internal error");
5188 } else { 5223 } else {
5189 return auxL_error(L, auxL_EOPENSSL, "ssl.context:setAlpnSelect"); 5224 return auxL_error(L, error, "ssl.context:setAlpnSelect");
5190 } 5225 }
5191 } 5226 }
5192 5227
@@ -5225,6 +5260,9 @@ static const luaL_Reg sx_methods[] = {
5225#if HAVE_SSL_CTX_SET_ALPN_PROTOS 5260#if HAVE_SSL_CTX_SET_ALPN_PROTOS
5226 { "setAlpnProtos", &sx_setAlpnProtos }, 5261 { "setAlpnProtos", &sx_setAlpnProtos },
5227#endif 5262#endif
5263#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
5264 { "setAlpnSelect", &sx_setAlpnSelect },
5265#endif
5228 { NULL, NULL }, 5266 { NULL, NULL },
5229}; 5267};
5230 5268