Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions luasec/https.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
----------------------------------------------------------------------------
-- LuaSec 1.0.2
-- Copyright (C) 2009-2021 PUC-Rio
--
-- Author: Pablo Musa
-- Author: Tomas Guisasola
---------------------------------------------------------------------------

local socket = require("socket")
local ssl = require("Zenitha.luasec.ssl")
local ltn12 = require("ltn12")
local http = require("socket.http")
local url = require("socket.url")

local try = socket.try

--
-- Module
--
local _M = {
_VERSION = "1.0.2",
_COPYRIGHT = "LuaSec 1.0.2 - Copyright (C) 2009-2021 PUC-Rio",
PORT = 443,
TIMEOUT = 60
}

-- TLS configuration
local cfg = {
protocol = "any",
options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"},
verify = "none",
}

--------------------------------------------------------------------
-- Auxiliar Functions
--------------------------------------------------------------------

-- Insert default HTTPS port.
local function default_https_port(u)
return url.build(url.parse(u, {port = _M.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),
method = body and "POST" or "GET",
sink = ltn12.sink.table(result_table)
}
if body then
url.source = ltn12.source.string(body)
url.headers = {
["content-length"] = #body,
["content-type"] = "application/x-www-form-urlencoded",
}
end
return url
end

-- Forward calls to the real connection object.
local function reg(conn)
local mt = getmetatable(conn.sock).__index
for name, method in pairs(mt) do
if type(method) == "function" then
conn[name] = function (self, ...)
return method(self.sock, ...)
end
end
end
end

-- Return a function which performs the SSL/TLS connection.
local function tcp(params)
params = params or {}
-- Default settings
for k, v in pairs(cfg) do
params[k] = params[k] or v
end
-- Force client mode
params.mode = "client"
-- '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, _M.TIMEOUT)
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))
self.sock:sni(host)
self.sock:settimeout(_M.TIMEOUT)
try(self.sock:dohandshake())
reg(self, getmetatable(self.sock))
return 1
end
return conn
end
end

--------------------------------------------------------------------
-- Main Function
--------------------------------------------------------------------

-- Make a HTTP request over secure connection. This function receives
-- the same parameters of LuaSocket's HTTP module (except 'proxy' and
-- 'redirect') plus LuaSec parameters.
--
-- @param url mandatory (string or table)
-- @param body optional (string)
-- @return (string if url == string or 1), code, headers, status
--
local function request(url, body)
local result_table = {}
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)
local res, code, headers, status = http.request(url)
if res and stringrequest then
return table.concat(result_table), code, headers, status
end
return res, code, headers, status
end

--------------------------------------------------------------------------------
-- Export module
--

_M.request = request
_M.tcp = tcp

return _M
93 changes: 93 additions & 0 deletions luasec/options.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
local function usage()
print("Usage:")
print("* Generate options of your system:")
print(" lua options.lua -g /path/to/ssl.h [version] > options.c")
print("* Examples:")
print(" lua options.lua -g /usr/include/openssl/ssl.h > options.c\n")
print(" lua options.lua -g /usr/include/openssl/ssl.h \"OpenSSL 1.1.1f\" > options.c\n")

print("* List options of your system:")
print(" lua options.lua -l /path/to/ssl.h\n")
end

--
local function printf(str, ...)
print(string.format(str, ...))
end

local function generate(options, version)
print([[
/*--------------------------------------------------------------------------
* LuaSec 1.1.1
*
* Copyright (C) 2006-2021 Bruno Silvestre
*
*--------------------------------------------------------------------------*/

#include <openssl/ssl.h>

#include "options.h"

/* If you need to generate these options again, see options.lua */

]])

printf([[
/*
OpenSSL version: %s
*/
]], version)

print([[static lsec_ssl_option_t ssl_options[] = {]])

for k, option in ipairs(options) do
local name = string.lower(string.sub(option, 8))
print(string.format([[#if defined(%s)]], option))
print(string.format([[ {"%s", %s},]], name, option))
print([[#endif]])
end
print([[ {NULL, 0L}]])
print([[
};

LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() {
return ssl_options;
}
]])
end

local function loadoptions(file)
local options = {}
local f = assert(io.open(file, "r"))
for line in f:lines() do
local op = string.match(line, "define%s+(SSL_OP_BIT%()")
if not op then
op = string.match(line, "define%s+(SSL_OP_%S+)")
if op then
table.insert(options, op)
end
end
end
table.sort(options, function(a,b) return a<b end)
return options
end
--

local options
local flag, file, version = ...

version = version or "Unknown"

if not file then
usage()
elseif flag == "-g" then
options = loadoptions(file)
generate(options, version)
elseif flag == "-l" then
options = loadoptions(file)
for k, option in ipairs(options) do
print(option)
end
else
usage()
end
Loading