13 Commits

Author SHA1 Message Date
c3176c5678 Add shutdown example 2025-05-08 15:51:38 -03:00
bccb1f74f0 Fix IO_DONE error, remove shutdown field 2025-05-08 15:50:30 -03:00
fff43542f9 Fix missing return 2025-05-07 08:32:34 -03:00
7cfb91d478 Add :shutdown() method for ending the TLS session before :close()
This allows applications to separate ending the TLS session from closing the
underlying socket. In particular, it enables us to avoid needing to set the
socket to blocking mode during close().
2025-02-06 15:23:27 +00:00
4c06287052 Release LuaSec 1.3.2 2023-08-31 17:09:53 -03:00
5f4799d8cf reset block timeout at send or receive
Addressing #159 and #160
2023-08-31 10:51:50 -03:00
5787d51bb8 Merge pull request #197 from Zash/errno-bug-again
Expand workaround for zero errno to OpenSSL 3.0.x
2023-07-12 21:41:40 -03:00
a2b211f847 Expand workaround for zero errno to OpenSSL 3.0.x
Encountered the bug in #172 after upgrading to OpenSSL 3.0.9, so it
appears to still be present.

Occurs when writing to a connection that has been closed by the remote.
2023-07-05 13:21:49 +02:00
769ac528e2 Merge pull request #196 from barracuda156/darwin
usocket.c: place EAI_OVERFLOW inside macro, unbreak build on <10.7
2023-05-09 10:25:21 -03:00
0f0e07eb41 usocket.c: place EAI_OVERFLOW inside macro, unbreak build on <10.7 2023-04-09 20:20:36 +08:00
fddde111f7 Release 1.3.1 2023-03-19 11:55:08 -03:00
6405645155 Check if PSK is available 2023-03-19 11:48:56 -03:00
e01c6e63cd Fix: check if PSK is available 2023-03-19 11:43:09 -03:00
26 changed files with 268 additions and 38 deletions

View File

@ -1,3 +1,19 @@
--------------------------------------------------------------------------------
LuaSec 1.3.2
---------------
This version includes:
* Fix: place EAI_OVERFLOW inside macro, unbreak build on <10.7 (Sergey Fedorov)
* Fix: Expand workaround for zero errno to OpenSSL 3.0.x (Kim Alvefur)
* Fix: reset block timeout at send or receive (MartinDahlberg)
--------------------------------------------------------------------------------
LuaSec 1.3.1
---------------
This version includes:
* Fix: check if PSK is available
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
LuaSec 1.3.0 LuaSec 1.3.0
--------------- ---------------

View File

@ -1,4 +1,4 @@
LuaSec 1.3.0 LuaSec 1.3.2
------------ ------------
* OpenSSL options: * OpenSSL options:

View File

@ -1,4 +1,4 @@
LuaSec 1.3.0 license LuaSec 1.3.2 license
Copyright (C) 2006-2023 Bruno Silvestre, UFG Copyright (C) 2006-2023 Bruno Silvestre, UFG
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining

View File

@ -1,4 +1,4 @@
LuaSec 1.3.0 LuaSec 1.3.2
=============== ===============
LuaSec depends on OpenSSL, and integrates with LuaSocket to make it LuaSec depends on OpenSSL, and integrates with LuaSocket to make it
easy to add secure connections to any Lua applications or scripts. easy to add secure connections to any Lua applications or scripts.

View File

@ -1,8 +1,8 @@
package = "LuaSec" package = "LuaSec"
version = "1.3.0-1" version = "1.3.2-1"
source = { source = {
url = "git+https://github.com/brunoos/luasec", url = "git+https://github.com/brunoos/luasec",
tag = "v1.3.0", tag = "v1.3.2",
} }
description = { description = {
summary = "A binding for OpenSSL library to provide TLS/SSL communication over LuaSocket.", summary = "A binding for OpenSSL library to provide TLS/SSL communication over LuaSocket.",

View File

@ -4,6 +4,11 @@
local socket = require("socket") local socket = require("socket")
local ssl = require("ssl") local ssl = require("ssl")
if not ssl.config.capabilities.psk then
print("[ERRO] PSK not available")
os.exit(1)
end
-- @param hint (nil | string) -- @param hint (nil | string)
-- @param max_identity_len (number) -- @param max_identity_len (number)
-- @param max_psk_len (number) -- @param max_psk_len (number)

View File

@ -4,6 +4,11 @@
local socket = require("socket") local socket = require("socket")
local ssl = require("ssl") local ssl = require("ssl")
if not ssl.config.capabilities.psk then
print("[ERRO] PSK not available")
os.exit(1)
end
-- @param identity (string) -- @param identity (string)
-- @param max_psk_len (number) -- @param max_psk_len (number)
-- @return psk (string) -- @return psk (string)

View File

@ -0,0 +1,85 @@
--
-- Test the conn:shutdown() function
--
-- Public domain
--
local socket = require("socket")
local ssl = require("ssl")
local params = {
mode = "client",
protocol = "tlsv1_2",
key = "../certs/clientAkey.pem",
certificate = "../certs/clientA.pem",
cafile = "../certs/rootA.pem",
verify = {"peer", "fail_if_no_peer_cert"},
options = "all",
}
-- Wait until socket is ready (for reading or writing)
local function wait(peer)
-- What event blocked us?
local err = peer:want()
print("Want? ", err)
if err == "read" then
socket.select({peer}, nil)
elseif err == "write" then
socket.select(nil, {peer})
elseif err == "nothing" then
return
else
peer:close()
os.exit(1)
end
end
-- Send data
local function send(peer, data)
local offset = 1
while true do
local succ, msg, part = peer:send(data, offset)
if succ then break end
if part then
offset = offset + part
wait(peer)
end
end
end
-- Start the TCP connection
local peer = socket.tcp()
peer:setoption('tcp-nodelay', true)
assert(peer:connect("127.0.0.1", 8888))
peer = assert(ssl.wrap(peer, params))
local ctx = assert(ssl.newcontext(params))
peer:settimeout(0.3)
print("*** Handshake")
while true do
local succ, msg = peer:dohandshake()
if succ then break end
wait(peer)
end
print("*** Send data")
for i = 1, 10 do
send(peer, string.rep('1', 8192))
end
print("*** Shutdown")
while true do
local succ, msg = peer:shutdown()
if succ then break end
print(succ, msg)
if msg ~= "inprogress" then
wait(peer)
end
end
print("*** Done")
peer:close()

View File

@ -0,0 +1,47 @@
--
-- Public domain
--
local socket = require("socket")
local ssl = require("ssl")
local params = {
mode = "server",
protocol = "any",
key = "../certs/serverAkey.pem",
certificate = "../certs/serverA.pem",
cafile = "../certs/rootA.pem",
verify = {"peer", "fail_if_no_peer_cert"},
options = "all",
}
local ctx = assert(ssl.newcontext(params))
local server = socket.tcp()
server:setoption('reuseaddr', true)
assert(server:bind("127.0.0.1", 8888))
server:listen()
while true do
local peer = server:accept()
peer:setoption('tcp-nodelay', true)
print("*** New connection")
peer = assert( ssl.wrap(peer, ctx) )
print("*** Handshake")
assert( peer:dohandshake() )
print("*** Receive")
while true do
local str = peer:receive(1024)
if not str then break end
socket.sleep(0.1)
end
print("*** Done")
peer:close()
end
server:close()

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *
@ -48,8 +48,14 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if !defined(LIBRESSL_VERSION_NUMBER) && ((OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x10101000L) #if !defined(LIBRESSL_VERSION_NUMBER) && ((OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x10101000L || (OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x30000000L)
#define LSEC_OPENSSL_1_1_1 #define LSEC_OPENSSL_ERRNO_BUG
#endif
//------------------------------------------------------------------------------
#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_NO_PSK)
#define LSEC_ENABLE_PSK
#endif #endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *
@ -74,6 +74,12 @@ LSEC_API int luaopen_ssl_config(lua_State *L)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
lua_rawset(L, -3); lua_rawset(L, -3);
#ifdef LSEC_ENABLE_PSK
lua_pushstring(L, "psk");
lua_pushboolean(L, 1);
lua_rawset(L, -3);
#endif
#ifdef LSEC_ENABLE_DANE #ifdef LSEC_ENABLE_DANE
// DANE // DANE
lua_pushstring(L, "dane"); lua_pushstring(L, "dane");

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
@ -707,6 +707,7 @@ static int set_alpn_cb(lua_State *L)
return 1; return 1;
} }
#if defined(LSEC_ENABLE_PSK)
/** /**
* Callback to select the PSK. * Callback to select the PSK.
*/ */
@ -841,6 +842,7 @@ static int set_client_psk_cb(lua_State *L) {
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
#endif
#if defined(LSEC_ENABLE_DANE) #if defined(LSEC_ENABLE_DANE)
/* /*
@ -893,9 +895,11 @@ static luaL_Reg funcs[] = {
{"setdhparam", set_dhparam}, {"setdhparam", set_dhparam},
{"setverify", set_verify}, {"setverify", set_verify},
{"setoptions", set_options}, {"setoptions", set_options},
#if defined(LSEC_ENABLE_PSK)
{"setpskhint", set_psk_identity_hint}, {"setpskhint", set_psk_identity_hint},
{"setserverpskcb", set_server_psk_cb}, {"setserverpskcb", set_server_psk_cb},
{"setclientpskcb", set_client_psk_cb}, {"setclientpskcb", set_client_psk_cb},
#endif
{"setmode", set_mode}, {"setmode", set_mode},
#if !defined(OPENSSL_NO_EC) #if !defined(OPENSSL_NO_EC)
{"setcurve", set_curve}, {"setcurve", set_curve},

View File

@ -2,7 +2,7 @@
#define LSEC_CONTEXT_H #define LSEC_CONTEXT_H
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -1,5 +1,5 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaSec 1.3.0 -- LuaSec 1.3.2
-- --
-- Copyright (C) 2009-2023 PUC-Rio -- Copyright (C) 2009-2023 PUC-Rio
-- --
@ -19,8 +19,8 @@ local try = socket.try
-- Module -- Module
-- --
local _M = { local _M = {
_VERSION = "1.3.0", _VERSION = "1.3.2",
_COPYRIGHT = "LuaSec 1.3.0 - Copyright (C) 2009-2023 PUC-Rio", _COPYRIGHT = "LuaSec 1.3.2 - Copyright (C) 2009-2023 PUC-Rio",
PORT = 443, PORT = 443,
TIMEOUT = 60 TIMEOUT = 60
} }

View File

@ -78,9 +78,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
const char *data = luaL_checklstring(L, 2, &size); const char *data = luaL_checklstring(L, 2, &size);
long start = (long) luaL_optnumber(L, 3, 1); long start = (long) luaL_optnumber(L, 3, 1);
long end = (long) luaL_optnumber(L, 4, -1); long end = (long) luaL_optnumber(L, 4, -1);
#ifdef LUASOCKET_DEBUG timeout_markstart(buf->tm);
p_timeout tm = timeout_markstart(buf->tm);
#endif
if (start < 0) start = (long) (size+start+1); if (start < 0) start = (long) (size+start+1);
if (end < 0) end = (long) (size+end+1); if (end < 0) end = (long) (size+end+1);
if (start < 1) start = (long) 1; if (start < 1) start = (long) 1;
@ -98,7 +96,7 @@ int buffer_meth_send(lua_State *L, p_buffer buf) {
} }
#ifdef LUASOCKET_DEBUG #ifdef LUASOCKET_DEBUG
/* push time elapsed during operation as the last return value */ /* push time elapsed during operation as the last return value */
lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm)); lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
#endif #endif
return lua_gettop(L) - top; return lua_gettop(L) - top;
} }
@ -117,9 +115,7 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
top = 3; top = 3;
} }
part = luaL_optlstring(L, 3, "", &size); part = luaL_optlstring(L, 3, "", &size);
#ifdef LUASOCKET_DEBUG timeout_markstart(buf->tm);
p_timeout tm = timeout_markstart(buf->tm);
#endif
/* initialize buffer with optional extra prefix /* initialize buffer with optional extra prefix
* (useful for concatenating previous partial results) */ * (useful for concatenating previous partial results) */
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
@ -155,7 +151,7 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
} }
#ifdef LUASOCKET_DEBUG #ifdef LUASOCKET_DEBUG
/* push time elapsed during operation as the last return value */ /* push time elapsed during operation as the last return value */
lua_pushnumber(L, timeout_gettime() - timeout_getstart(tm)); lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
#endif #endif
return lua_gettop(L) - top; return lua_gettop(L) - top;
} }

View File

@ -82,7 +82,6 @@ int socket_close(void) {
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
void socket_destroy(p_socket ps) { void socket_destroy(p_socket ps) {
if (*ps != SOCKET_INVALID) { if (*ps != SOCKET_INVALID) {
socket_setblocking(ps);
close(*ps); close(*ps);
*ps = SOCKET_INVALID; *ps = SOCKET_INVALID;
} }
@ -426,7 +425,9 @@ const char *socket_gaistrerror(int err) {
case EAI_MEMORY: return "memory allocation failure"; case EAI_MEMORY: return "memory allocation failure";
case EAI_NONAME: case EAI_NONAME:
return "host or service not provided, or not known"; return "host or service not provided, or not known";
#ifdef EAI_OVERFLOW
case EAI_OVERFLOW: return "argument buffer overflow"; case EAI_OVERFLOW: return "argument buffer overflow";
#endif
#ifdef EAI_PROTOCOL #ifdef EAI_PROTOCOL
case EAI_PROTOCOL: return "resolved protocol is unknown"; case EAI_PROTOCOL: return "resolved protocol is unknown";
#endif #endif

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -2,7 +2,7 @@
#define LSEC_OPTIONS_H #define LSEC_OPTIONS_H
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -18,7 +18,7 @@ end
local function generate(options, version) local function generate(options, version)
print([[ print([[
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
@ -11,6 +11,9 @@
#if defined(WIN32) #if defined(WIN32)
#include <winsock2.h> #include <winsock2.h>
#define LSEC_ERR_INPROGRESS WSAEINPROGRESS
#else
#define LSEC_ERR_INPROGRESS EINPROGRESS
#endif #endif
#include <openssl/ssl.h> #include <openssl/ssl.h>
@ -47,8 +50,8 @@ static int lsec_socket_error()
#if defined(WIN32) #if defined(WIN32)
return WSAGetLastError(); return WSAGetLastError();
#else #else
#if defined(LSEC_OPENSSL_1_1_1) #if defined(LSEC_OPENSSL_ERRNO_BUG)
// Bug in OpenSSL 1.1.1 // Bug in OpenSSL
if (errno == 0) if (errno == 0)
return LSEC_IO_SSL; return LSEC_IO_SSL;
#endif #endif
@ -152,6 +155,46 @@ static int handshake(p_ssl ssl)
return IO_UNKNOWN; return IO_UNKNOWN;
} }
/**
* Perform the TLS/SSL shutdown
*/
static int low_shutdown(p_ssl ssl)
{
int err;
p_timeout tm = timeout_markstart(&ssl->tm);
if (ssl->state == LSEC_STATE_CLOSED)
return IO_CLOSED;
for ( ; ; ) {
ERR_clear_error();
err = SSL_shutdown(ssl->ssl);
if (err == 0) return LSEC_ERR_INPROGRESS;
if (err == 1) return IO_DONE;
ssl->error = SSL_get_error(ssl->ssl, err);
switch (ssl->error) {
case SSL_ERROR_WANT_READ:
err = socket_waitfd(&ssl->sock, WAITFD_R, tm);
if (err == IO_TIMEOUT) return LSEC_IO_SSL;
if (err != IO_DONE) return err;
break;
case SSL_ERROR_WANT_WRITE:
err = socket_waitfd(&ssl->sock, WAITFD_W, tm);
if (err == IO_TIMEOUT) return LSEC_IO_SSL;
if (err != IO_DONE) return err;
break;
case SSL_ERROR_SYSCALL:
if (ERR_peek_error()) {
ssl->error = SSL_ERROR_SSL;
return LSEC_IO_SSL;
}
if (err == 0) return IO_CLOSED;
return lsec_socket_error();
default:
return LSEC_IO_SSL;
}
}
return IO_UNKNOWN;
}
/** /**
* Send data * Send data
*/ */
@ -407,6 +450,21 @@ static int meth_handshake(lua_State *L)
return 2; return 2;
} }
/**
* Lua shutdown function.
*/
static int meth_shutdown(lua_State *L) {
p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
int err = low_shutdown(ssl);
if (err == IO_DONE) {
lua_pushboolean(L, 1);
return 1;
}
lua_pushboolean(L, 0);
lua_pushstring(L, (err == LSEC_ERR_INPROGRESS) ? "inprogress" : ssl_ioerror((void*)ssl, err));
return 2;
}
/** /**
* Close the connection. * Close the connection.
*/ */
@ -947,7 +1005,7 @@ static int meth_getalpn(lua_State *L)
static int meth_copyright(lua_State *L) static int meth_copyright(lua_State *L)
{ {
lua_pushstring(L, "LuaSec 1.3.0 - Copyright (C) 2006-2023 Bruno Silvestre, UFG" lua_pushstring(L, "LuaSec 1.3.2 - Copyright (C) 2006-2023 Bruno Silvestre, UFG"
#if defined(WITH_LUASOCKET) #if defined(WITH_LUASOCKET)
"\nLuaSocket 3.0-RC1 - Copyright (C) 2004-2013 Diego Nehab" "\nLuaSocket 3.0-RC1 - Copyright (C) 2004-2013 Diego Nehab"
#endif #endif
@ -990,6 +1048,7 @@ static int meth_tlsa(lua_State *L)
*/ */
static luaL_Reg methods[] = { static luaL_Reg methods[] = {
{"close", meth_close}, {"close", meth_close},
{"shutdown", meth_shutdown},
{"getalpn", meth_getalpn}, {"getalpn", meth_getalpn},
{"getfd", meth_getfd}, {"getfd", meth_getfd},
{"getfinished", meth_getfinished}, {"getfinished", meth_getfinished},

View File

@ -2,7 +2,7 @@
#define LSEC_SSL_H #define LSEC_SSL_H
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2006-2023 Bruno Silvestre * Copyright (C) 2006-2023 Bruno Silvestre
* *

View File

@ -1,5 +1,5 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- LuaSec 1.3.0 -- LuaSec 1.3.2
-- --
-- Copyright (C) 2006-2023 Bruno Silvestre -- Copyright (C) 2006-2023 Bruno Silvestre
-- --
@ -202,7 +202,7 @@ local function newcontext(cfg)
end end
-- PSK -- PSK
if cfg.psk then if config.capabilities.psk and cfg.psk then
if cfg.mode == "client" then if cfg.mode == "client" then
if type(cfg.psk) ~= "function" then if type(cfg.psk) ~= "function" then
return nil, "invalid PSK configuration" return nil, "invalid PSK configuration"
@ -302,7 +302,7 @@ core.setmethod("info", info)
-- --
local _M = { local _M = {
_VERSION = "1.3.0", _VERSION = "1.3.2",
_COPYRIGHT = core.copyright(), _COPYRIGHT = core.copyright(),
config = config, config = config,
loadcertificate = x509.load, loadcertificate = x509.load,

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
* Copyright (C) 2014-2023 Bruno Silvestre * Copyright (C) 2014-2023 Bruno Silvestre

View File

@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
* LuaSec 1.3.0 * LuaSec 1.3.2
* *
* Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
* Copyright (C) 2013-2023 Bruno Silvestre * Copyright (C) 2013-2023 Bruno Silvestre