NIXIO: TLS-Support, bugfixes
authorSteven Barth <steven@midlink.org>
Sun, 22 Feb 2009 22:49:23 +0000 (22:49 +0000)
committerSteven Barth <steven@midlink.org>
Sun, 22 Feb 2009 22:49:23 +0000 (22:49 +0000)
15 files changed:
contrib/package/luci/Makefile
libs/nixio/.gitignore [new file with mode: 0644]
libs/nixio/Makefile
libs/nixio/axtls-config/.config [new file with mode: 0644]
libs/nixio/axtls-config/config.h [new file with mode: 0644]
libs/nixio/lua/nixio/util.lua
libs/nixio/src/file.c
libs/nixio/src/io.c
libs/nixio/src/nixio.c
libs/nixio/src/nixio.h
libs/nixio/src/openssl-compat.c [new file with mode: 0644]
libs/nixio/src/openssl-compat.h [new file with mode: 0644]
libs/nixio/src/socket.c
libs/nixio/src/tls-context.c [new file with mode: 0644]
libs/nixio/src/tls-socket.c [new file with mode: 0644]

index cebbf99..2ee3ee2 100644 (file)
@@ -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 (file)
index 0000000..30c8853
--- /dev/null
@@ -0,0 +1 @@
+axTLS
index 53869bf..61237af 100644 (file)
@@ -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 (file)
index 0000000..beb0d85
--- /dev/null
@@ -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 (file)
index 0000000..46a53cf
--- /dev/null
@@ -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
index cb9fcf5..5bfcc48 100644 (file)
@@ -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
index 7b65abd..3333e23 100644 (file)
@@ -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);
        }
index 58054b2..b337461 100644 (file)
@@ -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 {
index a4ef746..0c8ee6e 100644 (file)
@@ -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);
index cdb4359..5a491c5 100644 (file)
@@ -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 (file)
index 0000000..ee7600c
--- /dev/null
@@ -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 <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#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 (file)
index 0000000..afda58f
--- /dev/null
@@ -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 <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#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);
index f8fa3e6..258cdee 100644 (file)
@@ -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 (file)
index 0000000..723f8a8
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * 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 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 (file)
index 0000000..a305518
--- /dev/null
@@ -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");
+}