diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9976b19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/src/*.o +/src/luasocket/*.o +/ssl.dll diff --git a/luasec-0.5-3.rockspec b/luasec-0.5-3.rockspec new file mode 100644 index 0000000..caa6665 --- /dev/null +++ b/luasec-0.5-3.rockspec @@ -0,0 +1,98 @@ +package = "LuaSec" +version = "0.5-3" +source = { + url = "git://github.com/brunoos/luasec.git", + tag = "luasec-0.5" +} +description = { + summary = "A binding for OpenSSL library to provide TLS/SSL communication over LuaSocket.", + detailed = "This version delegates to LuaSocket the TCP connection establishment between the client and server. Then LuaSec uses this connection to start a secure TLS/SSL session.", + homepage = "https://github.com/brunoos/luasec/wiki", + license = "MIT" +} +dependencies = { + "lua >= 5.1", "luasocket" +} +external_dependencies = { + platforms = { + unix = { + OPENSSL = { + header = "openssl/ssl.h", + library = "ssl" + } + }, + windows = { + OPENSSL = { + header = "openssl/ssl.h", + } + }, + } +} +build = { + type = "builtin", + copy_directories = { + "samples" + }, + platforms = { + unix = { + install = { + lib = { + "ssl.so" + }, + lua = { + "src/ssl.lua", ['ssl.https'] = "src/https.lua" + } + }, + modules = { + ssl = { + incdirs = { + "$(OPENSSL_INCDIR)", "src/", "src/luasocket", + }, + libdirs = { + "$(OPENSSL_LIBDIR)" + }, + libraries = { + "ssl", "crypto" + }, + sources = { + "src/x509.c", "src/context.c", "src/ssl.c", + "src/luasocket/buffer.c", "src/luasocket/io.c", + "src/luasocket/timeout.c", "src/luasocket/usocket.c" + } + } + } + }, + windows = { + install = { + lib = { + "ssl.dll" + }, + lua = { + "src/ssl.lua", ['ssl.https'] = "src/https.lua" + } + }, + modules = { + ssl = { + defines = { + "WIN32", "NDEBUG", "_WINDOWS", "_USRDLL", "LSEC_EXPORTS", "BUFFER_DEBUG", "LSEC_API=__declspec(dllexport)" + }, + libdirs = { + "$(OPENSSL_LIBDIR)", + "$(OPENSSL_BINDIR)", + }, + libraries = { + "libeay32", "ssleay32", "ws2_32" + }, + incdirs = { + "$(OPENSSL_INCDIR)", "src/", "src/luasocket" + }, + sources = { + "src/x509.c", "src/context.c", "src/ssl.c", + "src/luasocket/buffer.c", "src/luasocket/io.c", + "src/luasocket/timeout.c", "src/luasocket/wsocket.c" + } + } + } + } + } +} diff --git a/src/https.lua b/src/https.lua index bdfc17d..b7bb611 100644 --- a/src/https.lua +++ b/src/https.lua @@ -13,7 +13,6 @@ local http = require("socket.http") local url = require("socket.url") local table = require("table") -local string = require("string") local try = socket.try local type = type @@ -38,15 +37,10 @@ local cfg = { -- Auxiliar Functions -------------------------------------------------------------------- --- Insert default HTTPS port. -local function default_https_port(u) - return url.build(url.parse(u, {port = PORT})) -end - -- Convert an URL to a table according to Luasocket needs. local function urlstring_totable(url, body, result_table) url = { - url = default_https_port(url), + url = url, method = body and "POST" or "GET", sink = ltn12.sink.table(result_table) } @@ -81,24 +75,43 @@ local function tcp(params) end -- Force client mode params.mode = "client" + -- upvalue to track https -> http redirection + local washttps = false -- 'create' function for LuaSocket - return function () - local conn = {} - conn.sock = try(socket.tcp()) - local st = getmetatable(conn.sock).__index.settimeout - function conn:settimeout(...) - return st(self.sock, ...) - end - -- Replace TCP's connection function - function conn:connect(host, port) - try(self.sock:connect(host, port)) - self.sock = try(ssl.wrap(self.sock, params)) - try(self.sock:dohandshake()) - reg(self, getmetatable(self.sock)) - return 1 - end - return conn - end + return function (reqt) + local u = url.parse(reqt.url) + if (reqt.scheme or u.scheme) == "https" then + -- https, provide an ssl wrapped socket + local conn = {} + conn.sock = try(socket.tcp()) + local st = getmetatable(conn.sock).__index.settimeout + function conn:settimeout(...) + return st(self.sock, ...) + end + -- Replace TCP's connection function + function conn:connect(host, port) + try(self.sock:connect(host, port)) + self.sock = try(ssl.wrap(self.sock, params)) + try(self.sock:dohandshake()) + reg(self, getmetatable(self.sock)) + return 1 + end + -- insert https default port, overriding http port inserted by LuaSocket + if not u.port then + u.port = PORT + reqt.url = url.build(u) + reqt.port = PORT + end + washttps = true + return conn + else + -- regular http, needs just a socket... + if washttps and params.redirect ~= "all" then + try(nil, "Unallowed insecure redirect https to http") + end + return socket.tcp() + end + end end -------------------------------------------------------------------- @@ -118,18 +131,12 @@ function request(url, body) local stringrequest = type(url) == "string" if stringrequest then url = urlstring_totable(url, body, result_table) - else - url.url = default_https_port(url.url) end if http.PROXY or url.proxy then return nil, "proxy not supported" - elseif url.redirect then - return nil, "redirect not supported" - elseif url.create then - return nil, "create function not permitted" end - -- New 'create' function to establish a secure connection - url.create = tcp(url) + -- New 'create' function to establish the proper connection + url.create = url.create or tcp(url) local res, code, headers, status = http.request(url) if res and stringrequest then return table.concat(result_table), code, headers, status