Skip to content

Instantly share code, notes, and snippets.

@rphillips rphillips/ssl.lua Secret
Last active Aug 29, 2015

Embed
What would you like to do?
local ssl = require('./ssl')
local ctx = ssl.new_ctx( {
protocol = "TLSv1_client",
verify = {"none"}
} )
ssl.connect('104.130.131.136', 443, ctx, function(self)
p(self)
self:write('GET / HTTP/1.0\r\n\r\n')
end)
uv.run()
local uv = require('uv')
local openssl=require'openssl'
local ssl = openssl.ssl
local bio = openssl.bio
local bit = require'bit'
local print = print
local M = {}
local function load(path)
local f = io.open(path,'rb')
if f then
local c = f:read('*a')
f:close()
return c
end
end
function M.new_ctx(params)
params = params or {}
local protocol = params.protocol or 'SSLv3_client'
local ctx = ssl.ctx_new(protocol, params.ciphers)
local xkey,xcert = nil,nil
if (params.certificate) then
xcert = assert(x509.read(load(params.certificate)))
end
if params.key then
if (type(params.password)=='nil') then
xkey = assert(pkey.read(load(params.key),true,'pem'))
elseif (type(params.password)=='string') then
xkey = assert(pkey.read(load(params.key),true,'pem',params.password))
elseif (type(params.password)=='function') then
local p = assert(params.password())
xkey = assert(pkey.read(load(params.key),true,'pem',p))
end
assert(ctx:use(xkey, xcert))
end
if(params.cafile or params.capath) then
ctx:verify_locations(params.cafile,params.capath)
end
local unpack = unpack or table.unpack
if(params.verify) then
ctx:set_verify(params.verify)
end
if params.options and #params.options>0 then
local args = {}
for i=1,#params.options do
table.insert(arg,params.options[i])
end
ctx:options(ssl.none)
end
if params.verifyext then
ctx:set_cert_verify(params.verifyext)
end
if params.dhparam then
ctx:set_tmp('dh',params.dhparam)
end
if params.curve then
ctx:set_tmp('ecdh',params.curve)
end
return ctx
end
local S = {}
S.__index = {
read = function(self, socket)
uv.read_start(socket, function(socket, err, chunk)
if self.ondata then
self:ondata(chunk)
end
end)
end,
handshake = function(self, connected_cb)
if not self.connecting then
self.ondata = function(self, chunk)
if chunk then
self.inp:write(chunk)
self:handshake(connected_cb)
end
end
self:read(self.socket)
self.connecting = true
end
local ret, msg = self.ssl:handshake()
if ret == nil then
else
local i, o = self.out:pending()
if i > 0 then
local data = self.out:read()
uv.write(self.socket, data, function()
self:handshake(connected_cb)
end)
return
end
if ret == false then
return
end
self.connected = true
self.connecting = nil
self.ondata = function(socket, chunk)
if not chunk then
return
end
local ret,err = self.inp:write(chunk)
if ret==nil then
return
end
local i,o = self.inp:pending()
if i>0 then
local ret, msg = self.ssl:read()
if ret then
p(ret)
self:ondata(ret)
end
end
if o > 0 then
assert(false,'never here')
end
end
connected_cb(self)
end
return self.connected
end,
shutdown = function(self,callback)
if not self.shutdown then
self.ssl:shutdown()
uv.close(self.socket)
if callback then
callback(self)
end
self.shutdown = true
end
end,
close = function(self)
if self.connected then
if self.onclose then
self.onclose(self)
end
self:shutdown()
if self.ssl then
self.ssl:shutdown()
end
self.ssl = nil
if self.inp then self.inp:close() end
if self.out then self.out:close() end
self.out,self.inp = nil,nil
if self.mode then
--server mode
uv.unref(self.socket)
end
uv.close(self.socket)
self.connected = nil
self.socket = nil
end
end,
write = function(self, data, cb)
if not self.ssl then
return
end
local ret,err = self.ssl:write(data)
if ret==nil then
return
end
local i, o = self.out:pending()
if i > 0 then
uv.write(self.socket, self.out:read(), cb)
end
if o > 0 then
assert(false,'never here')
end
end
}
function M.new_ssl(ctx,socket,server)
local s = {}
s.inp, s.out = bio.mem(8192), bio.mem(8192)
s.socket = socket
s.mode = server and server or false
s.ssl = ctx:ssl(s.inp,s.out,s.mode)
uv.tcp_nodelay(socket, true)
setmetatable(s,S)
return s
end
function M.connect(host,port,ctx,connected_cb)
if type(ctx)=='table' then
ctx = ssl.new_ctx(ctx)
end
local socket = uv.new_tcp()
local scli = M.new_ssl(ctx, socket)
uv.tcp_connect(socket, host, port, function(socket)
scli:handshake(function(scli)
if connected_cb then
connected_cb(scli)
end
end)
end)
return scli
end
function M.error()
return openssl.error(true)
end
return M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.