diff options
author | Steven Barth <steven@midlink.org> | 2009-02-22 22:49:23 +0000 |
---|---|---|
committer | Steven Barth <steven@midlink.org> | 2009-02-22 22:49:23 +0000 |
commit | d2b11117f26285186b711271d24733d35e0444a1 (patch) | |
tree | 7c08cbd29658d0f0a1331f12156f5ddc97570975 /libs/nixio/src/tls-socket.c | |
parent | da6f427d818573f76dd50771f4d60ff693eb8fd9 (diff) |
NIXIO: TLS-Support, bugfixes
Diffstat (limited to 'libs/nixio/src/tls-socket.c')
-rw-r--r-- | libs/nixio/src/tls-socket.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/libs/nixio/src/tls-socket.c b/libs/nixio/src/tls-socket.c new file mode 100644 index 000000000..a305518cd --- /dev/null +++ b/libs/nixio/src/tls-socket.c @@ -0,0 +1,196 @@ +/* + * nixio - Linux I/O library for lua + * + * Copyright (C) 2009 Steven Barth <steven@midlink.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nixio.h" +#include "string.h" + +#ifndef WITHOUT_OPENSSL +#include <openssl/ssl.h> +#endif + +static int nixio__tls_sock_perror(lua_State *L, SSL *sock, int code) { + lua_pushnil(L); + lua_pushinteger(L, code); + lua_pushinteger(L, SSL_get_error(sock, code)); + return 3; +} + +static int nixio__tls_sock_pstatus(lua_State *L, SSL *sock, int code) { + if (code == 1) { + lua_pushboolean(L, 1); + return 1; + } else { + return nixio__tls_sock_perror(L, sock, code); + } +} + +static SSL* nixio__checktlssock(lua_State *L) { + SSL **sock = (SSL **)luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META); + luaL_argcheck(L, *sock, 1, "invalid context"); + return *sock; +} + +static int nixio_tls_sock_recv(lua_State *L) { + SSL *sock = nixio__checktlssock(L); + int req = luaL_checkinteger(L, 2); + + luaL_argcheck(L, req >= 0, 2, "out of range"); + + /* We limit the readsize to NIXIO_BUFFERSIZE */ + req = (req > NIXIO_BUFFERSIZE) ? NIXIO_BUFFERSIZE : req; +#ifndef WITH_AXTLS + char buffer[NIXIO_BUFFERSIZE]; + int readc = SSL_read(sock, buffer, req); + + if (readc < 0) { + return nixio__tls_sock_pstatus(L, sock, readc); + } else { + lua_pushlstring(L, buffer, readc); + return 1; + } +#else + if (!req) { + lua_pushliteral(L, ""); + return 1; + } + + /* AXTLS doesn't handle buffering for us, so we have to hack around*/ + int buflen = 0; + lua_getmetatable(L, 1); + lua_getfield(L, -1, "_axbuffer"); + + if (lua_isstring(L, -1)) { + buflen = lua_objlen(L, -1); + } + + if (req < buflen) { + const char *axbuf = lua_tostring(L, -1); + lua_pushlstring(L, axbuf, req); + lua_pushlstring(L, axbuf + req, buflen - req); + lua_setfield(L, -4, "_axbuffer"); + return 1; + } else { + if (!lua_isstring(L, -1)) { + lua_pop(L, 1); + lua_pushliteral(L, ""); + } + + char *axbuf; + int axread; + + /* while handshake pending */ + while ((axread = ssl_read(sock, (uint8_t**)&axbuf)) == SSL_OK); + + if (axread < 0) { + /* There is an error */ + + if (axread != SSL_ERROR_CONN_LOST) { + lua_pushliteral(L, ""); + lua_setfield(L, -3, "_axbuffer"); + return nixio__tls_sock_perror(L, sock, axread); + } else { + lua_pushliteral(L, ""); + } + } else { + int stillwant = req - buflen; + if (stillwant < axread) { + /* we got more data than we need */ + lua_pushlstring(L, axbuf, stillwant); + lua_concat(L, 2); + + /* remaining data goes into the buffer */ + lua_pushlstring(L, axbuf + stillwant, axread - stillwant); + } else { + lua_pushlstring(L, axbuf, axread); + lua_concat(L, 2); + lua_pushliteral(L, ""); + } + } + lua_setfield(L, -3, "_axbuffer"); + return 1; + } + +#endif +} + +static int nixio_tls_sock_send(lua_State *L) { + SSL *sock = nixio__checktlssock(L); + size_t len; + ssize_t sent; + const char *data = luaL_checklstring(L, 2, &len); + sent = SSL_write(sock, data, len); + if (sent > 0) { + lua_pushinteger(L, sent); + return 1; + } else { + return nixio__tls_sock_pstatus(L, sock, len); + } +} + +static int nixio_tls_sock_accept(lua_State *L) { + SSL *sock = nixio__checktlssock(L); + return nixio__tls_sock_pstatus(L, sock, SSL_accept(sock)); +} + +static int nixio_tls_sock_connect(lua_State *L) { + SSL *sock = nixio__checktlssock(L); + return nixio__tls_sock_pstatus(L, sock, SSL_connect(sock)); +} + +static int nixio_tls_sock_shutdown(lua_State *L) { + SSL *sock = nixio__checktlssock(L); + return nixio__tls_sock_pstatus(L, sock, SSL_shutdown(sock)); +} + +static int nixio_tls_sock__gc(lua_State *L) { + SSL **sock = (SSL **)luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META); + if (*sock) { + SSL_free(*sock); + *sock = NULL; + } + return 0; +} + +static int nixio_tls_sock__tostring(lua_State *L) { + SSL *sock = nixio__checktlssock(L); + lua_pushfstring(L, "nixio TLS socket: %p", sock); + return 1; +} + + +/* ctx function table */ +static const luaL_reg M[] = { + {"recv", nixio_tls_sock_recv}, + {"send", nixio_tls_sock_send}, + {"accept", nixio_tls_sock_accept}, + {"connect", nixio_tls_sock_connect}, + {"shutdown", nixio_tls_sock_shutdown}, + {"__gc", nixio_tls_sock__gc}, + {"__tostring", nixio_tls_sock__tostring}, + {NULL, NULL} +}; + + +void nixio_open_tls_socket(lua_State *L) { + /* create socket metatable */ + luaL_newmetatable(L, NIXIO_TLS_SOCK_META); + luaL_register(L, NULL, M); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_setfield(L, -2, "tls_socket_meta"); +} |