This commit is contained in:
Thijs Schreijer 2015-03-08 16:24:44 +01:00
commit 9e93748671
8 changed files with 144 additions and 136 deletions

View File

@ -19,7 +19,8 @@ conn = ssl.wrap(conn, params)
-- Comment the lines to not send a name
--conn:sni("servera.br")
conn:sni("serveraa.br")
--conn:sni("serveraa.br")
conn:sni("serverb.br")
assert(conn:dohandshake())
--

View File

@ -39,10 +39,12 @@ local conn = server:accept()
conn = ssl.wrap(conn, ctx01)
-- Configure the name map
conn:sni({
local sni_map = {
["servera.br"] = ctx01,
["serveraa.br"] = ctx02,
})
}
conn:sni(sni_map, true)
assert(conn:dohandshake())
--

View File

@ -14,7 +14,11 @@
#endif
#if (LUA_VERSION_NUM == 501)
#define lua_rawlen(L, i) lua_objlen(L, i)
#define setfuncs(L, R) luaL_register(L, NULL, R)
#define lua_rawlen(L, i) lua_objlen(L, i)
#define luaL_newlib(L, R) do { lua_newtable(L); luaL_register(L, NULL, R); } while(0)
#else
#define setfuncs(L, R) luaL_setfuncs(L, R, 0)
#endif
#endif

View File

@ -429,7 +429,7 @@ static int set_cipher(lua_State *L)
static int set_depth(lua_State *L)
{
SSL_CTX *ctx = lsec_checkcontext(L, 1);
SSL_CTX_set_verify_depth(ctx, luaL_checkint(L, 2));
SSL_CTX_set_verify_depth(ctx, (int)luaL_checkinteger(L, 2));
lua_pushboolean(L, 1);
return 1;
}
@ -723,39 +723,19 @@ int lsec_getmode(lua_State *L, int idx)
/**
* Registre the module.
*/
#if (LUA_VERSION_NUM == 501)
LSEC_API int luaopen_ssl_context(lua_State *L)
{
luaL_newmetatable(L, "SSL:DH:Registry"); /* Keep all DH callbacks */
luaL_newmetatable(L, "SSL:Verify:Registry"); /* Keep all verify flags */
luaL_newmetatable(L, "SSL:Context");
luaL_register(L, NULL, meta);
setfuncs(L, meta);
/* Create __index metamethods for context */
lua_newtable(L);
luaL_register(L, NULL, meta_index);
lua_setfield(L, -2, "__index");
/* Register the module */
luaL_register(L, "ssl.context", funcs);
return 1;
}
#else
LSEC_API int luaopen_ssl_context(lua_State *L)
{
luaL_newmetatable(L, "SSL:DH:Registry"); /* Keep all DH callbacks */
luaL_newmetatable(L, "SSL:Verify:Registry"); /* Keep all verify flags */
luaL_newmetatable(L, "SSL:Context");
luaL_setfuncs(L, meta, 0);
/* Create __index metamethods for context */
lua_newtable(L);
luaL_setfuncs(L, meta_index, 0);
luaL_newlib(L, meta_index);
lua_setfield(L, -2, "__index");
/* Return the module */
lua_newtable(L);
luaL_setfuncs(L, funcs, 0);
luaL_newlib(L, funcs);
return 1;
}
#endif

View File

@ -12,22 +12,18 @@ local ltn12 = require("ltn12")
local http = require("socket.http")
local url = require("socket.url")
local table = require("table")
local string = require("string")
local try = socket.try
local try = socket.try
local type = type
local pairs = pairs
local getmetatable = getmetatable
module("ssl.https")
_VERSION = "0.5"
_COPYRIGHT = "LuaSec 0.5 - Copyright (C) 2009-2014 PUC-Rio"
-- Default settings
PORT = 443
--
-- Module
--
local _M = {
_VERSION = "0.5",
_COPYRIGHT = "LuaSec 0.5 - Copyright (C) 2009-2014 PUC-Rio",
PORT = 443,
}
-- TLS configuration
local cfg = {
protocol = "tlsv1",
options = "all",
@ -40,7 +36,7 @@ local cfg = {
-- Insert default HTTPS port.
local function default_https_port(u)
return url.build(url.parse(u, {port = PORT}))
return url.build(url.parse(u, {port = _M.PORT}))
end
-- Convert an URL to a table according to Luasocket needs.
@ -113,7 +109,7 @@ end
-- @param body optional (string)
-- @return (string if url == string or 1), code, headers, status
--
function request(url, body)
local function request(url, body)
local result_table = {}
local stringrequest = type(url) == "string"
if stringrequest then
@ -136,3 +132,11 @@ function request(url, body)
end
return res, code, headers, status
end
--------------------------------------------------------------------------------
-- Export module
--
_M.request = request
return _M

103
src/ssl.c
View File

@ -330,7 +330,7 @@ static int meth_setfd(lua_State *L)
p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
if (ssl->state != LSEC_STATE_NEW)
luaL_argerror(L, 1, "invalid SSL object state");
ssl->sock = luaL_checkint(L, 2);
ssl->sock = (t_socket)luaL_checkinteger(L, 2);
socket_setnonblocking(&ssl->sock);
SSL_set_fd(ssl->ssl, (int)ssl->sock);
return 0;
@ -406,18 +406,24 @@ static int meth_want(lua_State *L)
*/
static int meth_compression(lua_State *L)
{
#if !defined(OPENSSL_NO_COMP)
const COMP_METHOD *comp;
#endif
p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
if (ssl->state != LSEC_STATE_CONNECTED) {
lua_pushnil(L);
lua_pushstring(L, "closed");
return 2;
}
#if !defined(OPENSSL_NO_COMP)
comp = SSL_get_current_compression(ssl->ssl);
if (comp)
lua_pushstring(L, SSL_COMP_get_name(comp));
else
lua_pushnil(L);
#else
lua_pushnil(L);
#endif
return 1;
}
@ -436,7 +442,7 @@ static int meth_getpeercertificate(lua_State *L)
return 2;
}
/* Default to the first cert */
n = luaL_optint(L, 2, 1);
n = (int)luaL_optinteger(L, 2, 1);
/* This function is 1-based, but OpenSSL is 0-based */
--n;
if (n < 0) {
@ -660,6 +666,7 @@ static int meth_info(lua_State *L)
static int sni_cb(SSL *ssl, int *ad, void *arg)
{
int strict;
SSL_CTX *newctx = NULL;
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
lua_State *L = ((p_context)SSL_CTX_get_app_data(ctx))->L;
@ -667,41 +674,54 @@ static int sni_cb(SSL *ssl, int *ad, void *arg)
/* No name, use default context */
if (!name)
return SSL_TLSEXT_ERR_NOACK;
/* Search for the name in the map */
/* Retrieve struct from registry */
luaL_getmetatable(L, "SSL:SNI:Registry");
lua_pushlightuserdata(L, (void*)ssl);
lua_gettable(L, -2);
/* Strict search? */
lua_pushstring(L, "strict");
lua_gettable(L, -2);
strict = lua_toboolean(L, -1);
lua_pop(L, 1);
/* Search for the name in the map */
lua_pushstring(L, "map");
lua_gettable(L, -2);
lua_pushstring(L, name);
lua_gettable(L, -2);
if (lua_isuserdata(L, -1))
newctx = lsec_checkcontext(L, -1);
lua_pop(L, 3);
lua_pop(L, 4);
/* Found, use this context */
if (newctx) {
SSL_set_SSL_CTX(ssl, newctx);
return SSL_TLSEXT_ERR_OK;
}
/* Not found, but use initial context */
if (!strict)
return SSL_TLSEXT_ERR_OK;
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
static int meth_sni(lua_State *L)
{
int strict;
SSL_CTX *aux;
const char *name;
p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl->ssl);
p_context pctx = (p_context)SSL_CTX_get_app_data(ctx);
switch (pctx->mode) {
case LSEC_MODE_CLIENT:
if (pctx->mode == LSEC_MODE_CLIENT) {
name = luaL_checkstring(L, 2);
SSL_set_tlsext_host_name(ssl->ssl, name);
break;
case LSEC_MODE_SERVER:
return 0;
} else if (pctx->mode == LSEC_MODE_SERVER) {
luaL_checktype(L, 2, LUA_TTABLE);
strict = lua_toboolean(L, 3);
/* Check if the table contains only (string -> context) */
lua_pushnil(L);
while (lua_next(L, 2)) {
luaL_checkstring(L, 3);
aux = lsec_checkcontext(L, 4);
luaL_checkstring(L, -2);
aux = lsec_checkcontext(L, -1);
/* Set callback in every context */
SSL_CTX_set_tlsext_servername_callback(aux, sni_cb);
/* leave the next key on the stack */
@ -710,15 +730,31 @@ static int meth_sni(lua_State *L)
/* Save table in the register */
luaL_getmetatable(L, "SSL:SNI:Registry");
lua_pushlightuserdata(L, (void*)ssl->ssl);
lua_newtable(L);
lua_pushstring(L, "map");
lua_pushvalue(L, 2);
lua_settable(L, -3);
lua_pushstring(L, "strict");
lua_pushboolean(L, strict);
lua_settable(L, -3);
lua_settable(L, -3);
/* Set callback in the default context */
SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb);
break;
}
return 0;
}
static int meth_getsniname(lua_State *L)
{
p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
const char *name = SSL_get_servername(ssl->ssl, TLSEXT_NAMETYPE_host_name);
if (name)
lua_pushstring(L, name);
else
lua_pushnil(L);
return 1;
}
static int meth_copyright(lua_State *L)
{
lua_pushstring(L, "LuaSec 0.5 - Copyright (C) 2006-2011 Bruno Silvestre"
@ -742,6 +778,7 @@ static luaL_Reg methods[] = {
{"getpeerchain", meth_getpeerchain},
{"getpeerverification", meth_getpeerverification},
{"getpeerfinished", meth_getpeerfinished},
{"getsniname", meth_getsniname},
{"getstats", meth_getstats},
{"setstats", meth_setstats},
{"dirty", meth_dirty},
@ -779,7 +816,6 @@ static luaL_Reg funcs[] = {
/**
* Initialize modules.
*/
#if (LUA_VERSION_NUM == 501)
LSEC_API int luaopen_ssl_core(lua_State *L)
{
/* Initialize SSL */
@ -799,49 +835,12 @@ LSEC_API int luaopen_ssl_core(lua_State *L)
/* Register the functions and tables */
luaL_newmetatable(L, "SSL:Connection");
luaL_register(L, NULL, meta);
setfuncs(L, meta);
lua_newtable(L);
luaL_register(L, NULL, methods);
luaL_newlib(L, methods);
lua_setfield(L, -2, "__index");
luaL_register(L, "ssl.core", funcs);
lua_pushnumber(L, SOCKET_INVALID);
lua_setfield(L, -2, "invalidfd");
luaL_newlib(L, funcs);
return 1;
}
#else
LSEC_API int luaopen_ssl_core(lua_State *L)
{
/* Initialize SSL */
if (!SSL_library_init()) {
lua_pushstring(L, "unable to initialize SSL library");
lua_error(L);
}
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
#if defined(WITH_LUASOCKET)
/* Initialize internal library */
socket_open();
#endif
luaL_newmetatable(L, "SSL:SNI:Registry");
/* Register the functions and tables */
luaL_newmetatable(L, "SSL:Connection");
luaL_setfuncs(L, meta, 0);
lua_newtable(L);
luaL_setfuncs(L, methods, 0);
lua_setfield(L, -2, "__index");
lua_newtable(L);
luaL_setfuncs(L, funcs, 0);
lua_pushnumber(L, SOCKET_INVALID);
lua_setfield(L, -2, "invalidfd");
return 1;
}
#endif

View File

@ -8,13 +8,7 @@ local core = require("ssl.core")
local context = require("ssl.context")
local x509 = require("ssl.x509")
module("ssl", package.seeall)
_VERSION = "0.5"
_COPYRIGHT = core.copyright()
-- Export
loadcertificate = x509.load
local unpack = table.unpack or unpack
-- We must prevent the contexts to be collected before the connections,
-- otherwise the C registry will be cleared.
@ -37,7 +31,7 @@ end
--
--
--
function newcontext(cfg)
local function newcontext(cfg)
local succ, msg, ctx
-- Create the context
ctx, msg = context.create(cfg.protocol)
@ -115,7 +109,7 @@ end
--
--
--
function wrap(sock, cfg)
local function wrap(sock, cfg)
local ctx, msg
if type(cfg) == "table" then
ctx, msg = newcontext(cfg)
@ -126,7 +120,7 @@ function wrap(sock, cfg)
local s, msg = core.create(ctx)
if s then
core.setfd(s, sock:getfd())
sock:setfd(core.invalidfd)
sock:setfd(-1)
registry[s] = ctx
return s
end
@ -170,3 +164,16 @@ end
--
core.setmethod("info", info)
--------------------------------------------------------------------------------
-- Export module
--
local _M = {
_VERSION = "0.5",
_COPYRIGHT = core.copyright(),
loadcertificate = x509.load,
newcontext = newcontext,
wrap = wrap,
}
return _M

View File

@ -20,6 +20,11 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <lua.h>
#include <lauxlib.h>
@ -88,8 +93,10 @@ static void push_asn1_string(lua_State* L, ASN1_STRING *string, int encode)
{
int len;
unsigned char *data;
if (!string)
if (!string) {
lua_pushnil(L);
return;
}
switch (encode) {
case LSEC_AI5_STRING:
lua_pushlstring(L, (char*)ASN1_STRING_data(string),
@ -101,6 +108,8 @@ static void push_asn1_string(lua_State* L, ASN1_STRING *string, int encode)
lua_pushlstring(L, (char*)data, len);
OPENSSL_free(data);
}
else
lua_pushnil(L);
}
}
@ -119,6 +128,31 @@ static int push_asn1_time(lua_State *L, ASN1_UTCTIME *tm)
return 1;
}
/**
* Return a human readable IP address.
*/
static void push_asn1_ip(lua_State *L, ASN1_STRING *string)
{
unsigned char *ip = ASN1_STRING_data(string);
char dst[INET6_ADDRSTRLEN];
int typ;
switch(ASN1_STRING_length(string)) {
case 4:
typ = AF_INET;
break;
case 16:
typ = AF_INET6;
break;
default:
lua_pushnil(L);
return;
}
if(inet_ntop(typ, ip, dst, INET6_ADDRSTRLEN))
lua_pushstring(L, dst);
else
lua_pushnil(L);
}
/**
*
*/
@ -258,7 +292,7 @@ int meth_extensions(lua_State* L)
case GEN_IPADD:
lua_pushstring(L, "iPAddress");
push_subtable(L, -2);
push_asn1_string(L, general_name->d.iPAddress, px->encode);
push_asn1_ip(L, general_name->d.iPAddress);
lua_rawseti(L, -2, lua_rawlen(L, -2)+1);
lua_pop(L, 1);
break;
@ -532,39 +566,16 @@ static luaL_Reg funcs[] = {
/*--------------------------------------------------------------------------*/
#if (LUA_VERSION_NUM == 501)
LSEC_API int luaopen_ssl_x509(lua_State *L)
{
/* Register the functions and tables */
luaL_newmetatable(L, "SSL:Certificate");
luaL_register(L, NULL, meta);
setfuncs(L, meta);
lua_newtable(L);
luaL_register(L, NULL, methods);
luaL_newlib(L, methods);
lua_setfield(L, -2, "__index");
luaL_register(L, "ssl.x509", funcs);
luaL_newlib(L, funcs);
return 1;
}
#else
LSEC_API int luaopen_ssl_x509(lua_State *L)
{
/* Register the functions and tables */
luaL_newmetatable(L, "SSL:Certificate");
luaL_setfuncs(L, meta, 0);
lua_newtable(L);
luaL_setfuncs(L, methods, 0);
lua_setfield(L, -2, "__index");
lua_newtable(L);
luaL_setfuncs(L, funcs, 0);
return 1;
}
#endif