diff options
Diffstat (limited to 'vendor/luasec')
35 files changed, 6395 insertions, 0 deletions
diff --git a/vendor/luasec/.gitignore b/vendor/luasec/.gitignore new file mode 100644 index 00000000..355518b2 --- /dev/null +++ b/vendor/luasec/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | /src/*.o | ||
2 | /src/luasocket/*.o | ||
3 | /*.dll | ||
diff --git a/vendor/luasec/CHANGELOG b/vendor/luasec/CHANGELOG new file mode 100644 index 00000000..f7c0a780 --- /dev/null +++ b/vendor/luasec/CHANGELOG | |||
@@ -0,0 +1,257 @@ | |||
1 | -------------------------------------------------------------------------------- | ||
2 | LuaSec 1.3.2 | ||
3 | --------------- | ||
4 | This version includes: | ||
5 | |||
6 | * Fix: place EAI_OVERFLOW inside macro, unbreak build on <10.7 (Sergey Fedorov) | ||
7 | * Fix: Expand workaround for zero errno to OpenSSL 3.0.x (Kim Alvefur) | ||
8 | * Fix: reset block timeout at send or receive (MartinDahlberg) | ||
9 | |||
10 | -------------------------------------------------------------------------------- | ||
11 | LuaSec 1.3.1 | ||
12 | --------------- | ||
13 | This version includes: | ||
14 | |||
15 | * Fix: check if PSK is available | ||
16 | |||
17 | -------------------------------------------------------------------------------- | ||
18 | LuaSec 1.3.0 | ||
19 | --------------- | ||
20 | This version includes: | ||
21 | |||
22 | * Add :getlocalchain() + :getlocalcertificate() to mirror the peer methods (@mwild1) | ||
23 | * Add Pre-Shared Key (PSK) support (@jclab-joseph) | ||
24 | |||
25 | -------------------------------------------------------------------------------- | ||
26 | LuaSec 1.2.0 | ||
27 | --------------- | ||
28 | This version includes: | ||
29 | |||
30 | * Add key material export method | ||
31 | * Backguard compat for openssl on providers, like LTS linuxes | ||
32 | |||
33 | -------------------------------------------------------------------------------- | ||
34 | LuaSec 1.1.0 | ||
35 | --------------- | ||
36 | This version includes: | ||
37 | |||
38 | * Fix missing DANE flag | ||
39 | * Remove unused parameter in https.lua | ||
40 | |||
41 | -------------------------------------------------------------------------------- | ||
42 | LuaSec 1.0.2 | ||
43 | --------------- | ||
44 | This version includes: | ||
45 | |||
46 | * Fix handle SSL_send SYSCALL error without errno | ||
47 | * Fix off by one in cert:validat(notafter) | ||
48 | * Fix meth_get_{sinagure => signature}_name function name | ||
49 | * Fix update the Lua state reference on the selected SSL context after SNI | ||
50 | * Fix ignore SSL_OP_BIT(n) macro and update option.c | ||
51 | |||
52 | -------------------------------------------------------------------------------- | ||
53 | LuaSec 1.0.1 | ||
54 | --------------- | ||
55 | This version includes: | ||
56 | |||
57 | |||
58 | * Fix luaL_buffinit() can use the stack and broke buffer_meth_receive() | ||
59 | |||
60 | -------------------------------------------------------------------------------- | ||
61 | LuaSec 1.0 | ||
62 | --------------- | ||
63 | This version includes: | ||
64 | |||
65 | |||
66 | * Add cert:getsignaturename() | ||
67 | |||
68 | -------------------------------------------------------------------------------- | ||
69 | LuaSec 0.9 | ||
70 | --------------- | ||
71 | This version includes: | ||
72 | |||
73 | |||
74 | * Add DNS-based Authentication of Named Entities (DANE) support | ||
75 | * Add __close() metamethod | ||
76 | * Fix deprecation warnings with OpenSSL 1.1 | ||
77 | * Fix special case listing of TLS 1.3 EC curves | ||
78 | * Fix general_name leak in cert:extensions() | ||
79 | * Fix unexported 'ssl.config' table | ||
80 | * Replace $(LD) with $(CCLD) variable | ||
81 | * Remove multiple definitions of 'ssl_options' variable | ||
82 | * Use tag in git format: v0.9 | ||
83 | |||
84 | -------------------------------------------------------------------------------- | ||
85 | LuaSec 0.8.2 | ||
86 | --------------- | ||
87 | This version includes: | ||
88 | |||
89 | * Fix unexported 'ssl.config' table (backported) | ||
90 | |||
91 | -------------------------------------------------------------------------------- | ||
92 | LuaSec 0.8.1 | ||
93 | --------------- | ||
94 | This version includes: | ||
95 | |||
96 | * Fix general_name leak in cert:extensions() (backported) | ||
97 | |||
98 | -------------------------------------------------------------------------------- | ||
99 | LuaSec 0.8 | ||
100 | --------------- | ||
101 | This version includes: | ||
102 | |||
103 | * Add support to ALPN | ||
104 | * Add support to TLS 1.3 | ||
105 | * Add support to multiple certificates | ||
106 | * Add timeout to https module (https.TIMEOUT) | ||
107 | * Drop support to SSL 3.0 | ||
108 | * Drop support to TLS 1.0 from https module | ||
109 | * Fix invalid reference to Lua state | ||
110 | * Fix memory leak when get certficate extensions | ||
111 | |||
112 | -------------------------------------------------------------------------------- | ||
113 | LuaSec 0.7.2 | ||
114 | --------------- | ||
115 | This version includes: | ||
116 | |||
117 | * Fix unexported 'ssl.config' table (backported) | ||
118 | |||
119 | -------------------------------------------------------------------------------- | ||
120 | LuaSec 0.7.1 | ||
121 | --------------- | ||
122 | This version includes: | ||
123 | |||
124 | * Fix general_name leak in cert:extensions() (backported) | ||
125 | |||
126 | -------------------------------------------------------------------------------- | ||
127 | LuaSec 0.7 | ||
128 | --------------- | ||
129 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
130 | easy to add secure connections to any Lua applications or scripts. | ||
131 | |||
132 | Documentation: https://github.com/brunoos/luasec/wiki | ||
133 | |||
134 | This version includes: | ||
135 | |||
136 | * Add support to OpenSSL 1.1.0 | ||
137 | * Add support to elliptic curves list | ||
138 | * Add ssl.config that exports some OpenSSL information | ||
139 | * Add integration with luaossl | ||
140 | |||
141 | -------------------------------------------------------------------------------- | ||
142 | LuaSec 0.6 | ||
143 | ------------ | ||
144 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
145 | easy to add secure connections to any Lua applications or scripts. | ||
146 | |||
147 | Documentation: https://github.com/brunoos/luasec/wiki | ||
148 | |||
149 | This version includes: | ||
150 | |||
151 | * Lua 5.2 and 5.3 compatibility | ||
152 | |||
153 | * Context module: | ||
154 | - Add ctx:checkkey() | ||
155 | |||
156 | * SSL module: | ||
157 | - Add conn:sni() and conn:getsniname() | ||
158 | |||
159 | * Context options: | ||
160 | - Add "any" protocol ("sslv23" is deprecated) | ||
161 | |||
162 | * HTTPS module: | ||
163 | - Using "any" protocol without SSLv2/SSLv3, by default | ||
164 | |||
165 | * X509 module: | ||
166 | - Human readable IP address | ||
167 | - Add cert:issued() | ||
168 | - Add cert:pubkey() | ||
169 | |||
170 | * Some bug fixes | ||
171 | |||
172 | |||
173 | => Thanks to everyone who collaborate with LuaSec <= | ||
174 | |||
175 | -------------------------------------------------------------------------------- | ||
176 | LuaSec 0.5 | ||
177 | ------------ | ||
178 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
179 | easy to add secure connections to any Lua applications or scripts. | ||
180 | |||
181 | This version includes: | ||
182 | |||
183 | * A new certificate (X509) API, which supports: | ||
184 | - Reading the subject (identity) and issuer of the certificate. | ||
185 | - Reading various X509 extensions, including email and dnsName. | ||
186 | - Converting certificates to and from the standard ASCII PEM | ||
187 | format. | ||
188 | - Generating the fingerprint/digest of a certificate (using SHA1, | ||
189 | SHA256 or SHA512). | ||
190 | - Reading the certificate's expiration, serial number, and other | ||
191 | info. | ||
192 | |||
193 | * The ability to get more detailed information from OpenSSL about | ||
194 | why a certificate failed verification, for each certificate in the | ||
195 | chain. | ||
196 | |||
197 | * Flags to force acceptance of invalid certificates, e.g. to allow | ||
198 | the use of self-signed certificates in a Trust On First Use model. | ||
199 | |||
200 | * Flags to control checking CRLs for certificate revocation status. | ||
201 | |||
202 | * Support for ECDH cipher suites. | ||
203 | |||
204 | * An API to get the TLS 'finished' messages used for SASL channel | ||
205 | binding (e.g. the SCRAM PLUS mechanisms). | ||
206 | |||
207 | The work in this release was undertaken by Kim Alvefur, Paul Aurich, | ||
208 | Tobias Markmann, Bruno Silvestre and Matthew Wild. | ||
209 | |||
210 | -------------------------------------------------------------------------------- | ||
211 | LuaSec 0.4.1 | ||
212 | ------------ | ||
213 | - SSL options updated --- based on OpenSSL 1.0.0d. | ||
214 | - Activate SSL_MODE_RELEASE_BUFFERS by default if it is available. | ||
215 | (thanks Prosody project) | ||
216 | |||
217 | --------------------------------------------------------------------------------- | ||
218 | LuaSec 0.4 | ||
219 | ------------ | ||
220 | - Add option 'no_ticket' (included in OpenSSL 0.9.8f). | ||
221 | - Add HTTPS module. (thanks Tomas Guisasola and Pablo Musa) | ||
222 | |||
223 | -------------------------------------------------------------------------------- | ||
224 | LuaSec 0.3.3 | ||
225 | ------------ | ||
226 | - BUG: Clear the error queue before call I/O functions (see SSL_get_error | ||
227 | manual). | ||
228 | (thanks Matthew Wild) | ||
229 | |||
230 | -------------------------------------------------------------------------------- | ||
231 | LuaSec 0.3.2 | ||
232 | ------------ | ||
233 | - BUG: Windows uses a different way to report socket error. | ||
234 | (thanks Sebastien Perin) | ||
235 | |||
236 | -------------------------------------------------------------------------------- | ||
237 | LuaSec 0.3.1 | ||
238 | ------------ | ||
239 | - BUG: receive("a") returns 'closed' error instead of the content when the | ||
240 | SSL/TLS connection is shut down cleanly. (thanks Matthias Diener) | ||
241 | |||
242 | -------------------------------------------------------------------------------- | ||
243 | LuaSec 0.3 | ||
244 | ---------- | ||
245 | - Add functions ssl.rawcontext() and ssl.rawconnection() | ||
246 | - Add support to encrypted key password. (thanks Norbert Kiesel) | ||
247 | |||
248 | -------------------------------------------------------------------------------- | ||
249 | LuaSec 0.2.1 | ||
250 | ------------ | ||
251 | - 'key' and 'certificate' configurations become optional. (thanks René Rebe) | ||
252 | - Add '_VERSION' variable to module. | ||
253 | |||
254 | -------------------------------------------------------------------------------- | ||
255 | LuaSec 0.2 | ||
256 | ---------- | ||
257 | Initial version | ||
diff --git a/vendor/luasec/INSTALL b/vendor/luasec/INSTALL new file mode 100644 index 00000000..07b94df8 --- /dev/null +++ b/vendor/luasec/INSTALL | |||
@@ -0,0 +1,39 @@ | |||
1 | LuaSec 1.3.2 | ||
2 | ------------ | ||
3 | |||
4 | * OpenSSL options: | ||
5 | |||
6 | By default, this version includes options for OpenSSL 3.0.8 | ||
7 | |||
8 | If you need to generate the options for a different version of OpenSSL: | ||
9 | |||
10 | $ cd src | ||
11 | $ lua options.lua -g /usr/include/openssl/ssl.h > options.c | ||
12 | |||
13 | -------------------------------------------------------------------------------- | ||
14 | |||
15 | * On Linux, BSD, and Mac OS X: | ||
16 | |||
17 | - Edit 'Makefile' | ||
18 | * Inform the path to where install the Lua modules (LUAPATH) and binaries | ||
19 | modules (LUACPATH) | ||
20 | * If Lua or OpenSSL are not in the default path, set the | ||
21 | variables INCDIR and LIBDIR. | ||
22 | * For Mac OS X, set the variable MACOSX_VERSION. | ||
23 | |||
24 | - Use 'make <platform>' to compile | ||
25 | * Platforms: linux, bsd, or macosx | ||
26 | |||
27 | - Use 'make install' to install the modules. | ||
28 | |||
29 | -------------------------------------------------------------------------------- | ||
30 | |||
31 | * On Windows: | ||
32 | |||
33 | - Use the Visual C++ project to compile the library. | ||
34 | |||
35 | - Copy the 'ssl.lua' file to some place in your LUA_PATH. | ||
36 | |||
37 | - Copy the 'ssl.dll' file to some place in your LUA_CPATH. | ||
38 | |||
39 | - Create a directory 'ssl' in your LUA_PATH and copy 'https.lua' to it. | ||
diff --git a/vendor/luasec/LICENSE b/vendor/luasec/LICENSE new file mode 100644 index 00000000..09df9964 --- /dev/null +++ b/vendor/luasec/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | LuaSec 1.3.2 license | ||
2 | Copyright (C) 2006-2023 Bruno Silvestre, UFG | ||
3 | |||
4 | Permission is hereby granted, free of charge, to any person obtaining | ||
5 | a copy of this software and associated documentation files (the | ||
6 | "Software"), to deal in the Software without restriction, including | ||
7 | without limitation the rights to use, copy, modify, merge, publish, | ||
8 | distribute, sublicense, and/or sell copies of the Software, and to | ||
9 | permit persons to whom the Software is furnished to do so, subject to | ||
10 | the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be | ||
13 | included in all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
diff --git a/vendor/luasec/README.md b/vendor/luasec/README.md new file mode 100644 index 00000000..afdce4ee --- /dev/null +++ b/vendor/luasec/README.md | |||
@@ -0,0 +1,6 @@ | |||
1 | LuaSec 1.3.2 | ||
2 | =============== | ||
3 | LuaSec depends on OpenSSL, and integrates with LuaSocket to make it | ||
4 | easy to add secure connections to any Lua applications or scripts. | ||
5 | |||
6 | Documentation: https://github.com/brunoos/luasec/wiki | ||
diff --git a/vendor/luasec/luasec-1.3.2-1.rockspec b/vendor/luasec/luasec-1.3.2-1.rockspec new file mode 100644 index 00000000..a6a36d78 --- /dev/null +++ b/vendor/luasec/luasec-1.3.2-1.rockspec | |||
@@ -0,0 +1,105 @@ | |||
1 | package = "LuaSec" | ||
2 | version = "1.3.2-1" | ||
3 | source = { | ||
4 | url = "git+https://github.com/brunoos/luasec", | ||
5 | tag = "v1.3.2", | ||
6 | } | ||
7 | description = { | ||
8 | summary = "A binding for OpenSSL library to provide TLS/SSL communication over LuaSocket.", | ||
9 | detailed = "This version delegates to LuaSocket the TCP connection establishment between the client and server. Then LuaSec uses this connection to start a secure TLS/SSL session.", | ||
10 | homepage = "https://github.com/brunoos/luasec/wiki", | ||
11 | license = "MIT" | ||
12 | } | ||
13 | dependencies = { | ||
14 | "lua >= 5.1", "luasocket" | ||
15 | } | ||
16 | external_dependencies = { | ||
17 | platforms = { | ||
18 | unix = { | ||
19 | OPENSSL = { | ||
20 | header = "openssl/ssl.h", | ||
21 | library = "ssl" | ||
22 | } | ||
23 | }, | ||
24 | windows = { | ||
25 | OPENSSL = { | ||
26 | header = "openssl/ssl.h", | ||
27 | } | ||
28 | }, | ||
29 | } | ||
30 | } | ||
31 | build = { | ||
32 | type = "builtin", | ||
33 | copy_directories = { | ||
34 | "samples" | ||
35 | }, | ||
36 | platforms = { | ||
37 | unix = { | ||
38 | install = { | ||
39 | lib = { | ||
40 | "ssl.so" | ||
41 | }, | ||
42 | lua = { | ||
43 | "src/ssl.lua", ['ssl.https'] = "src/https.lua" | ||
44 | } | ||
45 | }, | ||
46 | modules = { | ||
47 | ssl = { | ||
48 | defines = { | ||
49 | "WITH_LUASOCKET", "LUASOCKET_DEBUG", | ||
50 | }, | ||
51 | incdirs = { | ||
52 | "$(OPENSSL_INCDIR)", "src/", "src/luasocket", | ||
53 | }, | ||
54 | libdirs = { | ||
55 | "$(OPENSSL_LIBDIR)" | ||
56 | }, | ||
57 | libraries = { | ||
58 | "ssl", "crypto" | ||
59 | }, | ||
60 | sources = { | ||
61 | "src/options.c", "src/config.c", "src/ec.c", | ||
62 | "src/x509.c", "src/context.c", "src/ssl.c", | ||
63 | "src/luasocket/buffer.c", "src/luasocket/io.c", | ||
64 | "src/luasocket/timeout.c", "src/luasocket/usocket.c" | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | }, | ||
69 | windows = { | ||
70 | install = { | ||
71 | lib = { | ||
72 | "ssl.dll" | ||
73 | }, | ||
74 | lua = { | ||
75 | "src/ssl.lua", ['ssl.https'] = "src/https.lua" | ||
76 | } | ||
77 | }, | ||
78 | modules = { | ||
79 | ssl = { | ||
80 | defines = { | ||
81 | "WIN32", "NDEBUG", "_WINDOWS", "_USRDLL", "LSEC_EXPORTS", "BUFFER_DEBUG", "LSEC_API=__declspec(dllexport)", | ||
82 | "WITH_LUASOCKET", "LUASOCKET_DEBUG", | ||
83 | "LUASEC_INET_NTOP", "WINVER=0x0501", "_WIN32_WINNT=0x0501", "NTDDI_VERSION=0x05010300" | ||
84 | }, | ||
85 | libdirs = { | ||
86 | "$(OPENSSL_LIBDIR)", | ||
87 | "$(OPENSSL_BINDIR)", | ||
88 | }, | ||
89 | libraries = { | ||
90 | "libssl", "libcrypto", "ws2_32" | ||
91 | }, | ||
92 | incdirs = { | ||
93 | "$(OPENSSL_INCDIR)", "src/", "src/luasocket" | ||
94 | }, | ||
95 | sources = { | ||
96 | "src/options.c", "src/config.c", "src/ec.c", | ||
97 | "src/x509.c", "src/context.c", "src/ssl.c", | ||
98 | "src/luasocket/buffer.c", "src/luasocket/io.c", | ||
99 | "src/luasocket/timeout.c", "src/luasocket/wsocket.c" | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | } | ||
diff --git a/vendor/luasec/src/Makefile b/vendor/luasec/src/Makefile new file mode 100644 index 00000000..9b06a038 --- /dev/null +++ b/vendor/luasec/src/Makefile | |||
@@ -0,0 +1,66 @@ | |||
1 | CMOD=ssl.so | ||
2 | LMOD=ssl.lua | ||
3 | |||
4 | OBJS= \ | ||
5 | options.o \ | ||
6 | x509.o \ | ||
7 | context.o \ | ||
8 | ssl.o \ | ||
9 | config.o \ | ||
10 | ec.o | ||
11 | |||
12 | LIBS=-lssl -lcrypto -lluasocket | ||
13 | |||
14 | WARN=-Wall -pedantic | ||
15 | |||
16 | BSD_CFLAGS=-O2 -fPIC $(WARN) $(INCDIR) $(DEFS) | ||
17 | BSD_LDFLAGS=-O -fPIC -shared $(LIBDIR) | ||
18 | |||
19 | LNX_CFLAGS=-O2 -fPIC $(WARN) $(INCDIR) $(DEFS) | ||
20 | LNX_LDFLAGS=-O -fPIC -shared $(LIBDIR) | ||
21 | |||
22 | MAC_ENV=env MACOSX_DEPLOYMENT_TARGET='$(MACVER)' | ||
23 | MAC_CFLAGS=-O2 -fno-common $(WARN) $(INCDIR) $(DEFS) | ||
24 | MAC_LDFLAGS=-bundle -undefined dynamic_lookup $(LIBDIR) | ||
25 | |||
26 | INSTALL = install | ||
27 | CC ?= cc | ||
28 | CCLD ?= $(MYENV) $(CC) | ||
29 | CFLAGS += $(MYCFLAGS) | ||
30 | LDFLAGS += $(MYLDFLAGS) | ||
31 | |||
32 | .PHONY: all clean install none linux bsd macosx luasocket | ||
33 | |||
34 | all: | ||
35 | |||
36 | install: $(CMOD) $(LMOD) | ||
37 | $(INSTALL) -d $(DESTDIR)$(LUAPATH)/ssl $(DESTDIR)$(LUACPATH) | ||
38 | $(INSTALL) $(CMOD) $(DESTDIR)$(LUACPATH) | ||
39 | $(INSTALL) -m644 $(LMOD) $(DESTDIR)$(LUAPATH) | ||
40 | $(INSTALL) -m644 https.lua $(DESTDIR)$(LUAPATH)/ssl | ||
41 | |||
42 | linux: | ||
43 | @$(MAKE) $(CMOD) MYCFLAGS="$(LNX_CFLAGS)" MYLDFLAGS="$(LNX_LDFLAGS)" EXTRA="$(EXTRA)" | ||
44 | |||
45 | bsd: | ||
46 | @$(MAKE) $(CMOD) MYCFLAGS="$(BSD_CFLAGS)" MYLDFLAGS="$(BSD_LDFLAGS)" EXTRA="$(EXTRA)" | ||
47 | |||
48 | macosx: | ||
49 | @$(MAKE) $(CMOD) MYCFLAGS="$(MAC_CFLAGS)" MYLDFLAGS="$(MAC_LDFLAGS)" MYENV="$(MAC_ENV)" EXTRA="$(EXTRA)" | ||
50 | |||
51 | luasocket: | ||
52 | @cd luasocket && $(MAKE) | ||
53 | |||
54 | $(CMOD): $(EXTRA) $(OBJS) | ||
55 | $(CCLD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) | ||
56 | |||
57 | clean: | ||
58 | cd luasocket && $(MAKE) clean | ||
59 | rm -f $(OBJS) $(CMOD) | ||
60 | |||
61 | options.o: options.h options.c | ||
62 | ec.o: ec.c ec.h | ||
63 | x509.o: x509.c x509.h compat.h | ||
64 | context.o: context.c context.h ec.h compat.h options.h | ||
65 | ssl.o: ssl.c ssl.h context.h x509.h compat.h | ||
66 | config.o: config.c ec.h options.h compat.h | ||
diff --git a/vendor/luasec/src/compat.h b/vendor/luasec/src/compat.h new file mode 100644 index 00000000..9f97e2a6 --- /dev/null +++ b/vendor/luasec/src/compat.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #ifndef LSEC_COMPAT_H | ||
9 | #define LSEC_COMPAT_H | ||
10 | |||
11 | #include <openssl/ssl.h> | ||
12 | |||
13 | //------------------------------------------------------------------------------ | ||
14 | |||
15 | #if defined(_WIN32) | ||
16 | #define LSEC_API __declspec(dllexport) | ||
17 | #else | ||
18 | #define LSEC_API extern | ||
19 | #endif | ||
20 | |||
21 | //------------------------------------------------------------------------------ | ||
22 | |||
23 | #if (LUA_VERSION_NUM == 501) | ||
24 | |||
25 | #define luaL_testudata(L, ud, tname) lsec_testudata(L, ud, tname) | ||
26 | #define setfuncs(L, R) luaL_register(L, NULL, R) | ||
27 | #define lua_rawlen(L, i) lua_objlen(L, i) | ||
28 | |||
29 | #ifndef luaL_newlib | ||
30 | #define luaL_newlib(L, R) do { lua_newtable(L); luaL_register(L, NULL, R); } while(0) | ||
31 | #endif | ||
32 | |||
33 | #else | ||
34 | #define setfuncs(L, R) luaL_setfuncs(L, R, 0) | ||
35 | #endif | ||
36 | |||
37 | //------------------------------------------------------------------------------ | ||
38 | |||
39 | #if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x1010000fL)) | ||
40 | #define LSEC_ENABLE_DANE | ||
41 | #endif | ||
42 | |||
43 | //------------------------------------------------------------------------------ | ||
44 | |||
45 | #if !((defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL)) || (OPENSSL_VERSION_NUMBER < 0x1010000fL)) | ||
46 | #define LSEC_API_OPENSSL_1_1_0 | ||
47 | #endif | ||
48 | |||
49 | //------------------------------------------------------------------------------ | ||
50 | |||
51 | #if !defined(LIBRESSL_VERSION_NUMBER) && ((OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x10101000L || (OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x30000000L) | ||
52 | #define LSEC_OPENSSL_ERRNO_BUG | ||
53 | #endif | ||
54 | |||
55 | //------------------------------------------------------------------------------ | ||
56 | |||
57 | #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_NO_PSK) | ||
58 | #define LSEC_ENABLE_PSK | ||
59 | #endif | ||
60 | |||
61 | //------------------------------------------------------------------------------ | ||
62 | |||
63 | #endif | ||
diff --git a/vendor/luasec/src/config.c b/vendor/luasec/src/config.c new file mode 100644 index 00000000..5f0e2c60 --- /dev/null +++ b/vendor/luasec/src/config.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #include "compat.h" | ||
9 | #include "options.h" | ||
10 | #include "ec.h" | ||
11 | |||
12 | /** | ||
13 | * Registre the module. | ||
14 | */ | ||
15 | LSEC_API int luaopen_ssl_config(lua_State *L) | ||
16 | { | ||
17 | lsec_ssl_option_t *opt; | ||
18 | |||
19 | lua_newtable(L); | ||
20 | |||
21 | // Options | ||
22 | lua_pushstring(L, "options"); | ||
23 | lua_newtable(L); | ||
24 | for (opt = lsec_get_ssl_options(); opt->name; opt++) { | ||
25 | lua_pushstring(L, opt->name); | ||
26 | lua_pushboolean(L, 1); | ||
27 | lua_rawset(L, -3); | ||
28 | } | ||
29 | lua_rawset(L, -3); | ||
30 | |||
31 | // Protocols | ||
32 | lua_pushstring(L, "protocols"); | ||
33 | lua_newtable(L); | ||
34 | |||
35 | lua_pushstring(L, "tlsv1"); | ||
36 | lua_pushboolean(L, 1); | ||
37 | lua_rawset(L, -3); | ||
38 | lua_pushstring(L, "tlsv1_1"); | ||
39 | lua_pushboolean(L, 1); | ||
40 | lua_rawset(L, -3); | ||
41 | lua_pushstring(L, "tlsv1_2"); | ||
42 | lua_pushboolean(L, 1); | ||
43 | lua_rawset(L, -3); | ||
44 | #ifdef TLS1_3_VERSION | ||
45 | lua_pushstring(L, "tlsv1_3"); | ||
46 | lua_pushboolean(L, 1); | ||
47 | lua_rawset(L, -3); | ||
48 | #endif | ||
49 | |||
50 | lua_rawset(L, -3); | ||
51 | |||
52 | // Algorithms | ||
53 | lua_pushstring(L, "algorithms"); | ||
54 | lua_newtable(L); | ||
55 | |||
56 | #ifndef OPENSSL_NO_EC | ||
57 | lua_pushstring(L, "ec"); | ||
58 | lua_pushboolean(L, 1); | ||
59 | lua_rawset(L, -3); | ||
60 | #endif | ||
61 | lua_rawset(L, -3); | ||
62 | |||
63 | // Curves | ||
64 | lua_pushstring(L, "curves"); | ||
65 | lsec_get_curves(L); | ||
66 | lua_rawset(L, -3); | ||
67 | |||
68 | // Capabilities | ||
69 | lua_pushstring(L, "capabilities"); | ||
70 | lua_newtable(L); | ||
71 | |||
72 | // ALPN | ||
73 | lua_pushstring(L, "alpn"); | ||
74 | lua_pushboolean(L, 1); | ||
75 | lua_rawset(L, -3); | ||
76 | |||
77 | #ifdef LSEC_ENABLE_PSK | ||
78 | lua_pushstring(L, "psk"); | ||
79 | lua_pushboolean(L, 1); | ||
80 | lua_rawset(L, -3); | ||
81 | #endif | ||
82 | |||
83 | #ifdef LSEC_ENABLE_DANE | ||
84 | // DANE | ||
85 | lua_pushstring(L, "dane"); | ||
86 | #ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS | ||
87 | lua_createtable(L, 0, 1); | ||
88 | lua_pushstring(L, "no_ee_namechecks"); | ||
89 | lua_pushboolean(L, 1); | ||
90 | lua_rawset(L, -3); | ||
91 | #else | ||
92 | lua_pushboolean(L, 1); | ||
93 | #endif | ||
94 | lua_rawset(L, -3); | ||
95 | #endif | ||
96 | |||
97 | #ifndef OPENSSL_NO_EC | ||
98 | lua_pushstring(L, "curves_list"); | ||
99 | lua_pushboolean(L, 1); | ||
100 | lua_rawset(L, -3); | ||
101 | lua_pushstring(L, "ecdh_auto"); | ||
102 | lua_pushboolean(L, 1); | ||
103 | lua_rawset(L, -3); | ||
104 | #endif | ||
105 | lua_rawset(L, -3); | ||
106 | |||
107 | return 1; | ||
108 | } | ||
diff --git a/vendor/luasec/src/context.c b/vendor/luasec/src/context.c new file mode 100644 index 00000000..881ebb90 --- /dev/null +++ b/vendor/luasec/src/context.c | |||
@@ -0,0 +1,1099 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #include <string.h> | ||
10 | |||
11 | #if defined(WIN32) | ||
12 | #include <windows.h> | ||
13 | #endif | ||
14 | |||
15 | #include <openssl/ssl.h> | ||
16 | #include <openssl/err.h> | ||
17 | #include <openssl/x509.h> | ||
18 | #include <openssl/x509v3.h> | ||
19 | #include <openssl/x509_vfy.h> | ||
20 | #include <openssl/dh.h> | ||
21 | |||
22 | #include <lua.h> | ||
23 | #include <lauxlib.h> | ||
24 | |||
25 | #include "compat.h" | ||
26 | #include "context.h" | ||
27 | #include "options.h" | ||
28 | |||
29 | #ifndef OPENSSL_NO_EC | ||
30 | #include <openssl/ec.h> | ||
31 | #include "ec.h" | ||
32 | #endif | ||
33 | |||
34 | /*--------------------------- Auxiliary Functions ----------------------------*/ | ||
35 | |||
36 | /** | ||
37 | * Return the context. | ||
38 | */ | ||
39 | static p_context checkctx(lua_State *L, int idx) | ||
40 | { | ||
41 | return (p_context)luaL_checkudata(L, idx, "SSL:Context"); | ||
42 | } | ||
43 | |||
44 | static p_context testctx(lua_State *L, int idx) | ||
45 | { | ||
46 | return (p_context)luaL_testudata(L, idx, "SSL:Context"); | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * Prepare the SSL options flag. | ||
51 | */ | ||
52 | static int set_option_flag(const char *opt, unsigned long *flag) | ||
53 | { | ||
54 | lsec_ssl_option_t *p; | ||
55 | for (p = lsec_get_ssl_options(); p->name; p++) { | ||
56 | if (!strcmp(opt, p->name)) { | ||
57 | *flag |= p->code; | ||
58 | return 1; | ||
59 | } | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
65 | /** | ||
66 | * Find the protocol. | ||
67 | */ | ||
68 | static const SSL_METHOD* str2method(const char *method, int *vmin, int *vmax) | ||
69 | { | ||
70 | (void)vmin; | ||
71 | (void)vmax; | ||
72 | if (!strcmp(method, "any")) return SSLv23_method(); | ||
73 | if (!strcmp(method, "sslv23")) return SSLv23_method(); // deprecated | ||
74 | if (!strcmp(method, "tlsv1")) return TLSv1_method(); | ||
75 | if (!strcmp(method, "tlsv1_1")) return TLSv1_1_method(); | ||
76 | if (!strcmp(method, "tlsv1_2")) return TLSv1_2_method(); | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | #else | ||
81 | |||
82 | /** | ||
83 | * Find the protocol. | ||
84 | */ | ||
85 | static const SSL_METHOD* str2method(const char *method, int *vmin, int *vmax) | ||
86 | { | ||
87 | if (!strcmp(method, "any") || !strcmp(method, "sslv23")) { // 'sslv23' is deprecated | ||
88 | *vmin = 0; | ||
89 | *vmax = 0; | ||
90 | return TLS_method(); | ||
91 | } | ||
92 | else if (!strcmp(method, "tlsv1")) { | ||
93 | *vmin = TLS1_VERSION; | ||
94 | *vmax = TLS1_VERSION; | ||
95 | return TLS_method(); | ||
96 | } | ||
97 | else if (!strcmp(method, "tlsv1_1")) { | ||
98 | *vmin = TLS1_1_VERSION; | ||
99 | *vmax = TLS1_1_VERSION; | ||
100 | return TLS_method(); | ||
101 | } | ||
102 | else if (!strcmp(method, "tlsv1_2")) { | ||
103 | *vmin = TLS1_2_VERSION; | ||
104 | *vmax = TLS1_2_VERSION; | ||
105 | return TLS_method(); | ||
106 | } | ||
107 | #if defined(TLS1_3_VERSION) | ||
108 | else if (!strcmp(method, "tlsv1_3")) { | ||
109 | *vmin = TLS1_3_VERSION; | ||
110 | *vmax = TLS1_3_VERSION; | ||
111 | return TLS_method(); | ||
112 | } | ||
113 | #endif | ||
114 | return NULL; | ||
115 | } | ||
116 | #endif | ||
117 | |||
118 | /** | ||
119 | * Prepare the SSL handshake verify flag. | ||
120 | */ | ||
121 | static int set_verify_flag(const char *str, int *flag) | ||
122 | { | ||
123 | if (!strcmp(str, "none")) { | ||
124 | *flag |= SSL_VERIFY_NONE; | ||
125 | return 1; | ||
126 | } | ||
127 | if (!strcmp(str, "peer")) { | ||
128 | *flag |= SSL_VERIFY_PEER; | ||
129 | return 1; | ||
130 | } | ||
131 | if (!strcmp(str, "client_once")) { | ||
132 | *flag |= SSL_VERIFY_CLIENT_ONCE; | ||
133 | return 1; | ||
134 | } | ||
135 | if (!strcmp(str, "fail_if_no_peer_cert")) { | ||
136 | *flag |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | ||
137 | return 1; | ||
138 | } | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * Password callback for reading the private key. | ||
144 | */ | ||
145 | static int passwd_cb(char *buf, int size, int flag, void *udata) | ||
146 | { | ||
147 | lua_State *L = (lua_State*)udata; | ||
148 | switch (lua_type(L, 3)) { | ||
149 | case LUA_TFUNCTION: | ||
150 | lua_pushvalue(L, 3); | ||
151 | lua_call(L, 0, 1); | ||
152 | if (lua_type(L, -1) != LUA_TSTRING) { | ||
153 | lua_pop(L, 1); /* Remove the result from the stack */ | ||
154 | return 0; | ||
155 | } | ||
156 | /* fallback */ | ||
157 | case LUA_TSTRING: | ||
158 | strncpy(buf, lua_tostring(L, -1), size); | ||
159 | lua_pop(L, 1); /* Remove the result from the stack */ | ||
160 | buf[size-1] = '\0'; | ||
161 | return (int)strlen(buf); | ||
162 | } | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Add an error related to a depth certificate of the chain. | ||
168 | */ | ||
169 | static void add_cert_error(lua_State *L, SSL *ssl, int err, int depth) | ||
170 | { | ||
171 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
172 | lua_pushlightuserdata(L, (void*)ssl); | ||
173 | lua_gettable(L, -2); | ||
174 | if (lua_isnil(L, -1)) { | ||
175 | lua_pop(L, 1); | ||
176 | /* Create an error table for this connection */ | ||
177 | lua_newtable(L); | ||
178 | lua_pushlightuserdata(L, (void*)ssl); | ||
179 | lua_pushvalue(L, -2); /* keep the table on stack */ | ||
180 | lua_settable(L, -4); | ||
181 | } | ||
182 | lua_rawgeti(L, -1, depth+1); | ||
183 | /* If the table doesn't exist, create it */ | ||
184 | if (lua_isnil(L, -1)) { | ||
185 | lua_pop(L, 1); /* remove 'nil' from stack */ | ||
186 | lua_newtable(L); | ||
187 | lua_pushvalue(L, -1); /* keep the table on stack */ | ||
188 | lua_rawseti(L, -3, depth+1); | ||
189 | } | ||
190 | lua_pushstring(L, X509_verify_cert_error_string(err)); | ||
191 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
192 | /* Clear the stack */ | ||
193 | lua_pop(L, 3); | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * Call Lua user function to get the DH key. | ||
198 | */ | ||
199 | static DH *dhparam_cb(SSL *ssl, int is_export, int keylength) | ||
200 | { | ||
201 | BIO *bio; | ||
202 | lua_State *L; | ||
203 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
204 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
205 | |||
206 | L = pctx->L; | ||
207 | |||
208 | /* Get the callback */ | ||
209 | luaL_getmetatable(L, "SSL:DH:Registry"); | ||
210 | lua_pushlightuserdata(L, (void*)ctx); | ||
211 | lua_gettable(L, -2); | ||
212 | |||
213 | /* Invoke the callback */ | ||
214 | lua_pushboolean(L, is_export); | ||
215 | lua_pushnumber(L, keylength); | ||
216 | lua_call(L, 2, 1); | ||
217 | |||
218 | /* Load parameters from returned value */ | ||
219 | if (lua_type(L, -1) != LUA_TSTRING) { | ||
220 | lua_pop(L, 2); /* Remove values from stack */ | ||
221 | return NULL; | ||
222 | } | ||
223 | |||
224 | bio = BIO_new_mem_buf((void*)lua_tostring(L, -1), lua_rawlen(L, -1)); | ||
225 | if (bio) { | ||
226 | pctx->dh_param = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | ||
227 | BIO_free(bio); | ||
228 | } | ||
229 | |||
230 | lua_pop(L, 2); /* Remove values from stack */ | ||
231 | return pctx->dh_param; | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * Set the "ignore purpose" before to start verifing the certificate chain. | ||
236 | */ | ||
237 | static int cert_verify_cb(X509_STORE_CTX *x509_ctx, void *ptr) | ||
238 | { | ||
239 | int verify; | ||
240 | lua_State *L; | ||
241 | SSL_CTX *ctx = (SSL_CTX*)ptr; | ||
242 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
243 | |||
244 | L = pctx->L; | ||
245 | |||
246 | /* Get verify flags */ | ||
247 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
248 | lua_pushlightuserdata(L, (void*)ctx); | ||
249 | lua_gettable(L, -2); | ||
250 | verify = (int)lua_tonumber(L, -1); | ||
251 | |||
252 | lua_pop(L, 2); /* Remove values from stack */ | ||
253 | |||
254 | if (verify & LSEC_VERIFY_IGNORE_PURPOSE) { | ||
255 | /* Set parameters to ignore the server purpose */ | ||
256 | X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(x509_ctx); | ||
257 | if (param) { | ||
258 | X509_VERIFY_PARAM_set_purpose(param, X509_PURPOSE_SSL_SERVER); | ||
259 | X509_VERIFY_PARAM_set_trust(param, X509_TRUST_SSL_SERVER); | ||
260 | } | ||
261 | } | ||
262 | /* Call OpenSSL standard verification function */ | ||
263 | return X509_verify_cert(x509_ctx); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * This callback implements the "continue on error" flag and log the errors. | ||
268 | */ | ||
269 | static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) | ||
270 | { | ||
271 | int err; | ||
272 | int verify; | ||
273 | SSL *ssl; | ||
274 | SSL_CTX *ctx; | ||
275 | p_context pctx; | ||
276 | lua_State *L; | ||
277 | |||
278 | /* Short-circuit optimization */ | ||
279 | if (preverify_ok) | ||
280 | return 1; | ||
281 | |||
282 | ssl = X509_STORE_CTX_get_ex_data(x509_ctx, | ||
283 | SSL_get_ex_data_X509_STORE_CTX_idx()); | ||
284 | ctx = SSL_get_SSL_CTX(ssl); | ||
285 | pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
286 | L = pctx->L; | ||
287 | |||
288 | /* Get verify flags */ | ||
289 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
290 | lua_pushlightuserdata(L, (void*)ctx); | ||
291 | lua_gettable(L, -2); | ||
292 | verify = (int)lua_tonumber(L, -1); | ||
293 | |||
294 | lua_pop(L, 2); /* Remove values from stack */ | ||
295 | |||
296 | err = X509_STORE_CTX_get_error(x509_ctx); | ||
297 | if (err != X509_V_OK) | ||
298 | add_cert_error(L, ssl, err, X509_STORE_CTX_get_error_depth(x509_ctx)); | ||
299 | |||
300 | return (verify & LSEC_VERIFY_CONTINUE ? 1 : preverify_ok); | ||
301 | } | ||
302 | |||
303 | /*------------------------------ Lua Functions -------------------------------*/ | ||
304 | |||
305 | /** | ||
306 | * Create a SSL context. | ||
307 | */ | ||
308 | static int create(lua_State *L) | ||
309 | { | ||
310 | p_context ctx; | ||
311 | const char *str_method; | ||
312 | const SSL_METHOD *method; | ||
313 | int vmin, vmax; | ||
314 | |||
315 | str_method = luaL_checkstring(L, 1); | ||
316 | method = str2method(str_method, &vmin, &vmax); | ||
317 | if (!method) { | ||
318 | lua_pushnil(L); | ||
319 | lua_pushfstring(L, "invalid protocol (%s)", str_method); | ||
320 | return 2; | ||
321 | } | ||
322 | ctx = (p_context) lua_newuserdata(L, sizeof(t_context)); | ||
323 | if (!ctx) { | ||
324 | lua_pushnil(L); | ||
325 | lua_pushstring(L, "error creating context"); | ||
326 | return 2; | ||
327 | } | ||
328 | memset(ctx, 0, sizeof(t_context)); | ||
329 | ctx->context = SSL_CTX_new(method); | ||
330 | if (!ctx->context) { | ||
331 | lua_pushnil(L); | ||
332 | lua_pushfstring(L, "error creating context (%s)", | ||
333 | ERR_reason_error_string(ERR_get_error())); | ||
334 | return 2; | ||
335 | } | ||
336 | #ifdef LSEC_API_OPENSSL_1_1_0 | ||
337 | SSL_CTX_set_min_proto_version(ctx->context, vmin); | ||
338 | SSL_CTX_set_max_proto_version(ctx->context, vmax); | ||
339 | #endif | ||
340 | ctx->mode = LSEC_MODE_INVALID; | ||
341 | ctx->L = L; | ||
342 | luaL_getmetatable(L, "SSL:Context"); | ||
343 | lua_setmetatable(L, -2); | ||
344 | |||
345 | /* No session support */ | ||
346 | SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF); | ||
347 | /* Link LuaSec context with the OpenSSL context */ | ||
348 | SSL_CTX_set_app_data(ctx->context, ctx); | ||
349 | |||
350 | return 1; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * Load the trusting certificates. | ||
355 | */ | ||
356 | static int load_locations(lua_State *L) | ||
357 | { | ||
358 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
359 | const char *cafile = luaL_optstring(L, 2, NULL); | ||
360 | const char *capath = luaL_optstring(L, 3, NULL); | ||
361 | if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1) { | ||
362 | lua_pushboolean(L, 0); | ||
363 | lua_pushfstring(L, "error loading CA locations (%s)", | ||
364 | ERR_reason_error_string(ERR_get_error())); | ||
365 | return 2; | ||
366 | } | ||
367 | lua_pushboolean(L, 1); | ||
368 | return 1; | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * Load the certificate file. | ||
373 | */ | ||
374 | static int load_cert(lua_State *L) | ||
375 | { | ||
376 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
377 | const char *filename = luaL_checkstring(L, 2); | ||
378 | if (SSL_CTX_use_certificate_chain_file(ctx, filename) != 1) { | ||
379 | lua_pushboolean(L, 0); | ||
380 | lua_pushfstring(L, "error loading certificate (%s)", | ||
381 | ERR_reason_error_string(ERR_get_error())); | ||
382 | return 2; | ||
383 | } | ||
384 | lua_pushboolean(L, 1); | ||
385 | return 1; | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * Load the key file -- only in PEM format. | ||
390 | */ | ||
391 | static int load_key(lua_State *L) | ||
392 | { | ||
393 | int ret = 1; | ||
394 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
395 | const char *filename = luaL_checkstring(L, 2); | ||
396 | switch (lua_type(L, 3)) { | ||
397 | case LUA_TSTRING: | ||
398 | case LUA_TFUNCTION: | ||
399 | SSL_CTX_set_default_passwd_cb(ctx, passwd_cb); | ||
400 | SSL_CTX_set_default_passwd_cb_userdata(ctx, L); | ||
401 | /* fallback */ | ||
402 | case LUA_TNIL: | ||
403 | if (SSL_CTX_use_PrivateKey_file(ctx, filename, SSL_FILETYPE_PEM) == 1) | ||
404 | lua_pushboolean(L, 1); | ||
405 | else { | ||
406 | ret = 2; | ||
407 | lua_pushboolean(L, 0); | ||
408 | lua_pushfstring(L, "error loading private key (%s)", | ||
409 | ERR_reason_error_string(ERR_get_error())); | ||
410 | } | ||
411 | SSL_CTX_set_default_passwd_cb(ctx, NULL); | ||
412 | SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL); | ||
413 | break; | ||
414 | default: | ||
415 | lua_pushstring(L, "invalid callback value"); | ||
416 | lua_error(L); | ||
417 | } | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * Check that the certificate public key matches the private key | ||
423 | */ | ||
424 | |||
425 | static int check_key(lua_State *L) | ||
426 | { | ||
427 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
428 | lua_pushboolean(L, SSL_CTX_check_private_key(ctx)); | ||
429 | return 1; | ||
430 | } | ||
431 | |||
432 | /** | ||
433 | * Set the cipher list. | ||
434 | */ | ||
435 | static int set_cipher(lua_State *L) | ||
436 | { | ||
437 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
438 | const char *list = luaL_checkstring(L, 2); | ||
439 | if (SSL_CTX_set_cipher_list(ctx, list) != 1) { | ||
440 | lua_pushboolean(L, 0); | ||
441 | lua_pushfstring(L, "error setting cipher list (%s)", ERR_reason_error_string(ERR_get_error())); | ||
442 | return 2; | ||
443 | } | ||
444 | lua_pushboolean(L, 1); | ||
445 | return 1; | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * Set the cipher suites. | ||
450 | */ | ||
451 | static int set_ciphersuites(lua_State *L) | ||
452 | { | ||
453 | #if defined(TLS1_3_VERSION) | ||
454 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
455 | const char *list = luaL_checkstring(L, 2); | ||
456 | if (SSL_CTX_set_ciphersuites(ctx, list) != 1) { | ||
457 | lua_pushboolean(L, 0); | ||
458 | lua_pushfstring(L, "error setting cipher list (%s)", ERR_reason_error_string(ERR_get_error())); | ||
459 | return 2; | ||
460 | } | ||
461 | #endif | ||
462 | lua_pushboolean(L, 1); | ||
463 | return 1; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * Set the depth for certificate checking. | ||
468 | */ | ||
469 | static int set_depth(lua_State *L) | ||
470 | { | ||
471 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
472 | SSL_CTX_set_verify_depth(ctx, (int)luaL_checkinteger(L, 2)); | ||
473 | lua_pushboolean(L, 1); | ||
474 | return 1; | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * Set the handshake verify options. | ||
479 | */ | ||
480 | static int set_verify(lua_State *L) | ||
481 | { | ||
482 | int i; | ||
483 | const char *str; | ||
484 | int flag = 0; | ||
485 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
486 | int max = lua_gettop(L); | ||
487 | for (i = 2; i <= max; i++) { | ||
488 | str = luaL_checkstring(L, i); | ||
489 | if (!set_verify_flag(str, &flag)) { | ||
490 | lua_pushboolean(L, 0); | ||
491 | lua_pushfstring(L, "invalid verify option (%s)", str); | ||
492 | return 2; | ||
493 | } | ||
494 | } | ||
495 | if (flag) SSL_CTX_set_verify(ctx, flag, NULL); | ||
496 | lua_pushboolean(L, 1); | ||
497 | return 1; | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * Set the protocol options. | ||
502 | */ | ||
503 | static int set_options(lua_State *L) | ||
504 | { | ||
505 | int i; | ||
506 | const char *str; | ||
507 | unsigned long flag = 0L; | ||
508 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
509 | int max = lua_gettop(L); | ||
510 | /* any option? */ | ||
511 | if (max > 1) { | ||
512 | for (i = 2; i <= max; i++) { | ||
513 | str = luaL_checkstring(L, i); | ||
514 | if (!set_option_flag(str, &flag)) { | ||
515 | lua_pushboolean(L, 0); | ||
516 | lua_pushfstring(L, "invalid option (%s)", str); | ||
517 | return 2; | ||
518 | } | ||
519 | } | ||
520 | SSL_CTX_set_options(ctx, flag); | ||
521 | } | ||
522 | lua_pushboolean(L, 1); | ||
523 | return 1; | ||
524 | } | ||
525 | |||
526 | /** | ||
527 | * Set the context mode. | ||
528 | */ | ||
529 | static int set_mode(lua_State *L) | ||
530 | { | ||
531 | p_context ctx = checkctx(L, 1); | ||
532 | const char *str = luaL_checkstring(L, 2); | ||
533 | if (!strcmp("server", str)) { | ||
534 | ctx->mode = LSEC_MODE_SERVER; | ||
535 | lua_pushboolean(L, 1); | ||
536 | return 1; | ||
537 | } | ||
538 | if (!strcmp("client", str)) { | ||
539 | ctx->mode = LSEC_MODE_CLIENT; | ||
540 | lua_pushboolean(L, 1); | ||
541 | return 1; | ||
542 | } | ||
543 | lua_pushboolean(L, 0); | ||
544 | lua_pushfstring(L, "invalid mode (%s)", str); | ||
545 | return 1; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * Configure DH parameters. | ||
550 | */ | ||
551 | static int set_dhparam(lua_State *L) | ||
552 | { | ||
553 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
554 | SSL_CTX_set_tmp_dh_callback(ctx, dhparam_cb); | ||
555 | |||
556 | /* Save callback */ | ||
557 | luaL_getmetatable(L, "SSL:DH:Registry"); | ||
558 | lua_pushlightuserdata(L, (void*)ctx); | ||
559 | lua_pushvalue(L, 2); | ||
560 | lua_settable(L, -3); | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | #if !defined(OPENSSL_NO_EC) | ||
566 | /** | ||
567 | * Set elliptic curve. | ||
568 | */ | ||
569 | static int set_curve(lua_State *L) | ||
570 | { | ||
571 | long ret; | ||
572 | EC_KEY *key = NULL; | ||
573 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
574 | const char *str = luaL_checkstring(L, 2); | ||
575 | |||
576 | SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); | ||
577 | |||
578 | key = lsec_find_ec_key(L, str); | ||
579 | |||
580 | if (!key) { | ||
581 | lua_pushboolean(L, 0); | ||
582 | lua_pushfstring(L, "elliptic curve '%s' not supported", str); | ||
583 | return 2; | ||
584 | } | ||
585 | |||
586 | ret = SSL_CTX_set_tmp_ecdh(ctx, key); | ||
587 | /* SSL_CTX_set_tmp_ecdh takes its own reference */ | ||
588 | EC_KEY_free(key); | ||
589 | |||
590 | if (!ret) { | ||
591 | lua_pushboolean(L, 0); | ||
592 | lua_pushfstring(L, "error setting elliptic curve (%s)", | ||
593 | ERR_reason_error_string(ERR_get_error())); | ||
594 | return 2; | ||
595 | } | ||
596 | |||
597 | lua_pushboolean(L, 1); | ||
598 | return 1; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * Set elliptic curves list. | ||
603 | */ | ||
604 | static int set_curves_list(lua_State *L) | ||
605 | { | ||
606 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
607 | const char *str = luaL_checkstring(L, 2); | ||
608 | |||
609 | SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); | ||
610 | |||
611 | if (SSL_CTX_set1_curves_list(ctx, str) != 1) { | ||
612 | lua_pushboolean(L, 0); | ||
613 | lua_pushfstring(L, "unknown elliptic curve in \"%s\"", str); | ||
614 | return 2; | ||
615 | } | ||
616 | |||
617 | #if defined(LIBRESSL_VERSION_NUMBER) || !defined(LSEC_API_OPENSSL_1_1_0) | ||
618 | (void)SSL_CTX_set_ecdh_auto(ctx, 1); | ||
619 | #endif | ||
620 | |||
621 | lua_pushboolean(L, 1); | ||
622 | return 1; | ||
623 | } | ||
624 | #endif | ||
625 | |||
626 | /** | ||
627 | * Set the protocols a client should send for ALPN. | ||
628 | */ | ||
629 | static int set_alpn(lua_State *L) | ||
630 | { | ||
631 | long ret; | ||
632 | size_t len; | ||
633 | p_context ctx = checkctx(L, 1); | ||
634 | const char *str = luaL_checklstring(L, 2, &len); | ||
635 | |||
636 | ret = SSL_CTX_set_alpn_protos(ctx->context, (const unsigned char*)str, len); | ||
637 | if (ret) { | ||
638 | lua_pushboolean(L, 0); | ||
639 | lua_pushfstring(L, "error setting ALPN (%s)", ERR_reason_error_string(ERR_get_error())); | ||
640 | return 2; | ||
641 | } | ||
642 | lua_pushboolean(L, 1); | ||
643 | return 1; | ||
644 | } | ||
645 | |||
646 | /** | ||
647 | * This standard callback calls the server's callback in Lua sapce. | ||
648 | * The server has to return a list in wire-format strings. | ||
649 | * This function uses a helper function to match server and client lists. | ||
650 | */ | ||
651 | static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, | ||
652 | const unsigned char *in, unsigned int inlen, void *arg) | ||
653 | { | ||
654 | int ret; | ||
655 | size_t server_len; | ||
656 | const char *server; | ||
657 | p_context ctx = (p_context)arg; | ||
658 | lua_State *L = ctx->L; | ||
659 | |||
660 | luaL_getmetatable(L, "SSL:ALPN:Registry"); | ||
661 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
662 | lua_gettable(L, -2); | ||
663 | |||
664 | lua_pushlstring(L, (const char*)in, inlen); | ||
665 | |||
666 | lua_call(L, 1, 1); | ||
667 | |||
668 | if (!lua_isstring(L, -1)) { | ||
669 | lua_pop(L, 2); | ||
670 | return SSL_TLSEXT_ERR_NOACK; | ||
671 | } | ||
672 | |||
673 | // Protocol list from server in wire-format string | ||
674 | server = luaL_checklstring(L, -1, &server_len); | ||
675 | ret = SSL_select_next_proto((unsigned char**)out, outlen, (const unsigned char*)server, | ||
676 | server_len, in, inlen); | ||
677 | if (ret != OPENSSL_NPN_NEGOTIATED) { | ||
678 | lua_pop(L, 2); | ||
679 | return SSL_TLSEXT_ERR_NOACK; | ||
680 | } | ||
681 | |||
682 | // Copy the result because lua_pop() can collect the pointer | ||
683 | ctx->alpn = malloc(*outlen); | ||
684 | memcpy(ctx->alpn, (void*)*out, *outlen); | ||
685 | *out = (const unsigned char*)ctx->alpn; | ||
686 | |||
687 | lua_pop(L, 2); | ||
688 | |||
689 | return SSL_TLSEXT_ERR_OK; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * Set a callback a server can use to select the next protocol with ALPN. | ||
694 | */ | ||
695 | static int set_alpn_cb(lua_State *L) | ||
696 | { | ||
697 | p_context ctx = checkctx(L, 1); | ||
698 | |||
699 | luaL_getmetatable(L, "SSL:ALPN:Registry"); | ||
700 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
701 | lua_pushvalue(L, 2); | ||
702 | lua_settable(L, -3); | ||
703 | |||
704 | SSL_CTX_set_alpn_select_cb(ctx->context, alpn_cb, ctx); | ||
705 | |||
706 | lua_pushboolean(L, 1); | ||
707 | return 1; | ||
708 | } | ||
709 | |||
710 | #if defined(LSEC_ENABLE_PSK) | ||
711 | /** | ||
712 | * Callback to select the PSK. | ||
713 | */ | ||
714 | static unsigned int server_psk_cb(SSL *ssl, const char *identity, unsigned char *psk, | ||
715 | unsigned int max_psk_len) | ||
716 | { | ||
717 | size_t psk_len; | ||
718 | const char *ret_psk; | ||
719 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
720 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
721 | lua_State *L = pctx->L; | ||
722 | |||
723 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
724 | lua_pushlightuserdata(L, (void*)pctx->context); | ||
725 | lua_gettable(L, -2); | ||
726 | |||
727 | lua_pushstring(L, identity); | ||
728 | lua_pushinteger(L, max_psk_len); | ||
729 | |||
730 | lua_call(L, 2, 1); | ||
731 | |||
732 | if (!lua_isstring(L, -1)) { | ||
733 | lua_pop(L, 2); | ||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | ret_psk = lua_tolstring(L, -1, &psk_len); | ||
738 | |||
739 | if (psk_len == 0 || psk_len > max_psk_len) | ||
740 | psk_len = 0; | ||
741 | else | ||
742 | memcpy(psk, ret_psk, psk_len); | ||
743 | |||
744 | lua_pop(L, 2); | ||
745 | |||
746 | return psk_len; | ||
747 | } | ||
748 | |||
749 | /** | ||
750 | * Set a PSK callback for server. | ||
751 | */ | ||
752 | static int set_server_psk_cb(lua_State *L) | ||
753 | { | ||
754 | p_context ctx = checkctx(L, 1); | ||
755 | |||
756 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
757 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
758 | lua_pushvalue(L, 2); | ||
759 | lua_settable(L, -3); | ||
760 | |||
761 | SSL_CTX_set_psk_server_callback(ctx->context, server_psk_cb); | ||
762 | |||
763 | lua_pushboolean(L, 1); | ||
764 | return 1; | ||
765 | } | ||
766 | |||
767 | /* | ||
768 | * Set the PSK indentity hint. | ||
769 | */ | ||
770 | static int set_psk_identity_hint(lua_State *L) | ||
771 | { | ||
772 | p_context ctx = checkctx(L, 1); | ||
773 | const char *hint = luaL_checkstring(L, 2); | ||
774 | int ret = SSL_CTX_use_psk_identity_hint(ctx->context, hint); | ||
775 | lua_pushboolean(L, ret); | ||
776 | return 1; | ||
777 | } | ||
778 | |||
779 | /* | ||
780 | * Client callback to PSK. | ||
781 | */ | ||
782 | static unsigned int client_psk_cb(SSL *ssl, const char *hint, char *identity, | ||
783 | unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len) | ||
784 | { | ||
785 | size_t psk_len; | ||
786 | size_t identity_len; | ||
787 | const char *ret_psk; | ||
788 | const char *ret_identity; | ||
789 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
790 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
791 | lua_State *L = pctx->L; | ||
792 | |||
793 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
794 | lua_pushlightuserdata(L, (void*)pctx->context); | ||
795 | lua_gettable(L, -2); | ||
796 | |||
797 | if (hint) | ||
798 | lua_pushstring(L, hint); | ||
799 | else | ||
800 | lua_pushnil(L); | ||
801 | |||
802 | // Leave space to '\0' | ||
803 | lua_pushinteger(L, max_identity_len-1); | ||
804 | lua_pushinteger(L, max_psk_len); | ||
805 | |||
806 | lua_call(L, 3, 2); | ||
807 | |||
808 | if (!lua_isstring(L, -1) || !lua_isstring(L, -2)) { | ||
809 | lua_pop(L, 3); | ||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | ret_identity = lua_tolstring(L, -2, &identity_len); | ||
814 | ret_psk = lua_tolstring(L, -1, &psk_len); | ||
815 | |||
816 | if (identity_len >= max_identity_len || psk_len > max_psk_len) | ||
817 | psk_len = 0; | ||
818 | else { | ||
819 | memcpy(identity, ret_identity, identity_len); | ||
820 | identity[identity_len] = 0; | ||
821 | memcpy(psk, ret_psk, psk_len); | ||
822 | } | ||
823 | |||
824 | lua_pop(L, 3); | ||
825 | |||
826 | return psk_len; | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * Set a PSK callback for client. | ||
831 | */ | ||
832 | static int set_client_psk_cb(lua_State *L) { | ||
833 | p_context ctx = checkctx(L, 1); | ||
834 | |||
835 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
836 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
837 | lua_pushvalue(L, 2); | ||
838 | lua_settable(L, -3); | ||
839 | |||
840 | SSL_CTX_set_psk_client_callback(ctx->context, client_psk_cb); | ||
841 | |||
842 | lua_pushboolean(L, 1); | ||
843 | return 1; | ||
844 | } | ||
845 | #endif | ||
846 | |||
847 | #if defined(LSEC_ENABLE_DANE) | ||
848 | /* | ||
849 | * DANE | ||
850 | */ | ||
851 | static int dane_options[] = { | ||
852 | /* TODO move into options.c | ||
853 | * however this symbol is not from openssl/ssl.h but rather from | ||
854 | * openssl/x509_vfy.h | ||
855 | * */ | ||
856 | #ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS | ||
857 | DANE_FLAG_NO_DANE_EE_NAMECHECKS, | ||
858 | #endif | ||
859 | 0 | ||
860 | }; | ||
861 | static const char *dane_option_names[] = { | ||
862 | #ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS | ||
863 | "no_ee_namechecks", | ||
864 | #endif | ||
865 | NULL | ||
866 | }; | ||
867 | |||
868 | static int set_dane(lua_State *L) | ||
869 | { | ||
870 | int ret, i; | ||
871 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
872 | ret = SSL_CTX_dane_enable(ctx); | ||
873 | for (i = 2; ret > 0 && i <= lua_gettop(L); i++) { | ||
874 | ret = SSL_CTX_dane_set_flags(ctx, dane_options[luaL_checkoption(L, i, NULL, dane_option_names)]); | ||
875 | } | ||
876 | lua_pushboolean(L, (ret > 0)); | ||
877 | return 1; | ||
878 | } | ||
879 | #endif | ||
880 | |||
881 | /** | ||
882 | * Package functions | ||
883 | */ | ||
884 | static luaL_Reg funcs[] = { | ||
885 | {"create", create}, | ||
886 | {"locations", load_locations}, | ||
887 | {"loadcert", load_cert}, | ||
888 | {"loadkey", load_key}, | ||
889 | {"checkkey", check_key}, | ||
890 | {"setalpn", set_alpn}, | ||
891 | {"setalpncb", set_alpn_cb}, | ||
892 | {"setcipher", set_cipher}, | ||
893 | {"setciphersuites", set_ciphersuites}, | ||
894 | {"setdepth", set_depth}, | ||
895 | {"setdhparam", set_dhparam}, | ||
896 | {"setverify", set_verify}, | ||
897 | {"setoptions", set_options}, | ||
898 | #if defined(LSEC_ENABLE_PSK) | ||
899 | {"setpskhint", set_psk_identity_hint}, | ||
900 | {"setserverpskcb", set_server_psk_cb}, | ||
901 | {"setclientpskcb", set_client_psk_cb}, | ||
902 | #endif | ||
903 | {"setmode", set_mode}, | ||
904 | #if !defined(OPENSSL_NO_EC) | ||
905 | {"setcurve", set_curve}, | ||
906 | {"setcurveslist", set_curves_list}, | ||
907 | #endif | ||
908 | #if defined(LSEC_ENABLE_DANE) | ||
909 | {"setdane", set_dane}, | ||
910 | #endif | ||
911 | {NULL, NULL} | ||
912 | }; | ||
913 | |||
914 | /*-------------------------------- Metamethods -------------------------------*/ | ||
915 | |||
916 | /** | ||
917 | * Collect SSL context -- GC metamethod. | ||
918 | */ | ||
919 | static int meth_destroy(lua_State *L) | ||
920 | { | ||
921 | p_context ctx = checkctx(L, 1); | ||
922 | if (ctx->context) { | ||
923 | /* Clear registries */ | ||
924 | luaL_getmetatable(L, "SSL:DH:Registry"); | ||
925 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
926 | lua_pushnil(L); | ||
927 | lua_settable(L, -3); | ||
928 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
929 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
930 | lua_pushnil(L); | ||
931 | lua_settable(L, -3); | ||
932 | luaL_getmetatable(L, "SSL:ALPN:Registry"); | ||
933 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
934 | lua_pushnil(L); | ||
935 | lua_settable(L, -3); | ||
936 | luaL_getmetatable(L, "SSL:PSK:Registry"); | ||
937 | lua_pushlightuserdata(L, (void*)ctx->context); | ||
938 | lua_pushnil(L); | ||
939 | lua_settable(L, -3); | ||
940 | |||
941 | SSL_CTX_free(ctx->context); | ||
942 | ctx->context = NULL; | ||
943 | } | ||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | /** | ||
948 | * Object information -- tostring metamethod. | ||
949 | */ | ||
950 | static int meth_tostring(lua_State *L) | ||
951 | { | ||
952 | p_context ctx = checkctx(L, 1); | ||
953 | lua_pushfstring(L, "SSL context: %p", ctx); | ||
954 | return 1; | ||
955 | } | ||
956 | |||
957 | /** | ||
958 | * Set extra flags for handshake verification. | ||
959 | */ | ||
960 | static int meth_set_verify_ext(lua_State *L) | ||
961 | { | ||
962 | int i; | ||
963 | const char *str; | ||
964 | int crl_flag = 0; | ||
965 | int lsec_flag = 0; | ||
966 | SSL_CTX *ctx = lsec_checkcontext(L, 1); | ||
967 | int max = lua_gettop(L); | ||
968 | for (i = 2; i <= max; i++) { | ||
969 | str = luaL_checkstring(L, i); | ||
970 | if (!strcmp(str, "lsec_continue")) { | ||
971 | lsec_flag |= LSEC_VERIFY_CONTINUE; | ||
972 | } else if (!strcmp(str, "lsec_ignore_purpose")) { | ||
973 | lsec_flag |= LSEC_VERIFY_IGNORE_PURPOSE; | ||
974 | } else if (!strcmp(str, "crl_check")) { | ||
975 | crl_flag |= X509_V_FLAG_CRL_CHECK; | ||
976 | } else if (!strcmp(str, "crl_check_chain")) { | ||
977 | crl_flag |= X509_V_FLAG_CRL_CHECK_ALL; | ||
978 | } else { | ||
979 | lua_pushboolean(L, 0); | ||
980 | lua_pushfstring(L, "invalid verify option (%s)", str); | ||
981 | return 2; | ||
982 | } | ||
983 | } | ||
984 | /* Set callback? */ | ||
985 | if (lsec_flag) { | ||
986 | SSL_CTX_set_verify(ctx, SSL_CTX_get_verify_mode(ctx), verify_cb); | ||
987 | SSL_CTX_set_cert_verify_callback(ctx, cert_verify_cb, (void*)ctx); | ||
988 | /* Save flag */ | ||
989 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
990 | lua_pushlightuserdata(L, (void*)ctx); | ||
991 | lua_pushnumber(L, lsec_flag); | ||
992 | lua_settable(L, -3); | ||
993 | } else { | ||
994 | SSL_CTX_set_verify(ctx, SSL_CTX_get_verify_mode(ctx), NULL); | ||
995 | SSL_CTX_set_cert_verify_callback(ctx, NULL, NULL); | ||
996 | /* Remove flag */ | ||
997 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
998 | lua_pushlightuserdata(L, (void*)ctx); | ||
999 | lua_pushnil(L); | ||
1000 | lua_settable(L, -3); | ||
1001 | } | ||
1002 | |||
1003 | /* X509 flag */ | ||
1004 | X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), crl_flag); | ||
1005 | |||
1006 | /* Ok */ | ||
1007 | lua_pushboolean(L, 1); | ||
1008 | return 1; | ||
1009 | } | ||
1010 | |||
1011 | /** | ||
1012 | * Context metamethods. | ||
1013 | */ | ||
1014 | static luaL_Reg meta[] = { | ||
1015 | {"__close", meth_destroy}, | ||
1016 | {"__gc", meth_destroy}, | ||
1017 | {"__tostring", meth_tostring}, | ||
1018 | {NULL, NULL} | ||
1019 | }; | ||
1020 | |||
1021 | /** | ||
1022 | * Index metamethods. | ||
1023 | */ | ||
1024 | static luaL_Reg meta_index[] = { | ||
1025 | {"setverifyext", meth_set_verify_ext}, | ||
1026 | {NULL, NULL} | ||
1027 | }; | ||
1028 | |||
1029 | |||
1030 | /*----------------------------- Public Functions ---------------------------*/ | ||
1031 | |||
1032 | /** | ||
1033 | * Retrieve the SSL context from the Lua stack. | ||
1034 | */ | ||
1035 | SSL_CTX* lsec_checkcontext(lua_State *L, int idx) | ||
1036 | { | ||
1037 | p_context ctx = checkctx(L, idx); | ||
1038 | return ctx->context; | ||
1039 | } | ||
1040 | |||
1041 | SSL_CTX* lsec_testcontext(lua_State *L, int idx) | ||
1042 | { | ||
1043 | p_context ctx = testctx(L, idx); | ||
1044 | return (ctx) ? ctx->context : NULL; | ||
1045 | } | ||
1046 | |||
1047 | /** | ||
1048 | * Retrieve the mode from the context in the Lua stack. | ||
1049 | */ | ||
1050 | int lsec_getmode(lua_State *L, int idx) | ||
1051 | { | ||
1052 | p_context ctx = checkctx(L, idx); | ||
1053 | return ctx->mode; | ||
1054 | } | ||
1055 | |||
1056 | /*-- Compat - Lua 5.1 --*/ | ||
1057 | #if (LUA_VERSION_NUM == 501) | ||
1058 | |||
1059 | void *lsec_testudata (lua_State *L, int ud, const char *tname) { | ||
1060 | void *p = lua_touserdata(L, ud); | ||
1061 | if (p != NULL) { /* value is a userdata? */ | ||
1062 | if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | ||
1063 | luaL_getmetatable(L, tname); /* get correct metatable */ | ||
1064 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ | ||
1065 | p = NULL; /* value is a userdata with wrong metatable */ | ||
1066 | lua_pop(L, 2); /* remove both metatables */ | ||
1067 | return p; | ||
1068 | } | ||
1069 | } | ||
1070 | return NULL; /* value is not a userdata with a metatable */ | ||
1071 | } | ||
1072 | |||
1073 | #endif | ||
1074 | |||
1075 | /*------------------------------ Initialization ------------------------------*/ | ||
1076 | |||
1077 | /** | ||
1078 | * Registre the module. | ||
1079 | */ | ||
1080 | LSEC_API int luaopen_ssl_context(lua_State *L) | ||
1081 | { | ||
1082 | luaL_newmetatable(L, "SSL:DH:Registry"); /* Keep all DH callbacks */ | ||
1083 | luaL_newmetatable(L, "SSL:ALPN:Registry"); /* Keep all ALPN callbacks */ | ||
1084 | luaL_newmetatable(L, "SSL:PSK:Registry"); /* Keep all PSK callbacks */ | ||
1085 | luaL_newmetatable(L, "SSL:Verify:Registry"); /* Keep all verify flags */ | ||
1086 | luaL_newmetatable(L, "SSL:Context"); | ||
1087 | setfuncs(L, meta); | ||
1088 | |||
1089 | /* Create __index metamethods for context */ | ||
1090 | luaL_newlib(L, meta_index); | ||
1091 | lua_setfield(L, -2, "__index"); | ||
1092 | |||
1093 | lsec_load_curves(L); | ||
1094 | |||
1095 | /* Return the module */ | ||
1096 | luaL_newlib(L, funcs); | ||
1097 | |||
1098 | return 1; | ||
1099 | } | ||
diff --git a/vendor/luasec/src/context.h b/vendor/luasec/src/context.h new file mode 100644 index 00000000..dd6bd098 --- /dev/null +++ b/vendor/luasec/src/context.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef LSEC_CONTEXT_H | ||
2 | #define LSEC_CONTEXT_H | ||
3 | |||
4 | /*-------------------------------------------------------------------------- | ||
5 | * LuaSec 1.3.2 | ||
6 | * | ||
7 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
8 | * | ||
9 | *--------------------------------------------------------------------------*/ | ||
10 | |||
11 | #include <lua.h> | ||
12 | #include <openssl/ssl.h> | ||
13 | |||
14 | #include "compat.h" | ||
15 | |||
16 | #define LSEC_MODE_INVALID 0 | ||
17 | #define LSEC_MODE_SERVER 1 | ||
18 | #define LSEC_MODE_CLIENT 2 | ||
19 | |||
20 | #define LSEC_VERIFY_CONTINUE 1 | ||
21 | #define LSEC_VERIFY_IGNORE_PURPOSE 2 | ||
22 | |||
23 | typedef struct t_context_ { | ||
24 | SSL_CTX *context; | ||
25 | lua_State *L; | ||
26 | DH *dh_param; | ||
27 | void *alpn; | ||
28 | int mode; | ||
29 | } t_context; | ||
30 | typedef t_context* p_context; | ||
31 | |||
32 | /* Retrieve the SSL context from the Lua stack */ | ||
33 | SSL_CTX *lsec_checkcontext(lua_State *L, int idx); | ||
34 | SSL_CTX *lsec_testcontext(lua_State *L, int idx); | ||
35 | |||
36 | /* Retrieve the mode from the context in the Lua stack */ | ||
37 | int lsec_getmode(lua_State *L, int idx); | ||
38 | |||
39 | /* Registre the module. */ | ||
40 | LSEC_API int luaopen_ssl_context(lua_State *L); | ||
41 | |||
42 | /* Compat - Lua 5.1 */ | ||
43 | #if (LUA_VERSION_NUM == 501) | ||
44 | void *lsec_testudata (lua_State *L, int ud, const char *tname); | ||
45 | #endif | ||
46 | |||
47 | #endif | ||
diff --git a/vendor/luasec/src/ec.c b/vendor/luasec/src/ec.c new file mode 100644 index 00000000..c7025a55 --- /dev/null +++ b/vendor/luasec/src/ec.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #include <openssl/objects.h> | ||
9 | |||
10 | #include "ec.h" | ||
11 | |||
12 | #ifndef OPENSSL_NO_EC | ||
13 | |||
14 | EC_KEY *lsec_find_ec_key(lua_State *L, const char *str) | ||
15 | { | ||
16 | int nid; | ||
17 | lua_pushstring(L, "SSL:EC:CURVES"); | ||
18 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
19 | lua_pushstring(L, str); | ||
20 | lua_rawget(L, -2); | ||
21 | |||
22 | if (!lua_isnumber(L, -1)) | ||
23 | return NULL; | ||
24 | |||
25 | nid = (int)lua_tonumber(L, -1); | ||
26 | return EC_KEY_new_by_curve_name(nid); | ||
27 | } | ||
28 | |||
29 | void lsec_load_curves(lua_State *L) | ||
30 | { | ||
31 | size_t i; | ||
32 | size_t size; | ||
33 | const char *name; | ||
34 | EC_builtin_curve *curves = NULL; | ||
35 | |||
36 | lua_pushstring(L, "SSL:EC:CURVES"); | ||
37 | lua_newtable(L); | ||
38 | |||
39 | size = EC_get_builtin_curves(NULL, 0); | ||
40 | if (size > 0) { | ||
41 | curves = (EC_builtin_curve*)malloc(sizeof(EC_builtin_curve) * size); | ||
42 | EC_get_builtin_curves(curves, size); | ||
43 | for (i = 0; i < size; i++) { | ||
44 | name = OBJ_nid2sn(curves[i].nid); | ||
45 | if (name != NULL) { | ||
46 | lua_pushstring(L, name); | ||
47 | lua_pushnumber(L, curves[i].nid); | ||
48 | lua_rawset(L, -3); | ||
49 | } | ||
50 | switch (curves[i].nid) { | ||
51 | case NID_X9_62_prime256v1: | ||
52 | lua_pushstring(L, "P-256"); | ||
53 | lua_pushnumber(L, curves[i].nid); | ||
54 | lua_rawset(L, -3); | ||
55 | break; | ||
56 | case NID_secp384r1: | ||
57 | lua_pushstring(L, "P-384"); | ||
58 | lua_pushnumber(L, curves[i].nid); | ||
59 | lua_rawset(L, -3); | ||
60 | break; | ||
61 | case NID_secp521r1: | ||
62 | lua_pushstring(L, "P-521"); | ||
63 | lua_pushnumber(L, curves[i].nid); | ||
64 | lua_rawset(L, -3); | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | free(curves); | ||
69 | } | ||
70 | |||
71 | /* These are special so are manually added here */ | ||
72 | #ifdef NID_X25519 | ||
73 | lua_pushstring(L, "X25519"); | ||
74 | lua_pushnumber(L, NID_X25519); | ||
75 | lua_rawset(L, -3); | ||
76 | #endif | ||
77 | |||
78 | #ifdef NID_X448 | ||
79 | lua_pushstring(L, "X448"); | ||
80 | lua_pushnumber(L, NID_X448); | ||
81 | lua_rawset(L, -3); | ||
82 | #endif | ||
83 | |||
84 | lua_rawset(L, LUA_REGISTRYINDEX); | ||
85 | } | ||
86 | |||
87 | void lsec_get_curves(lua_State *L) | ||
88 | { | ||
89 | lua_newtable(L); | ||
90 | |||
91 | lua_pushstring(L, "SSL:EC:CURVES"); | ||
92 | lua_rawget(L, LUA_REGISTRYINDEX); | ||
93 | |||
94 | lua_pushnil(L); | ||
95 | while (lua_next(L, -2) != 0) { | ||
96 | lua_pop(L, 1); | ||
97 | lua_pushvalue(L, -1); | ||
98 | lua_pushboolean(L, 1); | ||
99 | lua_rawset(L, -5); | ||
100 | } | ||
101 | lua_pop(L, 1); | ||
102 | } | ||
103 | |||
104 | #else | ||
105 | |||
106 | void lsec_load_curves(lua_State *L) | ||
107 | { | ||
108 | // do nothing | ||
109 | } | ||
110 | |||
111 | void lsec_get_curves(lua_State *L) | ||
112 | { | ||
113 | lua_newtable(L); | ||
114 | } | ||
115 | |||
116 | #endif | ||
diff --git a/vendor/luasec/src/ec.h b/vendor/luasec/src/ec.h new file mode 100644 index 00000000..16d29360 --- /dev/null +++ b/vendor/luasec/src/ec.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #ifndef LSEC_EC_H | ||
9 | #define LSEC_EC_H | ||
10 | |||
11 | #include <lua.h> | ||
12 | |||
13 | #ifndef OPENSSL_NO_EC | ||
14 | #include <openssl/ec.h> | ||
15 | |||
16 | EC_KEY *lsec_find_ec_key(lua_State *L, const char *str); | ||
17 | #endif | ||
18 | |||
19 | void lsec_get_curves(lua_State *L); | ||
20 | void lsec_load_curves(lua_State *L); | ||
21 | |||
22 | #endif | ||
diff --git a/vendor/luasec/src/https.lua b/vendor/luasec/src/https.lua new file mode 100644 index 00000000..85cef361 --- /dev/null +++ b/vendor/luasec/src/https.lua | |||
@@ -0,0 +1,147 @@ | |||
1 | ---------------------------------------------------------------------------- | ||
2 | -- LuaSec 1.3.2 | ||
3 | -- | ||
4 | -- Copyright (C) 2009-2023 PUC-Rio | ||
5 | -- | ||
6 | -- Author: Pablo Musa | ||
7 | -- Author: Tomas Guisasola | ||
8 | --------------------------------------------------------------------------- | ||
9 | |||
10 | local socket = require("socket") | ||
11 | local ssl = require("ssl") | ||
12 | local ltn12 = require("ltn12") | ||
13 | local http = require("socket.http") | ||
14 | local url = require("socket.url") | ||
15 | |||
16 | local try = socket.try | ||
17 | |||
18 | -- | ||
19 | -- Module | ||
20 | -- | ||
21 | local _M = { | ||
22 | _VERSION = "1.3.2", | ||
23 | _COPYRIGHT = "LuaSec 1.3.2 - Copyright (C) 2009-2023 PUC-Rio", | ||
24 | PORT = 443, | ||
25 | TIMEOUT = 60 | ||
26 | } | ||
27 | |||
28 | -- TLS configuration | ||
29 | local cfg = { | ||
30 | protocol = "any", | ||
31 | options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"}, | ||
32 | verify = "none", | ||
33 | } | ||
34 | |||
35 | -------------------------------------------------------------------- | ||
36 | -- Auxiliar Functions | ||
37 | -------------------------------------------------------------------- | ||
38 | |||
39 | -- Insert default HTTPS port. | ||
40 | local function default_https_port(u) | ||
41 | return url.build(url.parse(u, {port = _M.PORT})) | ||
42 | end | ||
43 | |||
44 | -- Convert an URL to a table according to Luasocket needs. | ||
45 | local function urlstring_totable(url, body, result_table) | ||
46 | url = { | ||
47 | url = default_https_port(url), | ||
48 | method = body and "POST" or "GET", | ||
49 | sink = ltn12.sink.table(result_table) | ||
50 | } | ||
51 | if body then | ||
52 | url.source = ltn12.source.string(body) | ||
53 | url.headers = { | ||
54 | ["content-length"] = #body, | ||
55 | ["content-type"] = "application/x-www-form-urlencoded", | ||
56 | } | ||
57 | end | ||
58 | return url | ||
59 | end | ||
60 | |||
61 | -- Forward calls to the real connection object. | ||
62 | local function reg(conn) | ||
63 | local mt = getmetatable(conn.sock).__index | ||
64 | for name, method in pairs(mt) do | ||
65 | if type(method) == "function" then | ||
66 | conn[name] = function (self, ...) | ||
67 | return method(self.sock, ...) | ||
68 | end | ||
69 | end | ||
70 | end | ||
71 | end | ||
72 | |||
73 | -- Return a function which performs the SSL/TLS connection. | ||
74 | local function tcp(params) | ||
75 | params = params or {} | ||
76 | -- Default settings | ||
77 | for k, v in pairs(cfg) do | ||
78 | params[k] = params[k] or v | ||
79 | end | ||
80 | -- Force client mode | ||
81 | params.mode = "client" | ||
82 | -- 'create' function for LuaSocket | ||
83 | return function () | ||
84 | local conn = {} | ||
85 | conn.sock = try(socket.tcp()) | ||
86 | local st = getmetatable(conn.sock).__index.settimeout | ||
87 | function conn:settimeout(...) | ||
88 | return st(self.sock, _M.TIMEOUT) | ||
89 | end | ||
90 | -- Replace TCP's connection function | ||
91 | function conn:connect(host, port) | ||
92 | try(self.sock:connect(host, port)) | ||
93 | self.sock = try(ssl.wrap(self.sock, params)) | ||
94 | self.sock:sni(host) | ||
95 | self.sock:settimeout(_M.TIMEOUT) | ||
96 | try(self.sock:dohandshake()) | ||
97 | reg(self) | ||
98 | return 1 | ||
99 | end | ||
100 | return conn | ||
101 | end | ||
102 | end | ||
103 | |||
104 | -------------------------------------------------------------------- | ||
105 | -- Main Function | ||
106 | -------------------------------------------------------------------- | ||
107 | |||
108 | -- Make a HTTP request over secure connection. This function receives | ||
109 | -- the same parameters of LuaSocket's HTTP module (except 'proxy' and | ||
110 | -- 'redirect') plus LuaSec parameters. | ||
111 | -- | ||
112 | -- @param url mandatory (string or table) | ||
113 | -- @param body optional (string) | ||
114 | -- @return (string if url == string or 1), code, headers, status | ||
115 | -- | ||
116 | local function request(url, body) | ||
117 | local result_table = {} | ||
118 | local stringrequest = type(url) == "string" | ||
119 | if stringrequest then | ||
120 | url = urlstring_totable(url, body, result_table) | ||
121 | else | ||
122 | url.url = default_https_port(url.url) | ||
123 | end | ||
124 | if http.PROXY or url.proxy then | ||
125 | return nil, "proxy not supported" | ||
126 | elseif url.redirect then | ||
127 | return nil, "redirect not supported" | ||
128 | elseif url.create then | ||
129 | return nil, "create function not permitted" | ||
130 | end | ||
131 | -- New 'create' function to establish a secure connection | ||
132 | url.create = tcp(url) | ||
133 | local res, code, headers, status = http.request(url) | ||
134 | if res and stringrequest then | ||
135 | return table.concat(result_table), code, headers, status | ||
136 | end | ||
137 | return res, code, headers, status | ||
138 | end | ||
139 | |||
140 | -------------------------------------------------------------------------------- | ||
141 | -- Export module | ||
142 | -- | ||
143 | |||
144 | _M.request = request | ||
145 | _M.tcp = tcp | ||
146 | |||
147 | return _M | ||
diff --git a/vendor/luasec/src/luasocket/LICENSE b/vendor/luasec/src/luasocket/LICENSE new file mode 100644 index 00000000..eadb747b --- /dev/null +++ b/vendor/luasec/src/luasocket/LICENSE | |||
@@ -0,0 +1,21 @@ | |||
1 | LuaSocket 3.0-RC1 license | ||
2 | Copyright (C) 2004-2013 Diego Nehab | ||
3 | |||
4 | Permission is hereby granted, free of charge, to any person obtaining | ||
5 | a copy of this software and associated documentation files (the | ||
6 | "Software"), to deal in the Software without restriction, including | ||
7 | without limitation the rights to use, copy, modify, merge, publish, | ||
8 | distribute, sublicense, and/or sell copies of the Software, and to | ||
9 | permit persons to whom the Software is furnished to do so, subject to | ||
10 | the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be | ||
13 | included in all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
diff --git a/vendor/luasec/src/luasocket/Makefile b/vendor/luasec/src/luasocket/Makefile new file mode 100644 index 00000000..b700fb63 --- /dev/null +++ b/vendor/luasec/src/luasocket/Makefile | |||
@@ -0,0 +1,26 @@ | |||
1 | OBJS= \ | ||
2 | io.o \ | ||
3 | buffer.o \ | ||
4 | timeout.o \ | ||
5 | usocket.o | ||
6 | |||
7 | CC ?= cc | ||
8 | CFLAGS += $(MYCFLAGS) -DLUASOCKET_DEBUG | ||
9 | AR ?= ar | ||
10 | RANLIB ?= ranlib | ||
11 | |||
12 | .PHONY: all clean | ||
13 | |||
14 | all: libluasocket.a | ||
15 | |||
16 | libluasocket.a: $(OBJS) | ||
17 | $(AR) rcu $@ $(OBJS) | ||
18 | $(RANLIB) $@ | ||
19 | |||
20 | clean: | ||
21 | rm -f $(OBJS) libluasocket.a | ||
22 | |||
23 | buffer.o: buffer.c buffer.h io.h timeout.h | ||
24 | io.o: io.c io.h timeout.h | ||
25 | timeout.o: timeout.c timeout.h | ||
26 | usocket.o: usocket.c socket.h io.h timeout.h usocket.h | ||
diff --git a/vendor/luasec/src/luasocket/buffer.c b/vendor/luasec/src/luasocket/buffer.c new file mode 100644 index 00000000..0eaac418 --- /dev/null +++ b/vendor/luasec/src/luasocket/buffer.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Input/Output interface for Lua programs | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "lua.h" | ||
6 | #include "lauxlib.h" | ||
7 | |||
8 | #include "buffer.h" | ||
9 | |||
10 | /*=========================================================================*\ | ||
11 | * Internal function prototypes | ||
12 | \*=========================================================================*/ | ||
13 | static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b); | ||
14 | static int recvline(p_buffer buf, luaL_Buffer *b); | ||
15 | static int recvall(p_buffer buf, luaL_Buffer *b); | ||
16 | static int buffer_get(p_buffer buf, const char **data, size_t *count); | ||
17 | static void buffer_skip(p_buffer buf, size_t count); | ||
18 | static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent); | ||
19 | |||
20 | /* min and max macros */ | ||
21 | #ifndef MIN | ||
22 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
23 | #endif | ||
24 | #ifndef MAX | ||
25 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
26 | #endif | ||
27 | |||
28 | /*=========================================================================*\ | ||
29 | * Exported functions | ||
30 | \*=========================================================================*/ | ||
31 | /*-------------------------------------------------------------------------*\ | ||
32 | * Initializes module | ||
33 | \*-------------------------------------------------------------------------*/ | ||
34 | int buffer_open(lua_State *L) { | ||
35 | (void) L; | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | /*-------------------------------------------------------------------------*\ | ||
40 | * Initializes C structure | ||
41 | \*-------------------------------------------------------------------------*/ | ||
42 | void buffer_init(p_buffer buf, p_io io, p_timeout tm) { | ||
43 | buf->first = buf->last = 0; | ||
44 | buf->io = io; | ||
45 | buf->tm = tm; | ||
46 | buf->received = buf->sent = 0; | ||
47 | buf->birthday = timeout_gettime(); | ||
48 | } | ||
49 | |||
50 | /*-------------------------------------------------------------------------*\ | ||
51 | * object:getstats() interface | ||
52 | \*-------------------------------------------------------------------------*/ | ||
53 | int buffer_meth_getstats(lua_State *L, p_buffer buf) { | ||
54 | lua_pushnumber(L, (lua_Number) buf->received); | ||
55 | lua_pushnumber(L, (lua_Number) buf->sent); | ||
56 | lua_pushnumber(L, timeout_gettime() - buf->birthday); | ||
57 | return 3; | ||
58 | } | ||
59 | |||
60 | /*-------------------------------------------------------------------------*\ | ||
61 | * object:setstats() interface | ||
62 | \*-------------------------------------------------------------------------*/ | ||
63 | int buffer_meth_setstats(lua_State *L, p_buffer buf) { | ||
64 | buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received); | ||
65 | buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent); | ||
66 | if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4); | ||
67 | lua_pushnumber(L, 1); | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | /*-------------------------------------------------------------------------*\ | ||
72 | * object:send() interface | ||
73 | \*-------------------------------------------------------------------------*/ | ||
74 | int buffer_meth_send(lua_State *L, p_buffer buf) { | ||
75 | int top = lua_gettop(L); | ||
76 | int err = IO_DONE; | ||
77 | size_t size = 0, sent = 0; | ||
78 | const char *data = luaL_checklstring(L, 2, &size); | ||
79 | long start = (long) luaL_optnumber(L, 3, 1); | ||
80 | long end = (long) luaL_optnumber(L, 4, -1); | ||
81 | timeout_markstart(buf->tm); | ||
82 | if (start < 0) start = (long) (size+start+1); | ||
83 | if (end < 0) end = (long) (size+end+1); | ||
84 | if (start < 1) start = (long) 1; | ||
85 | if (end > (long) size) end = (long) size; | ||
86 | if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent); | ||
87 | /* check if there was an error */ | ||
88 | if (err != IO_DONE) { | ||
89 | lua_pushnil(L); | ||
90 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | ||
91 | lua_pushnumber(L, (lua_Number) (sent+start-1)); | ||
92 | } else { | ||
93 | lua_pushnumber(L, (lua_Number) (sent+start-1)); | ||
94 | lua_pushnil(L); | ||
95 | lua_pushnil(L); | ||
96 | } | ||
97 | #ifdef LUASOCKET_DEBUG | ||
98 | /* push time elapsed during operation as the last return value */ | ||
99 | lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); | ||
100 | #endif | ||
101 | return lua_gettop(L) - top; | ||
102 | } | ||
103 | |||
104 | /*-------------------------------------------------------------------------*\ | ||
105 | * object:receive() interface | ||
106 | \*-------------------------------------------------------------------------*/ | ||
107 | int buffer_meth_receive(lua_State *L, p_buffer buf) { | ||
108 | luaL_Buffer b; | ||
109 | size_t size; | ||
110 | const char *part; | ||
111 | int err = IO_DONE; | ||
112 | int top = lua_gettop(L); | ||
113 | if (top < 3) { | ||
114 | lua_settop(L, 3); | ||
115 | top = 3; | ||
116 | } | ||
117 | part = luaL_optlstring(L, 3, "", &size); | ||
118 | timeout_markstart(buf->tm); | ||
119 | /* initialize buffer with optional extra prefix | ||
120 | * (useful for concatenating previous partial results) */ | ||
121 | luaL_buffinit(L, &b); | ||
122 | luaL_addlstring(&b, part, size); | ||
123 | /* receive new patterns */ | ||
124 | if (!lua_isnumber(L, 2)) { | ||
125 | const char *p= luaL_optstring(L, 2, "*l"); | ||
126 | if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b); | ||
127 | else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b); | ||
128 | else luaL_argcheck(L, 0, 2, "invalid receive pattern"); | ||
129 | /* get a fixed number of bytes (minus what was already partially | ||
130 | * received) */ | ||
131 | } else { | ||
132 | double n = lua_tonumber(L, 2); | ||
133 | size_t wanted = (size_t) n; | ||
134 | luaL_argcheck(L, n >= 0, 2, "invalid receive pattern"); | ||
135 | if (size == 0 || wanted > size) | ||
136 | err = recvraw(buf, wanted-size, &b); | ||
137 | } | ||
138 | /* check if there was an error */ | ||
139 | if (err != IO_DONE) { | ||
140 | /* we can't push anything in the stack before pushing the | ||
141 | * contents of the buffer. this is the reason for the complication */ | ||
142 | luaL_pushresult(&b); | ||
143 | lua_pushstring(L, buf->io->error(buf->io->ctx, err)); | ||
144 | lua_pushvalue(L, -2); | ||
145 | lua_pushnil(L); | ||
146 | lua_replace(L, -4); | ||
147 | } else { | ||
148 | luaL_pushresult(&b); | ||
149 | lua_pushnil(L); | ||
150 | lua_pushnil(L); | ||
151 | } | ||
152 | #ifdef LUASOCKET_DEBUG | ||
153 | /* push time elapsed during operation as the last return value */ | ||
154 | lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm)); | ||
155 | #endif | ||
156 | return lua_gettop(L) - top; | ||
157 | } | ||
158 | |||
159 | /*-------------------------------------------------------------------------*\ | ||
160 | * Determines if there is any data in the read buffer | ||
161 | \*-------------------------------------------------------------------------*/ | ||
162 | int buffer_isempty(p_buffer buf) { | ||
163 | return buf->first >= buf->last; | ||
164 | } | ||
165 | |||
166 | /*=========================================================================*\ | ||
167 | * Internal functions | ||
168 | \*=========================================================================*/ | ||
169 | /*-------------------------------------------------------------------------*\ | ||
170 | * Sends a block of data (unbuffered) | ||
171 | \*-------------------------------------------------------------------------*/ | ||
172 | #define STEPSIZE 8192 | ||
173 | static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) { | ||
174 | p_io io = buf->io; | ||
175 | p_timeout tm = buf->tm; | ||
176 | size_t total = 0; | ||
177 | int err = IO_DONE; | ||
178 | while (total < count && err == IO_DONE) { | ||
179 | size_t done = 0; | ||
180 | size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE; | ||
181 | err = io->send(io->ctx, data+total, step, &done, tm); | ||
182 | total += done; | ||
183 | } | ||
184 | *sent = total; | ||
185 | buf->sent += total; | ||
186 | return err; | ||
187 | } | ||
188 | |||
189 | /*-------------------------------------------------------------------------*\ | ||
190 | * Reads a fixed number of bytes (buffered) | ||
191 | \*-------------------------------------------------------------------------*/ | ||
192 | static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) { | ||
193 | int err = IO_DONE; | ||
194 | size_t total = 0; | ||
195 | while (err == IO_DONE) { | ||
196 | size_t count; const char *data; | ||
197 | err = buffer_get(buf, &data, &count); | ||
198 | count = MIN(count, wanted - total); | ||
199 | luaL_addlstring(b, data, count); | ||
200 | buffer_skip(buf, count); | ||
201 | total += count; | ||
202 | if (total >= wanted) break; | ||
203 | } | ||
204 | return err; | ||
205 | } | ||
206 | |||
207 | /*-------------------------------------------------------------------------*\ | ||
208 | * Reads everything until the connection is closed (buffered) | ||
209 | \*-------------------------------------------------------------------------*/ | ||
210 | static int recvall(p_buffer buf, luaL_Buffer *b) { | ||
211 | int err = IO_DONE; | ||
212 | size_t total = 0; | ||
213 | while (err == IO_DONE) { | ||
214 | const char *data; size_t count; | ||
215 | err = buffer_get(buf, &data, &count); | ||
216 | total += count; | ||
217 | luaL_addlstring(b, data, count); | ||
218 | buffer_skip(buf, count); | ||
219 | } | ||
220 | if (err == IO_CLOSED) { | ||
221 | if (total > 0) return IO_DONE; | ||
222 | else return IO_CLOSED; | ||
223 | } else return err; | ||
224 | } | ||
225 | |||
226 | /*-------------------------------------------------------------------------*\ | ||
227 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | ||
228 | * are not returned by the function and are discarded from the buffer | ||
229 | \*-------------------------------------------------------------------------*/ | ||
230 | static int recvline(p_buffer buf, luaL_Buffer *b) { | ||
231 | int err = IO_DONE; | ||
232 | while (err == IO_DONE) { | ||
233 | size_t count, pos; const char *data; | ||
234 | err = buffer_get(buf, &data, &count); | ||
235 | pos = 0; | ||
236 | while (pos < count && data[pos] != '\n') { | ||
237 | /* we ignore all \r's */ | ||
238 | if (data[pos] != '\r') luaL_addchar(b, data[pos]); | ||
239 | pos++; | ||
240 | } | ||
241 | if (pos < count) { /* found '\n' */ | ||
242 | buffer_skip(buf, pos+1); /* skip '\n' too */ | ||
243 | break; /* we are done */ | ||
244 | } else /* reached the end of the buffer */ | ||
245 | buffer_skip(buf, pos); | ||
246 | } | ||
247 | return err; | ||
248 | } | ||
249 | |||
250 | /*-------------------------------------------------------------------------*\ | ||
251 | * Skips a given number of bytes from read buffer. No data is read from the | ||
252 | * transport layer | ||
253 | \*-------------------------------------------------------------------------*/ | ||
254 | static void buffer_skip(p_buffer buf, size_t count) { | ||
255 | buf->received += count; | ||
256 | buf->first += count; | ||
257 | if (buffer_isempty(buf)) | ||
258 | buf->first = buf->last = 0; | ||
259 | } | ||
260 | |||
261 | /*-------------------------------------------------------------------------*\ | ||
262 | * Return any data available in buffer, or get more data from transport layer | ||
263 | * if buffer is empty | ||
264 | \*-------------------------------------------------------------------------*/ | ||
265 | static int buffer_get(p_buffer buf, const char **data, size_t *count) { | ||
266 | int err = IO_DONE; | ||
267 | p_io io = buf->io; | ||
268 | p_timeout tm = buf->tm; | ||
269 | if (buffer_isempty(buf)) { | ||
270 | size_t got; | ||
271 | err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm); | ||
272 | buf->first = 0; | ||
273 | buf->last = got; | ||
274 | } | ||
275 | *count = buf->last - buf->first; | ||
276 | *data = buf->data + buf->first; | ||
277 | return err; | ||
278 | } | ||
diff --git a/vendor/luasec/src/luasocket/buffer.h b/vendor/luasec/src/luasocket/buffer.h new file mode 100644 index 00000000..1281bb39 --- /dev/null +++ b/vendor/luasec/src/luasocket/buffer.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef BUF_H | ||
2 | #define BUF_H | ||
3 | /*=========================================================================*\ | ||
4 | * Input/Output interface for Lua programs | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * Line patterns require buffering. Reading one character at a time involves | ||
8 | * too many system calls and is very slow. This module implements the | ||
9 | * LuaSocket interface for input/output on connected objects, as seen by | ||
10 | * Lua programs. | ||
11 | * | ||
12 | * Input is buffered. Output is *not* buffered because there was no simple | ||
13 | * way of making sure the buffered output data would ever be sent. | ||
14 | * | ||
15 | * The module is built on top of the I/O abstraction defined in io.h and the | ||
16 | * timeout management is done with the timeout.h interface. | ||
17 | \*=========================================================================*/ | ||
18 | #include "lua.h" | ||
19 | |||
20 | #include "io.h" | ||
21 | #include "timeout.h" | ||
22 | |||
23 | /* buffer size in bytes */ | ||
24 | #define BUF_SIZE 8192 | ||
25 | |||
26 | /* buffer control structure */ | ||
27 | typedef struct t_buffer_ { | ||
28 | double birthday; /* throttle support info: creation time, */ | ||
29 | size_t sent, received; /* bytes sent, and bytes received */ | ||
30 | p_io io; /* IO driver used for this buffer */ | ||
31 | p_timeout tm; /* timeout management for this buffer */ | ||
32 | size_t first, last; /* index of first and last bytes of stored data */ | ||
33 | char data[BUF_SIZE]; /* storage space for buffer data */ | ||
34 | } t_buffer; | ||
35 | typedef t_buffer *p_buffer; | ||
36 | |||
37 | int buffer_open(lua_State *L); | ||
38 | void buffer_init(p_buffer buf, p_io io, p_timeout tm); | ||
39 | int buffer_meth_send(lua_State *L, p_buffer buf); | ||
40 | int buffer_meth_receive(lua_State *L, p_buffer buf); | ||
41 | int buffer_meth_getstats(lua_State *L, p_buffer buf); | ||
42 | int buffer_meth_setstats(lua_State *L, p_buffer buf); | ||
43 | int buffer_isempty(p_buffer buf); | ||
44 | |||
45 | #endif /* BUF_H */ | ||
diff --git a/vendor/luasec/src/luasocket/io.c b/vendor/luasec/src/luasocket/io.c new file mode 100644 index 00000000..35f46f78 --- /dev/null +++ b/vendor/luasec/src/luasocket/io.c | |||
@@ -0,0 +1,30 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Input/Output abstraction | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include "io.h" | ||
6 | |||
7 | /*=========================================================================*\ | ||
8 | * Exported functions | ||
9 | \*=========================================================================*/ | ||
10 | /*-------------------------------------------------------------------------*\ | ||
11 | * Initializes C structure | ||
12 | \*-------------------------------------------------------------------------*/ | ||
13 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) { | ||
14 | io->send = send; | ||
15 | io->recv = recv; | ||
16 | io->error = error; | ||
17 | io->ctx = ctx; | ||
18 | } | ||
19 | |||
20 | /*-------------------------------------------------------------------------*\ | ||
21 | * I/O error strings | ||
22 | \*-------------------------------------------------------------------------*/ | ||
23 | const char *io_strerror(int err) { | ||
24 | switch (err) { | ||
25 | case IO_DONE: return NULL; | ||
26 | case IO_CLOSED: return "closed"; | ||
27 | case IO_TIMEOUT: return "timeout"; | ||
28 | default: return "unknown error"; | ||
29 | } | ||
30 | } | ||
diff --git a/vendor/luasec/src/luasocket/io.h b/vendor/luasec/src/luasocket/io.h new file mode 100644 index 00000000..8945e2c0 --- /dev/null +++ b/vendor/luasec/src/luasocket/io.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef IO_H | ||
2 | #define IO_H | ||
3 | /*=========================================================================*\ | ||
4 | * Input/Output abstraction | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * This module defines the interface that LuaSocket expects from the | ||
8 | * transport layer for streamed input/output. The idea is that if any | ||
9 | * transport implements this interface, then the buffer.c functions | ||
10 | * automatically work on it. | ||
11 | * | ||
12 | * The module socket.h implements this interface, and thus the module tcp.h | ||
13 | * is very simple. | ||
14 | \*=========================================================================*/ | ||
15 | #include <stdio.h> | ||
16 | #include "lua.h" | ||
17 | |||
18 | #include "timeout.h" | ||
19 | |||
20 | /* IO error codes */ | ||
21 | enum { | ||
22 | IO_DONE = 0, /* operation completed successfully */ | ||
23 | IO_TIMEOUT = -1, /* operation timed out */ | ||
24 | IO_CLOSED = -2, /* the connection has been closed */ | ||
25 | IO_UNKNOWN = -3 | ||
26 | }; | ||
27 | |||
28 | /* interface to error message function */ | ||
29 | typedef const char *(*p_error) ( | ||
30 | void *ctx, /* context needed by send */ | ||
31 | int err /* error code */ | ||
32 | ); | ||
33 | |||
34 | /* interface to send function */ | ||
35 | typedef int (*p_send) ( | ||
36 | void *ctx, /* context needed by send */ | ||
37 | const char *data, /* pointer to buffer with data to send */ | ||
38 | size_t count, /* number of bytes to send from buffer */ | ||
39 | size_t *sent, /* number of bytes sent uppon return */ | ||
40 | p_timeout tm /* timeout control */ | ||
41 | ); | ||
42 | |||
43 | /* interface to recv function */ | ||
44 | typedef int (*p_recv) ( | ||
45 | void *ctx, /* context needed by recv */ | ||
46 | char *data, /* pointer to buffer where data will be written */ | ||
47 | size_t count, /* number of bytes to receive into buffer */ | ||
48 | size_t *got, /* number of bytes received uppon return */ | ||
49 | p_timeout tm /* timeout control */ | ||
50 | ); | ||
51 | |||
52 | /* IO driver definition */ | ||
53 | typedef struct t_io_ { | ||
54 | void *ctx; /* context needed by send/recv */ | ||
55 | p_send send; /* send function pointer */ | ||
56 | p_recv recv; /* receive function pointer */ | ||
57 | p_error error; /* strerror function */ | ||
58 | } t_io; | ||
59 | typedef t_io *p_io; | ||
60 | |||
61 | void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx); | ||
62 | const char *io_strerror(int err); | ||
63 | |||
64 | #endif /* IO_H */ | ||
65 | |||
diff --git a/vendor/luasec/src/luasocket/socket.h b/vendor/luasec/src/luasocket/socket.h new file mode 100644 index 00000000..07c20fe3 --- /dev/null +++ b/vendor/luasec/src/luasocket/socket.h | |||
@@ -0,0 +1,78 @@ | |||
1 | #ifndef SOCKET_H | ||
2 | #define SOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module | ||
5 | * LuaSocket toolkit | ||
6 | * | ||
7 | * BSD Sockets and WinSock are similar, but there are a few irritating | ||
8 | * differences. Also, not all *nix platforms behave the same. This module | ||
9 | * (and the associated usocket.h and wsocket.h) factor these differences and | ||
10 | * creates a interface compatible with the io.h module. | ||
11 | \*=========================================================================*/ | ||
12 | #include "io.h" | ||
13 | |||
14 | /*=========================================================================*\ | ||
15 | * Platform specific compatibilization | ||
16 | \*=========================================================================*/ | ||
17 | #ifdef _WIN32 | ||
18 | #include "wsocket.h" | ||
19 | #else | ||
20 | #include "usocket.h" | ||
21 | #endif | ||
22 | |||
23 | /*=========================================================================*\ | ||
24 | * The connect and accept functions accept a timeout and their | ||
25 | * implementations are somewhat complicated. We chose to move | ||
26 | * the timeout control into this module for these functions in | ||
27 | * order to simplify the modules that use them. | ||
28 | \*=========================================================================*/ | ||
29 | #include "timeout.h" | ||
30 | |||
31 | /* we are lazy... */ | ||
32 | typedef struct sockaddr SA; | ||
33 | |||
34 | /*=========================================================================*\ | ||
35 | * Functions below implement a comfortable platform independent | ||
36 | * interface to sockets | ||
37 | \*=========================================================================*/ | ||
38 | int socket_open(void); | ||
39 | int socket_close(void); | ||
40 | void socket_destroy(p_socket ps); | ||
41 | void socket_shutdown(p_socket ps, int how); | ||
42 | int socket_sendto(p_socket ps, const char *data, size_t count, | ||
43 | size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm); | ||
44 | int socket_recvfrom(p_socket ps, char *data, size_t count, | ||
45 | size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm); | ||
46 | |||
47 | void socket_setnonblocking(p_socket ps); | ||
48 | void socket_setblocking(p_socket ps); | ||
49 | |||
50 | int socket_waitfd(p_socket ps, int sw, p_timeout tm); | ||
51 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
52 | p_timeout tm); | ||
53 | |||
54 | int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm); | ||
55 | int socket_create(p_socket ps, int domain, int type, int protocol); | ||
56 | int socket_bind(p_socket ps, SA *addr, socklen_t addr_len); | ||
57 | int socket_listen(p_socket ps, int backlog); | ||
58 | int socket_accept(p_socket ps, p_socket pa, SA *addr, | ||
59 | socklen_t *addr_len, p_timeout tm); | ||
60 | |||
61 | const char *socket_hoststrerror(int err); | ||
62 | const char *socket_gaistrerror(int err); | ||
63 | const char *socket_strerror(int err); | ||
64 | |||
65 | /* these are perfect to use with the io abstraction module | ||
66 | and the buffered input module */ | ||
67 | int socket_send(p_socket ps, const char *data, size_t count, | ||
68 | size_t *sent, p_timeout tm); | ||
69 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
70 | int socket_write(p_socket ps, const char *data, size_t count, | ||
71 | size_t *sent, p_timeout tm); | ||
72 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
73 | const char *socket_ioerror(p_socket ps, int err); | ||
74 | |||
75 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); | ||
76 | int socket_gethostbyname(const char *addr, struct hostent **hp); | ||
77 | |||
78 | #endif /* SOCKET_H */ | ||
diff --git a/vendor/luasec/src/luasocket/timeout.c b/vendor/luasec/src/luasocket/timeout.c new file mode 100644 index 00000000..94a524be --- /dev/null +++ b/vendor/luasec/src/luasocket/timeout.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Timeout management functions | ||
3 | * LuaSocket toolkit | ||
4 | \*=========================================================================*/ | ||
5 | #include <stdio.h> | ||
6 | #include <limits.h> | ||
7 | #include <float.h> | ||
8 | |||
9 | #include "lua.h" | ||
10 | #include "lauxlib.h" | ||
11 | |||
12 | #include "timeout.h" | ||
13 | |||
14 | #ifdef _WIN32 | ||
15 | #include <windows.h> | ||
16 | #else | ||
17 | #include <time.h> | ||
18 | #include <sys/time.h> | ||
19 | #endif | ||
20 | |||
21 | /* min and max macros */ | ||
22 | #ifndef MIN | ||
23 | #define MIN(x, y) ((x) < (y) ? x : y) | ||
24 | #endif | ||
25 | #ifndef MAX | ||
26 | #define MAX(x, y) ((x) > (y) ? x : y) | ||
27 | #endif | ||
28 | |||
29 | /*=========================================================================*\ | ||
30 | * Internal function prototypes | ||
31 | \*=========================================================================*/ | ||
32 | static int timeout_lua_gettime(lua_State *L); | ||
33 | static int timeout_lua_sleep(lua_State *L); | ||
34 | |||
35 | static luaL_Reg func[] = { | ||
36 | { "gettime", timeout_lua_gettime }, | ||
37 | { "sleep", timeout_lua_sleep }, | ||
38 | { NULL, NULL } | ||
39 | }; | ||
40 | |||
41 | /*=========================================================================*\ | ||
42 | * Exported functions. | ||
43 | \*=========================================================================*/ | ||
44 | /*-------------------------------------------------------------------------*\ | ||
45 | * Initialize structure | ||
46 | \*-------------------------------------------------------------------------*/ | ||
47 | void timeout_init(p_timeout tm, double block, double total) { | ||
48 | tm->block = block; | ||
49 | tm->total = total; | ||
50 | } | ||
51 | |||
52 | /*-------------------------------------------------------------------------*\ | ||
53 | * Determines how much time we have left for the next system call, | ||
54 | * if the previous call was successful | ||
55 | * Input | ||
56 | * tm: timeout control structure | ||
57 | * Returns | ||
58 | * the number of ms left or -1 if there is no time limit | ||
59 | \*-------------------------------------------------------------------------*/ | ||
60 | double timeout_get(p_timeout tm) { | ||
61 | if (tm->block < 0.0 && tm->total < 0.0) { | ||
62 | return -1; | ||
63 | } else if (tm->block < 0.0) { | ||
64 | double t = tm->total - timeout_gettime() + tm->start; | ||
65 | return MAX(t, 0.0); | ||
66 | } else if (tm->total < 0.0) { | ||
67 | return tm->block; | ||
68 | } else { | ||
69 | double t = tm->total - timeout_gettime() + tm->start; | ||
70 | return MIN(tm->block, MAX(t, 0.0)); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | /*-------------------------------------------------------------------------*\ | ||
75 | * Returns time since start of operation | ||
76 | * Input | ||
77 | * tm: timeout control structure | ||
78 | * Returns | ||
79 | * start field of structure | ||
80 | \*-------------------------------------------------------------------------*/ | ||
81 | double timeout_getstart(p_timeout tm) { | ||
82 | return tm->start; | ||
83 | } | ||
84 | |||
85 | /*-------------------------------------------------------------------------*\ | ||
86 | * Determines how much time we have left for the next system call, | ||
87 | * if the previous call was a failure | ||
88 | * Input | ||
89 | * tm: timeout control structure | ||
90 | * Returns | ||
91 | * the number of ms left or -1 if there is no time limit | ||
92 | \*-------------------------------------------------------------------------*/ | ||
93 | double timeout_getretry(p_timeout tm) { | ||
94 | if (tm->block < 0.0 && tm->total < 0.0) { | ||
95 | return -1; | ||
96 | } else if (tm->block < 0.0) { | ||
97 | double t = tm->total - timeout_gettime() + tm->start; | ||
98 | return MAX(t, 0.0); | ||
99 | } else if (tm->total < 0.0) { | ||
100 | double t = tm->block - timeout_gettime() + tm->start; | ||
101 | return MAX(t, 0.0); | ||
102 | } else { | ||
103 | double t = tm->total - timeout_gettime() + tm->start; | ||
104 | return MIN(tm->block, MAX(t, 0.0)); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /*-------------------------------------------------------------------------*\ | ||
109 | * Marks the operation start time in structure | ||
110 | * Input | ||
111 | * tm: timeout control structure | ||
112 | \*-------------------------------------------------------------------------*/ | ||
113 | p_timeout timeout_markstart(p_timeout tm) { | ||
114 | tm->start = timeout_gettime(); | ||
115 | return tm; | ||
116 | } | ||
117 | |||
118 | /*-------------------------------------------------------------------------*\ | ||
119 | * Gets time in s, relative to January 1, 1970 (UTC) | ||
120 | * Returns | ||
121 | * time in s. | ||
122 | \*-------------------------------------------------------------------------*/ | ||
123 | #ifdef _WIN32 | ||
124 | double timeout_gettime(void) { | ||
125 | FILETIME ft; | ||
126 | double t; | ||
127 | GetSystemTimeAsFileTime(&ft); | ||
128 | /* Windows file time (time since January 1, 1601 (UTC)) */ | ||
129 | t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); | ||
130 | /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ | ||
131 | return (t - 11644473600.0); | ||
132 | } | ||
133 | #else | ||
134 | double timeout_gettime(void) { | ||
135 | struct timeval v; | ||
136 | gettimeofday(&v, (struct timezone *) NULL); | ||
137 | /* Unix Epoch time (time since January 1, 1970 (UTC)) */ | ||
138 | return v.tv_sec + v.tv_usec/1.0e6; | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | /*-------------------------------------------------------------------------*\ | ||
143 | * Initializes module | ||
144 | \*-------------------------------------------------------------------------*/ | ||
145 | int timeout_open(lua_State *L) { | ||
146 | #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) | ||
147 | luaL_setfuncs(L, func, 0); | ||
148 | #else | ||
149 | luaL_openlib(L, NULL, func, 0); | ||
150 | #endif | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | /*-------------------------------------------------------------------------*\ | ||
155 | * Sets timeout values for IO operations | ||
156 | * Lua Input: base, time [, mode] | ||
157 | * time: time out value in seconds | ||
158 | * mode: "b" for block timeout, "t" for total timeout. (default: b) | ||
159 | \*-------------------------------------------------------------------------*/ | ||
160 | int timeout_meth_settimeout(lua_State *L, p_timeout tm) { | ||
161 | double t = luaL_optnumber(L, 2, -1); | ||
162 | const char *mode = luaL_optstring(L, 3, "b"); | ||
163 | switch (*mode) { | ||
164 | case 'b': | ||
165 | tm->block = t; | ||
166 | break; | ||
167 | case 'r': case 't': | ||
168 | tm->total = t; | ||
169 | break; | ||
170 | default: | ||
171 | luaL_argcheck(L, 0, 3, "invalid timeout mode"); | ||
172 | break; | ||
173 | } | ||
174 | lua_pushnumber(L, 1); | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | /*=========================================================================*\ | ||
179 | * Test support functions | ||
180 | \*=========================================================================*/ | ||
181 | /*-------------------------------------------------------------------------*\ | ||
182 | * Returns the time the system has been up, in secconds. | ||
183 | \*-------------------------------------------------------------------------*/ | ||
184 | static int timeout_lua_gettime(lua_State *L) | ||
185 | { | ||
186 | lua_pushnumber(L, timeout_gettime()); | ||
187 | return 1; | ||
188 | } | ||
189 | |||
190 | /*-------------------------------------------------------------------------*\ | ||
191 | * Sleep for n seconds. | ||
192 | \*-------------------------------------------------------------------------*/ | ||
193 | #ifdef _WIN32 | ||
194 | int timeout_lua_sleep(lua_State *L) | ||
195 | { | ||
196 | double n = luaL_checknumber(L, 1); | ||
197 | if (n < 0.0) n = 0.0; | ||
198 | if (n < DBL_MAX/1000.0) n *= 1000.0; | ||
199 | if (n > INT_MAX) n = INT_MAX; | ||
200 | Sleep((int)n); | ||
201 | return 0; | ||
202 | } | ||
203 | #else | ||
204 | int timeout_lua_sleep(lua_State *L) | ||
205 | { | ||
206 | double n = luaL_checknumber(L, 1); | ||
207 | struct timespec t, r; | ||
208 | if (n < 0.0) n = 0.0; | ||
209 | if (n > INT_MAX) n = INT_MAX; | ||
210 | t.tv_sec = (int) n; | ||
211 | n -= t.tv_sec; | ||
212 | t.tv_nsec = (int) (n * 1000000000); | ||
213 | if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; | ||
214 | while (nanosleep(&t, &r) != 0) { | ||
215 | t.tv_sec = r.tv_sec; | ||
216 | t.tv_nsec = r.tv_nsec; | ||
217 | } | ||
218 | return 0; | ||
219 | } | ||
220 | #endif | ||
diff --git a/vendor/luasec/src/luasocket/timeout.h b/vendor/luasec/src/luasocket/timeout.h new file mode 100644 index 00000000..4957593b --- /dev/null +++ b/vendor/luasec/src/luasocket/timeout.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef TIMEOUT_H | ||
2 | #define TIMEOUT_H | ||
3 | /*=========================================================================*\ | ||
4 | * Timeout management functions | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | #include "lua.h" | ||
8 | |||
9 | /* timeout control structure */ | ||
10 | typedef struct t_timeout_ { | ||
11 | double block; /* maximum time for blocking calls */ | ||
12 | double total; /* total number of milliseconds for operation */ | ||
13 | double start; /* time of start of operation */ | ||
14 | } t_timeout; | ||
15 | typedef t_timeout *p_timeout; | ||
16 | |||
17 | int timeout_open(lua_State *L); | ||
18 | void timeout_init(p_timeout tm, double block, double total); | ||
19 | double timeout_get(p_timeout tm); | ||
20 | double timeout_getretry(p_timeout tm); | ||
21 | p_timeout timeout_markstart(p_timeout tm); | ||
22 | double timeout_getstart(p_timeout tm); | ||
23 | double timeout_gettime(void); | ||
24 | int timeout_meth_settimeout(lua_State *L, p_timeout tm); | ||
25 | |||
26 | #define timeout_iszero(tm) ((tm)->block == 0.0) | ||
27 | |||
28 | #endif /* TIMEOUT_H */ | ||
diff --git a/vendor/luasec/src/luasocket/usocket.c b/vendor/luasec/src/luasocket/usocket.c new file mode 100644 index 00000000..49e618c4 --- /dev/null +++ b/vendor/luasec/src/luasocket/usocket.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Socket compatibilization module for Unix | ||
3 | * LuaSocket toolkit | ||
4 | * | ||
5 | * The code is now interrupt-safe. | ||
6 | * The penalty of calling select to avoid busy-wait is only paid when | ||
7 | * the I/O call fail in the first place. | ||
8 | \*=========================================================================*/ | ||
9 | #include <string.h> | ||
10 | #include <signal.h> | ||
11 | |||
12 | #include "socket.h" | ||
13 | |||
14 | /*-------------------------------------------------------------------------*\ | ||
15 | * Wait for readable/writable/connected socket with timeout | ||
16 | \*-------------------------------------------------------------------------*/ | ||
17 | #ifndef SOCKET_SELECT | ||
18 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
19 | int ret; | ||
20 | struct pollfd pfd; | ||
21 | pfd.fd = *ps; | ||
22 | pfd.events = sw; | ||
23 | pfd.revents = 0; | ||
24 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
25 | do { | ||
26 | int t = (int)(timeout_getretry(tm)*1e3); | ||
27 | ret = poll(&pfd, 1, t >= 0? t: -1); | ||
28 | } while (ret == -1 && errno == EINTR); | ||
29 | if (ret == -1) return errno; | ||
30 | if (ret == 0) return IO_TIMEOUT; | ||
31 | if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED; | ||
32 | return IO_DONE; | ||
33 | } | ||
34 | #else | ||
35 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
36 | int ret; | ||
37 | fd_set rfds, wfds, *rp, *wp; | ||
38 | struct timeval tv, *tp; | ||
39 | double t; | ||
40 | if (*ps >= FD_SETSIZE) return EINVAL; | ||
41 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
42 | do { | ||
43 | /* must set bits within loop, because select may have modified them */ | ||
44 | rp = wp = NULL; | ||
45 | if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; } | ||
46 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | ||
47 | t = timeout_getretry(tm); | ||
48 | tp = NULL; | ||
49 | if (t >= 0.0) { | ||
50 | tv.tv_sec = (int)t; | ||
51 | tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6); | ||
52 | tp = &tv; | ||
53 | } | ||
54 | ret = select(*ps+1, rp, wp, NULL, tp); | ||
55 | } while (ret == -1 && errno == EINTR); | ||
56 | if (ret == -1) return errno; | ||
57 | if (ret == 0) return IO_TIMEOUT; | ||
58 | if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED; | ||
59 | return IO_DONE; | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | |||
64 | /*-------------------------------------------------------------------------*\ | ||
65 | * Initializes module | ||
66 | \*-------------------------------------------------------------------------*/ | ||
67 | int socket_open(void) { | ||
68 | /* instals a handler to ignore sigpipe or it will crash us */ | ||
69 | signal(SIGPIPE, SIG_IGN); | ||
70 | return 1; | ||
71 | } | ||
72 | |||
73 | /*-------------------------------------------------------------------------*\ | ||
74 | * Close module | ||
75 | \*-------------------------------------------------------------------------*/ | ||
76 | int socket_close(void) { | ||
77 | return 1; | ||
78 | } | ||
79 | |||
80 | /*-------------------------------------------------------------------------*\ | ||
81 | * Close and inutilize socket | ||
82 | \*-------------------------------------------------------------------------*/ | ||
83 | void socket_destroy(p_socket ps) { | ||
84 | if (*ps != SOCKET_INVALID) { | ||
85 | socket_setblocking(ps); | ||
86 | close(*ps); | ||
87 | *ps = SOCKET_INVALID; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /*-------------------------------------------------------------------------*\ | ||
92 | * Select with timeout control | ||
93 | \*-------------------------------------------------------------------------*/ | ||
94 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
95 | p_timeout tm) { | ||
96 | int ret; | ||
97 | do { | ||
98 | struct timeval tv; | ||
99 | double t = timeout_getretry(tm); | ||
100 | tv.tv_sec = (int) t; | ||
101 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | ||
102 | /* timeout = 0 means no wait */ | ||
103 | ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL); | ||
104 | } while (ret < 0 && errno == EINTR); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | /*-------------------------------------------------------------------------*\ | ||
109 | * Creates and sets up a socket | ||
110 | \*-------------------------------------------------------------------------*/ | ||
111 | int socket_create(p_socket ps, int domain, int type, int protocol) { | ||
112 | *ps = socket(domain, type, protocol); | ||
113 | if (*ps != SOCKET_INVALID) return IO_DONE; | ||
114 | else return errno; | ||
115 | } | ||
116 | |||
117 | /*-------------------------------------------------------------------------*\ | ||
118 | * Binds or returns error message | ||
119 | \*-------------------------------------------------------------------------*/ | ||
120 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | ||
121 | int err = IO_DONE; | ||
122 | socket_setblocking(ps); | ||
123 | if (bind(*ps, addr, len) < 0) err = errno; | ||
124 | socket_setnonblocking(ps); | ||
125 | return err; | ||
126 | } | ||
127 | |||
128 | /*-------------------------------------------------------------------------*\ | ||
129 | * | ||
130 | \*-------------------------------------------------------------------------*/ | ||
131 | int socket_listen(p_socket ps, int backlog) { | ||
132 | int err = IO_DONE; | ||
133 | socket_setblocking(ps); | ||
134 | if (listen(*ps, backlog)) err = errno; | ||
135 | socket_setnonblocking(ps); | ||
136 | return err; | ||
137 | } | ||
138 | |||
139 | /*-------------------------------------------------------------------------*\ | ||
140 | * | ||
141 | \*-------------------------------------------------------------------------*/ | ||
142 | void socket_shutdown(p_socket ps, int how) { | ||
143 | socket_setblocking(ps); | ||
144 | shutdown(*ps, how); | ||
145 | socket_setnonblocking(ps); | ||
146 | } | ||
147 | |||
148 | /*-------------------------------------------------------------------------*\ | ||
149 | * Connects or returns error message | ||
150 | \*-------------------------------------------------------------------------*/ | ||
151 | int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | ||
152 | int err; | ||
153 | /* avoid calling on closed sockets */ | ||
154 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
155 | /* call connect until done or failed without being interrupted */ | ||
156 | do if (connect(*ps, addr, len) == 0) return IO_DONE; | ||
157 | while ((err = errno) == EINTR); | ||
158 | /* if connection failed immediately, return error code */ | ||
159 | if (err != EINPROGRESS && err != EAGAIN) return err; | ||
160 | /* zero timeout case optimization */ | ||
161 | if (timeout_iszero(tm)) return IO_TIMEOUT; | ||
162 | /* wait until we have the result of the connection attempt or timeout */ | ||
163 | err = socket_waitfd(ps, WAITFD_C, tm); | ||
164 | if (err == IO_CLOSED) { | ||
165 | if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE; | ||
166 | else return errno; | ||
167 | } else return err; | ||
168 | } | ||
169 | |||
170 | /*-------------------------------------------------------------------------*\ | ||
171 | * Accept with timeout | ||
172 | \*-------------------------------------------------------------------------*/ | ||
173 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { | ||
174 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
175 | for ( ;; ) { | ||
176 | int err; | ||
177 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | ||
178 | err = errno; | ||
179 | if (err == EINTR) continue; | ||
180 | if (err != EAGAIN && err != ECONNABORTED) return err; | ||
181 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
182 | } | ||
183 | /* can't reach here */ | ||
184 | return IO_UNKNOWN; | ||
185 | } | ||
186 | |||
187 | /*-------------------------------------------------------------------------*\ | ||
188 | * Send with timeout | ||
189 | \*-------------------------------------------------------------------------*/ | ||
190 | int socket_send(p_socket ps, const char *data, size_t count, | ||
191 | size_t *sent, p_timeout tm) | ||
192 | { | ||
193 | int err; | ||
194 | *sent = 0; | ||
195 | /* avoid making system calls on closed sockets */ | ||
196 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
197 | /* loop until we send something or we give up on error */ | ||
198 | for ( ;; ) { | ||
199 | long put = (long) send(*ps, data, count, 0); | ||
200 | /* if we sent anything, we are done */ | ||
201 | if (put >= 0) { | ||
202 | *sent = put; | ||
203 | return IO_DONE; | ||
204 | } | ||
205 | err = errno; | ||
206 | /* EPIPE means the connection was closed */ | ||
207 | if (err == EPIPE) return IO_CLOSED; | ||
208 | /* we call was interrupted, just try again */ | ||
209 | if (err == EINTR) continue; | ||
210 | /* if failed fatal reason, report error */ | ||
211 | if (err != EAGAIN) return err; | ||
212 | /* wait until we can send something or we timeout */ | ||
213 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
214 | } | ||
215 | /* can't reach here */ | ||
216 | return IO_UNKNOWN; | ||
217 | } | ||
218 | |||
219 | /*-------------------------------------------------------------------------*\ | ||
220 | * Sendto with timeout | ||
221 | \*-------------------------------------------------------------------------*/ | ||
222 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||
223 | SA *addr, socklen_t len, p_timeout tm) | ||
224 | { | ||
225 | int err; | ||
226 | *sent = 0; | ||
227 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
228 | for ( ;; ) { | ||
229 | long put = (long) sendto(*ps, data, count, 0, addr, len); | ||
230 | if (put >= 0) { | ||
231 | *sent = put; | ||
232 | return IO_DONE; | ||
233 | } | ||
234 | err = errno; | ||
235 | if (err == EPIPE) return IO_CLOSED; | ||
236 | if (err == EINTR) continue; | ||
237 | if (err != EAGAIN) return err; | ||
238 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
239 | } | ||
240 | return IO_UNKNOWN; | ||
241 | } | ||
242 | |||
243 | /*-------------------------------------------------------------------------*\ | ||
244 | * Receive with timeout | ||
245 | \*-------------------------------------------------------------------------*/ | ||
246 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||
247 | int err; | ||
248 | *got = 0; | ||
249 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
250 | for ( ;; ) { | ||
251 | long taken = (long) recv(*ps, data, count, 0); | ||
252 | if (taken > 0) { | ||
253 | *got = taken; | ||
254 | return IO_DONE; | ||
255 | } | ||
256 | err = errno; | ||
257 | if (taken == 0) return IO_CLOSED; | ||
258 | if (err == EINTR) continue; | ||
259 | if (err != EAGAIN) return err; | ||
260 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
261 | } | ||
262 | return IO_UNKNOWN; | ||
263 | } | ||
264 | |||
265 | /*-------------------------------------------------------------------------*\ | ||
266 | * Recvfrom with timeout | ||
267 | \*-------------------------------------------------------------------------*/ | ||
268 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||
269 | SA *addr, socklen_t *len, p_timeout tm) { | ||
270 | int err; | ||
271 | *got = 0; | ||
272 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
273 | for ( ;; ) { | ||
274 | long taken = (long) recvfrom(*ps, data, count, 0, addr, len); | ||
275 | if (taken > 0) { | ||
276 | *got = taken; | ||
277 | return IO_DONE; | ||
278 | } | ||
279 | err = errno; | ||
280 | if (taken == 0) return IO_CLOSED; | ||
281 | if (err == EINTR) continue; | ||
282 | if (err != EAGAIN) return err; | ||
283 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
284 | } | ||
285 | return IO_UNKNOWN; | ||
286 | } | ||
287 | |||
288 | |||
289 | /*-------------------------------------------------------------------------*\ | ||
290 | * Write with timeout | ||
291 | * | ||
292 | * socket_read and socket_write are cut-n-paste of socket_send and socket_recv, | ||
293 | * with send/recv replaced with write/read. We can't just use write/read | ||
294 | * in the socket version, because behaviour when size is zero is different. | ||
295 | \*-------------------------------------------------------------------------*/ | ||
296 | int socket_write(p_socket ps, const char *data, size_t count, | ||
297 | size_t *sent, p_timeout tm) | ||
298 | { | ||
299 | int err; | ||
300 | *sent = 0; | ||
301 | /* avoid making system calls on closed sockets */ | ||
302 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
303 | /* loop until we send something or we give up on error */ | ||
304 | for ( ;; ) { | ||
305 | long put = (long) write(*ps, data, count); | ||
306 | /* if we sent anything, we are done */ | ||
307 | if (put >= 0) { | ||
308 | *sent = put; | ||
309 | return IO_DONE; | ||
310 | } | ||
311 | err = errno; | ||
312 | /* EPIPE means the connection was closed */ | ||
313 | if (err == EPIPE) return IO_CLOSED; | ||
314 | /* we call was interrupted, just try again */ | ||
315 | if (err == EINTR) continue; | ||
316 | /* if failed fatal reason, report error */ | ||
317 | if (err != EAGAIN) return err; | ||
318 | /* wait until we can send something or we timeout */ | ||
319 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
320 | } | ||
321 | /* can't reach here */ | ||
322 | return IO_UNKNOWN; | ||
323 | } | ||
324 | |||
325 | /*-------------------------------------------------------------------------*\ | ||
326 | * Read with timeout | ||
327 | * See note for socket_write | ||
328 | \*-------------------------------------------------------------------------*/ | ||
329 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||
330 | int err; | ||
331 | *got = 0; | ||
332 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
333 | for ( ;; ) { | ||
334 | long taken = (long) read(*ps, data, count); | ||
335 | if (taken > 0) { | ||
336 | *got = taken; | ||
337 | return IO_DONE; | ||
338 | } | ||
339 | err = errno; | ||
340 | if (taken == 0) return IO_CLOSED; | ||
341 | if (err == EINTR) continue; | ||
342 | if (err != EAGAIN) return err; | ||
343 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
344 | } | ||
345 | return IO_UNKNOWN; | ||
346 | } | ||
347 | |||
348 | /*-------------------------------------------------------------------------*\ | ||
349 | * Put socket into blocking mode | ||
350 | \*-------------------------------------------------------------------------*/ | ||
351 | void socket_setblocking(p_socket ps) { | ||
352 | int flags = fcntl(*ps, F_GETFL, 0); | ||
353 | flags &= (~(O_NONBLOCK)); | ||
354 | fcntl(*ps, F_SETFL, flags); | ||
355 | } | ||
356 | |||
357 | /*-------------------------------------------------------------------------*\ | ||
358 | * Put socket into non-blocking mode | ||
359 | \*-------------------------------------------------------------------------*/ | ||
360 | void socket_setnonblocking(p_socket ps) { | ||
361 | int flags = fcntl(*ps, F_GETFL, 0); | ||
362 | flags |= O_NONBLOCK; | ||
363 | fcntl(*ps, F_SETFL, flags); | ||
364 | } | ||
365 | |||
366 | /*-------------------------------------------------------------------------*\ | ||
367 | * DNS helpers | ||
368 | \*-------------------------------------------------------------------------*/ | ||
369 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | ||
370 | *hp = gethostbyaddr(addr, len, AF_INET); | ||
371 | if (*hp) return IO_DONE; | ||
372 | else if (h_errno) return h_errno; | ||
373 | else if (errno) return errno; | ||
374 | else return IO_UNKNOWN; | ||
375 | } | ||
376 | |||
377 | int socket_gethostbyname(const char *addr, struct hostent **hp) { | ||
378 | *hp = gethostbyname(addr); | ||
379 | if (*hp) return IO_DONE; | ||
380 | else if (h_errno) return h_errno; | ||
381 | else if (errno) return errno; | ||
382 | else return IO_UNKNOWN; | ||
383 | } | ||
384 | |||
385 | /*-------------------------------------------------------------------------*\ | ||
386 | * Error translation functions | ||
387 | * Make sure important error messages are standard | ||
388 | \*-------------------------------------------------------------------------*/ | ||
389 | const char *socket_hoststrerror(int err) { | ||
390 | if (err <= 0) return io_strerror(err); | ||
391 | switch (err) { | ||
392 | case HOST_NOT_FOUND: return "host not found"; | ||
393 | default: return hstrerror(err); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | const char *socket_strerror(int err) { | ||
398 | if (err <= 0) return io_strerror(err); | ||
399 | switch (err) { | ||
400 | case EADDRINUSE: return "address already in use"; | ||
401 | case EISCONN: return "already connected"; | ||
402 | case EACCES: return "permission denied"; | ||
403 | case ECONNREFUSED: return "connection refused"; | ||
404 | case ECONNABORTED: return "closed"; | ||
405 | case ECONNRESET: return "closed"; | ||
406 | case ETIMEDOUT: return "timeout"; | ||
407 | default: return strerror(err); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | const char *socket_ioerror(p_socket ps, int err) { | ||
412 | (void) ps; | ||
413 | return socket_strerror(err); | ||
414 | } | ||
415 | |||
416 | const char *socket_gaistrerror(int err) { | ||
417 | if (err == 0) return NULL; | ||
418 | switch (err) { | ||
419 | case EAI_AGAIN: return "temporary failure in name resolution"; | ||
420 | case EAI_BADFLAGS: return "invalid value for ai_flags"; | ||
421 | #ifdef EAI_BADHINTS | ||
422 | case EAI_BADHINTS: return "invalid value for hints"; | ||
423 | #endif | ||
424 | case EAI_FAIL: return "non-recoverable failure in name resolution"; | ||
425 | case EAI_FAMILY: return "ai_family not supported"; | ||
426 | case EAI_MEMORY: return "memory allocation failure"; | ||
427 | case EAI_NONAME: | ||
428 | return "host or service not provided, or not known"; | ||
429 | #ifdef EAI_OVERFLOW | ||
430 | case EAI_OVERFLOW: return "argument buffer overflow"; | ||
431 | #endif | ||
432 | #ifdef EAI_PROTOCOL | ||
433 | case EAI_PROTOCOL: return "resolved protocol is unknown"; | ||
434 | #endif | ||
435 | case EAI_SERVICE: return "service not supported for socket type"; | ||
436 | case EAI_SOCKTYPE: return "ai_socktype not supported"; | ||
437 | case EAI_SYSTEM: return strerror(errno); | ||
438 | default: return gai_strerror(err); | ||
439 | } | ||
440 | } | ||
441 | |||
diff --git a/vendor/luasec/src/luasocket/usocket.h b/vendor/luasec/src/luasocket/usocket.h new file mode 100644 index 00000000..ecbcd8e5 --- /dev/null +++ b/vendor/luasec/src/luasocket/usocket.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef USOCKET_H | ||
2 | #define USOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module for Unix | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * BSD include files | ||
10 | \*=========================================================================*/ | ||
11 | /* error codes */ | ||
12 | #include <errno.h> | ||
13 | /* close function */ | ||
14 | #include <unistd.h> | ||
15 | /* fnctnl function and associated constants */ | ||
16 | #include <fcntl.h> | ||
17 | /* struct sockaddr */ | ||
18 | #include <sys/types.h> | ||
19 | /* socket function */ | ||
20 | #include <sys/socket.h> | ||
21 | /* struct timeval */ | ||
22 | #include <sys/time.h> | ||
23 | /* gethostbyname and gethostbyaddr functions */ | ||
24 | #include <netdb.h> | ||
25 | /* sigpipe handling */ | ||
26 | #include <signal.h> | ||
27 | /* IP stuff*/ | ||
28 | #include <netinet/in.h> | ||
29 | #include <arpa/inet.h> | ||
30 | /* TCP options (nagle algorithm disable) */ | ||
31 | #include <netinet/tcp.h> | ||
32 | #include <net/if.h> | ||
33 | |||
34 | #ifndef SOCKET_SELECT | ||
35 | #include <sys/poll.h> | ||
36 | #define WAITFD_R POLLIN | ||
37 | #define WAITFD_W POLLOUT | ||
38 | #define WAITFD_C (POLLIN|POLLOUT) | ||
39 | #else | ||
40 | #define WAITFD_R 1 | ||
41 | #define WAITFD_W 2 | ||
42 | #define WAITFD_C (WAITFD_R|WAITFD_W) | ||
43 | #endif | ||
44 | |||
45 | #ifndef SO_REUSEPORT | ||
46 | #define SO_REUSEPORT SO_REUSEADDR | ||
47 | #endif | ||
48 | |||
49 | /* Some platforms use IPV6_JOIN_GROUP instead if | ||
50 | * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */ | ||
51 | #ifndef IPV6_ADD_MEMBERSHIP | ||
52 | #ifdef IPV6_JOIN_GROUP | ||
53 | #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP | ||
54 | #endif /* IPV6_JOIN_GROUP */ | ||
55 | #endif /* !IPV6_ADD_MEMBERSHIP */ | ||
56 | |||
57 | /* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */ | ||
58 | #ifndef IPV6_DROP_MEMBERSHIP | ||
59 | #ifdef IPV6_LEAVE_GROUP | ||
60 | #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP | ||
61 | #endif /* IPV6_LEAVE_GROUP */ | ||
62 | #endif /* !IPV6_DROP_MEMBERSHIP */ | ||
63 | |||
64 | typedef int t_socket; | ||
65 | typedef t_socket *p_socket; | ||
66 | typedef struct sockaddr_storage t_sockaddr_storage; | ||
67 | |||
68 | #define SOCKET_INVALID (-1) | ||
69 | |||
70 | #endif /* USOCKET_H */ | ||
diff --git a/vendor/luasec/src/luasocket/wsocket.c b/vendor/luasec/src/luasocket/wsocket.c new file mode 100644 index 00000000..8c7640eb --- /dev/null +++ b/vendor/luasec/src/luasocket/wsocket.c | |||
@@ -0,0 +1,429 @@ | |||
1 | /*=========================================================================*\ | ||
2 | * Socket compatibilization module for Win32 | ||
3 | * LuaSocket toolkit | ||
4 | * | ||
5 | * The penalty of calling select to avoid busy-wait is only paid when | ||
6 | * the I/O call fail in the first place. | ||
7 | \*=========================================================================*/ | ||
8 | #include <string.h> | ||
9 | |||
10 | #include "socket.h" | ||
11 | |||
12 | /* WinSock doesn't have a strerror... */ | ||
13 | static const char *wstrerror(int err); | ||
14 | |||
15 | /*-------------------------------------------------------------------------*\ | ||
16 | * Initializes module | ||
17 | \*-------------------------------------------------------------------------*/ | ||
18 | int socket_open(void) { | ||
19 | WSADATA wsaData; | ||
20 | WORD wVersionRequested = MAKEWORD(2, 0); | ||
21 | int err = WSAStartup(wVersionRequested, &wsaData ); | ||
22 | if (err != 0) return 0; | ||
23 | if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) && | ||
24 | (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) { | ||
25 | WSACleanup(); | ||
26 | return 0; | ||
27 | } | ||
28 | return 1; | ||
29 | } | ||
30 | |||
31 | /*-------------------------------------------------------------------------*\ | ||
32 | * Close module | ||
33 | \*-------------------------------------------------------------------------*/ | ||
34 | int socket_close(void) { | ||
35 | WSACleanup(); | ||
36 | return 1; | ||
37 | } | ||
38 | |||
39 | /*-------------------------------------------------------------------------*\ | ||
40 | * Wait for readable/writable/connected socket with timeout | ||
41 | \*-------------------------------------------------------------------------*/ | ||
42 | int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||
43 | int ret; | ||
44 | fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL; | ||
45 | struct timeval tv, *tp = NULL; | ||
46 | double t; | ||
47 | if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ | ||
48 | if (sw & WAITFD_R) { | ||
49 | FD_ZERO(&rfds); | ||
50 | FD_SET(*ps, &rfds); | ||
51 | rp = &rfds; | ||
52 | } | ||
53 | if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; } | ||
54 | if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; } | ||
55 | if ((t = timeout_get(tm)) >= 0.0) { | ||
56 | tv.tv_sec = (int) t; | ||
57 | tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6); | ||
58 | tp = &tv; | ||
59 | } | ||
60 | ret = select(0, rp, wp, ep, tp); | ||
61 | if (ret == -1) return WSAGetLastError(); | ||
62 | if (ret == 0) return IO_TIMEOUT; | ||
63 | if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED; | ||
64 | return IO_DONE; | ||
65 | } | ||
66 | |||
67 | /*-------------------------------------------------------------------------*\ | ||
68 | * Select with int timeout in ms | ||
69 | \*-------------------------------------------------------------------------*/ | ||
70 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | ||
71 | p_timeout tm) { | ||
72 | struct timeval tv; | ||
73 | double t = timeout_get(tm); | ||
74 | tv.tv_sec = (int) t; | ||
75 | tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6); | ||
76 | if (n <= 0) { | ||
77 | Sleep((DWORD) (1000*t)); | ||
78 | return 0; | ||
79 | } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL); | ||
80 | } | ||
81 | |||
82 | /*-------------------------------------------------------------------------*\ | ||
83 | * Close and inutilize socket | ||
84 | \*-------------------------------------------------------------------------*/ | ||
85 | void socket_destroy(p_socket ps) { | ||
86 | if (*ps != SOCKET_INVALID) { | ||
87 | socket_setblocking(ps); /* close can take a long time on WIN32 */ | ||
88 | closesocket(*ps); | ||
89 | *ps = SOCKET_INVALID; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | /*-------------------------------------------------------------------------*\ | ||
94 | * | ||
95 | \*-------------------------------------------------------------------------*/ | ||
96 | void socket_shutdown(p_socket ps, int how) { | ||
97 | socket_setblocking(ps); | ||
98 | shutdown(*ps, how); | ||
99 | socket_setnonblocking(ps); | ||
100 | } | ||
101 | |||
102 | /*-------------------------------------------------------------------------*\ | ||
103 | * Creates and sets up a socket | ||
104 | \*-------------------------------------------------------------------------*/ | ||
105 | int socket_create(p_socket ps, int domain, int type, int protocol) { | ||
106 | *ps = socket(domain, type, protocol); | ||
107 | if (*ps != SOCKET_INVALID) return IO_DONE; | ||
108 | else return WSAGetLastError(); | ||
109 | } | ||
110 | |||
111 | /*-------------------------------------------------------------------------*\ | ||
112 | * Connects or returns error message | ||
113 | \*-------------------------------------------------------------------------*/ | ||
114 | int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | ||
115 | int err; | ||
116 | /* don't call on closed socket */ | ||
117 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
118 | /* ask system to connect */ | ||
119 | if (connect(*ps, addr, len) == 0) return IO_DONE; | ||
120 | /* make sure the system is trying to connect */ | ||
121 | err = WSAGetLastError(); | ||
122 | if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err; | ||
123 | /* zero timeout case optimization */ | ||
124 | if (timeout_iszero(tm)) return IO_TIMEOUT; | ||
125 | /* we wait until something happens */ | ||
126 | err = socket_waitfd(ps, WAITFD_C, tm); | ||
127 | if (err == IO_CLOSED) { | ||
128 | int len = sizeof(err); | ||
129 | /* give windows time to set the error (yes, disgusting) */ | ||
130 | Sleep(10); | ||
131 | /* find out why we failed */ | ||
132 | getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len); | ||
133 | /* we KNOW there was an error. if 'why' is 0, we will return | ||
134 | * "unknown error", but it's not really our fault */ | ||
135 | return err > 0? err: IO_UNKNOWN; | ||
136 | } else return err; | ||
137 | |||
138 | } | ||
139 | |||
140 | /*-------------------------------------------------------------------------*\ | ||
141 | * Binds or returns error message | ||
142 | \*-------------------------------------------------------------------------*/ | ||
143 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | ||
144 | int err = IO_DONE; | ||
145 | socket_setblocking(ps); | ||
146 | if (bind(*ps, addr, len) < 0) err = WSAGetLastError(); | ||
147 | socket_setnonblocking(ps); | ||
148 | return err; | ||
149 | } | ||
150 | |||
151 | /*-------------------------------------------------------------------------*\ | ||
152 | * | ||
153 | \*-------------------------------------------------------------------------*/ | ||
154 | int socket_listen(p_socket ps, int backlog) { | ||
155 | int err = IO_DONE; | ||
156 | socket_setblocking(ps); | ||
157 | if (listen(*ps, backlog) < 0) err = WSAGetLastError(); | ||
158 | socket_setnonblocking(ps); | ||
159 | return err; | ||
160 | } | ||
161 | |||
162 | /*-------------------------------------------------------------------------*\ | ||
163 | * Accept with timeout | ||
164 | \*-------------------------------------------------------------------------*/ | ||
165 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, | ||
166 | p_timeout tm) { | ||
167 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
168 | for ( ;; ) { | ||
169 | int err; | ||
170 | /* try to get client socket */ | ||
171 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | ||
172 | /* find out why we failed */ | ||
173 | err = WSAGetLastError(); | ||
174 | /* if we failed because there was no connectoin, keep trying */ | ||
175 | if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err; | ||
176 | /* call select to avoid busy wait */ | ||
177 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /*-------------------------------------------------------------------------*\ | ||
182 | * Send with timeout | ||
183 | * On windows, if you try to send 10MB, the OS will buffer EVERYTHING | ||
184 | * this can take an awful lot of time and we will end up blocked. | ||
185 | * Therefore, whoever calls this function should not pass a huge buffer. | ||
186 | \*-------------------------------------------------------------------------*/ | ||
187 | int socket_send(p_socket ps, const char *data, size_t count, | ||
188 | size_t *sent, p_timeout tm) | ||
189 | { | ||
190 | int err; | ||
191 | *sent = 0; | ||
192 | /* avoid making system calls on closed sockets */ | ||
193 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
194 | /* loop until we send something or we give up on error */ | ||
195 | for ( ;; ) { | ||
196 | /* try to send something */ | ||
197 | int put = send(*ps, data, (int) count, 0); | ||
198 | /* if we sent something, we are done */ | ||
199 | if (put > 0) { | ||
200 | *sent = put; | ||
201 | return IO_DONE; | ||
202 | } | ||
203 | /* deal with failure */ | ||
204 | err = WSAGetLastError(); | ||
205 | /* we can only proceed if there was no serious error */ | ||
206 | if (err != WSAEWOULDBLOCK) return err; | ||
207 | /* avoid busy wait */ | ||
208 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /*-------------------------------------------------------------------------*\ | ||
213 | * Sendto with timeout | ||
214 | \*-------------------------------------------------------------------------*/ | ||
215 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||
216 | SA *addr, socklen_t len, p_timeout tm) | ||
217 | { | ||
218 | int err; | ||
219 | *sent = 0; | ||
220 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
221 | for ( ;; ) { | ||
222 | int put = sendto(*ps, data, (int) count, 0, addr, len); | ||
223 | if (put > 0) { | ||
224 | *sent = put; | ||
225 | return IO_DONE; | ||
226 | } | ||
227 | err = WSAGetLastError(); | ||
228 | if (err != WSAEWOULDBLOCK) return err; | ||
229 | if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | /*-------------------------------------------------------------------------*\ | ||
234 | * Receive with timeout | ||
235 | \*-------------------------------------------------------------------------*/ | ||
236 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, | ||
237 | p_timeout tm) | ||
238 | { | ||
239 | int err, prev = IO_DONE; | ||
240 | *got = 0; | ||
241 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
242 | for ( ;; ) { | ||
243 | int taken = recv(*ps, data, (int) count, 0); | ||
244 | if (taken > 0) { | ||
245 | *got = taken; | ||
246 | return IO_DONE; | ||
247 | } | ||
248 | if (taken == 0) return IO_CLOSED; | ||
249 | err = WSAGetLastError(); | ||
250 | /* On UDP, a connreset simply means the previous send failed. | ||
251 | * So we try again. | ||
252 | * On TCP, it means our socket is now useless, so the error passes. | ||
253 | * (We will loop again, exiting because the same error will happen) */ | ||
254 | if (err != WSAEWOULDBLOCK) { | ||
255 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
256 | prev = err; | ||
257 | } | ||
258 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /*-------------------------------------------------------------------------*\ | ||
263 | * Recvfrom with timeout | ||
264 | \*-------------------------------------------------------------------------*/ | ||
265 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||
266 | SA *addr, socklen_t *len, p_timeout tm) | ||
267 | { | ||
268 | int err, prev = IO_DONE; | ||
269 | *got = 0; | ||
270 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||
271 | for ( ;; ) { | ||
272 | int taken = recvfrom(*ps, data, (int) count, 0, addr, len); | ||
273 | if (taken > 0) { | ||
274 | *got = taken; | ||
275 | return IO_DONE; | ||
276 | } | ||
277 | if (taken == 0) return IO_CLOSED; | ||
278 | err = WSAGetLastError(); | ||
279 | /* On UDP, a connreset simply means the previous send failed. | ||
280 | * So we try again. | ||
281 | * On TCP, it means our socket is now useless, so the error passes. | ||
282 | * (We will loop again, exiting because the same error will happen) */ | ||
283 | if (err != WSAEWOULDBLOCK) { | ||
284 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; | ||
285 | prev = err; | ||
286 | } | ||
287 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /*-------------------------------------------------------------------------*\ | ||
292 | * Put socket into blocking mode | ||
293 | \*-------------------------------------------------------------------------*/ | ||
294 | void socket_setblocking(p_socket ps) { | ||
295 | u_long argp = 0; | ||
296 | ioctlsocket(*ps, FIONBIO, &argp); | ||
297 | } | ||
298 | |||
299 | /*-------------------------------------------------------------------------*\ | ||
300 | * Put socket into non-blocking mode | ||
301 | \*-------------------------------------------------------------------------*/ | ||
302 | void socket_setnonblocking(p_socket ps) { | ||
303 | u_long argp = 1; | ||
304 | ioctlsocket(*ps, FIONBIO, &argp); | ||
305 | } | ||
306 | |||
307 | /*-------------------------------------------------------------------------*\ | ||
308 | * DNS helpers | ||
309 | \*-------------------------------------------------------------------------*/ | ||
310 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | ||
311 | *hp = gethostbyaddr(addr, len, AF_INET); | ||
312 | if (*hp) return IO_DONE; | ||
313 | else return WSAGetLastError(); | ||
314 | } | ||
315 | |||
316 | int socket_gethostbyname(const char *addr, struct hostent **hp) { | ||
317 | *hp = gethostbyname(addr); | ||
318 | if (*hp) return IO_DONE; | ||
319 | else return WSAGetLastError(); | ||
320 | } | ||
321 | |||
322 | /*-------------------------------------------------------------------------*\ | ||
323 | * Error translation functions | ||
324 | \*-------------------------------------------------------------------------*/ | ||
325 | const char *socket_hoststrerror(int err) { | ||
326 | if (err <= 0) return io_strerror(err); | ||
327 | switch (err) { | ||
328 | case WSAHOST_NOT_FOUND: return "host not found"; | ||
329 | default: return wstrerror(err); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | const char *socket_strerror(int err) { | ||
334 | if (err <= 0) return io_strerror(err); | ||
335 | switch (err) { | ||
336 | case WSAEADDRINUSE: return "address already in use"; | ||
337 | case WSAECONNREFUSED: return "connection refused"; | ||
338 | case WSAEISCONN: return "already connected"; | ||
339 | case WSAEACCES: return "permission denied"; | ||
340 | case WSAECONNABORTED: return "closed"; | ||
341 | case WSAECONNRESET: return "closed"; | ||
342 | case WSAETIMEDOUT: return "timeout"; | ||
343 | default: return wstrerror(err); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | const char *socket_ioerror(p_socket ps, int err) { | ||
348 | (void) ps; | ||
349 | return socket_strerror(err); | ||
350 | } | ||
351 | |||
352 | static const char *wstrerror(int err) { | ||
353 | switch (err) { | ||
354 | case WSAEINTR: return "Interrupted function call"; | ||
355 | case WSAEACCES: return "Permission denied"; | ||
356 | case WSAEFAULT: return "Bad address"; | ||
357 | case WSAEINVAL: return "Invalid argument"; | ||
358 | case WSAEMFILE: return "Too many open files"; | ||
359 | case WSAEWOULDBLOCK: return "Resource temporarily unavailable"; | ||
360 | case WSAEINPROGRESS: return "Operation now in progress"; | ||
361 | case WSAEALREADY: return "Operation already in progress"; | ||
362 | case WSAENOTSOCK: return "Socket operation on nonsocket"; | ||
363 | case WSAEDESTADDRREQ: return "Destination address required"; | ||
364 | case WSAEMSGSIZE: return "Message too long"; | ||
365 | case WSAEPROTOTYPE: return "Protocol wrong type for socket"; | ||
366 | case WSAENOPROTOOPT: return "Bad protocol option"; | ||
367 | case WSAEPROTONOSUPPORT: return "Protocol not supported"; | ||
368 | case WSAESOCKTNOSUPPORT: return "Socket type not supported"; | ||
369 | case WSAEOPNOTSUPP: return "Operation not supported"; | ||
370 | case WSAEPFNOSUPPORT: return "Protocol family not supported"; | ||
371 | case WSAEAFNOSUPPORT: | ||
372 | return "Address family not supported by protocol family"; | ||
373 | case WSAEADDRINUSE: return "Address already in use"; | ||
374 | case WSAEADDRNOTAVAIL: return "Cannot assign requested address"; | ||
375 | case WSAENETDOWN: return "Network is down"; | ||
376 | case WSAENETUNREACH: return "Network is unreachable"; | ||
377 | case WSAENETRESET: return "Network dropped connection on reset"; | ||
378 | case WSAECONNABORTED: return "Software caused connection abort"; | ||
379 | case WSAECONNRESET: return "Connection reset by peer"; | ||
380 | case WSAENOBUFS: return "No buffer space available"; | ||
381 | case WSAEISCONN: return "Socket is already connected"; | ||
382 | case WSAENOTCONN: return "Socket is not connected"; | ||
383 | case WSAESHUTDOWN: return "Cannot send after socket shutdown"; | ||
384 | case WSAETIMEDOUT: return "Connection timed out"; | ||
385 | case WSAECONNREFUSED: return "Connection refused"; | ||
386 | case WSAEHOSTDOWN: return "Host is down"; | ||
387 | case WSAEHOSTUNREACH: return "No route to host"; | ||
388 | case WSAEPROCLIM: return "Too many processes"; | ||
389 | case WSASYSNOTREADY: return "Network subsystem is unavailable"; | ||
390 | case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range"; | ||
391 | case WSANOTINITIALISED: | ||
392 | return "Successful WSAStartup not yet performed"; | ||
393 | case WSAEDISCON: return "Graceful shutdown in progress"; | ||
394 | case WSAHOST_NOT_FOUND: return "Host not found"; | ||
395 | case WSATRY_AGAIN: return "Nonauthoritative host not found"; | ||
396 | case WSANO_RECOVERY: return "Nonrecoverable name lookup error"; | ||
397 | case WSANO_DATA: return "Valid name, no data record of requested type"; | ||
398 | default: return "Unknown error"; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | const char *socket_gaistrerror(int err) { | ||
403 | if (err == 0) return NULL; | ||
404 | switch (err) { | ||
405 | case EAI_AGAIN: return "temporary failure in name resolution"; | ||
406 | case EAI_BADFLAGS: return "invalid value for ai_flags"; | ||
407 | #ifdef EAI_BADHINTS | ||
408 | case EAI_BADHINTS: return "invalid value for hints"; | ||
409 | #endif | ||
410 | case EAI_FAIL: return "non-recoverable failure in name resolution"; | ||
411 | case EAI_FAMILY: return "ai_family not supported"; | ||
412 | case EAI_MEMORY: return "memory allocation failure"; | ||
413 | case EAI_NONAME: | ||
414 | return "host or service not provided, or not known"; | ||
415 | #ifdef EAI_OVERFLOW | ||
416 | case EAI_OVERFLOW: return "argument buffer overflow"; | ||
417 | #endif | ||
418 | #ifdef EAI_PROTOCOL | ||
419 | case EAI_PROTOCOL: return "resolved protocol is unknown"; | ||
420 | #endif | ||
421 | case EAI_SERVICE: return "service not supported for socket type"; | ||
422 | case EAI_SOCKTYPE: return "ai_socktype not supported"; | ||
423 | #ifdef EAI_SYSTEM | ||
424 | case EAI_SYSTEM: return strerror(errno); | ||
425 | #endif | ||
426 | default: return gai_strerror(err); | ||
427 | } | ||
428 | } | ||
429 | |||
diff --git a/vendor/luasec/src/luasocket/wsocket.h b/vendor/luasec/src/luasocket/wsocket.h new file mode 100644 index 00000000..c5a4b1ce --- /dev/null +++ b/vendor/luasec/src/luasocket/wsocket.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef WSOCKET_H | ||
2 | #define WSOCKET_H | ||
3 | /*=========================================================================*\ | ||
4 | * Socket compatibilization module for Win32 | ||
5 | * LuaSocket toolkit | ||
6 | \*=========================================================================*/ | ||
7 | |||
8 | /*=========================================================================*\ | ||
9 | * WinSock include files | ||
10 | \*=========================================================================*/ | ||
11 | #include <winsock2.h> | ||
12 | #include <ws2tcpip.h> | ||
13 | |||
14 | typedef int socklen_t; | ||
15 | typedef SOCKADDR_STORAGE t_sockaddr_storage; | ||
16 | typedef SOCKET t_socket; | ||
17 | typedef t_socket *p_socket; | ||
18 | |||
19 | #define WAITFD_R 1 | ||
20 | #define WAITFD_W 2 | ||
21 | #define WAITFD_E 4 | ||
22 | #define WAITFD_C (WAITFD_E|WAITFD_W) | ||
23 | |||
24 | #ifndef IPV6_V6ONLY | ||
25 | #define IPV6_V6ONLY 27 | ||
26 | #endif | ||
27 | |||
28 | #define SOCKET_INVALID (INVALID_SOCKET) | ||
29 | |||
30 | #ifndef SO_REUSEPORT | ||
31 | #define SO_REUSEPORT SO_REUSEADDR | ||
32 | #endif | ||
33 | |||
34 | #ifndef AI_NUMERICSERV | ||
35 | #define AI_NUMERICSERV (0) | ||
36 | #endif | ||
37 | |||
38 | #endif /* WSOCKET_H */ | ||
diff --git a/vendor/luasec/src/options.c b/vendor/luasec/src/options.c new file mode 100644 index 00000000..3d17d6d5 --- /dev/null +++ b/vendor/luasec/src/options.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | * | ||
6 | *--------------------------------------------------------------------------*/ | ||
7 | |||
8 | #include <openssl/ssl.h> | ||
9 | |||
10 | #include "options.h" | ||
11 | |||
12 | /* If you need to generate these options again, see options.lua */ | ||
13 | |||
14 | |||
15 | /* | ||
16 | OpenSSL version: OpenSSL 3.0.8 | ||
17 | */ | ||
18 | |||
19 | static lsec_ssl_option_t ssl_options[] = { | ||
20 | #if defined(SSL_OP_ALL) | ||
21 | {"all", SSL_OP_ALL}, | ||
22 | #endif | ||
23 | #if defined(SSL_OP_ALLOW_CLIENT_RENEGOTIATION) | ||
24 | {"allow_client_renegotiation", SSL_OP_ALLOW_CLIENT_RENEGOTIATION}, | ||
25 | #endif | ||
26 | #if defined(SSL_OP_ALLOW_NO_DHE_KEX) | ||
27 | {"allow_no_dhe_kex", SSL_OP_ALLOW_NO_DHE_KEX}, | ||
28 | #endif | ||
29 | #if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) | ||
30 | {"allow_unsafe_legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION}, | ||
31 | #endif | ||
32 | #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE) | ||
33 | {"cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE}, | ||
34 | #endif | ||
35 | #if defined(SSL_OP_CISCO_ANYCONNECT) | ||
36 | {"cisco_anyconnect", SSL_OP_CISCO_ANYCONNECT}, | ||
37 | #endif | ||
38 | #if defined(SSL_OP_CLEANSE_PLAINTEXT) | ||
39 | {"cleanse_plaintext", SSL_OP_CLEANSE_PLAINTEXT}, | ||
40 | #endif | ||
41 | #if defined(SSL_OP_COOKIE_EXCHANGE) | ||
42 | {"cookie_exchange", SSL_OP_COOKIE_EXCHANGE}, | ||
43 | #endif | ||
44 | #if defined(SSL_OP_CRYPTOPRO_TLSEXT_BUG) | ||
45 | {"cryptopro_tlsext_bug", SSL_OP_CRYPTOPRO_TLSEXT_BUG}, | ||
46 | #endif | ||
47 | #if defined(SSL_OP_DISABLE_TLSEXT_CA_NAMES) | ||
48 | {"disable_tlsext_ca_names", SSL_OP_DISABLE_TLSEXT_CA_NAMES}, | ||
49 | #endif | ||
50 | #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | ||
51 | {"dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS}, | ||
52 | #endif | ||
53 | #if defined(SSL_OP_ENABLE_KTLS) | ||
54 | {"enable_ktls", SSL_OP_ENABLE_KTLS}, | ||
55 | #endif | ||
56 | #if defined(SSL_OP_ENABLE_MIDDLEBOX_COMPAT) | ||
57 | {"enable_middlebox_compat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT}, | ||
58 | #endif | ||
59 | #if defined(SSL_OP_EPHEMERAL_RSA) | ||
60 | {"ephemeral_rsa", SSL_OP_EPHEMERAL_RSA}, | ||
61 | #endif | ||
62 | #if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) | ||
63 | {"ignore_unexpected_eof", SSL_OP_IGNORE_UNEXPECTED_EOF}, | ||
64 | #endif | ||
65 | #if defined(SSL_OP_LEGACY_SERVER_CONNECT) | ||
66 | {"legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT}, | ||
67 | #endif | ||
68 | #if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) | ||
69 | {"microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER}, | ||
70 | #endif | ||
71 | #if defined(SSL_OP_MICROSOFT_SESS_ID_BUG) | ||
72 | {"microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG}, | ||
73 | #endif | ||
74 | #if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING) | ||
75 | {"msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING}, | ||
76 | #endif | ||
77 | #if defined(SSL_OP_NETSCAPE_CA_DN_BUG) | ||
78 | {"netscape_ca_dn_bug", SSL_OP_NETSCAPE_CA_DN_BUG}, | ||
79 | #endif | ||
80 | #if defined(SSL_OP_NETSCAPE_CHALLENGE_BUG) | ||
81 | {"netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG}, | ||
82 | #endif | ||
83 | #if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG) | ||
84 | {"netscape_demo_cipher_change_bug", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG}, | ||
85 | #endif | ||
86 | #if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) | ||
87 | {"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG}, | ||
88 | #endif | ||
89 | #if defined(SSL_OP_NO_ANTI_REPLAY) | ||
90 | {"no_anti_replay", SSL_OP_NO_ANTI_REPLAY}, | ||
91 | #endif | ||
92 | #if defined(SSL_OP_NO_COMPRESSION) | ||
93 | {"no_compression", SSL_OP_NO_COMPRESSION}, | ||
94 | #endif | ||
95 | #if defined(SSL_OP_NO_DTLS_MASK) | ||
96 | {"no_dtls_mask", SSL_OP_NO_DTLS_MASK}, | ||
97 | #endif | ||
98 | #if defined(SSL_OP_NO_DTLSv1) | ||
99 | {"no_dtlsv1", SSL_OP_NO_DTLSv1}, | ||
100 | #endif | ||
101 | #if defined(SSL_OP_NO_DTLSv1_2) | ||
102 | {"no_dtlsv1_2", SSL_OP_NO_DTLSv1_2}, | ||
103 | #endif | ||
104 | #if defined(SSL_OP_NO_ENCRYPT_THEN_MAC) | ||
105 | {"no_encrypt_then_mac", SSL_OP_NO_ENCRYPT_THEN_MAC}, | ||
106 | #endif | ||
107 | #if defined(SSL_OP_NO_EXTENDED_MASTER_SECRET) | ||
108 | {"no_extended_master_secret", SSL_OP_NO_EXTENDED_MASTER_SECRET}, | ||
109 | #endif | ||
110 | #if defined(SSL_OP_NO_QUERY_MTU) | ||
111 | {"no_query_mtu", SSL_OP_NO_QUERY_MTU}, | ||
112 | #endif | ||
113 | #if defined(SSL_OP_NO_RENEGOTIATION) | ||
114 | {"no_renegotiation", SSL_OP_NO_RENEGOTIATION}, | ||
115 | #endif | ||
116 | #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) | ||
117 | {"no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION}, | ||
118 | #endif | ||
119 | #if defined(SSL_OP_NO_SSL_MASK) | ||
120 | {"no_ssl_mask", SSL_OP_NO_SSL_MASK}, | ||
121 | #endif | ||
122 | #if defined(SSL_OP_NO_SSLv2) | ||
123 | {"no_sslv2", SSL_OP_NO_SSLv2}, | ||
124 | #endif | ||
125 | #if defined(SSL_OP_NO_SSLv3) | ||
126 | {"no_sslv3", SSL_OP_NO_SSLv3}, | ||
127 | #endif | ||
128 | #if defined(SSL_OP_NO_TICKET) | ||
129 | {"no_ticket", SSL_OP_NO_TICKET}, | ||
130 | #endif | ||
131 | #if defined(SSL_OP_NO_TLSv1) | ||
132 | {"no_tlsv1", SSL_OP_NO_TLSv1}, | ||
133 | #endif | ||
134 | #if defined(SSL_OP_NO_TLSv1_1) | ||
135 | {"no_tlsv1_1", SSL_OP_NO_TLSv1_1}, | ||
136 | #endif | ||
137 | #if defined(SSL_OP_NO_TLSv1_2) | ||
138 | {"no_tlsv1_2", SSL_OP_NO_TLSv1_2}, | ||
139 | #endif | ||
140 | #if defined(SSL_OP_NO_TLSv1_3) | ||
141 | {"no_tlsv1_3", SSL_OP_NO_TLSv1_3}, | ||
142 | #endif | ||
143 | #if defined(SSL_OP_PKCS1_CHECK_1) | ||
144 | {"pkcs1_check_1", SSL_OP_PKCS1_CHECK_1}, | ||
145 | #endif | ||
146 | #if defined(SSL_OP_PKCS1_CHECK_2) | ||
147 | {"pkcs1_check_2", SSL_OP_PKCS1_CHECK_2}, | ||
148 | #endif | ||
149 | #if defined(SSL_OP_PRIORITIZE_CHACHA) | ||
150 | {"prioritize_chacha", SSL_OP_PRIORITIZE_CHACHA}, | ||
151 | #endif | ||
152 | #if defined(SSL_OP_SAFARI_ECDHE_ECDSA_BUG) | ||
153 | {"safari_ecdhe_ecdsa_bug", SSL_OP_SAFARI_ECDHE_ECDSA_BUG}, | ||
154 | #endif | ||
155 | #if defined(SSL_OP_SINGLE_DH_USE) | ||
156 | {"single_dh_use", SSL_OP_SINGLE_DH_USE}, | ||
157 | #endif | ||
158 | #if defined(SSL_OP_SINGLE_ECDH_USE) | ||
159 | {"single_ecdh_use", SSL_OP_SINGLE_ECDH_USE}, | ||
160 | #endif | ||
161 | #if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG) | ||
162 | {"ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG}, | ||
163 | #endif | ||
164 | #if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG) | ||
165 | {"sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG}, | ||
166 | #endif | ||
167 | #if defined(SSL_OP_TLSEXT_PADDING) | ||
168 | {"tlsext_padding", SSL_OP_TLSEXT_PADDING}, | ||
169 | #endif | ||
170 | #if defined(SSL_OP_TLS_BLOCK_PADDING_BUG) | ||
171 | {"tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG}, | ||
172 | #endif | ||
173 | #if defined(SSL_OP_TLS_D5_BUG) | ||
174 | {"tls_d5_bug", SSL_OP_TLS_D5_BUG}, | ||
175 | #endif | ||
176 | #if defined(SSL_OP_TLS_ROLLBACK_BUG) | ||
177 | {"tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG}, | ||
178 | #endif | ||
179 | {NULL, 0L} | ||
180 | }; | ||
181 | |||
182 | LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() { | ||
183 | return ssl_options; | ||
184 | } | ||
185 | |||
diff --git a/vendor/luasec/src/options.h b/vendor/luasec/src/options.h new file mode 100644 index 00000000..c72d52d0 --- /dev/null +++ b/vendor/luasec/src/options.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef LSEC_OPTIONS_H | ||
2 | #define LSEC_OPTIONS_H | ||
3 | |||
4 | /*-------------------------------------------------------------------------- | ||
5 | * LuaSec 1.3.2 | ||
6 | * | ||
7 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
8 | * | ||
9 | *--------------------------------------------------------------------------*/ | ||
10 | |||
11 | #include "compat.h" | ||
12 | |||
13 | struct lsec_ssl_option_s { | ||
14 | const char *name; | ||
15 | unsigned long code; | ||
16 | }; | ||
17 | |||
18 | typedef struct lsec_ssl_option_s lsec_ssl_option_t; | ||
19 | |||
20 | LSEC_API lsec_ssl_option_t* lsec_get_ssl_options(); | ||
21 | |||
22 | #endif | ||
diff --git a/vendor/luasec/src/options.lua b/vendor/luasec/src/options.lua new file mode 100644 index 00000000..72428c01 --- /dev/null +++ b/vendor/luasec/src/options.lua | |||
@@ -0,0 +1,93 @@ | |||
1 | local function usage() | ||
2 | print("Usage:") | ||
3 | print("* Generate options of your system:") | ||
4 | print(" lua options.lua -g /path/to/ssl.h [version] > options.c") | ||
5 | print("* Examples:") | ||
6 | print(" lua options.lua -g /usr/include/openssl/ssl.h > options.c\n") | ||
7 | print(" lua options.lua -g /usr/include/openssl/ssl.h \"OpenSSL 1.1.1f\" > options.c\n") | ||
8 | |||
9 | print("* List options of your system:") | ||
10 | print(" lua options.lua -l /path/to/ssl.h\n") | ||
11 | end | ||
12 | |||
13 | -- | ||
14 | local function printf(str, ...) | ||
15 | print(string.format(str, ...)) | ||
16 | end | ||
17 | |||
18 | local function generate(options, version) | ||
19 | print([[ | ||
20 | /*-------------------------------------------------------------------------- | ||
21 | * LuaSec 1.3.2 | ||
22 | * | ||
23 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
24 | * | ||
25 | *--------------------------------------------------------------------------*/ | ||
26 | |||
27 | #include <openssl/ssl.h> | ||
28 | |||
29 | #include "options.h" | ||
30 | |||
31 | /* If you need to generate these options again, see options.lua */ | ||
32 | |||
33 | ]]) | ||
34 | |||
35 | printf([[ | ||
36 | /* | ||
37 | OpenSSL version: %s | ||
38 | */ | ||
39 | ]], version) | ||
40 | |||
41 | print([[static lsec_ssl_option_t ssl_options[] = {]]) | ||
42 | |||
43 | for k, option in ipairs(options) do | ||
44 | local name = string.lower(string.sub(option, 8)) | ||
45 | print(string.format([[#if defined(%s)]], option)) | ||
46 | print(string.format([[ {"%s", %s},]], name, option)) | ||
47 | print([[#endif]]) | ||
48 | end | ||
49 | print([[ {NULL, 0L}]]) | ||
50 | print([[ | ||
51 | }; | ||
52 | |||
53 | LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() { | ||
54 | return ssl_options; | ||
55 | } | ||
56 | ]]) | ||
57 | end | ||
58 | |||
59 | local function loadoptions(file) | ||
60 | local options = {} | ||
61 | local f = assert(io.open(file, "r")) | ||
62 | for line in f:lines() do | ||
63 | local op = string.match(line, "define%s+(SSL_OP_BIT%()") | ||
64 | if not op then | ||
65 | op = string.match(line, "define%s+(SSL_OP_%S+)") | ||
66 | if op then | ||
67 | table.insert(options, op) | ||
68 | end | ||
69 | end | ||
70 | end | ||
71 | table.sort(options, function(a,b) return a<b end) | ||
72 | return options | ||
73 | end | ||
74 | -- | ||
75 | |||
76 | local options | ||
77 | local flag, file, version = ... | ||
78 | |||
79 | version = version or "Unknown" | ||
80 | |||
81 | if not file then | ||
82 | usage() | ||
83 | elseif flag == "-g" then | ||
84 | options = loadoptions(file) | ||
85 | generate(options, version) | ||
86 | elseif flag == "-l" then | ||
87 | options = loadoptions(file) | ||
88 | for k, option in ipairs(options) do | ||
89 | print(option) | ||
90 | end | ||
91 | else | ||
92 | usage() | ||
93 | end | ||
diff --git a/vendor/luasec/src/ssl.c b/vendor/luasec/src/ssl.c new file mode 100644 index 00000000..934bb81b --- /dev/null +++ b/vendor/luasec/src/ssl.c | |||
@@ -0,0 +1,1092 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #include <errno.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | #if defined(WIN32) | ||
13 | #include <winsock2.h> | ||
14 | #endif | ||
15 | |||
16 | #include <openssl/ssl.h> | ||
17 | #include <openssl/x509v3.h> | ||
18 | #include <openssl/x509_vfy.h> | ||
19 | #include <openssl/err.h> | ||
20 | #include <openssl/dh.h> | ||
21 | |||
22 | #include <lua.h> | ||
23 | #include <lauxlib.h> | ||
24 | |||
25 | #include <luasocket/io.h> | ||
26 | #include <luasocket/buffer.h> | ||
27 | #include <luasocket/timeout.h> | ||
28 | #include <luasocket/socket.h> | ||
29 | |||
30 | #include "x509.h" | ||
31 | #include "context.h" | ||
32 | #include "ssl.h" | ||
33 | |||
34 | |||
35 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
36 | #define SSL_is_server(s) (s->server) | ||
37 | #define SSL_up_ref(ssl) CRYPTO_add(&(ssl)->references, 1, CRYPTO_LOCK_SSL) | ||
38 | #define X509_up_ref(c) CRYPTO_add(&c->references, 1, CRYPTO_LOCK_X509) | ||
39 | #endif | ||
40 | |||
41 | |||
42 | /** | ||
43 | * Underline socket error. | ||
44 | */ | ||
45 | static int lsec_socket_error() | ||
46 | { | ||
47 | #if defined(WIN32) | ||
48 | return WSAGetLastError(); | ||
49 | #else | ||
50 | #if defined(LSEC_OPENSSL_ERRNO_BUG) | ||
51 | // Bug in OpenSSL | ||
52 | if (errno == 0) | ||
53 | return LSEC_IO_SSL; | ||
54 | #endif | ||
55 | return errno; | ||
56 | #endif | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Map error code into string. | ||
61 | */ | ||
62 | static const char *ssl_ioerror(void *ctx, int err) | ||
63 | { | ||
64 | if (err == LSEC_IO_SSL) { | ||
65 | p_ssl ssl = (p_ssl) ctx; | ||
66 | switch(ssl->error) { | ||
67 | case SSL_ERROR_NONE: return "No error"; | ||
68 | case SSL_ERROR_ZERO_RETURN: return "closed"; | ||
69 | case SSL_ERROR_WANT_READ: return "wantread"; | ||
70 | case SSL_ERROR_WANT_WRITE: return "wantwrite"; | ||
71 | case SSL_ERROR_WANT_CONNECT: return "'connect' not completed"; | ||
72 | case SSL_ERROR_WANT_ACCEPT: return "'accept' not completed"; | ||
73 | case SSL_ERROR_WANT_X509_LOOKUP: return "Waiting for callback"; | ||
74 | case SSL_ERROR_SYSCALL: return "System error"; | ||
75 | case SSL_ERROR_SSL: return ERR_reason_error_string(ERR_get_error()); | ||
76 | default: return "Unknown SSL error"; | ||
77 | } | ||
78 | } | ||
79 | return socket_strerror(err); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Close the connection before the GC collect the object. | ||
84 | */ | ||
85 | static int meth_destroy(lua_State *L) | ||
86 | { | ||
87 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
88 | if (ssl->state == LSEC_STATE_CONNECTED) { | ||
89 | socket_setblocking(&ssl->sock); | ||
90 | SSL_shutdown(ssl->ssl); | ||
91 | } | ||
92 | if (ssl->sock != SOCKET_INVALID) { | ||
93 | socket_destroy(&ssl->sock); | ||
94 | } | ||
95 | ssl->state = LSEC_STATE_CLOSED; | ||
96 | if (ssl->ssl) { | ||
97 | /* Clear the registries */ | ||
98 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
99 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
100 | lua_pushnil(L); | ||
101 | lua_settable(L, -3); | ||
102 | luaL_getmetatable(L, "SSL:SNI:Registry"); | ||
103 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
104 | lua_pushnil(L); | ||
105 | lua_settable(L, -3); | ||
106 | /* Destroy the object */ | ||
107 | SSL_free(ssl->ssl); | ||
108 | ssl->ssl = NULL; | ||
109 | } | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Perform the TLS/SSL handshake | ||
115 | */ | ||
116 | static int handshake(p_ssl ssl) | ||
117 | { | ||
118 | int err; | ||
119 | p_timeout tm = timeout_markstart(&ssl->tm); | ||
120 | if (ssl->state == LSEC_STATE_CLOSED) | ||
121 | return IO_CLOSED; | ||
122 | for ( ; ; ) { | ||
123 | ERR_clear_error(); | ||
124 | err = SSL_do_handshake(ssl->ssl); | ||
125 | ssl->error = SSL_get_error(ssl->ssl, err); | ||
126 | switch (ssl->error) { | ||
127 | case SSL_ERROR_NONE: | ||
128 | ssl->state = LSEC_STATE_CONNECTED; | ||
129 | return IO_DONE; | ||
130 | case SSL_ERROR_WANT_READ: | ||
131 | err = socket_waitfd(&ssl->sock, WAITFD_R, tm); | ||
132 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
133 | if (err != IO_DONE) return err; | ||
134 | break; | ||
135 | case SSL_ERROR_WANT_WRITE: | ||
136 | err = socket_waitfd(&ssl->sock, WAITFD_W, tm); | ||
137 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
138 | if (err != IO_DONE) return err; | ||
139 | break; | ||
140 | case SSL_ERROR_SYSCALL: | ||
141 | if (ERR_peek_error()) { | ||
142 | ssl->error = SSL_ERROR_SSL; | ||
143 | return LSEC_IO_SSL; | ||
144 | } | ||
145 | if (err == 0) | ||
146 | return IO_CLOSED; | ||
147 | return lsec_socket_error(); | ||
148 | default: | ||
149 | return LSEC_IO_SSL; | ||
150 | } | ||
151 | } | ||
152 | return IO_UNKNOWN; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Send data | ||
157 | */ | ||
158 | static int ssl_send(void *ctx, const char *data, size_t count, size_t *sent, | ||
159 | p_timeout tm) | ||
160 | { | ||
161 | int err; | ||
162 | p_ssl ssl = (p_ssl)ctx; | ||
163 | if (ssl->state != LSEC_STATE_CONNECTED) | ||
164 | return IO_CLOSED; | ||
165 | *sent = 0; | ||
166 | for ( ; ; ) { | ||
167 | ERR_clear_error(); | ||
168 | err = SSL_write(ssl->ssl, data, (int)count); | ||
169 | ssl->error = SSL_get_error(ssl->ssl, err); | ||
170 | switch (ssl->error) { | ||
171 | case SSL_ERROR_NONE: | ||
172 | *sent = err; | ||
173 | return IO_DONE; | ||
174 | case SSL_ERROR_WANT_READ: | ||
175 | err = socket_waitfd(&ssl->sock, WAITFD_R, tm); | ||
176 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
177 | if (err != IO_DONE) return err; | ||
178 | break; | ||
179 | case SSL_ERROR_WANT_WRITE: | ||
180 | err = socket_waitfd(&ssl->sock, WAITFD_W, tm); | ||
181 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
182 | if (err != IO_DONE) return err; | ||
183 | break; | ||
184 | case SSL_ERROR_SYSCALL: | ||
185 | if (ERR_peek_error()) { | ||
186 | ssl->error = SSL_ERROR_SSL; | ||
187 | return LSEC_IO_SSL; | ||
188 | } | ||
189 | if (err == 0) | ||
190 | return IO_CLOSED; | ||
191 | return lsec_socket_error(); | ||
192 | default: | ||
193 | return LSEC_IO_SSL; | ||
194 | } | ||
195 | } | ||
196 | return IO_UNKNOWN; | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * Receive data | ||
201 | */ | ||
202 | static int ssl_recv(void *ctx, char *data, size_t count, size_t *got, | ||
203 | p_timeout tm) | ||
204 | { | ||
205 | int err; | ||
206 | p_ssl ssl = (p_ssl)ctx; | ||
207 | *got = 0; | ||
208 | if (ssl->state != LSEC_STATE_CONNECTED) | ||
209 | return IO_CLOSED; | ||
210 | for ( ; ; ) { | ||
211 | ERR_clear_error(); | ||
212 | err = SSL_read(ssl->ssl, data, (int)count); | ||
213 | ssl->error = SSL_get_error(ssl->ssl, err); | ||
214 | switch (ssl->error) { | ||
215 | case SSL_ERROR_NONE: | ||
216 | *got = err; | ||
217 | return IO_DONE; | ||
218 | case SSL_ERROR_ZERO_RETURN: | ||
219 | return IO_CLOSED; | ||
220 | case SSL_ERROR_WANT_READ: | ||
221 | err = socket_waitfd(&ssl->sock, WAITFD_R, tm); | ||
222 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
223 | if (err != IO_DONE) return err; | ||
224 | break; | ||
225 | case SSL_ERROR_WANT_WRITE: | ||
226 | err = socket_waitfd(&ssl->sock, WAITFD_W, tm); | ||
227 | if (err == IO_TIMEOUT) return LSEC_IO_SSL; | ||
228 | if (err != IO_DONE) return err; | ||
229 | break; | ||
230 | case SSL_ERROR_SYSCALL: | ||
231 | if (ERR_peek_error()) { | ||
232 | ssl->error = SSL_ERROR_SSL; | ||
233 | return LSEC_IO_SSL; | ||
234 | } | ||
235 | if (err == 0) | ||
236 | return IO_CLOSED; | ||
237 | return lsec_socket_error(); | ||
238 | default: | ||
239 | return LSEC_IO_SSL; | ||
240 | } | ||
241 | } | ||
242 | return IO_UNKNOWN; | ||
243 | } | ||
244 | |||
245 | static SSL_CTX* luaossl_testcontext(lua_State *L, int arg) { | ||
246 | SSL_CTX **ctx = luaL_testudata(L, arg, "SSL_CTX*"); | ||
247 | if (ctx) | ||
248 | return *ctx; | ||
249 | return NULL; | ||
250 | } | ||
251 | |||
252 | static SSL* luaossl_testssl(lua_State *L, int arg) { | ||
253 | SSL **ssl = luaL_testudata(L, arg, "SSL*"); | ||
254 | if (ssl) | ||
255 | return *ssl; | ||
256 | return NULL; | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * Create a new TLS/SSL object and mark it as new. | ||
261 | */ | ||
262 | static int meth_create(lua_State *L) | ||
263 | { | ||
264 | p_ssl ssl; | ||
265 | int mode; | ||
266 | SSL_CTX *ctx; | ||
267 | |||
268 | lua_settop(L, 1); | ||
269 | |||
270 | ssl = (p_ssl)lua_newuserdata(L, sizeof(t_ssl)); | ||
271 | if (!ssl) { | ||
272 | lua_pushnil(L); | ||
273 | lua_pushstring(L, "error creating SSL object"); | ||
274 | return 2; | ||
275 | } | ||
276 | |||
277 | if ((ctx = lsec_testcontext(L, 1))) { | ||
278 | mode = lsec_getmode(L, 1); | ||
279 | if (mode == LSEC_MODE_INVALID) { | ||
280 | lua_pushnil(L); | ||
281 | lua_pushstring(L, "invalid mode"); | ||
282 | return 2; | ||
283 | } | ||
284 | ssl->ssl = SSL_new(ctx); | ||
285 | if (!ssl->ssl) { | ||
286 | lua_pushnil(L); | ||
287 | lua_pushfstring(L, "error creating SSL object (%s)", | ||
288 | ERR_reason_error_string(ERR_get_error())); | ||
289 | return 2; | ||
290 | } | ||
291 | } else if ((ctx = luaossl_testcontext(L, 1))) { | ||
292 | ssl->ssl = SSL_new(ctx); | ||
293 | if (!ssl->ssl) { | ||
294 | lua_pushnil(L); | ||
295 | lua_pushfstring(L, "error creating SSL object (%s)", | ||
296 | ERR_reason_error_string(ERR_get_error())); | ||
297 | return 2; | ||
298 | } | ||
299 | mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT; | ||
300 | } else if ((ssl->ssl = luaossl_testssl(L, 1))) { | ||
301 | SSL_up_ref(ssl->ssl); | ||
302 | mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT; | ||
303 | } else { | ||
304 | return luaL_argerror(L, 1, "invalid context"); | ||
305 | } | ||
306 | ssl->state = LSEC_STATE_NEW; | ||
307 | SSL_set_fd(ssl->ssl, (int)SOCKET_INVALID); | ||
308 | SSL_set_mode(ssl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE | | ||
309 | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); | ||
310 | SSL_set_mode(ssl->ssl, SSL_MODE_RELEASE_BUFFERS); | ||
311 | if (mode == LSEC_MODE_SERVER) | ||
312 | SSL_set_accept_state(ssl->ssl); | ||
313 | else | ||
314 | SSL_set_connect_state(ssl->ssl); | ||
315 | |||
316 | io_init(&ssl->io, (p_send)ssl_send, (p_recv)ssl_recv, | ||
317 | (p_error) ssl_ioerror, ssl); | ||
318 | timeout_init(&ssl->tm, -1, -1); | ||
319 | buffer_init(&ssl->buf, &ssl->io, &ssl->tm); | ||
320 | |||
321 | luaL_getmetatable(L, "SSL:Connection"); | ||
322 | lua_setmetatable(L, -2); | ||
323 | return 1; | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * Buffer send function | ||
328 | */ | ||
329 | static int meth_send(lua_State *L) { | ||
330 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
331 | return buffer_meth_send(L, &ssl->buf); | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * Buffer receive function | ||
336 | */ | ||
337 | static int meth_receive(lua_State *L) { | ||
338 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
339 | return buffer_meth_receive(L, &ssl->buf); | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * Get the buffer's statistics. | ||
344 | */ | ||
345 | static int meth_getstats(lua_State *L) { | ||
346 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
347 | return buffer_meth_getstats(L, &ssl->buf); | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * Set the buffer's statistics. | ||
352 | */ | ||
353 | static int meth_setstats(lua_State *L) { | ||
354 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
355 | return buffer_meth_setstats(L, &ssl->buf); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Select support methods | ||
360 | */ | ||
361 | static int meth_getfd(lua_State *L) | ||
362 | { | ||
363 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
364 | lua_pushnumber(L, ssl->sock); | ||
365 | return 1; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * Set the TLS/SSL file descriptor. | ||
370 | * Call it *before* the handshake. | ||
371 | */ | ||
372 | static int meth_setfd(lua_State *L) | ||
373 | { | ||
374 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
375 | if (ssl->state != LSEC_STATE_NEW) | ||
376 | luaL_argerror(L, 1, "invalid SSL object state"); | ||
377 | ssl->sock = (t_socket)luaL_checkinteger(L, 2); | ||
378 | socket_setnonblocking(&ssl->sock); | ||
379 | SSL_set_fd(ssl->ssl, (int)ssl->sock); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Lua handshake function. | ||
385 | */ | ||
386 | static int meth_handshake(lua_State *L) | ||
387 | { | ||
388 | int err; | ||
389 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
390 | p_context ctx = (p_context)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl->ssl)); | ||
391 | ctx->L = L; | ||
392 | err = handshake(ssl); | ||
393 | if (ctx->dh_param) { | ||
394 | DH_free(ctx->dh_param); | ||
395 | ctx->dh_param = NULL; | ||
396 | } | ||
397 | if (ctx->alpn) { | ||
398 | free(ctx->alpn); | ||
399 | ctx->alpn = NULL; | ||
400 | } | ||
401 | if (err == IO_DONE) { | ||
402 | lua_pushboolean(L, 1); | ||
403 | return 1; | ||
404 | } | ||
405 | lua_pushboolean(L, 0); | ||
406 | lua_pushstring(L, ssl_ioerror((void*)ssl, err)); | ||
407 | return 2; | ||
408 | } | ||
409 | |||
410 | /** | ||
411 | * Close the connection. | ||
412 | */ | ||
413 | static int meth_close(lua_State *L) | ||
414 | { | ||
415 | meth_destroy(L); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /** | ||
420 | * Set timeout. | ||
421 | */ | ||
422 | static int meth_settimeout(lua_State *L) | ||
423 | { | ||
424 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
425 | return timeout_meth_settimeout(L, &ssl->tm); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * Check if there is data in the buffer. | ||
430 | */ | ||
431 | static int meth_dirty(lua_State *L) | ||
432 | { | ||
433 | int res = 0; | ||
434 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
435 | if (ssl->state != LSEC_STATE_CLOSED) | ||
436 | res = !buffer_isempty(&ssl->buf) || SSL_pending(ssl->ssl); | ||
437 | lua_pushboolean(L, res); | ||
438 | return 1; | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * Return the state information about the SSL object. | ||
443 | */ | ||
444 | static int meth_want(lua_State *L) | ||
445 | { | ||
446 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
447 | int code = (ssl->state == LSEC_STATE_CLOSED) | ||
448 | ? SSL_NOTHING | ||
449 | : SSL_want(ssl->ssl); | ||
450 | switch(code) { | ||
451 | case SSL_NOTHING: lua_pushstring(L, "nothing"); break; | ||
452 | case SSL_READING: lua_pushstring(L, "read"); break; | ||
453 | case SSL_WRITING: lua_pushstring(L, "write"); break; | ||
454 | case SSL_X509_LOOKUP: lua_pushstring(L, "x509lookup"); break; | ||
455 | } | ||
456 | return 1; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * Return the compression method used. | ||
461 | */ | ||
462 | static int meth_compression(lua_State *L) | ||
463 | { | ||
464 | #ifdef OPENSSL_NO_COMP | ||
465 | const void *comp; | ||
466 | #else | ||
467 | const COMP_METHOD *comp; | ||
468 | #endif | ||
469 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
470 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
471 | lua_pushnil(L); | ||
472 | lua_pushstring(L, "closed"); | ||
473 | return 2; | ||
474 | } | ||
475 | comp = SSL_get_current_compression(ssl->ssl); | ||
476 | if (comp) | ||
477 | lua_pushstring(L, SSL_COMP_get_name(comp)); | ||
478 | else | ||
479 | lua_pushnil(L); | ||
480 | return 1; | ||
481 | } | ||
482 | |||
483 | /** | ||
484 | * Return the nth certificate of the peer's chain. | ||
485 | */ | ||
486 | static int meth_getpeercertificate(lua_State *L) | ||
487 | { | ||
488 | int n; | ||
489 | X509 *cert; | ||
490 | STACK_OF(X509) *certs; | ||
491 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
492 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
493 | lua_pushnil(L); | ||
494 | lua_pushstring(L, "closed"); | ||
495 | return 2; | ||
496 | } | ||
497 | /* Default to the first cert */ | ||
498 | n = (int)luaL_optinteger(L, 2, 1); | ||
499 | /* This function is 1-based, but OpenSSL is 0-based */ | ||
500 | --n; | ||
501 | if (n < 0) { | ||
502 | lua_pushnil(L); | ||
503 | lua_pushliteral(L, "invalid certificate index"); | ||
504 | return 2; | ||
505 | } | ||
506 | if (n == 0) { | ||
507 | cert = SSL_get_peer_certificate(ssl->ssl); | ||
508 | if (cert) | ||
509 | lsec_pushx509(L, cert); | ||
510 | else | ||
511 | lua_pushnil(L); | ||
512 | return 1; | ||
513 | } | ||
514 | /* In a server-context, the stack doesn't contain the peer cert, | ||
515 | * so adjust accordingly. | ||
516 | */ | ||
517 | if (SSL_is_server(ssl->ssl)) | ||
518 | --n; | ||
519 | certs = SSL_get_peer_cert_chain(ssl->ssl); | ||
520 | if (n >= sk_X509_num(certs)) { | ||
521 | lua_pushnil(L); | ||
522 | return 1; | ||
523 | } | ||
524 | cert = sk_X509_value(certs, n); | ||
525 | /* Increment the reference counting of the object. */ | ||
526 | /* See SSL_get_peer_certificate() source code. */ | ||
527 | X509_up_ref(cert); | ||
528 | lsec_pushx509(L, cert); | ||
529 | return 1; | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * Return the nth certificate of the chain sent to our peer. | ||
534 | */ | ||
535 | static int meth_getlocalcertificate(lua_State *L) | ||
536 | { | ||
537 | int n; | ||
538 | X509 *cert; | ||
539 | STACK_OF(X509) *certs; | ||
540 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
541 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
542 | lua_pushnil(L); | ||
543 | lua_pushstring(L, "closed"); | ||
544 | return 2; | ||
545 | } | ||
546 | /* Default to the first cert */ | ||
547 | n = (int)luaL_optinteger(L, 2, 1); | ||
548 | /* This function is 1-based, but OpenSSL is 0-based */ | ||
549 | --n; | ||
550 | if (n < 0) { | ||
551 | lua_pushnil(L); | ||
552 | lua_pushliteral(L, "invalid certificate index"); | ||
553 | return 2; | ||
554 | } | ||
555 | if (n == 0) { | ||
556 | cert = SSL_get_certificate(ssl->ssl); | ||
557 | if (cert) | ||
558 | lsec_pushx509(L, cert); | ||
559 | else | ||
560 | lua_pushnil(L); | ||
561 | return 1; | ||
562 | } | ||
563 | /* In a server-context, the stack doesn't contain the peer cert, | ||
564 | * so adjust accordingly. | ||
565 | */ | ||
566 | if (SSL_is_server(ssl->ssl)) | ||
567 | --n; | ||
568 | if(SSL_get0_chain_certs(ssl->ssl, &certs) != 1) { | ||
569 | lua_pushnil(L); | ||
570 | } else { | ||
571 | if (n >= sk_X509_num(certs)) { | ||
572 | lua_pushnil(L); | ||
573 | return 1; | ||
574 | } | ||
575 | cert = sk_X509_value(certs, n); | ||
576 | /* Increment the reference counting of the object. */ | ||
577 | /* See SSL_get_peer_certificate() source code. */ | ||
578 | X509_up_ref(cert); | ||
579 | lsec_pushx509(L, cert); | ||
580 | } | ||
581 | return 1; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * Return the chain of certificate of the peer. | ||
586 | */ | ||
587 | static int meth_getpeerchain(lua_State *L) | ||
588 | { | ||
589 | int i; | ||
590 | int idx = 1; | ||
591 | int n_certs; | ||
592 | X509 *cert; | ||
593 | STACK_OF(X509) *certs; | ||
594 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
595 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
596 | lua_pushnil(L); | ||
597 | lua_pushstring(L, "closed"); | ||
598 | return 2; | ||
599 | } | ||
600 | lua_newtable(L); | ||
601 | if (SSL_is_server(ssl->ssl)) { | ||
602 | lsec_pushx509(L, SSL_get_peer_certificate(ssl->ssl)); | ||
603 | lua_rawseti(L, -2, idx++); | ||
604 | } | ||
605 | certs = SSL_get_peer_cert_chain(ssl->ssl); | ||
606 | n_certs = sk_X509_num(certs); | ||
607 | for (i = 0; i < n_certs; i++) { | ||
608 | cert = sk_X509_value(certs, i); | ||
609 | /* Increment the reference counting of the object. */ | ||
610 | /* See SSL_get_peer_certificate() source code. */ | ||
611 | X509_up_ref(cert); | ||
612 | lsec_pushx509(L, cert); | ||
613 | lua_rawseti(L, -2, idx++); | ||
614 | } | ||
615 | return 1; | ||
616 | } | ||
617 | |||
618 | /** | ||
619 | * Return the chain of certificates sent to the peer. | ||
620 | */ | ||
621 | static int meth_getlocalchain(lua_State *L) | ||
622 | { | ||
623 | int i; | ||
624 | int idx = 1; | ||
625 | int n_certs; | ||
626 | X509 *cert; | ||
627 | STACK_OF(X509) *certs; | ||
628 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
629 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
630 | lua_pushnil(L); | ||
631 | lua_pushstring(L, "closed"); | ||
632 | return 2; | ||
633 | } | ||
634 | lua_newtable(L); | ||
635 | if (SSL_is_server(ssl->ssl)) { | ||
636 | lsec_pushx509(L, SSL_get_certificate(ssl->ssl)); | ||
637 | lua_rawseti(L, -2, idx++); | ||
638 | } | ||
639 | if(SSL_get0_chain_certs(ssl->ssl, &certs)) { | ||
640 | n_certs = sk_X509_num(certs); | ||
641 | for (i = 0; i < n_certs; i++) { | ||
642 | cert = sk_X509_value(certs, i); | ||
643 | /* Increment the reference counting of the object. */ | ||
644 | /* See SSL_get_peer_certificate() source code. */ | ||
645 | X509_up_ref(cert); | ||
646 | lsec_pushx509(L, cert); | ||
647 | lua_rawseti(L, -2, idx++); | ||
648 | } | ||
649 | } | ||
650 | return 1; | ||
651 | } | ||
652 | |||
653 | /** | ||
654 | * Copy the table src to the table dst. | ||
655 | */ | ||
656 | static void copy_error_table(lua_State *L, int src, int dst) | ||
657 | { | ||
658 | lua_pushnil(L); | ||
659 | while (lua_next(L, src) != 0) { | ||
660 | if (lua_istable(L, -1)) { | ||
661 | /* Replace the table with its copy */ | ||
662 | lua_newtable(L); | ||
663 | copy_error_table(L, dst+2, dst+3); | ||
664 | lua_remove(L, dst+2); | ||
665 | } | ||
666 | lua_pushvalue(L, -2); | ||
667 | lua_pushvalue(L, -2); | ||
668 | lua_rawset(L, dst); | ||
669 | /* Remove the value and leave the key */ | ||
670 | lua_pop(L, 1); | ||
671 | } | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * Return the verification state of the peer chain. | ||
676 | */ | ||
677 | static int meth_getpeerverification(lua_State *L) | ||
678 | { | ||
679 | long err; | ||
680 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
681 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
682 | lua_pushboolean(L, 0); | ||
683 | lua_pushstring(L, "closed"); | ||
684 | return 2; | ||
685 | } | ||
686 | err = SSL_get_verify_result(ssl->ssl); | ||
687 | if (err == X509_V_OK) { | ||
688 | lua_pushboolean(L, 1); | ||
689 | return 1; | ||
690 | } | ||
691 | luaL_getmetatable(L, "SSL:Verify:Registry"); | ||
692 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
693 | lua_gettable(L, -2); | ||
694 | if (lua_isnil(L, -1)) | ||
695 | lua_pushstring(L, X509_verify_cert_error_string(err)); | ||
696 | else { | ||
697 | /* Copy the table of errors to avoid modifications */ | ||
698 | lua_newtable(L); | ||
699 | copy_error_table(L, lua_gettop(L)-1, lua_gettop(L)); | ||
700 | } | ||
701 | lua_pushboolean(L, 0); | ||
702 | lua_pushvalue(L, -2); | ||
703 | return 2; | ||
704 | } | ||
705 | |||
706 | /** | ||
707 | * Get the latest "Finished" message sent out. | ||
708 | */ | ||
709 | static int meth_getfinished(lua_State *L) | ||
710 | { | ||
711 | size_t len = 0; | ||
712 | char *buffer = NULL; | ||
713 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
714 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
715 | lua_pushnil(L); | ||
716 | lua_pushstring(L, "closed"); | ||
717 | return 2; | ||
718 | } | ||
719 | if ((len = SSL_get_finished(ssl->ssl, NULL, 0)) == 0) | ||
720 | return 0; | ||
721 | buffer = (char*)malloc(len); | ||
722 | if (!buffer) { | ||
723 | lua_pushnil(L); | ||
724 | lua_pushstring(L, "out of memory"); | ||
725 | return 2; | ||
726 | } | ||
727 | SSL_get_finished(ssl->ssl, buffer, len); | ||
728 | lua_pushlstring(L, buffer, len); | ||
729 | free(buffer); | ||
730 | return 1; | ||
731 | } | ||
732 | |||
733 | /** | ||
734 | * Gets the latest "Finished" message received. | ||
735 | */ | ||
736 | static int meth_getpeerfinished(lua_State *L) | ||
737 | { | ||
738 | size_t len = 0; | ||
739 | char *buffer = NULL; | ||
740 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
741 | if (ssl->state != LSEC_STATE_CONNECTED) { | ||
742 | lua_pushnil(L); | ||
743 | lua_pushstring(L, "closed"); | ||
744 | return 0; | ||
745 | } | ||
746 | if ((len = SSL_get_peer_finished(ssl->ssl, NULL, 0)) == 0) | ||
747 | return 0; | ||
748 | buffer = (char*)malloc(len); | ||
749 | if (!buffer) { | ||
750 | lua_pushnil(L); | ||
751 | lua_pushstring(L, "out of memory"); | ||
752 | return 2; | ||
753 | } | ||
754 | SSL_get_peer_finished(ssl->ssl, buffer, len); | ||
755 | lua_pushlstring(L, buffer, len); | ||
756 | free(buffer); | ||
757 | return 1; | ||
758 | } | ||
759 | |||
760 | /** | ||
761 | * Get some shared keying material | ||
762 | */ | ||
763 | static int meth_exportkeyingmaterial(lua_State *L) | ||
764 | { | ||
765 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
766 | |||
767 | if(ssl->state != LSEC_STATE_CONNECTED) { | ||
768 | lua_pushnil(L); | ||
769 | lua_pushstring(L, "closed"); | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | size_t llen = 0; | ||
774 | size_t contextlen = 0; | ||
775 | const unsigned char *context = NULL; | ||
776 | const char *label = (const char*)luaL_checklstring(L, 2, &llen); | ||
777 | size_t olen = (size_t)luaL_checkinteger(L, 3); | ||
778 | |||
779 | if (!lua_isnoneornil(L, 4)) | ||
780 | context = (const unsigned char*)luaL_checklstring(L, 4, &contextlen); | ||
781 | |||
782 | /* Temporary buffer memory-managed by Lua itself */ | ||
783 | unsigned char *out = (unsigned char*)lua_newuserdata(L, olen); | ||
784 | |||
785 | if(SSL_export_keying_material(ssl->ssl, out, olen, label, llen, context, contextlen, context != NULL) != 1) { | ||
786 | lua_pushnil(L); | ||
787 | lua_pushstring(L, "error exporting keying material"); | ||
788 | return 2; | ||
789 | } | ||
790 | |||
791 | lua_pushlstring(L, (char*)out, olen); | ||
792 | return 1; | ||
793 | } | ||
794 | |||
795 | /** | ||
796 | * Object information -- tostring metamethod | ||
797 | */ | ||
798 | static int meth_tostring(lua_State *L) | ||
799 | { | ||
800 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
801 | lua_pushfstring(L, "SSL connection: %p%s", ssl, | ||
802 | ssl->state == LSEC_STATE_CLOSED ? " (closed)" : ""); | ||
803 | return 1; | ||
804 | } | ||
805 | |||
806 | /** | ||
807 | * Add a method in the SSL metatable. | ||
808 | */ | ||
809 | static int meth_setmethod(lua_State *L) | ||
810 | { | ||
811 | luaL_getmetatable(L, "SSL:Connection"); | ||
812 | lua_pushstring(L, "__index"); | ||
813 | lua_gettable(L, -2); | ||
814 | lua_pushvalue(L, 1); | ||
815 | lua_pushvalue(L, 2); | ||
816 | lua_settable(L, -3); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | /** | ||
821 | * Return information about the connection. | ||
822 | */ | ||
823 | static int meth_info(lua_State *L) | ||
824 | { | ||
825 | int bits = 0; | ||
826 | int algbits = 0; | ||
827 | char buf[256] = {0}; | ||
828 | const SSL_CIPHER *cipher; | ||
829 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
830 | cipher = SSL_get_current_cipher(ssl->ssl); | ||
831 | if (!cipher) | ||
832 | return 0; | ||
833 | SSL_CIPHER_description(cipher, buf, sizeof(buf)); | ||
834 | bits = SSL_CIPHER_get_bits(cipher, &algbits); | ||
835 | lua_pushstring(L, buf); | ||
836 | lua_pushnumber(L, bits); | ||
837 | lua_pushnumber(L, algbits); | ||
838 | lua_pushstring(L, SSL_get_version(ssl->ssl)); | ||
839 | return 4; | ||
840 | } | ||
841 | |||
842 | static int sni_cb(SSL *ssl, int *ad, void *arg) | ||
843 | { | ||
844 | int strict; | ||
845 | SSL_CTX *newctx = NULL; | ||
846 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); | ||
847 | lua_State *L = ((p_context)SSL_CTX_get_app_data(ctx))->L; | ||
848 | const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); | ||
849 | /* No name, use default context */ | ||
850 | if (!name) | ||
851 | return SSL_TLSEXT_ERR_NOACK; | ||
852 | /* Retrieve struct from registry */ | ||
853 | luaL_getmetatable(L, "SSL:SNI:Registry"); | ||
854 | lua_pushlightuserdata(L, (void*)ssl); | ||
855 | lua_gettable(L, -2); | ||
856 | /* Strict search? */ | ||
857 | lua_pushstring(L, "strict"); | ||
858 | lua_gettable(L, -2); | ||
859 | strict = lua_toboolean(L, -1); | ||
860 | lua_pop(L, 1); | ||
861 | /* Search for the name in the map */ | ||
862 | lua_pushstring(L, "map"); | ||
863 | lua_gettable(L, -2); | ||
864 | lua_pushstring(L, name); | ||
865 | lua_gettable(L, -2); | ||
866 | if (lua_isuserdata(L, -1)) | ||
867 | newctx = lsec_checkcontext(L, -1); | ||
868 | lua_pop(L, 4); | ||
869 | /* Found, use this context */ | ||
870 | if (newctx) { | ||
871 | p_context pctx = (p_context)SSL_CTX_get_app_data(newctx); | ||
872 | pctx->L = L; | ||
873 | SSL_set_SSL_CTX(ssl, newctx); | ||
874 | return SSL_TLSEXT_ERR_OK; | ||
875 | } | ||
876 | /* Not found, but use initial context */ | ||
877 | if (!strict) | ||
878 | return SSL_TLSEXT_ERR_OK; | ||
879 | return SSL_TLSEXT_ERR_ALERT_FATAL; | ||
880 | } | ||
881 | |||
882 | static int meth_sni(lua_State *L) | ||
883 | { | ||
884 | int strict; | ||
885 | SSL_CTX *aux; | ||
886 | const char *name; | ||
887 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
888 | SSL_CTX *ctx = SSL_get_SSL_CTX(ssl->ssl); | ||
889 | p_context pctx = (p_context)SSL_CTX_get_app_data(ctx); | ||
890 | if (pctx->mode == LSEC_MODE_CLIENT) { | ||
891 | name = luaL_checkstring(L, 2); | ||
892 | SSL_set_tlsext_host_name(ssl->ssl, name); | ||
893 | return 0; | ||
894 | } else if (pctx->mode == LSEC_MODE_SERVER) { | ||
895 | luaL_checktype(L, 2, LUA_TTABLE); | ||
896 | strict = lua_toboolean(L, 3); | ||
897 | /* Check if the table contains only (string -> context) */ | ||
898 | lua_pushnil(L); | ||
899 | while (lua_next(L, 2)) { | ||
900 | luaL_checkstring(L, -2); | ||
901 | aux = lsec_checkcontext(L, -1); | ||
902 | /* Set callback in every context */ | ||
903 | SSL_CTX_set_tlsext_servername_callback(aux, sni_cb); | ||
904 | /* leave the next key on the stack */ | ||
905 | lua_pop(L, 1); | ||
906 | } | ||
907 | /* Save table in the register */ | ||
908 | luaL_getmetatable(L, "SSL:SNI:Registry"); | ||
909 | lua_pushlightuserdata(L, (void*)ssl->ssl); | ||
910 | lua_newtable(L); | ||
911 | lua_pushstring(L, "map"); | ||
912 | lua_pushvalue(L, 2); | ||
913 | lua_settable(L, -3); | ||
914 | lua_pushstring(L, "strict"); | ||
915 | lua_pushboolean(L, strict); | ||
916 | lua_settable(L, -3); | ||
917 | lua_settable(L, -3); | ||
918 | /* Set callback in the default context */ | ||
919 | SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb); | ||
920 | } | ||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | static int meth_getsniname(lua_State *L) | ||
925 | { | ||
926 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
927 | const char *name = SSL_get_servername(ssl->ssl, TLSEXT_NAMETYPE_host_name); | ||
928 | if (name) | ||
929 | lua_pushstring(L, name); | ||
930 | else | ||
931 | lua_pushnil(L); | ||
932 | return 1; | ||
933 | } | ||
934 | |||
935 | static int meth_getalpn(lua_State *L) | ||
936 | { | ||
937 | unsigned len; | ||
938 | const unsigned char *data; | ||
939 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
940 | SSL_get0_alpn_selected(ssl->ssl, &data, &len); | ||
941 | if (data == NULL && len == 0) | ||
942 | lua_pushnil(L); | ||
943 | else | ||
944 | lua_pushlstring(L, (const char*)data, len); | ||
945 | return 1; | ||
946 | } | ||
947 | |||
948 | static int meth_copyright(lua_State *L) | ||
949 | { | ||
950 | lua_pushstring(L, "LuaSec 1.3.2 - Copyright (C) 2006-2023 Bruno Silvestre, UFG" | ||
951 | #if defined(WITH_LUASOCKET) | ||
952 | "\nLuaSocket 3.0-RC1 - Copyright (C) 2004-2013 Diego Nehab" | ||
953 | #endif | ||
954 | ); | ||
955 | return 1; | ||
956 | } | ||
957 | |||
958 | #if defined(LSEC_ENABLE_DANE) | ||
959 | static int meth_dane(lua_State *L) | ||
960 | { | ||
961 | int ret; | ||
962 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
963 | ret = SSL_dane_enable(ssl->ssl, luaL_checkstring(L, 2)); | ||
964 | lua_pushboolean(L, (ret > 0)); | ||
965 | return 1; | ||
966 | } | ||
967 | |||
968 | static int meth_tlsa(lua_State *L) | ||
969 | { | ||
970 | int ret; | ||
971 | size_t len; | ||
972 | p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); | ||
973 | uint8_t usage = (uint8_t)luaL_checkinteger(L, 2); | ||
974 | uint8_t selector = (uint8_t)luaL_checkinteger(L, 3); | ||
975 | uint8_t mtype = (uint8_t)luaL_checkinteger(L, 4); | ||
976 | unsigned char *data = (unsigned char*)luaL_checklstring(L, 5, &len); | ||
977 | |||
978 | ERR_clear_error(); | ||
979 | ret = SSL_dane_tlsa_add(ssl->ssl, usage, selector, mtype, data, len); | ||
980 | lua_pushboolean(L, (ret > 0)); | ||
981 | |||
982 | return 1; | ||
983 | } | ||
984 | #endif | ||
985 | |||
986 | /*---------------------------------------------------------------------------*/ | ||
987 | |||
988 | /** | ||
989 | * SSL methods | ||
990 | */ | ||
991 | static luaL_Reg methods[] = { | ||
992 | {"close", meth_close}, | ||
993 | {"getalpn", meth_getalpn}, | ||
994 | {"getfd", meth_getfd}, | ||
995 | {"getfinished", meth_getfinished}, | ||
996 | {"getpeercertificate", meth_getpeercertificate}, | ||
997 | {"getlocalcertificate", meth_getlocalcertificate}, | ||
998 | {"getpeerchain", meth_getpeerchain}, | ||
999 | {"getlocalchain", meth_getlocalchain}, | ||
1000 | {"getpeerverification", meth_getpeerverification}, | ||
1001 | {"getpeerfinished", meth_getpeerfinished}, | ||
1002 | {"exportkeyingmaterial",meth_exportkeyingmaterial}, | ||
1003 | {"getsniname", meth_getsniname}, | ||
1004 | {"getstats", meth_getstats}, | ||
1005 | {"setstats", meth_setstats}, | ||
1006 | {"dirty", meth_dirty}, | ||
1007 | {"dohandshake", meth_handshake}, | ||
1008 | {"receive", meth_receive}, | ||
1009 | {"send", meth_send}, | ||
1010 | {"settimeout", meth_settimeout}, | ||
1011 | {"sni", meth_sni}, | ||
1012 | {"want", meth_want}, | ||
1013 | #if defined(LSEC_ENABLE_DANE) | ||
1014 | {"setdane", meth_dane}, | ||
1015 | {"settlsa", meth_tlsa}, | ||
1016 | #endif | ||
1017 | {NULL, NULL} | ||
1018 | }; | ||
1019 | |||
1020 | /** | ||
1021 | * SSL metamethods. | ||
1022 | */ | ||
1023 | static luaL_Reg meta[] = { | ||
1024 | {"__close", meth_destroy}, | ||
1025 | {"__gc", meth_destroy}, | ||
1026 | {"__tostring", meth_tostring}, | ||
1027 | {NULL, NULL} | ||
1028 | }; | ||
1029 | |||
1030 | /** | ||
1031 | * SSL functions. | ||
1032 | */ | ||
1033 | static luaL_Reg funcs[] = { | ||
1034 | {"compression", meth_compression}, | ||
1035 | {"create", meth_create}, | ||
1036 | {"info", meth_info}, | ||
1037 | {"setfd", meth_setfd}, | ||
1038 | {"setmethod", meth_setmethod}, | ||
1039 | {"copyright", meth_copyright}, | ||
1040 | {NULL, NULL} | ||
1041 | }; | ||
1042 | |||
1043 | /** | ||
1044 | * Initialize modules. | ||
1045 | */ | ||
1046 | LSEC_API int luaopen_ssl_core(lua_State *L) | ||
1047 | { | ||
1048 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
1049 | /* Initialize SSL */ | ||
1050 | if (!SSL_library_init()) { | ||
1051 | lua_pushstring(L, "unable to initialize SSL library"); | ||
1052 | lua_error(L); | ||
1053 | } | ||
1054 | OpenSSL_add_all_algorithms(); | ||
1055 | SSL_load_error_strings(); | ||
1056 | #endif | ||
1057 | |||
1058 | #if defined(WITH_LUASOCKET) | ||
1059 | /* Initialize internal library */ | ||
1060 | socket_open(); | ||
1061 | #endif | ||
1062 | |||
1063 | luaL_newmetatable(L, "SSL:SNI:Registry"); | ||
1064 | |||
1065 | /* Register the functions and tables */ | ||
1066 | luaL_newmetatable(L, "SSL:Connection"); | ||
1067 | setfuncs(L, meta); | ||
1068 | |||
1069 | luaL_newlib(L, methods); | ||
1070 | lua_setfield(L, -2, "__index"); | ||
1071 | |||
1072 | luaL_newlib(L, funcs); | ||
1073 | |||
1074 | lua_pushstring(L, "SOCKET_INVALID"); | ||
1075 | lua_pushinteger(L, SOCKET_INVALID); | ||
1076 | lua_rawset(L, -3); | ||
1077 | |||
1078 | return 1; | ||
1079 | } | ||
1080 | |||
1081 | //------------------------------------------------------------------------------ | ||
1082 | |||
1083 | #if defined(_MSC_VER) | ||
1084 | |||
1085 | /* Empty implementation to allow building with LuaRocks and MS compilers */ | ||
1086 | LSEC_API int luaopen_ssl(lua_State *L) { | ||
1087 | lua_pushstring(L, "you should not call this function"); | ||
1088 | lua_error(L); | ||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | #endif | ||
diff --git a/vendor/luasec/src/ssl.h b/vendor/luasec/src/ssl.h new file mode 100644 index 00000000..2362ffe5 --- /dev/null +++ b/vendor/luasec/src/ssl.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef LSEC_SSL_H | ||
2 | #define LSEC_SSL_H | ||
3 | |||
4 | /*-------------------------------------------------------------------------- | ||
5 | * LuaSec 1.3.2 | ||
6 | * | ||
7 | * Copyright (C) 2006-2023 Bruno Silvestre | ||
8 | * | ||
9 | *--------------------------------------------------------------------------*/ | ||
10 | |||
11 | #include <openssl/ssl.h> | ||
12 | #include <lua.h> | ||
13 | |||
14 | #include <luasocket/io.h> | ||
15 | #include <luasocket/buffer.h> | ||
16 | #include <luasocket/timeout.h> | ||
17 | #include <luasocket/socket.h> | ||
18 | |||
19 | #include "compat.h" | ||
20 | #include "context.h" | ||
21 | |||
22 | #define LSEC_STATE_NEW 1 | ||
23 | #define LSEC_STATE_CONNECTED 2 | ||
24 | #define LSEC_STATE_CLOSED 3 | ||
25 | |||
26 | #define LSEC_IO_SSL -100 | ||
27 | |||
28 | typedef struct t_ssl_ { | ||
29 | t_socket sock; | ||
30 | t_io io; | ||
31 | t_buffer buf; | ||
32 | t_timeout tm; | ||
33 | SSL *ssl; | ||
34 | int state; | ||
35 | int error; | ||
36 | } t_ssl; | ||
37 | typedef t_ssl* p_ssl; | ||
38 | |||
39 | LSEC_API int luaopen_ssl_core(lua_State *L); | ||
40 | |||
41 | #endif | ||
diff --git a/vendor/luasec/src/ssl.lua b/vendor/luasec/src/ssl.lua new file mode 100644 index 00000000..e22c047e --- /dev/null +++ b/vendor/luasec/src/ssl.lua | |||
@@ -0,0 +1,313 @@ | |||
1 | ------------------------------------------------------------------------------ | ||
2 | -- LuaSec 1.3.2 | ||
3 | -- | ||
4 | -- Copyright (C) 2006-2023 Bruno Silvestre | ||
5 | -- | ||
6 | ------------------------------------------------------------------------------ | ||
7 | |||
8 | local core = require("ssl.core") | ||
9 | local context = require("ssl.context") | ||
10 | local x509 = require("ssl.x509") | ||
11 | local config = require("ssl.config") | ||
12 | |||
13 | local unpack = table.unpack or unpack | ||
14 | |||
15 | -- We must prevent the contexts to be collected before the connections, | ||
16 | -- otherwise the C registry will be cleared. | ||
17 | local registry = setmetatable({}, {__mode="k"}) | ||
18 | |||
19 | -- | ||
20 | -- | ||
21 | -- | ||
22 | local function optexec(func, param, ctx) | ||
23 | if param then | ||
24 | if type(param) == "table" then | ||
25 | return func(ctx, unpack(param)) | ||
26 | else | ||
27 | return func(ctx, param) | ||
28 | end | ||
29 | end | ||
30 | return true | ||
31 | end | ||
32 | |||
33 | -- | ||
34 | -- Convert an array of strings to wire-format | ||
35 | -- | ||
36 | local function array2wireformat(array) | ||
37 | local str = "" | ||
38 | for k, v in ipairs(array) do | ||
39 | if type(v) ~= "string" then return nil end | ||
40 | local len = #v | ||
41 | if len == 0 then | ||
42 | return nil, "invalid ALPN name (empty string)" | ||
43 | elseif len > 255 then | ||
44 | return nil, "invalid ALPN name (length > 255)" | ||
45 | end | ||
46 | str = str .. string.char(len) .. v | ||
47 | end | ||
48 | if str == "" then return nil, "invalid ALPN list (empty)" end | ||
49 | return str | ||
50 | end | ||
51 | |||
52 | -- | ||
53 | -- Convert wire-string format to array | ||
54 | -- | ||
55 | local function wireformat2array(str) | ||
56 | local i = 1 | ||
57 | local array = {} | ||
58 | while i < #str do | ||
59 | local len = str:byte(i) | ||
60 | array[#array + 1] = str:sub(i + 1, i + len) | ||
61 | i = i + len + 1 | ||
62 | end | ||
63 | return array | ||
64 | end | ||
65 | |||
66 | -- | ||
67 | -- | ||
68 | -- | ||
69 | local function newcontext(cfg) | ||
70 | local succ, msg, ctx | ||
71 | -- Create the context | ||
72 | ctx, msg = context.create(cfg.protocol) | ||
73 | if not ctx then return nil, msg end | ||
74 | -- Mode | ||
75 | succ, msg = context.setmode(ctx, cfg.mode) | ||
76 | if not succ then return nil, msg end | ||
77 | local certificates = cfg.certificates | ||
78 | if not certificates then | ||
79 | certificates = { | ||
80 | { certificate = cfg.certificate, key = cfg.key, password = cfg.password } | ||
81 | } | ||
82 | end | ||
83 | for _, certificate in ipairs(certificates) do | ||
84 | -- Load the key | ||
85 | if certificate.key then | ||
86 | if certificate.password and | ||
87 | type(certificate.password) ~= "function" and | ||
88 | type(certificate.password) ~= "string" | ||
89 | then | ||
90 | return nil, "invalid password type" | ||
91 | end | ||
92 | succ, msg = context.loadkey(ctx, certificate.key, certificate.password) | ||
93 | if not succ then return nil, msg end | ||
94 | end | ||
95 | -- Load the certificate(s) | ||
96 | if certificate.certificate then | ||
97 | succ, msg = context.loadcert(ctx, certificate.certificate) | ||
98 | if not succ then return nil, msg end | ||
99 | if certificate.key and context.checkkey then | ||
100 | succ = context.checkkey(ctx) | ||
101 | if not succ then return nil, "private key does not match public key" end | ||
102 | end | ||
103 | end | ||
104 | end | ||
105 | -- Load the CA certificates | ||
106 | if cfg.cafile or cfg.capath then | ||
107 | succ, msg = context.locations(ctx, cfg.cafile, cfg.capath) | ||
108 | if not succ then return nil, msg end | ||
109 | end | ||
110 | -- Set SSL ciphers | ||
111 | if cfg.ciphers then | ||
112 | succ, msg = context.setcipher(ctx, cfg.ciphers) | ||
113 | if not succ then return nil, msg end | ||
114 | end | ||
115 | -- Set SSL cipher suites | ||
116 | if cfg.ciphersuites then | ||
117 | succ, msg = context.setciphersuites(ctx, cfg.ciphersuites) | ||
118 | if not succ then return nil, msg end | ||
119 | end | ||
120 | -- Set the verification options | ||
121 | succ, msg = optexec(context.setverify, cfg.verify, ctx) | ||
122 | if not succ then return nil, msg end | ||
123 | -- Set SSL options | ||
124 | succ, msg = optexec(context.setoptions, cfg.options, ctx) | ||
125 | if not succ then return nil, msg end | ||
126 | -- Set the depth for certificate verification | ||
127 | if cfg.depth then | ||
128 | succ, msg = context.setdepth(ctx, cfg.depth) | ||
129 | if not succ then return nil, msg end | ||
130 | end | ||
131 | |||
132 | -- NOTE: Setting DH parameters and elliptic curves needs to come after | ||
133 | -- setoptions(), in case the user has specified the single_{dh,ecdh}_use | ||
134 | -- options. | ||
135 | |||
136 | -- Set DH parameters | ||
137 | if cfg.dhparam then | ||
138 | if type(cfg.dhparam) ~= "function" then | ||
139 | return nil, "invalid DH parameter type" | ||
140 | end | ||
141 | context.setdhparam(ctx, cfg.dhparam) | ||
142 | end | ||
143 | |||
144 | -- Set elliptic curves | ||
145 | if (not config.algorithms.ec) and (cfg.curve or cfg.curveslist) then | ||
146 | return false, "elliptic curves not supported" | ||
147 | end | ||
148 | if config.capabilities.curves_list and cfg.curveslist then | ||
149 | succ, msg = context.setcurveslist(ctx, cfg.curveslist) | ||
150 | if not succ then return nil, msg end | ||
151 | elseif cfg.curve then | ||
152 | succ, msg = context.setcurve(ctx, cfg.curve) | ||
153 | if not succ then return nil, msg end | ||
154 | end | ||
155 | |||
156 | -- Set extra verification options | ||
157 | if cfg.verifyext and ctx.setverifyext then | ||
158 | succ, msg = optexec(ctx.setverifyext, cfg.verifyext, ctx) | ||
159 | if not succ then return nil, msg end | ||
160 | end | ||
161 | |||
162 | -- ALPN | ||
163 | if cfg.mode == "server" and cfg.alpn then | ||
164 | if type(cfg.alpn) == "function" then | ||
165 | local alpncb = cfg.alpn | ||
166 | -- This callback function has to return one value only | ||
167 | succ, msg = context.setalpncb(ctx, function(str) | ||
168 | local protocols = alpncb(wireformat2array(str)) | ||
169 | if type(protocols) == "string" then | ||
170 | protocols = { protocols } | ||
171 | elseif type(protocols) ~= "table" then | ||
172 | return nil | ||
173 | end | ||
174 | return (array2wireformat(protocols)) -- use "()" to drop error message | ||
175 | end) | ||
176 | if not succ then return nil, msg end | ||
177 | elseif type(cfg.alpn) == "table" then | ||
178 | local protocols = cfg.alpn | ||
179 | -- check if array is valid before use it | ||
180 | succ, msg = array2wireformat(protocols) | ||
181 | if not succ then return nil, msg end | ||
182 | -- This callback function has to return one value only | ||
183 | succ, msg = context.setalpncb(ctx, function() | ||
184 | return (array2wireformat(protocols)) -- use "()" to drop error message | ||
185 | end) | ||
186 | if not succ then return nil, msg end | ||
187 | else | ||
188 | return nil, "invalid ALPN parameter" | ||
189 | end | ||
190 | elseif cfg.mode == "client" and cfg.alpn then | ||
191 | local alpn | ||
192 | if type(cfg.alpn) == "string" then | ||
193 | alpn, msg = array2wireformat({ cfg.alpn }) | ||
194 | elseif type(cfg.alpn) == "table" then | ||
195 | alpn, msg = array2wireformat(cfg.alpn) | ||
196 | else | ||
197 | return nil, "invalid ALPN parameter" | ||
198 | end | ||
199 | if not alpn then return nil, msg end | ||
200 | succ, msg = context.setalpn(ctx, alpn) | ||
201 | if not succ then return nil, msg end | ||
202 | end | ||
203 | |||
204 | -- PSK | ||
205 | if config.capabilities.psk and cfg.psk then | ||
206 | if cfg.mode == "client" then | ||
207 | if type(cfg.psk) ~= "function" then | ||
208 | return nil, "invalid PSK configuration" | ||
209 | end | ||
210 | succ = context.setclientpskcb(ctx, cfg.psk) | ||
211 | if not succ then return nil, msg end | ||
212 | elseif cfg.mode == "server" then | ||
213 | if type(cfg.psk) == "function" then | ||
214 | succ, msg = context.setserverpskcb(ctx, cfg.psk) | ||
215 | if not succ then return nil, msg end | ||
216 | elseif type(cfg.psk) == "table" then | ||
217 | if type(cfg.psk.hint) == "string" and type(cfg.psk.callback) == "function" then | ||
218 | succ, msg = context.setpskhint(ctx, cfg.psk.hint) | ||
219 | if not succ then return succ, msg end | ||
220 | succ = context.setserverpskcb(ctx, cfg.psk.callback) | ||
221 | if not succ then return succ, msg end | ||
222 | else | ||
223 | return nil, "invalid PSK configuration" | ||
224 | end | ||
225 | else | ||
226 | return nil, "invalid PSK configuration" | ||
227 | end | ||
228 | end | ||
229 | end | ||
230 | |||
231 | if config.capabilities.dane and cfg.dane then | ||
232 | if type(cfg.dane) == "table" then | ||
233 | context.setdane(ctx, unpack(cfg.dane)) | ||
234 | else | ||
235 | context.setdane(ctx) | ||
236 | end | ||
237 | end | ||
238 | |||
239 | return ctx | ||
240 | end | ||
241 | |||
242 | -- | ||
243 | -- | ||
244 | -- | ||
245 | local function wrap(sock, cfg) | ||
246 | local ctx, msg | ||
247 | if type(cfg) == "table" then | ||
248 | ctx, msg = newcontext(cfg) | ||
249 | if not ctx then return nil, msg end | ||
250 | else | ||
251 | ctx = cfg | ||
252 | end | ||
253 | local s, msg = core.create(ctx) | ||
254 | if s then | ||
255 | core.setfd(s, sock:getfd()) | ||
256 | sock:setfd(core.SOCKET_INVALID) | ||
257 | registry[s] = ctx | ||
258 | return s | ||
259 | end | ||
260 | return nil, msg | ||
261 | end | ||
262 | |||
263 | -- | ||
264 | -- Extract connection information. | ||
265 | -- | ||
266 | local function info(ssl, field) | ||
267 | local str, comp, err, protocol | ||
268 | comp, err = core.compression(ssl) | ||
269 | if err then | ||
270 | return comp, err | ||
271 | end | ||
272 | -- Avoid parser | ||
273 | if field == "compression" then | ||
274 | return comp | ||
275 | end | ||
276 | local info = {compression = comp} | ||
277 | str, info.bits, info.algbits, protocol = core.info(ssl) | ||
278 | if str then | ||
279 | info.cipher, info.protocol, info.key, | ||
280 | info.authentication, info.encryption, info.mac = | ||
281 | string.match(str, | ||
282 | "^(%S+)%s+(%S+)%s+Kx=(%S+)%s+Au=(%S+)%s+Enc=(%S+)%s+Mac=(%S+)") | ||
283 | info.export = (string.match(str, "%sexport%s*$") ~= nil) | ||
284 | end | ||
285 | if protocol then | ||
286 | info.protocol = protocol | ||
287 | end | ||
288 | if field then | ||
289 | return info[field] | ||
290 | end | ||
291 | -- Empty? | ||
292 | return ( (next(info)) and info ) | ||
293 | end | ||
294 | |||
295 | -- | ||
296 | -- Set method for SSL connections. | ||
297 | -- | ||
298 | core.setmethod("info", info) | ||
299 | |||
300 | -------------------------------------------------------------------------------- | ||
301 | -- Export module | ||
302 | -- | ||
303 | |||
304 | local _M = { | ||
305 | _VERSION = "1.3.2", | ||
306 | _COPYRIGHT = core.copyright(), | ||
307 | config = config, | ||
308 | loadcertificate = x509.load, | ||
309 | newcontext = newcontext, | ||
310 | wrap = wrap, | ||
311 | } | ||
312 | |||
313 | return _M | ||
diff --git a/vendor/luasec/src/x509.c b/vendor/luasec/src/x509.c new file mode 100644 index 00000000..6833d46f --- /dev/null +++ b/vendor/luasec/src/x509.c | |||
@@ -0,0 +1,750 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2014-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #include <stdio.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | #if defined(WIN32) | ||
13 | #include <ws2tcpip.h> | ||
14 | #include <windows.h> | ||
15 | #else | ||
16 | #include <sys/types.h> | ||
17 | #include <sys/socket.h> | ||
18 | #include <netinet/in.h> | ||
19 | #include <arpa/inet.h> | ||
20 | #endif | ||
21 | |||
22 | #include <openssl/ssl.h> | ||
23 | #include <openssl/x509v3.h> | ||
24 | #include <openssl/evp.h> | ||
25 | #include <openssl/err.h> | ||
26 | #include <openssl/asn1.h> | ||
27 | #include <openssl/bio.h> | ||
28 | #include <openssl/bn.h> | ||
29 | |||
30 | #include <lua.h> | ||
31 | #include <lauxlib.h> | ||
32 | |||
33 | #include "x509.h" | ||
34 | |||
35 | |||
36 | #ifndef LSEC_API_OPENSSL_1_1_0 | ||
37 | #define X509_get0_notBefore X509_get_notBefore | ||
38 | #define X509_get0_notAfter X509_get_notAfter | ||
39 | #define ASN1_STRING_get0_data ASN1_STRING_data | ||
40 | #endif | ||
41 | |||
42 | static const char* hex_tab = "0123456789abcdef"; | ||
43 | |||
44 | /** | ||
45 | * Push the certificate on the stack. | ||
46 | */ | ||
47 | void lsec_pushx509(lua_State* L, X509 *cert) | ||
48 | { | ||
49 | p_x509 cert_obj = (p_x509)lua_newuserdata(L, sizeof(t_x509)); | ||
50 | cert_obj->cert = cert; | ||
51 | cert_obj->encode = LSEC_AI5_STRING; | ||
52 | luaL_getmetatable(L, "SSL:Certificate"); | ||
53 | lua_setmetatable(L, -2); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * Return the OpenSSL certificate X509. | ||
58 | */ | ||
59 | X509* lsec_checkx509(lua_State* L, int idx) | ||
60 | { | ||
61 | return ((p_x509)luaL_checkudata(L, idx, "SSL:Certificate"))->cert; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * Return LuaSec certificate X509 representation. | ||
66 | */ | ||
67 | p_x509 lsec_checkp_x509(lua_State* L, int idx) | ||
68 | { | ||
69 | return (p_x509)luaL_checkudata(L, idx, "SSL:Certificate"); | ||
70 | } | ||
71 | |||
72 | /*---------------------------------------------------------------------------*/ | ||
73 | |||
74 | #if defined(LUASEC_INET_NTOP) | ||
75 | /* | ||
76 | * For WinXP (SP3), set the following preprocessor macros: | ||
77 | * LUASEC_INET_NTOP | ||
78 | * WINVER=0x0501 | ||
79 | * _WIN32_WINNT=0x0501 | ||
80 | * NTDDI_VERSION=0x05010300 | ||
81 | * | ||
82 | * For IPv6 addresses, you need to add IPv6 Protocol to your interface. | ||
83 | * | ||
84 | */ | ||
85 | static const char *inet_ntop(int af, const char *src, char *dst, socklen_t size) | ||
86 | { | ||
87 | int addrsize; | ||
88 | struct sockaddr *addr; | ||
89 | struct sockaddr_in addr4; | ||
90 | struct sockaddr_in6 addr6; | ||
91 | |||
92 | switch (af) { | ||
93 | case AF_INET: | ||
94 | memset((void*)&addr4, 0, sizeof(addr4)); | ||
95 | addr4.sin_family = AF_INET; | ||
96 | memcpy((void*)&addr4.sin_addr, src, sizeof(struct in_addr)); | ||
97 | addr = (struct sockaddr*)&addr4; | ||
98 | addrsize = sizeof(struct sockaddr_in); | ||
99 | break; | ||
100 | case AF_INET6: | ||
101 | memset((void*)&addr6, 0, sizeof(addr6)); | ||
102 | addr6.sin6_family = AF_INET6; | ||
103 | memcpy((void*)&addr6.sin6_addr, src, sizeof(struct in6_addr)); | ||
104 | addr = (struct sockaddr*)&addr6; | ||
105 | addrsize = sizeof(struct sockaddr_in6); | ||
106 | break; | ||
107 | default: | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | if(getnameinfo(addr, addrsize, dst, size, NULL, 0, NI_NUMERICHOST) != 0) | ||
112 | return NULL; | ||
113 | return dst; | ||
114 | } | ||
115 | #endif | ||
116 | |||
117 | /*---------------------------------------------------------------------------*/ | ||
118 | |||
119 | /** | ||
120 | * Convert the buffer 'in' to hexadecimal. | ||
121 | */ | ||
122 | static void to_hex(const char* in, int length, char* out) | ||
123 | { | ||
124 | int i; | ||
125 | for (i = 0; i < length; i++) { | ||
126 | out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; | ||
127 | out[i*2+1] = hex_tab[(in[i]) & 0xF]; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Converts the ASN1_OBJECT into a textual representation and put it | ||
133 | * on the Lua stack. | ||
134 | */ | ||
135 | static void push_asn1_objname(lua_State* L, ASN1_OBJECT *object, int no_name) | ||
136 | { | ||
137 | char buffer[256]; | ||
138 | int len = OBJ_obj2txt(buffer, sizeof(buffer), object, no_name); | ||
139 | len = (len < sizeof(buffer)) ? len : sizeof(buffer); | ||
140 | lua_pushlstring(L, buffer, len); | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * Push the ASN1 string on the stack. | ||
145 | */ | ||
146 | static void push_asn1_string(lua_State* L, ASN1_STRING *string, int encode) | ||
147 | { | ||
148 | int len; | ||
149 | unsigned char *data; | ||
150 | if (!string) { | ||
151 | lua_pushnil(L); | ||
152 | return; | ||
153 | } | ||
154 | switch (encode) { | ||
155 | case LSEC_AI5_STRING: | ||
156 | lua_pushlstring(L, (char*)ASN1_STRING_get0_data(string), ASN1_STRING_length(string)); | ||
157 | break; | ||
158 | case LSEC_UTF8_STRING: | ||
159 | len = ASN1_STRING_to_UTF8(&data, string); | ||
160 | if (len >= 0) { | ||
161 | lua_pushlstring(L, (char*)data, len); | ||
162 | OPENSSL_free(data); | ||
163 | } | ||
164 | else | ||
165 | lua_pushnil(L); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Return a human readable time. | ||
171 | */ | ||
172 | static int push_asn1_time(lua_State *L, const ASN1_UTCTIME *tm) | ||
173 | { | ||
174 | char *tmp; | ||
175 | long size; | ||
176 | BIO *out = BIO_new(BIO_s_mem()); | ||
177 | ASN1_TIME_print(out, tm); | ||
178 | size = BIO_get_mem_data(out, &tmp); | ||
179 | lua_pushlstring(L, tmp, size); | ||
180 | BIO_free(out); | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Return a human readable IP address. | ||
186 | */ | ||
187 | static void push_asn1_ip(lua_State *L, ASN1_STRING *string) | ||
188 | { | ||
189 | int af; | ||
190 | char dst[INET6_ADDRSTRLEN]; | ||
191 | unsigned char *ip = (unsigned char*)ASN1_STRING_get0_data(string); | ||
192 | switch(ASN1_STRING_length(string)) { | ||
193 | case 4: | ||
194 | af = AF_INET; | ||
195 | break; | ||
196 | case 16: | ||
197 | af = AF_INET6; | ||
198 | break; | ||
199 | default: | ||
200 | lua_pushnil(L); | ||
201 | return; | ||
202 | } | ||
203 | if(inet_ntop(af, ip, dst, INET6_ADDRSTRLEN)) | ||
204 | lua_pushstring(L, dst); | ||
205 | else | ||
206 | lua_pushnil(L); | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * | ||
211 | */ | ||
212 | static int push_subtable(lua_State* L, int idx) | ||
213 | { | ||
214 | lua_pushvalue(L, -1); | ||
215 | lua_gettable(L, idx-1); | ||
216 | if (lua_isnil(L, -1)) { | ||
217 | lua_pop(L, 1); | ||
218 | lua_newtable(L); | ||
219 | lua_pushvalue(L, -2); | ||
220 | lua_pushvalue(L, -2); | ||
221 | lua_settable(L, idx-3); | ||
222 | lua_replace(L, -2); /* Replace key with table */ | ||
223 | return 1; | ||
224 | } | ||
225 | lua_replace(L, -2); /* Replace key with table */ | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Retrieve the general names from the object. | ||
231 | */ | ||
232 | static int push_x509_name(lua_State* L, X509_NAME *name, int encode) | ||
233 | { | ||
234 | int i; | ||
235 | int n_entries; | ||
236 | ASN1_OBJECT *object; | ||
237 | X509_NAME_ENTRY *entry; | ||
238 | lua_newtable(L); | ||
239 | n_entries = X509_NAME_entry_count(name); | ||
240 | for (i = 0; i < n_entries; i++) { | ||
241 | entry = X509_NAME_get_entry(name, i); | ||
242 | object = X509_NAME_ENTRY_get_object(entry); | ||
243 | lua_newtable(L); | ||
244 | push_asn1_objname(L, object, 1); | ||
245 | lua_setfield(L, -2, "oid"); | ||
246 | push_asn1_objname(L, object, 0); | ||
247 | lua_setfield(L, -2, "name"); | ||
248 | push_asn1_string(L, X509_NAME_ENTRY_get_data(entry), encode); | ||
249 | lua_setfield(L, -2, "value"); | ||
250 | lua_rawseti(L, -2, i+1); | ||
251 | } | ||
252 | return 1; | ||
253 | } | ||
254 | |||
255 | /*---------------------------------------------------------------------------*/ | ||
256 | |||
257 | /** | ||
258 | * Retrieve the Subject from the certificate. | ||
259 | */ | ||
260 | static int meth_subject(lua_State* L) | ||
261 | { | ||
262 | p_x509 px = lsec_checkp_x509(L, 1); | ||
263 | return push_x509_name(L, X509_get_subject_name(px->cert), px->encode); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * Retrieve the Issuer from the certificate. | ||
268 | */ | ||
269 | static int meth_issuer(lua_State* L) | ||
270 | { | ||
271 | p_x509 px = lsec_checkp_x509(L, 1); | ||
272 | return push_x509_name(L, X509_get_issuer_name(px->cert), px->encode); | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Retrieve the extensions from the certificate. | ||
277 | */ | ||
278 | int meth_extensions(lua_State* L) | ||
279 | { | ||
280 | int j; | ||
281 | int i = -1; | ||
282 | int n_general_names; | ||
283 | OTHERNAME *otherName; | ||
284 | X509_EXTENSION *extension; | ||
285 | GENERAL_NAME *general_name; | ||
286 | STACK_OF(GENERAL_NAME) *values; | ||
287 | p_x509 px = lsec_checkp_x509(L, 1); | ||
288 | X509 *peer = px->cert; | ||
289 | |||
290 | /* Return (ret) */ | ||
291 | lua_newtable(L); | ||
292 | |||
293 | while ((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1) { | ||
294 | extension = X509_get_ext(peer, i); | ||
295 | if (extension == NULL) | ||
296 | break; | ||
297 | values = X509V3_EXT_d2i(extension); | ||
298 | if (values == NULL) | ||
299 | break; | ||
300 | |||
301 | /* Push ret[oid] */ | ||
302 | push_asn1_objname(L, X509_EXTENSION_get_object(extension), 1); | ||
303 | push_subtable(L, -2); | ||
304 | |||
305 | /* Set ret[oid].name = name */ | ||
306 | push_asn1_objname(L, X509_EXTENSION_get_object(extension), 0); | ||
307 | lua_setfield(L, -2, "name"); | ||
308 | |||
309 | n_general_names = sk_GENERAL_NAME_num(values); | ||
310 | for (j = 0; j < n_general_names; j++) { | ||
311 | general_name = sk_GENERAL_NAME_value(values, j); | ||
312 | switch (general_name->type) { | ||
313 | case GEN_OTHERNAME: | ||
314 | otherName = general_name->d.otherName; | ||
315 | push_asn1_objname(L, otherName->type_id, 1); | ||
316 | if (push_subtable(L, -2)) { | ||
317 | push_asn1_objname(L, otherName->type_id, 0); | ||
318 | lua_setfield(L, -2, "name"); | ||
319 | } | ||
320 | push_asn1_string(L, otherName->value->value.asn1_string, px->encode); | ||
321 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
322 | lua_pop(L, 1); | ||
323 | break; | ||
324 | case GEN_DNS: | ||
325 | lua_pushstring(L, "dNSName"); | ||
326 | push_subtable(L, -2); | ||
327 | push_asn1_string(L, general_name->d.dNSName, px->encode); | ||
328 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
329 | lua_pop(L, 1); | ||
330 | break; | ||
331 | case GEN_EMAIL: | ||
332 | lua_pushstring(L, "rfc822Name"); | ||
333 | push_subtable(L, -2); | ||
334 | push_asn1_string(L, general_name->d.rfc822Name, px->encode); | ||
335 | lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); | ||
336 | lua_pop(L, 1); | ||
337 | break; | ||
338 | case GEN_URI: | ||
339 | lua_pushstring(L, "uniformResourceIdentifier"); | ||
340 | push_subtable(L, -2); | ||
341 | push_asn1_string(L, general_name->d.uniformResourceIdentifier, px->encode); | ||
342 | lua_rawseti(L, -2, lua_rawlen(L, -2)+1); | ||
343 | lua_pop(L, 1); | ||
344 | break; | ||
345 | case GEN_IPADD: | ||
346 | lua_pushstring(L, "iPAddress"); | ||
347 | push_subtable(L, -2); | ||
348 | push_asn1_ip(L, general_name->d.iPAddress); | ||
349 | lua_rawseti(L, -2, lua_rawlen(L, -2)+1); | ||
350 | lua_pop(L, 1); | ||
351 | break; | ||
352 | case GEN_X400: | ||
353 | /* x400Address */ | ||
354 | /* not supported */ | ||
355 | break; | ||
356 | case GEN_DIRNAME: | ||
357 | /* directoryName */ | ||
358 | /* not supported */ | ||
359 | break; | ||
360 | case GEN_EDIPARTY: | ||
361 | /* ediPartyName */ | ||
362 | /* not supported */ | ||
363 | break; | ||
364 | case GEN_RID: | ||
365 | /* registeredID */ | ||
366 | /* not supported */ | ||
367 | break; | ||
368 | } | ||
369 | GENERAL_NAME_free(general_name); | ||
370 | } | ||
371 | sk_GENERAL_NAME_free(values); | ||
372 | lua_pop(L, 1); /* ret[oid] */ | ||
373 | i++; /* Next extension */ | ||
374 | } | ||
375 | return 1; | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * Convert the certificate to PEM format. | ||
380 | */ | ||
381 | static int meth_pem(lua_State* L) | ||
382 | { | ||
383 | char* data; | ||
384 | long bytes; | ||
385 | X509* cert = lsec_checkx509(L, 1); | ||
386 | BIO *bio = BIO_new(BIO_s_mem()); | ||
387 | if (!PEM_write_bio_X509(bio, cert)) { | ||
388 | lua_pushnil(L); | ||
389 | return 1; | ||
390 | } | ||
391 | bytes = BIO_get_mem_data(bio, &data); | ||
392 | if (bytes > 0) | ||
393 | lua_pushlstring(L, data, bytes); | ||
394 | else | ||
395 | lua_pushnil(L); | ||
396 | BIO_free(bio); | ||
397 | return 1; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * Extract public key in PEM format. | ||
402 | */ | ||
403 | static int meth_pubkey(lua_State* L) | ||
404 | { | ||
405 | char* data; | ||
406 | long bytes; | ||
407 | int ret = 1; | ||
408 | X509* cert = lsec_checkx509(L, 1); | ||
409 | BIO *bio = BIO_new(BIO_s_mem()); | ||
410 | EVP_PKEY *pkey = X509_get_pubkey(cert); | ||
411 | if(PEM_write_bio_PUBKEY(bio, pkey)) { | ||
412 | bytes = BIO_get_mem_data(bio, &data); | ||
413 | if (bytes > 0) { | ||
414 | lua_pushlstring(L, data, bytes); | ||
415 | switch(EVP_PKEY_base_id(pkey)) { | ||
416 | case EVP_PKEY_RSA: | ||
417 | lua_pushstring(L, "RSA"); | ||
418 | break; | ||
419 | case EVP_PKEY_DSA: | ||
420 | lua_pushstring(L, "DSA"); | ||
421 | break; | ||
422 | case EVP_PKEY_DH: | ||
423 | lua_pushstring(L, "DH"); | ||
424 | break; | ||
425 | case EVP_PKEY_EC: | ||
426 | lua_pushstring(L, "EC"); | ||
427 | break; | ||
428 | default: | ||
429 | lua_pushstring(L, "Unknown"); | ||
430 | break; | ||
431 | } | ||
432 | lua_pushinteger(L, EVP_PKEY_bits(pkey)); | ||
433 | ret = 3; | ||
434 | } | ||
435 | else | ||
436 | lua_pushnil(L); | ||
437 | } | ||
438 | else | ||
439 | lua_pushnil(L); | ||
440 | /* Cleanup */ | ||
441 | BIO_free(bio); | ||
442 | EVP_PKEY_free(pkey); | ||
443 | return ret; | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * Compute the fingerprint. | ||
448 | */ | ||
449 | static int meth_digest(lua_State* L) | ||
450 | { | ||
451 | unsigned int bytes; | ||
452 | const EVP_MD *digest = NULL; | ||
453 | unsigned char buffer[EVP_MAX_MD_SIZE]; | ||
454 | char hex_buffer[EVP_MAX_MD_SIZE*2]; | ||
455 | X509 *cert = lsec_checkx509(L, 1); | ||
456 | const char *str = luaL_optstring(L, 2, NULL); | ||
457 | if (!str) | ||
458 | digest = EVP_sha1(); | ||
459 | else { | ||
460 | if (!strcmp(str, "sha1")) | ||
461 | digest = EVP_sha1(); | ||
462 | else if (!strcmp(str, "sha256")) | ||
463 | digest = EVP_sha256(); | ||
464 | else if (!strcmp(str, "sha512")) | ||
465 | digest = EVP_sha512(); | ||
466 | } | ||
467 | if (!digest) { | ||
468 | lua_pushnil(L); | ||
469 | lua_pushfstring(L, "digest algorithm not supported (%s)", str); | ||
470 | return 2; | ||
471 | } | ||
472 | if (!X509_digest(cert, digest, buffer, &bytes)) { | ||
473 | lua_pushnil(L); | ||
474 | lua_pushfstring(L, "error processing the certificate (%s)", | ||
475 | ERR_reason_error_string(ERR_get_error())); | ||
476 | return 2; | ||
477 | } | ||
478 | to_hex((char*)buffer, bytes, hex_buffer); | ||
479 | lua_pushlstring(L, hex_buffer, bytes*2); | ||
480 | return 1; | ||
481 | } | ||
482 | |||
483 | /** | ||
484 | * Check if the certificate is valid in a given time. | ||
485 | */ | ||
486 | static int meth_valid_at(lua_State* L) | ||
487 | { | ||
488 | int nb, na; | ||
489 | X509* cert = lsec_checkx509(L, 1); | ||
490 | time_t time = luaL_checkinteger(L, 2); | ||
491 | nb = X509_cmp_time(X509_get0_notBefore(cert), &time); | ||
492 | time -= 1; | ||
493 | na = X509_cmp_time(X509_get0_notAfter(cert), &time); | ||
494 | lua_pushboolean(L, nb == -1 && na == 1); | ||
495 | return 1; | ||
496 | } | ||
497 | |||
498 | /** | ||
499 | * Return the serial number. | ||
500 | */ | ||
501 | static int meth_serial(lua_State *L) | ||
502 | { | ||
503 | char *tmp; | ||
504 | BIGNUM *bn; | ||
505 | ASN1_INTEGER *serial; | ||
506 | X509* cert = lsec_checkx509(L, 1); | ||
507 | serial = X509_get_serialNumber(cert); | ||
508 | bn = ASN1_INTEGER_to_BN(serial, NULL); | ||
509 | tmp = BN_bn2hex(bn); | ||
510 | lua_pushstring(L, tmp); | ||
511 | BN_free(bn); | ||
512 | OPENSSL_free(tmp); | ||
513 | return 1; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * Return not before date. | ||
518 | */ | ||
519 | static int meth_notbefore(lua_State *L) | ||
520 | { | ||
521 | X509* cert = lsec_checkx509(L, 1); | ||
522 | return push_asn1_time(L, X509_get0_notBefore(cert)); | ||
523 | } | ||
524 | |||
525 | /** | ||
526 | * Return not after date. | ||
527 | */ | ||
528 | static int meth_notafter(lua_State *L) | ||
529 | { | ||
530 | X509* cert = lsec_checkx509(L, 1); | ||
531 | return push_asn1_time(L, X509_get0_notAfter(cert)); | ||
532 | } | ||
533 | |||
534 | /** | ||
535 | * Check if this certificate issued some other certificate | ||
536 | */ | ||
537 | static int meth_issued(lua_State* L) | ||
538 | { | ||
539 | int ret, i, len; | ||
540 | |||
541 | X509_STORE_CTX* ctx = NULL; | ||
542 | X509_STORE* root = NULL; | ||
543 | STACK_OF(X509)* chain = NULL; | ||
544 | |||
545 | X509* issuer = lsec_checkx509(L, 1); | ||
546 | X509* subject = lsec_checkx509(L, 2); | ||
547 | X509* cert = NULL; | ||
548 | |||
549 | len = lua_gettop(L); | ||
550 | |||
551 | /* Check that all arguments are certificates */ | ||
552 | |||
553 | for (i = 3; i <= len; i++) { | ||
554 | lsec_checkx509(L, i); | ||
555 | } | ||
556 | |||
557 | /* Before allocating things that require freeing afterwards */ | ||
558 | |||
559 | chain = sk_X509_new_null(); | ||
560 | ctx = X509_STORE_CTX_new(); | ||
561 | root = X509_STORE_new(); | ||
562 | |||
563 | if (ctx == NULL || root == NULL) { | ||
564 | lua_pushnil(L); | ||
565 | lua_pushstring(L, "X509_STORE_new() or X509_STORE_CTX_new() error"); | ||
566 | ret = 2; | ||
567 | goto cleanup; | ||
568 | } | ||
569 | |||
570 | ret = X509_STORE_add_cert(root, issuer); | ||
571 | |||
572 | if(!ret) { | ||
573 | lua_pushnil(L); | ||
574 | lua_pushstring(L, "X509_STORE_add_cert() error"); | ||
575 | ret = 2; | ||
576 | goto cleanup; | ||
577 | } | ||
578 | |||
579 | for (i = 3; i <= len && lua_isuserdata(L, i); i++) { | ||
580 | cert = lsec_checkx509(L, i); | ||
581 | sk_X509_push(chain, cert); | ||
582 | } | ||
583 | |||
584 | ret = X509_STORE_CTX_init(ctx, root, subject, chain); | ||
585 | |||
586 | if(!ret) { | ||
587 | lua_pushnil(L); | ||
588 | lua_pushstring(L, "X509_STORE_CTX_init() error"); | ||
589 | ret = 2; | ||
590 | goto cleanup; | ||
591 | } | ||
592 | |||
593 | /* Actual verification */ | ||
594 | if (X509_verify_cert(ctx) <= 0) { | ||
595 | ret = X509_STORE_CTX_get_error(ctx); | ||
596 | lua_pushnil(L); | ||
597 | lua_pushstring(L, X509_verify_cert_error_string(ret)); | ||
598 | ret = 2; | ||
599 | } else { | ||
600 | lua_pushboolean(L, 1); | ||
601 | ret = 1; | ||
602 | } | ||
603 | |||
604 | cleanup: | ||
605 | |||
606 | if (ctx != NULL) { | ||
607 | X509_STORE_CTX_free(ctx); | ||
608 | } | ||
609 | |||
610 | if (chain != NULL) { | ||
611 | X509_STORE_free(root); | ||
612 | } | ||
613 | |||
614 | sk_X509_free(chain); | ||
615 | |||
616 | return ret; | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * Collect X509 objects. | ||
621 | */ | ||
622 | static int meth_destroy(lua_State* L) | ||
623 | { | ||
624 | p_x509 px = lsec_checkp_x509(L, 1); | ||
625 | if (px->cert) { | ||
626 | X509_free(px->cert); | ||
627 | px->cert = NULL; | ||
628 | } | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static int meth_tostring(lua_State *L) | ||
633 | { | ||
634 | X509* cert = lsec_checkx509(L, 1); | ||
635 | lua_pushfstring(L, "X509 certificate: %p", cert); | ||
636 | return 1; | ||
637 | } | ||
638 | |||
639 | /** | ||
640 | * Set the encode for ASN.1 string. | ||
641 | */ | ||
642 | static int meth_set_encode(lua_State* L) | ||
643 | { | ||
644 | int succ = 0; | ||
645 | p_x509 px = lsec_checkp_x509(L, 1); | ||
646 | const char *enc = luaL_checkstring(L, 2); | ||
647 | if (strncmp(enc, "ai5", 3) == 0) { | ||
648 | succ = 1; | ||
649 | px->encode = LSEC_AI5_STRING; | ||
650 | } else if (strncmp(enc, "utf8", 4) == 0) { | ||
651 | succ = 1; | ||
652 | px->encode = LSEC_UTF8_STRING; | ||
653 | } | ||
654 | lua_pushboolean(L, succ); | ||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) | ||
659 | /** | ||
660 | * Get signature name. | ||
661 | */ | ||
662 | static int meth_get_signature_name(lua_State* L) | ||
663 | { | ||
664 | p_x509 px = lsec_checkp_x509(L, 1); | ||
665 | int nid = X509_get_signature_nid(px->cert); | ||
666 | const char *name = OBJ_nid2sn(nid); | ||
667 | if (!name) | ||
668 | lua_pushnil(L); | ||
669 | else | ||
670 | lua_pushstring(L, name); | ||
671 | return 1; | ||
672 | } | ||
673 | #endif | ||
674 | |||
675 | /*---------------------------------------------------------------------------*/ | ||
676 | |||
677 | static int load_cert(lua_State* L) | ||
678 | { | ||
679 | X509 *cert; | ||
680 | size_t bytes; | ||
681 | const char* data; | ||
682 | BIO *bio = BIO_new(BIO_s_mem()); | ||
683 | data = luaL_checklstring(L, 1, &bytes); | ||
684 | BIO_write(bio, data, bytes); | ||
685 | cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); | ||
686 | if (cert) | ||
687 | lsec_pushx509(L, cert); | ||
688 | else | ||
689 | lua_pushnil(L); | ||
690 | BIO_free(bio); | ||
691 | return 1; | ||
692 | } | ||
693 | |||
694 | /*---------------------------------------------------------------------------*/ | ||
695 | |||
696 | /** | ||
697 | * Certificate methods. | ||
698 | */ | ||
699 | static luaL_Reg methods[] = { | ||
700 | {"digest", meth_digest}, | ||
701 | {"setencode", meth_set_encode}, | ||
702 | {"extensions", meth_extensions}, | ||
703 | #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) | ||
704 | {"getsignaturename", meth_get_signature_name}, | ||
705 | #endif | ||
706 | {"issuer", meth_issuer}, | ||
707 | {"notbefore", meth_notbefore}, | ||
708 | {"notafter", meth_notafter}, | ||
709 | {"issued", meth_issued}, | ||
710 | {"pem", meth_pem}, | ||
711 | {"pubkey", meth_pubkey}, | ||
712 | {"serial", meth_serial}, | ||
713 | {"subject", meth_subject}, | ||
714 | {"validat", meth_valid_at}, | ||
715 | {NULL, NULL} | ||
716 | }; | ||
717 | |||
718 | /** | ||
719 | * X509 metamethods. | ||
720 | */ | ||
721 | static luaL_Reg meta[] = { | ||
722 | {"__close", meth_destroy}, | ||
723 | {"__gc", meth_destroy}, | ||
724 | {"__tostring", meth_tostring}, | ||
725 | {NULL, NULL} | ||
726 | }; | ||
727 | |||
728 | /** | ||
729 | * X509 functions. | ||
730 | */ | ||
731 | static luaL_Reg funcs[] = { | ||
732 | {"load", load_cert}, | ||
733 | {NULL, NULL} | ||
734 | }; | ||
735 | |||
736 | /*--------------------------------------------------------------------------*/ | ||
737 | |||
738 | LSEC_API int luaopen_ssl_x509(lua_State *L) | ||
739 | { | ||
740 | /* Register the functions and tables */ | ||
741 | luaL_newmetatable(L, "SSL:Certificate"); | ||
742 | setfuncs(L, meta); | ||
743 | |||
744 | luaL_newlib(L, methods); | ||
745 | lua_setfield(L, -2, "__index"); | ||
746 | |||
747 | luaL_newlib(L, funcs); | ||
748 | |||
749 | return 1; | ||
750 | } | ||
diff --git a/vendor/luasec/src/x509.h b/vendor/luasec/src/x509.h new file mode 100644 index 00000000..acdbe6c0 --- /dev/null +++ b/vendor/luasec/src/x509.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /*-------------------------------------------------------------------------- | ||
2 | * LuaSec 1.3.2 | ||
3 | * | ||
4 | * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild | ||
5 | * Copyright (C) 2013-2023 Bruno Silvestre | ||
6 | * | ||
7 | *--------------------------------------------------------------------------*/ | ||
8 | |||
9 | #ifndef LSEC_X509_H | ||
10 | #define LSEC_X509_H | ||
11 | |||
12 | #include <openssl/x509v3.h> | ||
13 | #include <lua.h> | ||
14 | |||
15 | #include "compat.h" | ||
16 | |||
17 | /* We do not support UniversalString nor BMPString as ASN.1 String types */ | ||
18 | enum { LSEC_AI5_STRING, LSEC_UTF8_STRING }; | ||
19 | |||
20 | typedef struct t_x509_ { | ||
21 | X509 *cert; | ||
22 | int encode; | ||
23 | } t_x509; | ||
24 | typedef t_x509* p_x509; | ||
25 | |||
26 | void lsec_pushx509(lua_State* L, X509* cert); | ||
27 | X509* lsec_checkx509(lua_State* L, int idx); | ||
28 | |||
29 | LSEC_API int luaopen_ssl_x509(lua_State *L); | ||
30 | |||
31 | #endif | ||