diff options
Diffstat (limited to 'plugins/coro-tls/init.lua')
-rw-r--r-- | plugins/coro-tls/init.lua | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/plugins/coro-tls/init.lua b/plugins/coro-tls/init.lua new file mode 100644 index 00000000000..03d6e1c3f76 --- /dev/null +++ b/plugins/coro-tls/init.lua @@ -0,0 +1,122 @@ +local exports = {} +exports.name = "creationix/coro-tls" +exports.version = "1.2.1" +exports.homepage = "https://github.com/luvit/lit/blob/master/deps/coro-tls.lua" +exports.description = "A coro-stream wrapper implementing tls sessions." +exports.tags = {"coro", "tls", "ssl"} +exports.license = "MIT" +exports.author = { name = "Tim Caswell" } + +local openssl = require('openssl') +local bit = require('bit') + +local DEFAULT_CIPHERS = 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' .. -- TLS 1.2 + 'RC4:HIGH:!MD5:!aNULL:!EDH' -- TLS 1.0 + +-- Given a read/write pair, return a new read/write pair for plaintext +exports.wrap = function (read, write, options) + if not options then + options = {} + end + + local ctx = openssl.ssl.ctx_new(options.protocol or 'TLSv1_2', options.ciphers or DEFAULT_CIPHERS) + + local key, cert, ca + if options.key then + key = assert(openssl.pkey.read(options.key, true, 'pem')) + end + if options.cert then + cert = assert(openssl.x509.read(options.cert)) + end + if options.ca then + if type(options.ca) == "string" then + ca = { assert(openssl.x509.read(options.ca)) } + elseif type(options.ca) == "table" then + ca = {} + for i = 1, #options.ca do + ca[i] = assert(openssl.x509.read(options.ca[i])) + end + else + error("options.ca must be string or table of strings") + end + end + if key and cert then + assert(ctx:use(key, cert)) + end + if ca then + local store = openssl.x509.store:new() + for i = 1, #ca do + assert(store:add(ca[i])) + end + ctx:cert_store(store) + else + ctx:verify_mode({"none"}) + end + + ctx:options(bit.bor( + openssl.ssl.no_sslv2, + openssl.ssl.no_sslv3, + openssl.ssl.no_compression)) + local bin, bout = openssl.bio.mem(8192), openssl.bio.mem(8192) + local ssl = ctx:ssl(bin, bout, options.server) + + local function flush() + while bout:pending() > 0 do + write(bout:read()) + end + end + + -- Do handshake + while true do + if ssl:handshake() then break end + flush() + local chunk = read() + if chunk then + bin:write(chunk) + else + error("disconnect while handshaking") + end + end + flush() + + local done = false + local function shutdown() + if done then return end + done = true + while true do + if ssl:shutdown() then break end + flush() + local chunk = read() + if chunk then + bin:write(chunk) + else + break + end + end + flush() + write() + end + + local function plainRead() + while true do + local chunk = ssl:read() + if chunk then return chunk end + local cipher = read() + if not cipher then return end + bin:write(cipher) + end + end + + local function plainWrite(plain) + if not plain then + return shutdown() + end + ssl:write(plain) + flush() + end + + return plainRead, plainWrite + +end + +return exports |