diff --git a/samples/luaossl/client.lua b/samples/luaossl/client.lua new file mode 100644 index 0000000..a98b105 --- /dev/null +++ b/samples/luaossl/client.lua @@ -0,0 +1,40 @@ +-- +-- Public domain +-- +local socket = require("socket") +local ssl = require("ssl") + +local pkey = require "openssl.pkey" +local ssl_context = require "openssl.ssl.context" +local x509 = require "openssl.x509" +local x509_store = require "openssl.x509.store" + +local function read_file(path) + local file, err, errno = io.open(path, "rb") + if not file then + return nil, err, errno + end + local contents + contents, err, errno = file:read "*a" + file:close() + return contents, err, errno +end + +local ctx = ssl_context.new("TLSv1_2", false) +ctx:setPrivateKey(pkey.new(assert(read_file("../certs/clientAkey.pem")))) +ctx:setCertificate(x509.new(assert(read_file("../certs/clientA.pem")))) +local store = x509_store.new() +store:add("../certs/rootA.pem") +ctx:setStore(store) +ctx:setVerify(ssl_context.VERIFY_FAIL_IF_NO_PEER_CERT) + +local peer = socket.tcp() +peer:connect("127.0.0.1", 8888) + +-- [[ SSL wrapper +peer = assert( ssl.wrap(peer, ctx) ) +assert(peer:dohandshake()) +--]] + +print(peer:receive("*l")) +peer:close() diff --git a/samples/luaossl/server.lua b/samples/luaossl/server.lua new file mode 100644 index 0000000..3e4a9f5 --- /dev/null +++ b/samples/luaossl/server.lua @@ -0,0 +1,58 @@ +-- +-- Public domain +-- +local socket = require("socket") +local ssl = require("ssl") + +local pkey = require "openssl.pkey" +local ssl_context = require "openssl.ssl.context" +local x509 = require "openssl.x509" +local x509_store = require "openssl.x509.store" + +local function read_file(path) + local file, err, errno = io.open(path, "rb") + if not file then + return nil, err, errno + end + local contents + contents, err, errno = file:read "*a" + file:close() + return contents, err, errno +end + +local ctx = ssl_context.new("TLSv1_2", true) +ctx:setPrivateKey(pkey.new(assert(read_file("../certs/serverAkey.pem")))) +ctx:setCertificate(x509.new(assert(read_file("../certs/serverA.pem")))) +local store = x509_store.new() +store:add("../certs/rootA.pem") +ctx:setStore(store) +ctx:setVerify(ssl_context.VERIFY_FAIL_IF_NO_PEER_CERT) + + +local server = socket.tcp() +server:setoption('reuseaddr', true) +assert( server:bind("127.0.0.1", 8888) ) +server:listen() + +local peer = server:accept() + +-- [[ SSL wrapper +peer = assert( ssl.wrap(peer, ctx) ) + +-- Before handshake: nil +print( peer:info() ) + +assert( peer:dohandshake() ) +--]] + +print("---") +local info = peer:info() +for k, v in pairs(info) do + print(k, v) +end + +print("---") +print("-> Compression", peer:info("compression")) + +peer:send("oneshot test\n") +peer:close() diff --git a/src/ssl.c b/src/ssl.c index 0734487..b270390 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -34,6 +34,7 @@ #if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER<0x10100000L #define SSL_is_server(s) (s->server) +#define SSL_up_ref(ssl) CRYPTO_add(&(ssl)->references, 1, CRYPTO_LOCK_SSL) #define X509_up_ref(c) CRYPTO_add(&c->references, 1, CRYPTO_LOCK_X509) #endif @@ -236,32 +237,60 @@ static int ssl_recv(void *ctx, char *data, size_t count, size_t *got, return IO_UNKNOWN; } +static SSL_CTX* luaossl_testcontext(lua_State *L, int arg) { + SSL_CTX **ctx = luaL_testudata(L, arg, "SSL_CTX*"); + if (ctx) + return *ctx; + return NULL; +} + +static SSL* luaossl_testssl(lua_State *L, int arg) { + SSL **ssl = luaL_testudata(L, arg, "SSL*"); + if (ssl) + return *ssl; + return NULL; +} + /** * Create a new TLS/SSL object and mark it as new. */ static int meth_create(lua_State *L) { p_ssl ssl; - int mode = lsec_getmode(L, 1); - SSL_CTX *ctx = lsec_checkcontext(L, 1); + int mode; + SSL_CTX *ctx; - if (mode == LSEC_MODE_INVALID) { - lua_pushnil(L); - lua_pushstring(L, "invalid mode"); - return 2; - } + lua_settop(L, 1); ssl = (p_ssl)lua_newuserdata(L, sizeof(t_ssl)); - if (!ssl) { - lua_pushnil(L); - lua_pushstring(L, "error creating SSL object"); - return 2; - } - ssl->ssl = SSL_new(ctx); - if (!ssl->ssl) { - lua_pushnil(L); - lua_pushfstring(L, "error creating SSL object (%s)", - ERR_reason_error_string(ERR_get_error())); - return 2; + + if ((ctx = lsec_testcontext(L, 1))) { + mode = lsec_getmode(L, 1); + if (mode == LSEC_MODE_INVALID) { + lua_pushnil(L); + lua_pushstring(L, "invalid mode"); + return 2; + } + ssl->ssl = SSL_new(ctx); + if (!ssl->ssl) { + lua_pushnil(L); + lua_pushfstring(L, "error creating SSL object (%s)", + ERR_reason_error_string(ERR_get_error())); + return 2; + } + } else if ((ctx = luaossl_testcontext(L, 1))) { + ssl->ssl = SSL_new(ctx); + if (!ssl->ssl) { + lua_pushnil(L); + lua_pushfstring(L, "error creating SSL object (%s)", + ERR_reason_error_string(ERR_get_error())); + return 2; + } + mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT; + } else if ((ssl->ssl = luaossl_testssl(L, 1))) { + SSL_up_ref(ssl->ssl); + mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT; + } else { + return luaL_argerror(L, 1, "expected SSL_CTX* or SSL*"); } ssl->state = LSEC_STATE_NEW; SSL_set_fd(ssl->ssl, (int)SOCKET_INVALID);