From d2b11117f26285186b711271d24733d35e0444a1 Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Sun, 22 Feb 2009 22:49:23 +0000 Subject: [PATCH] NIXIO: TLS-Support, bugfixes --- contrib/package/luci/Makefile | 14 ++ libs/nixio/.gitignore | 1 + libs/nixio/Makefile | 47 ++++- libs/nixio/axtls-config/.config | 112 ++++++++++++ libs/nixio/axtls-config/config.h | 113 ++++++++++++ libs/nixio/lua/nixio/util.lua | 7 +- libs/nixio/src/file.c | 12 +- libs/nixio/src/io.c | 6 +- libs/nixio/src/nixio.c | 2 + libs/nixio/src/nixio.h | 4 + libs/nixio/src/openssl-compat.c | 297 +++++++++++++++++++++++++++++++ libs/nixio/src/openssl-compat.h | 144 +++++++++++++++ libs/nixio/src/socket.c | 12 +- libs/nixio/src/tls-context.c | 202 +++++++++++++++++++++ libs/nixio/src/tls-socket.c | 196 ++++++++++++++++++++ 15 files changed, 1153 insertions(+), 16 deletions(-) create mode 100644 libs/nixio/.gitignore create mode 100644 libs/nixio/axtls-config/.config create mode 100644 libs/nixio/axtls-config/config.h create mode 100644 libs/nixio/src/openssl-compat.c create mode 100644 libs/nixio/src/openssl-compat.h create mode 100644 libs/nixio/src/tls-context.c create mode 100644 libs/nixio/src/tls-socket.c diff --git a/contrib/package/luci/Makefile b/contrib/package/luci/Makefile index cebbf99c16..2ee3ee2486 100644 --- a/contrib/package/luci/Makefile +++ b/contrib/package/luci/Makefile @@ -202,6 +202,16 @@ define Package/luci-json/install endef +define Package/luci-nixio + $(call Package/luci/libtemplate) + TITLE:=NIXIO Socket Library +endef + +define Package/luci-nixio/install + $(call Package/luci/install/template,$(1),libs/nixio) +endef + + define Package/luci-sys $(call Package/luci/libtemplate) TITLE:=LuCI Linux/POSIX system library @@ -764,6 +774,9 @@ endif ifneq ($(CONFIG_PACKAGE_luci-json),) PKG_SELECTED_MODULES+=libs/json endif +ifneq ($(CONFIG_PACKAGE_luci-nixio),) + PKG_SELECTED_MODULES+=libs/nixio +endif ifneq ($(CONFIG_PACKAGE_luci-uci),) PKG_SELECTED_MODULES+=libs/uci endif @@ -933,6 +946,7 @@ $(eval $(call BuildPackage,luci-fastindex)) $(eval $(call BuildPackage,luci-http)) $(eval $(call BuildPackage,luci-ipkg)) $(eval $(call BuildPackage,luci-json)) +$(eval $(call BuildPackage,luci-nixio)) $(eval $(call BuildPackage,luci-uci)) $(eval $(call BuildPackage,luci-sys)) $(eval $(call BuildPackage,luci-web)) diff --git a/libs/nixio/.gitignore b/libs/nixio/.gitignore new file mode 100644 index 0000000000..30c8853540 --- /dev/null +++ b/libs/nixio/.gitignore @@ -0,0 +1 @@ +axTLS diff --git a/libs/nixio/Makefile b/libs/nixio/Makefile index 53869bfbae..61237af44b 100644 --- a/libs/nixio/Makefile +++ b/libs/nixio/Makefile @@ -2,13 +2,54 @@ include ../../build/config.mk include ../../build/module.mk include ../../build/gccconfig.mk +AXTLS_VERSION = 1.2.1 +AXTLS_DIR = axTLS +AXTLS_FILE = $(AXTLS_DIR)-$(AXTLS_VERSION).tar.gz +NIXIO_TLS ?= axtls + +NIXIO_OBJ = src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o \ + src/poll.o src/io.o src/file.o src/splice.o src/tls-context.o \ + src/tls-socket.o + +ifeq ($(NIXIO_TLS),axtls) + TLS_CFLAGS = -IaxTLS/{ssl,crypto,config} -include src/openssl-compat.h + TLS_LDFLAGS = + TLS_DEPENDS = src/openssl-compat.o + NIXIO_OBJ += src/openssl-compat.o src/libaxtls.a +endif + +ifeq ($(NIXIO_TLS),openssl) + TLS_LDFLAGS = -lssl +endif + %.o: %.c $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $< -compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o src/io.o src/file.o src/splice.o - $(LINK) $(SHLIB_FLAGS) -o src/nixio.so src/*.o +src/tls-context.o: $(TLS_DEPENDS) src/tls-context.c + $(COMPILE) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/tls-context.c + +src/tls-socket.o: $(TLS_DEPENDS) src/tls-socket.c + $(COMPILE) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/tls-socket.c + +src/openssl-compat.o: src/libaxtls.a src/openssl-compat.c + $(COMPILE) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/openssl-compat.c + + +compile: $(NIXIO_OBJ) + $(LINK) $(SHLIB_FLAGS) $(TLS_LDFLAGS) -o src/nixio.so $(NIXIO_OBJ) mkdir -p dist$(LUA_LIBRARYDIR) cp src/nixio.so dist$(LUA_LIBRARYDIR)/nixio.so +$(AXTLS_DIR)/.prepared: $(AXTLS_FILE) + rm -rf $(AXTLS_DIR) + tar xvfz $(AXTLS_FILE) + cp axtls-config/{.config,config.h} $(AXTLS_DIR)/config + touch $@ + +src/libaxtls.a: $(AXTLS_DIR)/.prepared + $(MAKE) -C $(AXTLS_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(EXTRA_CFLAGS) $(FPIC) -Wall -pedantic -I../config -I../ssl -I../crypto" LDFLAGS="$(LDFLAGS)" OS="$(OS)" clean all + cp -p $(AXTLS_DIR)/_stage/libaxtls.a src + clean: luaclean - rm -f src/*.o src/*.so + rm -f src/*.o src/*.so src/*.a + rm -rf $(AXTLS_DIR) diff --git a/libs/nixio/axtls-config/.config b/libs/nixio/axtls-config/.config new file mode 100644 index 0000000000..beb0d85fca --- /dev/null +++ b/libs/nixio/axtls-config/.config @@ -0,0 +1,112 @@ +# +# Automatically generated make config: don't edit +# +HAVE_DOT_CONFIG=y +CONFIG_PLATFORM_LINUX=y +# CONFIG_PLATFORM_CYGWIN is not set +# CONFIG_PLATFORM_WIN32 is not set + +# +# General Configuration +# +PREFIX="/usr" +# CONFIG_DEBUG is not set +CONFIG_STRIP_UNWANTED_SECTIONS=y +# CONFIG_VISUAL_STUDIO_7_0 is not set +# CONFIG_VISUAL_STUDIO_8_0 is not set +CONFIG_VISUAL_STUDIO_7_0_BASE="" +CONFIG_VISUAL_STUDIO_8_0_BASE="" +CONFIG_EXTRA_CFLAGS_OPTIONS="-fpic" +CONFIG_EXTRA_LDFLAGS_OPTIONS="" + +# +# SSL Library +# +# CONFIG_SSL_SERVER_ONLY is not set +# CONFIG_SSL_CERT_VERIFICATION is not set +CONFIG_SSL_ENABLE_CLIENT=y +# CONFIG_SSL_FULL_MODE is not set +# CONFIG_SSL_SKELETON_MODE is not set +# CONFIG_SSL_PROT_LOW is not set +CONFIG_SSL_PROT_MEDIUM=y +# CONFIG_SSL_PROT_HIGH is not set +CONFIG_SSL_USE_DEFAULT_KEY=y +CONFIG_SSL_PRIVATE_KEY_LOCATION="" +CONFIG_SSL_PRIVATE_KEY_PASSWORD="" +CONFIG_SSL_X509_CERT_LOCATION="" +CONFIG_SSL_GENERATE_X509_CERT=y +CONFIG_SSL_X509_COMMON_NAME="" +CONFIG_SSL_X509_ORGANIZATION_NAME="" +CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME="" +CONFIG_SSL_ENABLE_V23_HANDSHAKE=y +CONFIG_SSL_HAS_PEM=y +# CONFIG_SSL_USE_PKCS12 is not set +CONFIG_SSL_EXPIRY_TIME=24 +CONFIG_X509_MAX_CA_CERTS=4 +CONFIG_SSL_MAX_CERTS=2 +CONFIG_SSL_CTX_MUTEXING=y +CONFIG_USE_DEV_URANDOM=y +# CONFIG_WIN32_USE_CRYPTO_LIB is not set +# CONFIG_OPENSSL_COMPATIBLE is not set +# CONFIG_PERFORMANCE_TESTING is not set +# CONFIG_SSL_TEST is not set +# CONFIG_AXHTTPD is not set +# CONFIG_HTTP_STATIC_BUILD is not set +CONFIG_HTTP_PORT=0 +CONFIG_HTTP_HTTPS_PORT=0 +CONFIG_HTTP_SESSION_CACHE_SIZE=0 +CONFIG_HTTP_WEBROOT="" +CONFIG_HTTP_TIMEOUT=0 +# CONFIG_HTTP_HAS_CGI is not set +CONFIG_HTTP_CGI_EXTENSIONS="" +# CONFIG_HTTP_ENABLE_LUA is not set +CONFIG_HTTP_LUA_PREFIX="" +CONFIG_HTTP_LUA_CGI_LAUNCHER="" +# CONFIG_HTTP_BUILD_LUA is not set +# CONFIG_HTTP_DIRECTORIES is not set +# CONFIG_HTTP_HAS_AUTHORIZATION is not set +# CONFIG_HTTP_HAS_IPV6 is not set +# CONFIG_HTTP_ENABLE_DIFFERENT_USER is not set +CONFIG_HTTP_USER="" +# CONFIG_HTTP_VERBOSE is not set +# CONFIG_HTTP_IS_DAEMON is not set + +# +# Language Bindings +# +# CONFIG_BINDINGS is not set +# CONFIG_CSHARP_BINDINGS is not set +# CONFIG_VBNET_BINDINGS is not set +CONFIG_DOT_NET_FRAMEWORK_BASE="" +# CONFIG_JAVA_BINDINGS is not set +CONFIG_JAVA_HOME="" +# CONFIG_PERL_BINDINGS is not set +CONFIG_PERL_CORE="" +CONFIG_PERL_LIB="" +# CONFIG_LUA_BINDINGS is not set +CONFIG_LUA_CORE="" + +# +# Samples +# +# CONFIG_SAMPLES is not set +# CONFIG_C_SAMPLES is not set +# CONFIG_CSHARP_SAMPLES is not set +# CONFIG_VBNET_SAMPLES is not set +# CONFIG_JAVA_SAMPLES is not set +# CONFIG_PERL_SAMPLES is not set +# CONFIG_LUA_SAMPLES is not set + +# +# BigInt Options +# +# CONFIG_BIGINT_CLASSICAL is not set +# CONFIG_BIGINT_MONTGOMERY is not set +CONFIG_BIGINT_BARRETT=y +CONFIG_BIGINT_CRT=y +# CONFIG_BIGINT_KARATSUBA is not set +MUL_KARATSUBA_THRESH=0 +SQU_KARATSUBA_THRESH=0 +CONFIG_BIGINT_SLIDING_WINDOW=y +CONFIG_BIGINT_SQUARE=y +# CONFIG_BIGINT_CHECK_ON is not set diff --git a/libs/nixio/axtls-config/config.h b/libs/nixio/axtls-config/config.h new file mode 100644 index 0000000000..46a53cf0ee --- /dev/null +++ b/libs/nixio/axtls-config/config.h @@ -0,0 +1,113 @@ +/* + * Automatically generated header file: don't edit + */ + +#define HAVE_DOT_CONFIG 1 +#define CONFIG_PLATFORM_LINUX 1 +#undef CONFIG_PLATFORM_CYGWIN +#undef CONFIG_PLATFORM_WIN32 + +/* + * General Configuration + */ +#define PREFIX "/usr" +#undef CONFIG_DEBUG +#define CONFIG_STRIP_UNWANTED_SECTIONS 1 +#undef CONFIG_VISUAL_STUDIO_7_0 +#undef CONFIG_VISUAL_STUDIO_8_0 +#define CONFIG_VISUAL_STUDIO_7_0_BASE "" +#define CONFIG_VISUAL_STUDIO_8_0_BASE "" +#define CONFIG_EXTRA_CFLAGS_OPTIONS "-fpic" +#define CONFIG_EXTRA_LDFLAGS_OPTIONS "" + +/* + * SSL Library + */ +#undef CONFIG_SSL_SERVER_ONLY +#undef CONFIG_SSL_CERT_VERIFICATION +#define CONFIG_SSL_ENABLE_CLIENT 1 +#undef CONFIG_SSL_FULL_MODE +#undef CONFIG_SSL_SKELETON_MODE +#undef CONFIG_SSL_PROT_LOW +#define CONFIG_SSL_PROT_MEDIUM 1 +#undef CONFIG_SSL_PROT_HIGH +#define CONFIG_SSL_USE_DEFAULT_KEY 1 +#define CONFIG_SSL_PRIVATE_KEY_LOCATION "" +#define CONFIG_SSL_PRIVATE_KEY_PASSWORD "" +#define CONFIG_SSL_X509_CERT_LOCATION "" +#define CONFIG_SSL_GENERATE_X509_CERT 1 +#define CONFIG_SSL_X509_COMMON_NAME "" +#define CONFIG_SSL_X509_ORGANIZATION_NAME "" +#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME "" +#define CONFIG_SSL_ENABLE_V23_HANDSHAKE 1 +#define CONFIG_SSL_HAS_PEM 1 +#undef CONFIG_SSL_USE_PKCS12 +#define CONFIG_SSL_EXPIRY_TIME 24 +#define CONFIG_X509_MAX_CA_CERTS 4 +#define CONFIG_SSL_MAX_CERTS 2 +#define CONFIG_SSL_CTX_MUTEXING 1 +#define CONFIG_USE_DEV_URANDOM 1 +#undef CONFIG_WIN32_USE_CRYPTO_LIB +#undef CONFIG_OPENSSL_COMPATIBLE +#undef CONFIG_PERFORMANCE_TESTING +#undef CONFIG_SSL_TEST +#undef CONFIG_AXHTTPD +#undef CONFIG_HTTP_STATIC_BUILD +#define CONFIG_HTTP_PORT +#define CONFIG_HTTP_HTTPS_PORT +#define CONFIG_HTTP_SESSION_CACHE_SIZE +#define CONFIG_HTTP_WEBROOT "" +#define CONFIG_HTTP_TIMEOUT +#undef CONFIG_HTTP_HAS_CGI +#define CONFIG_HTTP_CGI_EXTENSIONS "" +#undef CONFIG_HTTP_ENABLE_LUA +#define CONFIG_HTTP_LUA_PREFIX "" +#define CONFIG_HTTP_LUA_CGI_LAUNCHER "" +#undef CONFIG_HTTP_BUILD_LUA +#undef CONFIG_HTTP_DIRECTORIES +#undef CONFIG_HTTP_HAS_AUTHORIZATION +#undef CONFIG_HTTP_HAS_IPV6 +#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER +#define CONFIG_HTTP_USER "" +#undef CONFIG_HTTP_VERBOSE +#undef CONFIG_HTTP_IS_DAEMON + +/* + * Language Bindings + */ +#undef CONFIG_BINDINGS +#undef CONFIG_CSHARP_BINDINGS +#undef CONFIG_VBNET_BINDINGS +#define CONFIG_DOT_NET_FRAMEWORK_BASE "" +#undef CONFIG_JAVA_BINDINGS +#define CONFIG_JAVA_HOME "" +#undef CONFIG_PERL_BINDINGS +#define CONFIG_PERL_CORE "" +#define CONFIG_PERL_LIB "" +#undef CONFIG_LUA_BINDINGS +#define CONFIG_LUA_CORE "" + +/* + * Samples + */ +#undef CONFIG_SAMPLES +#undef CONFIG_C_SAMPLES +#undef CONFIG_CSHARP_SAMPLES +#undef CONFIG_VBNET_SAMPLES +#undef CONFIG_JAVA_SAMPLES +#undef CONFIG_PERL_SAMPLES +#undef CONFIG_LUA_SAMPLES + +/* + * BigInt Options + */ +#undef CONFIG_BIGINT_CLASSICAL +#undef CONFIG_BIGINT_MONTGOMERY +#define CONFIG_BIGINT_BARRETT 1 +#define CONFIG_BIGINT_CRT 1 +#undef CONFIG_BIGINT_KARATSUBA +#define MUL_KARATSUBA_THRESH +#define SQU_KARATSUBA_THRESH +#define CONFIG_BIGINT_SLIDING_WINDOW 1 +#define CONFIG_BIGINT_SQUARE 1 +#undef CONFIG_BIGINT_CHECK_ON diff --git a/libs/nixio/lua/nixio/util.lua b/libs/nixio/lua/nixio/util.lua index cb9fcf56f9..5bfcc48d9f 100644 --- a/libs/nixio/lua/nixio/util.lua +++ b/libs/nixio/lua/nixio/util.lua @@ -20,6 +20,7 @@ module "nixio.util" local BUFFERSIZE = 8096 local socket = nixio.socket_meta +local tls_socket = nixio.tls_socket_meta function socket.recvall(self, len) local block, code, msg = self:recv(len) @@ -46,6 +47,7 @@ function socket.recvall(self, len) return (#data > 1 and table.concat(data) or data[1]), nil, nil, 0 end +tls_socket.recvall = socket.recvall function socket.sendall(self, data) local total, block = 0 @@ -66,6 +68,7 @@ function socket.sendall(self, data) return total + sent, nil, nil, "" end +tls_socket.sendall = socket.sendall function socket.linesource(self, limit) limit = limit or BUFFERSIZE @@ -101,6 +104,7 @@ function socket.linesource(self, limit) end end end +tls_socket.linesource = socket.linesource function socket.blocksource(self, bs, limit) bs = bs or BUFFERSIZE @@ -128,4 +132,5 @@ function socket.blocksource(self, bs, limit) return block end end -end \ No newline at end of file +end +tls_socket.blocksource = socket.blocksource \ No newline at end of file diff --git a/libs/nixio/src/file.c b/libs/nixio/src/file.c index 7b65abdc12..3333e23691 100644 --- a/libs/nixio/src/file.c +++ b/libs/nixio/src/file.c @@ -33,7 +33,11 @@ static int nixio_file(lua_State *L) { return nixio__perror(L); } - FILE **udata = lua_newuserdata(L, sizeof(FILE**)); + FILE **udata = lua_newuserdata(L, sizeof(FILE*)); + if (!udata) { + return luaL_error(L, "out of memory"); + } + *udata = file; luaL_getmetatable(L, NIXIO_FILE_META); @@ -50,7 +54,11 @@ static int nixio_pipe(lua_State *L) { } luaL_getmetatable(L, NIXIO_FILE_META); - udata = lua_newuserdata(L, sizeof(FILE**)); + udata = lua_newuserdata(L, sizeof(FILE*)); + if (!udata) { + return luaL_error(L, "out of memory"); + } + if (!(*udata = fdopen(pipefd[0], "r"))) { return nixio__perror(L); } diff --git a/libs/nixio/src/io.c b/libs/nixio/src/io.c index 58054b2eb3..b337461212 100644 --- a/libs/nixio/src/io.c +++ b/libs/nixio/src/io.c @@ -36,8 +36,8 @@ static int nixio_sock__sendto(lua_State *L, int to) { socklen_t alen = 0; if (to) { - const char *address = luaL_checklstring(L, 2, NULL); - uint16_t port = (uint16_t)luaL_checkinteger(L, 3); + const char *address = luaL_checklstring(L, 3, NULL); + uint16_t port = (uint16_t)luaL_checkinteger(L, 4); struct sockaddr_storage addrstor; addr = (struct sockaddr*)&addrstor; if (sock->domain == AF_INET) { @@ -65,7 +65,7 @@ static int nixio_sock__sendto(lua_State *L, int to) { do { sent = sendto(sock->fd, data, len, 0, addr, alen); } while(sent == -1 && errno == EINTR); - if (len >= 0) { + if (sent >= 0) { lua_pushinteger(L, sent); return 1; } else { diff --git a/libs/nixio/src/nixio.c b/libs/nixio/src/nixio.c index a4ef7462ef..0c8ee6eeb1 100644 --- a/libs/nixio/src/nixio.c +++ b/libs/nixio/src/nixio.c @@ -118,6 +118,8 @@ LUALIB_API int luaopen_nixio(lua_State *L) { nixio_open_poll(L); nixio_open_io(L); nixio_open_splice(L); + nixio_open_tls_context(L); + nixio_open_tls_socket(L); /* module version */ lua_pushnumber(L, VERSION); diff --git a/libs/nixio/src/nixio.h b/libs/nixio/src/nixio.h index cdb43599ee..5a491c52bb 100644 --- a/libs/nixio/src/nixio.h +++ b/libs/nixio/src/nixio.h @@ -3,6 +3,8 @@ #define NIXIO_META "nixio.socket" #define NIXIO_FILE_META "nixio.file" +#define NIXIO_TLS_CTX_META "nixio.tls.ctx" +#define NIXIO_TLS_SOCK_META "nixio.tls.sock" #define NIXIO_BUFFERSIZE 8096 #define _FILE_OFFSET_BITS 64 @@ -43,6 +45,8 @@ void nixio_open_address(lua_State *L); void nixio_open_poll(lua_State *L); void nixio_open_io(lua_State *L); void nixio_open_splice(lua_State *L); +void nixio_open_tls_context(lua_State *L); +void nixio_open_tls_socket(lua_State *L); /* Method functions */ diff --git a/libs/nixio/src/openssl-compat.c b/libs/nixio/src/openssl-compat.c new file mode 100644 index 0000000000..ee7600c08f --- /dev/null +++ b/libs/nixio/src/openssl-compat.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2007, Cameron Rich + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Enable a subset of openssl compatible functions. We don't aim to be 100% + * compatible - just to be able to do basic ports etc. + * + * Only really tested on mini_httpd, so I'm not too sure how extensive this + * port is. + */ + +#include "config.h" + +#include +#include +#include +#include "ssl.h" + +static char *key_password = NULL; + +void *SSLv23_server_method(void) { return NULL; } +void *SSLv3_server_method(void) { return NULL; } +void *TLSv1_server_method(void) { return NULL; } +void *SSLv23_client_method(void) { return NULL; } +void *SSLv3_client_method(void) { return NULL; } +void *TLSv1_client_method(void) { return NULL; } +void *SSLv23_method(void) { return NULL; } +void *TLSv1_method(void) { return NULL; } + +SSL_CTX * SSL_CTX_new(void *meth) +{ + SSL_CTX *ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER, 5); + return ssl_ctx; +} + +void SSL_CTX_free(SSL_CTX * ssl_ctx) +{ + ssl_ctx_free(ssl_ctx); +} + +SSL * SSL_new(SSL_CTX *ssl_ctx) +{ + SSL *ssl; + + ssl = ssl_new(ssl_ctx, -1); /* fd is set later */ + + return ssl; +} + +int SSL_set_fd(SSL *s, int fd) +{ + s->client_fd = fd; + return 1; /* always succeeds */ +} + +int SSL_accept(SSL *ssl) +{ + ssl->next_state = HS_CLIENT_HELLO; + while (ssl_read(ssl, NULL) == SSL_OK) + { + if (ssl->next_state == HS_CLIENT_HELLO) + return 1; /* we're done */ + } + + return -1; +} + +int SSL_connect(SSL *ssl) +{ + SET_SSL_FLAG(SSL_IS_CLIENT); + int stat = do_client_connect(ssl); + ssl_display_error(stat); + return (stat == SSL_OK) ? 1 : -1; +} + +void SSL_free(SSL *ssl) +{ + ssl_free(ssl); +} + +int SSL_read(SSL *ssl, void *buf, int num) +{ + uint8_t *read_buf; + int ret; + + while ((ret = ssl_read(ssl, &read_buf)) == SSL_OK); + + if (ret > SSL_OK) + { + memcpy(buf, read_buf, ret > num ? num : ret); + } + + return ret; +} + +int SSL_write(SSL *ssl, const void *buf, int num) +{ + return ssl_write(ssl, buf, num); +} + +int SSL_CTX_use_certificate_file(SSL_CTX *ssl_ctx, const char *file, int type) +{ + return (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, file, NULL) == SSL_OK); +} + +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ssl_ctx, const char *file, int type) +{ + return (ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, file, key_password) == SSL_OK); +} + +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ssl_ctx, int len, const uint8_t *d) +{ + return (ssl_obj_memory_load(ssl_ctx, + SSL_OBJ_X509_CERT, d, len, NULL) == SSL_OK); +} + +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + return 1; +} + +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) +{ + return 1; +} + +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ssl_ctx, const char *file) +{ + return (ssl_obj_load(ssl_ctx, + SSL_OBJ_X509_CERT, file, NULL) == SSL_OK); +} + +int SSL_shutdown(SSL *ssl) +{ + return 1; +} + +/*** get/set session ***/ +SSL_SESSION *SSL_get1_session(SSL *ssl) +{ + return (SSL_SESSION *)ssl_get_session_id(ssl); /* note: wrong cast */ +} + +int SSL_set_session(SSL *ssl, SSL_SESSION *session) +{ + memcpy(ssl->session_id, (uint8_t *)session, SSL_SESSION_ID_SIZE); + return 1; +} + +void SSL_SESSION_free(SSL_SESSION *session) { } +/*** end get/set session ***/ + +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +{ + return 0; +} + +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*verify_callback)(int, void *)) { + if (mode & SSL_VERIFY_PEER) { + ctx->options &= ~SSL_SERVER_VERIFY_LATER; + ctx->options |= SSL_CLIENT_AUTHENTICATION; + } else { + ctx->options |= SSL_SERVER_VERIFY_LATER; + ctx->options &= ~SSL_CLIENT_AUTHENTICATION; + } +} + +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) { } + +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath) +{ + return 1; +} + +void *SSL_load_client_CA_file(const char *file) +{ + return (void *)file; +} + +void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file) +{ + + ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, (const char *)file, NULL); +} + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb) { } + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u) +{ + key_password = (char *)u; +} + +int SSL_peek(SSL *ssl, void *buf, int num) +{ + memcpy(buf, ssl->bm_data, num); + return num; +} + +void SSL_set_bio(SSL *ssl, void *rbio, void *wbio) { } + +long SSL_get_verify_result(const SSL *ssl) +{ + return ssl_handshake_status(ssl); +} + +int SSL_state(SSL *ssl) +{ + return 0x03; // ok state +} + +/** end of could do better list */ + +void *SSL_get_peer_certificate(const SSL *ssl) +{ + return &ssl->ssl_ctx->certs[0]; +} + +int SSL_clear(SSL *ssl) +{ + return 1; +} + + +int SSL_CTX_check_private_key(const SSL_CTX *ctx) +{ + return 1; +} + +int SSL_CTX_set_cipher_list(SSL_CTX *s, const char *str) +{ + return 1; +} + +int SSL_get_error(const SSL *ssl, int ret) +{ + ssl_display_error(ret); + return 0; /* TODO: return proper return code */ +} + +void SSL_CTX_set_options(SSL_CTX *ssl_ctx, int option) {} +int SSL_library_init(void ) { return 1; } +void SSL_load_error_strings(void ) {} +void ERR_print_errors_fp(FILE *fp) {} + +long SSL_CTX_get_timeout(const SSL_CTX *ssl_ctx) { + return CONFIG_SSL_EXPIRY_TIME*3600; } +long SSL_CTX_set_timeout(SSL_CTX *ssl_ctx, long t) { + return SSL_CTX_get_timeout(ssl_ctx); } +void BIO_printf(FILE *f, const char *format, ...) +{ + va_list(ap); + va_start(ap, format); + vfprintf(f, format, ap); + va_end(ap); +} + +void* BIO_s_null(void) { return NULL; } +FILE *BIO_new(bio_func_type_t func) +{ + if (func == BIO_s_null) + return fopen("/dev/null", "r"); + else + return NULL; +} + +FILE *BIO_new_fp(FILE *stream, int close_flag) { return stream; } +int BIO_free(FILE *a) { if (a != stdout && a != stderr) fclose(a); return 1; } diff --git a/libs/nixio/src/openssl-compat.h b/libs/nixio/src/openssl-compat.h new file mode 100644 index 0000000000..afda58fbae --- /dev/null +++ b/libs/nixio/src/openssl-compat.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2007, Cameron Rich + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Enable a subset of openssl compatible functions. We don't aim to be 100% + * compatible - just to be able to do basic ports etc. + * + * Only really tested on mini_httpd, so I'm not too sure how extensive this + * port is. + */ + +#include "config.h" + +#define WITH_AXTLS 1 +#define WITHOUT_OPENSSL 1 +#define SSL_OP_NO_SSLv3 0x02000000L +#define SSL_OP_NO_SSLv2 0x01000000L +#define SSL_FILETYPE_PEM 1 +#define SSL_VERIFY_NONE 0x00 +#define SSL_VERIFY_PEER 0x01 +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +#define SSL_VERIFY_CLIENT_ONCE 0x03 + +#include +#include +#include +#include "ssl.h" + +void *SSLv23_server_method(void); +void *SSLv3_server_method(void); +void *TLSv1_server_method(void); +void *SSLv23_client_method(void); +void *SSLv3_client_method(void); +void *TLSv1_client_method(void); +void *SSLv23_method(void); +void *TLSv1_method(void); + + +typedef void * (*ssl_func_type_t)(void); +typedef void * (*bio_func_type_t)(void); + +SSL_CTX * SSL_CTX_new(void *meth); +void SSL_CTX_free(SSL_CTX * ssl_ctx); +SSL * SSL_new(SSL_CTX *ssl_ctx); +int SSL_set_fd(SSL *s, int fd); +int SSL_accept(SSL *ssl); +int SSL_connect(SSL *ssl); +void SSL_free(SSL *ssl); +int SSL_read(SSL *ssl, void *buf, int num); +int SSL_write(SSL *ssl, const void *buf, int num); +int SSL_CTX_use_certificate_file(SSL_CTX *ssl_ctx, const char *file, int type); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ssl_ctx, const char *file, int type); +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ssl_ctx, int len, const uint8_t *d); +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, + unsigned int sid_ctx_len); +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ssl_ctx, const char *file); +int SSL_shutdown(SSL *ssl); + +/*** get/set session ***/ +SSL_SESSION *SSL_get1_session(SSL *ssl); +int SSL_set_session(SSL *ssl, SSL_SESSION *session); +void SSL_SESSION_free(SSL_SESSION *session); +/*** end get/set session ***/ + +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*verify_callback)(int, void *)); + +void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth); + +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); + +void *SSL_load_client_CA_file(const char *file); + +void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb); + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); + +int SSL_peek(SSL *ssl, void *buf, int num); + +void SSL_set_bio(SSL *ssl, void *rbio, void *wbio); + +long SSL_get_verify_result(const SSL *ssl); + +int SSL_state(SSL *ssl); + +/** end of could do better list */ + +void *SSL_get_peer_certificate(const SSL *ssl); + +int SSL_clear(SSL *ssl); + + +int SSL_CTX_check_private_key(const SSL_CTX *ctx); + +int SSL_CTX_set_cipher_list(SSL_CTX *s, const char *str); + +int SSL_get_error(const SSL *ssl, int ret); + +void SSL_CTX_set_options(SSL_CTX *ssl_ctx, int option); +int SSL_library_init(void ); +void SSL_load_error_strings(void ); +void ERR_print_errors_fp(FILE *fp); + +long SSL_CTX_get_timeout(const SSL_CTX *ssl_ctx); +long SSL_CTX_set_timeout(SSL_CTX *ssl_ctx, long t); +void BIO_printf(FILE *f, const char *format, ...); + +void* BIO_s_null(void); +FILE *BIO_new(bio_func_type_t func); + +FILE *BIO_new_fp(FILE *stream, int close_flag); +int BIO_free(FILE *a); diff --git a/libs/nixio/src/socket.c b/libs/nixio/src/socket.c index f8fa3e649a..258cdeece8 100644 --- a/libs/nixio/src/socket.c +++ b/libs/nixio/src/socket.c @@ -34,6 +34,9 @@ static int nixio_socket(lua_State *L) { const char *proto = lua_tolstring(L, 3, NULL); nixio_sock *sock = lua_newuserdata(L, sizeof(nixio_sock)); + if (!sock) { + return luaL_error(L, "out of memory"); + } if (!strcmp(domain, "inet")) { sock->domain = AF_INET; @@ -142,17 +145,12 @@ static const luaL_reg R[] = { static const luaL_reg M[] = { {"close", nixio_sock_close}, {"shutdown", nixio_sock_shutdown}, + {"__gc", nixio_sock__gc}, + {"__tostring", nixio_sock__tostring}, {NULL, NULL} }; void nixio_open_socket(lua_State *L) { - luaL_getmetatable(L, NIXIO_META); - lua_pushcfunction(L, nixio_sock__gc); - lua_setfield(L, -2, "__gc"); - lua_pushcfunction(L, nixio_sock__tostring); - lua_setfield(L, -2, "__tostring"); - lua_pop(L, 1); - luaL_register(L, NULL, R); lua_pushvalue(L, -2); diff --git a/libs/nixio/src/tls-context.c b/libs/nixio/src/tls-context.c new file mode 100644 index 0000000000..723f8a85fd --- /dev/null +++ b/libs/nixio/src/tls-context.c @@ -0,0 +1,202 @@ +/* + * nixio - Linux I/O library for lua + * + * Copyright (C) 2009 Steven Barth + * + * 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 +#endif + +static SSL_CTX* nixio__checktlsctx(lua_State *L) { + SSL_CTX **ctx = (SSL_CTX **)luaL_checkudata(L, 1, NIXIO_TLS_CTX_META); + luaL_argcheck(L, *ctx, 1, "invalid context"); + return *ctx; +} + +static int nixio__tls_perror(lua_State *L, int code) { + lua_pushnil(L); + lua_pushinteger(L, code); + return 2; +} + +static int nixio__tls_pstatus(lua_State *L, int code) { + if (code == 1) { + lua_pushboolean(L, 1); + return 1; + } else { + return nixio__tls_perror(L, code); + } +} + +static int nixio_tls_ctx(lua_State * L) { + const char *method = luaL_optlstring(L, 1, "tlsv1", NULL); + + SSL_CTX **ctx = lua_newuserdata(L, sizeof(SSL_CTX *)); + if (!ctx) { + return luaL_error(L, "out of memory"); + } + + /* create userdata */ + luaL_getmetatable(L, NIXIO_TLS_CTX_META); + lua_setmetatable(L, -2); + + if (!strcmp(method, "tlsv1")) { + *ctx = SSL_CTX_new(TLSv1_method()); + } else if (!strcmp(method, "sslv23")) { + *ctx = SSL_CTX_new(SSLv23_method()); + } else { + return luaL_argerror(L, 1, "supported values: tlsv1, sslv23"); + } + + + SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + if (!(*ctx)) { + return luaL_error(L, "unable to create TLS context"); + } + + return 1; +} + +static int nixio_tls_ctx_create(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + int fd = nixio__checkfd(L, 2); + + SSL **sock = lua_newuserdata(L, sizeof(SSL *)); + if (!sock) { + return luaL_error(L, "out of memory"); + } + + /* create userdata */ + luaL_getmetatable(L, NIXIO_TLS_SOCK_META); + lua_setmetatable(L, -2); + + *sock = SSL_new(ctx); + if (!(*sock)) { + return nixio__tls_perror(L, 0); + } + + if (SSL_set_fd(*sock, fd) != 1) { + return nixio__tls_perror(L, 0); + } + + return 1; +} + +static int nixio_tls_ctx_set_cert(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + const char *cert = luaL_checkstring(L, 2); + return nixio__tls_pstatus(L, SSL_CTX_use_certificate_chain_file(ctx, cert)); +} + +static int nixio_tls_ctx_set_key(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + const char *cert = luaL_checkstring(L, 2); + const int ktype = SSL_FILETYPE_PEM; + return nixio__tls_pstatus(L, SSL_CTX_use_PrivateKey_file(ctx, cert, ktype)); +} + +static int nixio_tls_ctx_set_ciphers(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + size_t len; + const char *ciphers = luaL_checklstring(L, 2, &len); + luaL_argcheck(L, len < 255, 2, "cipher string too long"); + return nixio__tls_pstatus(L, SSL_CTX_set_cipher_list(ctx, ciphers)); +} + +static int nixio_tls_ctx_set_verify_depth(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + const int depth = luaL_checkinteger(L, 2); + SSL_CTX_set_verify_depth(ctx, depth); + return 0; +} + +static int nixio_tls_ctx_set_verify(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + const int j = lua_gettop(L); + int flags = 0; + for (int i=2; i<=j; i++) { + const char *flag = luaL_checkstring(L, i); + if (!strcmp(flag, "none")) { + flags |= SSL_VERIFY_NONE; + } else if (!strcmp(flag, "peer")) { + flags |= SSL_VERIFY_PEER; + } else if (!strcmp(flag, "verify_fail_if_no_peer_cert")) { + flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + } else if (!strcmp(flag, "client_once")) { + flags |= SSL_VERIFY_CLIENT_ONCE; + } else { + return luaL_argerror(L, i, "supported values: none, peer, " + "verify_fail_if_no_peer_cert, client_once"); + } + } + SSL_CTX_set_verify(ctx, flags, NULL); + return 0; +} + +static int nixio_tls_ctx__gc(lua_State *L) { + SSL_CTX **ctx = (SSL_CTX **)luaL_checkudata(L, 1, NIXIO_TLS_CTX_META); + if (*ctx) { + SSL_CTX_free(*ctx); + *ctx = NULL; + } + return 0; +} + +static int nixio_tls_ctx__tostring(lua_State *L) { + SSL_CTX *ctx = nixio__checktlsctx(L); + lua_pushfstring(L, "nixio TLS context: %p", ctx); + return 1; +} + +/* module table */ +static const luaL_reg R[] = { + {"tls", nixio_tls_ctx}, + {NULL, NULL} +}; + +/* ctx function table */ +static const luaL_reg CTX_M[] = { + {"set_cert", nixio_tls_ctx_set_cert}, + {"set_key", nixio_tls_ctx_set_key}, + {"set_ciphers", nixio_tls_ctx_set_ciphers}, + {"set_verify_depth", nixio_tls_ctx_set_verify_depth}, + {"set_verify", nixio_tls_ctx_set_verify}, + {"create", nixio_tls_ctx_create}, + {"__gc", nixio_tls_ctx__gc}, + {"__tostring", nixio_tls_ctx__tostring}, + {NULL, NULL} +}; + + +void nixio_open_tls_context(lua_State *L) { + /* initialize tls library */ + SSL_load_error_strings(); + SSL_library_init(); + + /* register module functions */ + luaL_register(L, NULL, R); + + /* create context metatable */ + luaL_newmetatable(L, NIXIO_TLS_CTX_META); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_register(L, NULL, CTX_M); + lua_pop(L, 1); +} diff --git a/libs/nixio/src/tls-socket.c b/libs/nixio/src/tls-socket.c new file mode 100644 index 0000000000..a305518cd1 --- /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 + * + * 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 +#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"); +} -- 2.30.2