summaryrefslogtreecommitdiffhomepage
path: root/libs/nixio/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/nixio/src')
-rw-r--r--libs/nixio/src/file.c12
-rw-r--r--libs/nixio/src/io.c6
-rw-r--r--libs/nixio/src/nixio.c2
-rw-r--r--libs/nixio/src/nixio.h4
-rw-r--r--libs/nixio/src/openssl-compat.c297
-rw-r--r--libs/nixio/src/openssl-compat.h144
-rw-r--r--libs/nixio/src/socket.c12
-rw-r--r--libs/nixio/src/tls-context.c202
-rw-r--r--libs/nixio/src/tls-socket.c196
9 files changed, 863 insertions, 12 deletions
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 <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
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 <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);
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 <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
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 <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");
+}