2012-09-02 16:15:49 +02:00
|
|
|
------------------------------------------------------------------------------
|
2014-01-29 21:43:33 +01:00
|
|
|
-- LuaSec 0.5
|
|
|
|
-- Copyright (C) 2006-2014 Bruno Silvestre
|
2012-09-02 16:15:49 +02:00
|
|
|
--
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
2013-03-30 13:21:40 +01:00
|
|
|
local core = require("ssl.core")
|
|
|
|
local context = require("ssl.context")
|
|
|
|
local x509 = require("ssl.x509")
|
2012-09-02 16:15:49 +02:00
|
|
|
|
2013-03-30 13:21:40 +01:00
|
|
|
module("ssl", package.seeall)
|
2012-09-02 16:15:49 +02:00
|
|
|
|
2014-04-21 18:20:17 +02:00
|
|
|
_VERSION = "0.5"
|
2013-03-30 13:21:40 +01:00
|
|
|
_COPYRIGHT = core.copyright()
|
2012-09-02 16:22:22 +02:00
|
|
|
|
2013-03-30 13:21:40 +01:00
|
|
|
-- Export
|
|
|
|
loadcertificate = x509.load
|
2012-09-02 16:15:49 +02:00
|
|
|
|
2013-03-30 13:21:40 +01:00
|
|
|
-- We must prevent the contexts to be collected before the connections,
|
|
|
|
-- otherwise the C registry will be cleared.
|
|
|
|
local registry = setmetatable({}, {__mode="k"})
|
2012-09-02 16:22:22 +02:00
|
|
|
|
2012-09-02 16:15:49 +02:00
|
|
|
--
|
|
|
|
--
|
|
|
|
--
|
|
|
|
local function optexec(func, param, ctx)
|
|
|
|
if param then
|
|
|
|
if type(param) == "table" then
|
|
|
|
return func(ctx, unpack(param))
|
|
|
|
else
|
|
|
|
return func(ctx, param)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
--
|
|
|
|
--
|
|
|
|
--
|
|
|
|
function newcontext(cfg)
|
|
|
|
local succ, msg, ctx
|
|
|
|
-- Create the context
|
|
|
|
ctx, msg = context.create(cfg.protocol)
|
|
|
|
if not ctx then return nil, msg end
|
|
|
|
-- Mode
|
|
|
|
succ, msg = context.setmode(ctx, cfg.mode)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
-- Load the key
|
2012-09-02 16:22:22 +02:00
|
|
|
if cfg.key then
|
2013-03-30 13:21:40 +01:00
|
|
|
if cfg.password and
|
|
|
|
type(cfg.password) ~= "function" and
|
|
|
|
type(cfg.password) ~= "string"
|
|
|
|
then
|
|
|
|
return nil, "invalid password type"
|
|
|
|
end
|
2012-09-02 16:22:22 +02:00
|
|
|
succ, msg = context.loadkey(ctx, cfg.key, cfg.password)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
end
|
2012-09-02 16:15:49 +02:00
|
|
|
-- Load the certificate
|
2012-09-02 16:22:22 +02:00
|
|
|
if cfg.certificate then
|
2014-02-05 16:51:30 +01:00
|
|
|
succ, msg = context.loadcert(ctx, cfg.certificate)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
if cfg.key and context.checkkey then
|
|
|
|
succ = context.checkkey(ctx)
|
|
|
|
if not succ then return nil, "private key does not match public key" end
|
|
|
|
end
|
2014-02-05 01:48:58 +01:00
|
|
|
end
|
2012-09-02 16:15:49 +02:00
|
|
|
-- Load the CA certificates
|
|
|
|
if cfg.cafile or cfg.capath then
|
|
|
|
succ, msg = context.locations(ctx, cfg.cafile, cfg.capath)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
end
|
2013-03-30 13:21:40 +01:00
|
|
|
-- Set SSL ciphers
|
|
|
|
if cfg.ciphers then
|
|
|
|
succ, msg = context.setcipher(ctx, cfg.ciphers)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
end
|
2012-09-02 16:15:49 +02:00
|
|
|
-- Set the verification options
|
|
|
|
succ, msg = optexec(context.setverify, cfg.verify, ctx)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
-- Set SSL options
|
|
|
|
succ, msg = optexec(context.setoptions, cfg.options, ctx)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
-- Set the depth for certificate verification
|
|
|
|
if cfg.depth then
|
|
|
|
succ, msg = context.setdepth(ctx, cfg.depth)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
end
|
2013-09-07 23:51:30 +02:00
|
|
|
|
|
|
|
-- NOTE: Setting DH parameters and elliptic curves needs to come after
|
|
|
|
-- setoptions(), in case the user has specified the single_{dh,ecdh}_use
|
|
|
|
-- options.
|
|
|
|
|
2013-03-30 13:21:40 +01:00
|
|
|
-- Set DH parameters
|
|
|
|
if cfg.dhparam then
|
|
|
|
if type(cfg.dhparam) ~= "function" then
|
|
|
|
return nil, "invalid DH parameter type"
|
|
|
|
end
|
|
|
|
context.setdhparam(ctx, cfg.dhparam)
|
|
|
|
end
|
|
|
|
-- Set elliptic curve
|
|
|
|
if cfg.curve then
|
|
|
|
succ, msg = context.setcurve(ctx, cfg.curve)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
end
|
|
|
|
-- Set extra verification options
|
|
|
|
if cfg.verifyext and ctx.setverifyext then
|
|
|
|
succ, msg = optexec(ctx.setverifyext, cfg.verifyext, ctx)
|
|
|
|
if not succ then return nil, msg end
|
|
|
|
end
|
|
|
|
|
2012-09-02 16:15:49 +02:00
|
|
|
return ctx
|
|
|
|
end
|
|
|
|
|
|
|
|
--
|
|
|
|
--
|
|
|
|
--
|
|
|
|
function wrap(sock, cfg)
|
|
|
|
local ctx, msg
|
|
|
|
if type(cfg) == "table" then
|
|
|
|
ctx, msg = newcontext(cfg)
|
|
|
|
if not ctx then return nil, msg end
|
|
|
|
else
|
|
|
|
ctx = cfg
|
|
|
|
end
|
|
|
|
local s, msg = core.create(ctx)
|
|
|
|
if s then
|
|
|
|
core.setfd(s, sock:getfd())
|
2014-09-10 19:41:09 +02:00
|
|
|
sock:setfd(-1)
|
2013-03-30 13:21:40 +01:00
|
|
|
registry[s] = ctx
|
2012-09-02 16:15:49 +02:00
|
|
|
return s
|
|
|
|
end
|
|
|
|
return nil, msg
|
|
|
|
end
|
2013-03-30 13:21:40 +01:00
|
|
|
|
|
|
|
--
|
|
|
|
-- Extract connection information.
|
|
|
|
--
|
|
|
|
local function info(ssl, field)
|
2013-09-06 13:52:34 +02:00
|
|
|
local str, comp, err, protocol
|
2013-03-30 13:21:40 +01:00
|
|
|
comp, err = core.compression(ssl)
|
|
|
|
if err then
|
|
|
|
return comp, err
|
|
|
|
end
|
|
|
|
-- Avoid parser
|
|
|
|
if field == "compression" then
|
|
|
|
return comp
|
|
|
|
end
|
|
|
|
local info = {compression = comp}
|
2013-09-06 13:52:34 +02:00
|
|
|
str, info.bits, info.algbits, protocol = core.info(ssl)
|
2013-03-30 13:21:40 +01:00
|
|
|
if str then
|
|
|
|
info.cipher, info.protocol, info.key,
|
|
|
|
info.authentication, info.encryption, info.mac =
|
|
|
|
string.match(str,
|
|
|
|
"^(%S+)%s+(%S+)%s+Kx=(%S+)%s+Au=(%S+)%s+Enc=(%S+)%s+Mac=(%S+)")
|
|
|
|
info.export = (string.match(str, "%sexport%s*$") ~= nil)
|
|
|
|
end
|
2013-09-06 13:52:34 +02:00
|
|
|
if protocol then
|
|
|
|
info.protocol = protocol
|
|
|
|
end
|
2013-03-30 13:21:40 +01:00
|
|
|
if field then
|
|
|
|
return info[field]
|
|
|
|
end
|
|
|
|
-- Empty?
|
|
|
|
return ( (next(info)) and info )
|
|
|
|
end
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Set method for SSL connections.
|
|
|
|
--
|
|
|
|
core.setmethod("info", info)
|
|
|
|
|