# HG changeset patch # User jbe # Date 1471822308 -7200 # Node ID 00e1ee683355790a12c026d6cf2e2861e4c9405e # Parent 29322b2a1af8f3eae69b3f720e5900ecad58e0da Method :starttls(...) for I/O handle diff -r 29322b2a1af8 -r 00e1ee683355 moonbridge_io.c --- a/moonbridge_io.c Mon Aug 22 00:40:30 2016 +0200 +++ b/moonbridge_io.c Mon Aug 22 01:31:48 2016 +0200 @@ -82,6 +82,9 @@ int writebufout; char readbuf[MOONBR_IO_READBUFLEN]; char writebuf[MOONBR_IO_WRITEBUFLEN]; +#ifdef MOONBR_IO_USE_TLS + struct tls *tls, *servertls; +#endif } moonbr_io_handle_t; typedef struct { @@ -740,6 +743,16 @@ lua_pushinteger(L, 0); lua_call(L, 2, 0); } +#ifdef MOONBR_IO_USE_TLS + if (handle->tls) { + tls_free(handle->tls); + handle->tls = NULL; + } + if (handle->servertls) { + tls_free(handle->servertls); + handle->servertls = NULL; + } +#endif return 0; } @@ -787,6 +800,10 @@ handle->writeqoff = 0; handle->writebufin = 0; handle->writebufout = 0; +#ifdef MOONBR_IO_USE_TLS + handle->tls = NULL; + handle->servertls = NULL; +#endif handle->fd = *fd; /* required for set_linger call */ moonbr_io_handle_set_linger(L, handle, 0); handle->fd = -1; /* avoid closing incomplete handle */ @@ -1755,6 +1772,64 @@ return 0; } +static int moonbr_io_starttls(lua_State *L) { + moonbr_io_handle_t *handle; + struct tls_config *tlsconf; + const char *mode; + const char *servername; + struct tls *tls, *tls2; + int is_server = 0; + handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); + if (lua_type(L, 2) == LUA_TTABLE) { + lua_pushcfunction(L, moonbr_io_tlsconf); + lua_pushvalue(L, 2); + lua_call(L, 1, 2); + if (lua_isnil(L, -2)) return 2; + lua_pop(L, 1); + lua_replace(L, 2); + } + tlsconf = luaL_checkudata(L, 2, MOONBR_IO_TLSCONF_MT_REGKEY); + if (handle->closed) return luaL_error(L, "Attempt to start TLS on a closed I/O handle"); + if (handle->finished) return luaL_error(L, "Attempt to start TLS on a finished I/O handle"); + if (handle->readbufin || handle->writebufin) { + return luaL_error(L, "Attempt to start TLS on an I/O handle with non-empty buffers"); + } + lua_getfield(L, 2, "mode"); + mode = lua_tostring(L, -1); + if (mode && !strcmp(mode, "server")) { + lua_pop(L, 1); + tls = tls_server(); + is_server = 1; + } else if (mode && !strcmp(mode, "client")) { + lua_pop(L, 1); + servername = luaL_checkstring(L, 3); + tls = tls_client(); + } else { + /* shouldn't happen unless table has been modified */ + lua_pop(L, 1); + return luaL_error(L, "Field \"mode\" of TLS configuration is neither set to \"server\" nor \"client\""); + } + if (!tls) { + return luaL_error(L, "Could not allocate memory for TLS context"); + } + if (tls_configure(tls, tlsconf)) goto moonbr_io_starttls_error; + if (is_server) { + if (tls_accept_socket(tls, &tls2, handle->fd)) goto moonbr_io_starttls_error; + handle->servertls = tls; + handle->tls = tls2; + } else { + if (tls_connect_socket(tls, handle->fd, servername)) goto moonbr_io_starttls_error; + handle->tls = tls; + } + lua_settop(L, 1); + return 1; + moonbr_io_starttls_error: + lua_pushnil(L); + lua_pushstring(L, tls_error(tls)); + tls_free(tls); + return 2; +} + #endif static const struct luaL_Reg moonbr_io_handle_methods[] = { @@ -1777,6 +1852,9 @@ {"finish", moonbr_io_finish}, {"close", moonbr_io_close}, {"reset", moonbr_io_reset}, +#ifdef MOONBR_IO_USE_TLS + {"starttls", moonbr_io_starttls}, +#endif {NULL, NULL} };