moonbridge
changeset 246:00e1ee683355
Method :starttls(...) for I/O handle
author | jbe |
---|---|
date | Mon Aug 22 01:31:48 2016 +0200 (2016-08-22) |
parents | 29322b2a1af8 |
children | ba5ed7cf0a30 |
files | moonbridge_io.c |
line diff
1.1 --- a/moonbridge_io.c Mon Aug 22 00:40:30 2016 +0200 1.2 +++ b/moonbridge_io.c Mon Aug 22 01:31:48 2016 +0200 1.3 @@ -82,6 +82,9 @@ 1.4 int writebufout; 1.5 char readbuf[MOONBR_IO_READBUFLEN]; 1.6 char writebuf[MOONBR_IO_WRITEBUFLEN]; 1.7 +#ifdef MOONBR_IO_USE_TLS 1.8 + struct tls *tls, *servertls; 1.9 +#endif 1.10 } moonbr_io_handle_t; 1.11 1.12 typedef struct { 1.13 @@ -740,6 +743,16 @@ 1.14 lua_pushinteger(L, 0); 1.15 lua_call(L, 2, 0); 1.16 } 1.17 +#ifdef MOONBR_IO_USE_TLS 1.18 + if (handle->tls) { 1.19 + tls_free(handle->tls); 1.20 + handle->tls = NULL; 1.21 + } 1.22 + if (handle->servertls) { 1.23 + tls_free(handle->servertls); 1.24 + handle->servertls = NULL; 1.25 + } 1.26 +#endif 1.27 return 0; 1.28 } 1.29 1.30 @@ -787,6 +800,10 @@ 1.31 handle->writeqoff = 0; 1.32 handle->writebufin = 0; 1.33 handle->writebufout = 0; 1.34 +#ifdef MOONBR_IO_USE_TLS 1.35 + handle->tls = NULL; 1.36 + handle->servertls = NULL; 1.37 +#endif 1.38 handle->fd = *fd; /* required for set_linger call */ 1.39 moonbr_io_handle_set_linger(L, handle, 0); 1.40 handle->fd = -1; /* avoid closing incomplete handle */ 1.41 @@ -1755,6 +1772,64 @@ 1.42 return 0; 1.43 } 1.44 1.45 +static int moonbr_io_starttls(lua_State *L) { 1.46 + moonbr_io_handle_t *handle; 1.47 + struct tls_config *tlsconf; 1.48 + const char *mode; 1.49 + const char *servername; 1.50 + struct tls *tls, *tls2; 1.51 + int is_server = 0; 1.52 + handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); 1.53 + if (lua_type(L, 2) == LUA_TTABLE) { 1.54 + lua_pushcfunction(L, moonbr_io_tlsconf); 1.55 + lua_pushvalue(L, 2); 1.56 + lua_call(L, 1, 2); 1.57 + if (lua_isnil(L, -2)) return 2; 1.58 + lua_pop(L, 1); 1.59 + lua_replace(L, 2); 1.60 + } 1.61 + tlsconf = luaL_checkudata(L, 2, MOONBR_IO_TLSCONF_MT_REGKEY); 1.62 + if (handle->closed) return luaL_error(L, "Attempt to start TLS on a closed I/O handle"); 1.63 + if (handle->finished) return luaL_error(L, "Attempt to start TLS on a finished I/O handle"); 1.64 + if (handle->readbufin || handle->writebufin) { 1.65 + return luaL_error(L, "Attempt to start TLS on an I/O handle with non-empty buffers"); 1.66 + } 1.67 + lua_getfield(L, 2, "mode"); 1.68 + mode = lua_tostring(L, -1); 1.69 + if (mode && !strcmp(mode, "server")) { 1.70 + lua_pop(L, 1); 1.71 + tls = tls_server(); 1.72 + is_server = 1; 1.73 + } else if (mode && !strcmp(mode, "client")) { 1.74 + lua_pop(L, 1); 1.75 + servername = luaL_checkstring(L, 3); 1.76 + tls = tls_client(); 1.77 + } else { 1.78 + /* shouldn't happen unless table has been modified */ 1.79 + lua_pop(L, 1); 1.80 + return luaL_error(L, "Field \"mode\" of TLS configuration is neither set to \"server\" nor \"client\""); 1.81 + } 1.82 + if (!tls) { 1.83 + return luaL_error(L, "Could not allocate memory for TLS context"); 1.84 + } 1.85 + if (tls_configure(tls, tlsconf)) goto moonbr_io_starttls_error; 1.86 + if (is_server) { 1.87 + if (tls_accept_socket(tls, &tls2, handle->fd)) goto moonbr_io_starttls_error; 1.88 + handle->servertls = tls; 1.89 + handle->tls = tls2; 1.90 + } else { 1.91 + if (tls_connect_socket(tls, handle->fd, servername)) goto moonbr_io_starttls_error; 1.92 + handle->tls = tls; 1.93 + } 1.94 + lua_settop(L, 1); 1.95 + return 1; 1.96 + moonbr_io_starttls_error: 1.97 + lua_pushnil(L); 1.98 + lua_pushstring(L, tls_error(tls)); 1.99 + tls_free(tls); 1.100 + return 2; 1.101 +} 1.102 + 1.103 #endif 1.104 1.105 static const struct luaL_Reg moonbr_io_handle_methods[] = { 1.106 @@ -1777,6 +1852,9 @@ 1.107 {"finish", moonbr_io_finish}, 1.108 {"close", moonbr_io_close}, 1.109 {"reset", moonbr_io_reset}, 1.110 +#ifdef MOONBR_IO_USE_TLS 1.111 + {"starttls", moonbr_io_starttls}, 1.112 +#endif 1.113 {NULL, NULL} 1.114 }; 1.115