diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/GNUmakefile | 136 | ||||
-rw-r--r-- | src/compat52.h | 160 | ||||
-rw-r--r-- | src/openssl.c | 866 | ||||
-rw-r--r-- | src/openssl.ocsp.basic.lua | 3 | ||||
-rw-r--r-- | src/openssl.ocsp.response.lua | 3 |
5 files changed, 852 insertions, 316 deletions
diff --git a/src/GNUmakefile b/src/GNUmakefile index 015a93c..e257ba6 100644 --- a/src/GNUmakefile +++ b/src/GNUmakefile @@ -16,66 +16,46 @@ include $(d)/../GNUmakefile # # C O M P I L A T I O N F L A G S # -OS_$(d) = $(shell $(d)/../mk/vendor.os) -CC_$(d) = $(shell env CC="$(CC) "$(d)/../mk/vendor.cc) -LUAPATH_$(d) = $(shell env CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" $(<D)/../mk/luapath -krxm3 -I$(DESTDIR)$(includedir) -I/usr/include -I/usr/local/include -P$(DESTDIR)$(bindir) -P$(bindir) -L$(DESTDIR)$(libdir) -L$(libdir) -v$(1) $(2)) - -CPPFLAGS_$(d) = $(CPPFLAGS_$(abspath $(@D)/../..)) -DLUA_COMPAT_APIINTCASTS -DHAVE_CONFIG_H -CFLAGS_$(d) = $(CFLAGS_$(abspath $(@D)/../..)) -LDFLAGS_$(d) = $(LDFLAGS_$(abspath $(@D)/../..)) -SOFLAGS_$(d) = $(SOFLAGS_$(abspath $(@D)/../..)) - -ifeq ($(CC_$(d)), sunpro) -CPPFLAGS_$(d) += -DOPENSSL_NO_EC -endif - -LDFLAGS_$(d) += -lssl -lcrypto -lpthread -lm - -# NetBSD, FreeBSD, OpenBSD (and presumably descendants) lack any libdl; -# dlopen, et al are part of libc. -ifneq ($(patsubst %BSD,BSD,$(OS_$(d))), BSD) -LDFLAGS_$(d) += -ldl -endif - +CPPFLAGS_$(d) = $(ALL_CPPFLAGS) -DHAVE_CONFIG_H -DCOMPAT53_PREFIX=luaossl +CFLAGS_$(d) = $(ALL_CFLAGS) +SOFLAGS_$(d) = $(ALL_SOFLAGS) +LDFLAGS_$(d) = $(ALL_LDFLAGS) +LIBS_$(d) = $(ALL_LIBS) # # C O M P I L A T I O N R U L E S # +OBJS_$(d) = openssl.o ../vendor/compat53/c-api/compat-5.3.o + $(d)/config.h: $(abspath $(d)/..)/config.h $(CP) $< $@ define BUILD_$(d) -.SECONDARY: liblua$(1)-openssl openssl$(1) +$$(d)/$(1)/openssl.so: $$(addprefix $$(d)/$(1)/, $$(OBJS_$(d))) + $$(CC) -o $$@ $$^ $$(SOFLAGS_$$(abspath $$(@D)/..)) $$(LDFLAGS_$$(abspath $$(@D)/..)) $$(LIBS_$$(abspath $$(@D)/..)) -$$(d)/$(1)/openssl.so: $$(d)/$(1)/openssl.o - $$(CC) -o $$@ $$^ $$(SOFLAGS_$$(abspath $$(@D)/..)) $$(SOFLAGS) $$(LDFLAGS_$$(abspath $$(@D)/..)) $$(LDFLAGS) - -$$(d)/$(1)/openssl.o: $$(d)/openssl.c $$(d)/compat52.h $$(d)/config.h - test "$$(notdir $$(@D))" = "$$(call LUAPATH_$$(<D), $$(notdir $$(@D)), version)" +$$(d)/$(1)/%.o: $$(d)/%.c $$(d)/../vendor/compat53/c-api/compat-5.3.h $$(d)/config.h $$(MKDIR) -p $$(@D) - $$(CC) $$(CFLAGS_$$(<D)) $$(CFLAGS) $$(call LUAPATH_$$(<D), $$(notdir $$(@D)), cppflags) $$(CPPFLAGS_$$(<D)) $$(CPPFLAGS) -c -o $$@ $$< + $$(CC) $$(CFLAGS_$$(<D)) $$(ALL_LUA$(subst .,,$(1))_CPPFLAGS) $$(CPPFLAGS_$$(<D)) -c -o $$@ $$< + +.SECONDARY: liblua$(1)-openssl openssl$(1) openssl -liblua$(1)-openssl openssl$(1): $$(d)/$(1)/openssl.so +liblua$(1)-openssl openssl$(1) openssl: $$(d)/$(1)/openssl.so endef # BUILD_$(d) $(eval $(call BUILD_$(d),5.1)) - $(eval $(call BUILD_$(d),5.2)) - $(eval $(call BUILD_$(d),5.3)) ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" "" -.SECONDARY: all5.1 all5.2 all +.SECONDARY: all all5.1 all5.2 all5.3 all5.1: liblua5.1-openssl - all5.2: liblua5.2-openssl - all5.3: liblua5.3-openssl - -all: all5.1 all5.2 +all: $(foreach API,$(strip $(LUA_APIS)),all$(API)) endif @@ -85,13 +65,13 @@ endif # define INSTALL_$(d) -LUAC$(1)_$(d) = $$(or $$(call LUAPATH_$(d), $(1), luac), true) - MODS$(1)_$(d) = \ $$(DESTDIR)$(2)/_openssl.so \ $$(DESTDIR)$(3)/openssl.lua \ $$(DESTDIR)$(3)/openssl/auxlib.lua \ $$(DESTDIR)$(3)/openssl/bignum.lua \ + $$(DESTDIR)$(3)/openssl/ocsp/basic.lua \ + $$(DESTDIR)$(3)/openssl/ocsp/response.lua \ $$(DESTDIR)$(3)/openssl/pkey.lua \ $$(DESTDIR)$(3)/openssl/pubkey.lua \ $$(DESTDIR)$(3)/openssl/x509.lua \ @@ -114,42 +94,34 @@ MODS$(1)_$(d) = \ .SECONDARY: liblua$(1)-openssl-install openssl$(1)-install -$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so - $$(MKDIR) -p $$(@D) - $$(CP) -fp $$< $$@ +liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d)) -$$(DESTDIR)$(3)/openssl.lua: $$(d)/openssl.lua - $$(LUAC$(1)_$(d)) -p $$< +$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so $$(MKDIR) -p $$(@D) $$(CP) -p $$< $$@ -$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua - $$(LUAC$(1)_$(d)) -p $$< +$$(DESTDIR)$(3)/%.lua: $$(d)/%.lua + $$(LUAC$(subst .,,$(1))) -p $$< $$(MKDIR) -p $$(@D) $$(CP) -p $$< $$@ -# pubkey.lua used to be symbolic link to pkey.lua, but that caused packaging -# headaches. Now it's a stub, but the cp -p in the inference rule will copy -# to the target of the symbolic link, so we need a special install rule to -# clean up the mess. -$$(DESTDIR)$(3)/openssl/pubkey.lua: $$(d)/openssl.pubkey.lua - $$(LUAC$(1)_$(d)) -p $$< +$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua + $$(LUAC$(subst .,,$(1))) -p $$< $$(MKDIR) -p $$(@D) - $$(RM) -f $$@ $$(CP) -p $$< $$@ -$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/openssl.x509.%.lua - $$(LUAC$(1)_$(d)) -p $$< +$$(DESTDIR)$(3)/openssl/ocsp/%.lua: $$(d)/ocsp.%.lua + $$(LUAC$(subst .,,$(1))) -p $$< $$(MKDIR) -p $$(@D) $$(CP) -p $$< $$@ -$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua - $$(LUAC$(1)_$(d)) -p $$< +$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/x509.%.lua + $$(LUAC$(subst .,,$(1))) -p $$< $$(MKDIR) -p $$(@D) $$(CP) -p $$< $$@ -$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua - $$(LUAC$(1)_$(d)) -p $$< +$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/ssl.%.lua + $$(LUAC$(subst .,,$(1))) -p $$< $$(MKDIR) -p $$(@D) $$(CP) -p $$< $$@ @@ -159,6 +131,7 @@ liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d)) liblua$(1)-openssl-uninstall openssl$(1)-uninstall: $$(RM) -f $$(MODS$(1)_$(d)) + -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ocsp -$$(RMDIR) $$(DESTDIR)$(3)/openssl/x509 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ssl -$$(RMDIR) $$(DESTDIR)$(3)/openssl @@ -166,31 +139,24 @@ liblua$(1)-openssl-uninstall openssl$(1)-uninstall: endef # INSTALL_$(d) $(eval $(call INSTALL_$(d),5.1,$$(lua51cpath),$$(lua51path))) - $(eval $(call INSTALL_$(d),5.2,$$(lua52cpath),$$(lua52path))) - $(eval $(call INSTALL_$(d),5.3,$$(lua53cpath),$$(lua53path))) ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" "" + .SECONDARY: install5.1 install5.2 install5.3 install install5.1: liblua5.1-openssl-install - install5.2: liblua5.2-openssl-install - install5.3: liblua5.3-openssl-install - -install: install5.1 install5.2 +install: $(foreach API,$(strip $(LUA_APIS)),install$(API)) .PHONY: uninstall5.1 uninstall5.2 uninstall5.3 uninstall uninstall5.1: liblua5.1-openssl-uninstall - uninstall5.2: liblua5.2-openssl-uninstall - uninstall5.3: liblua5.3-openssl-uninstall - -uninstall: uninstall5.1 uninstall5.2 +uninstall: $(foreach API,$(strip $(LUA_APIS)),uninstall$(API)) endif @@ -201,7 +167,7 @@ endif .PHONY: $(d)/clean $(d)/clean~ clean clean~ $(d)/clean: - $(RM) -fr $(@D)/*.so $(@D)/*.o $(@D)/*.dSYM $(@D)/5.1 $(@D)/5.2 $(@D)/5.3 + $(RM) -fr $(@D)/config.h $(@D)/*.dSYM $(@D)/5.1 $(@D)/5.2 $(@D)/5.3 $(d)/clean~: $(d)/clean $(RM) -f $(@D)/*~ @@ -218,27 +184,27 @@ clean~: $(d)/clean~ $(d)/help: @echo - @echo "ext/ targets:" + @echo "src/ targets:" @echo "" - @echo " all - build all binary targets" - @echo "openssl - invokes openssl5.1 and openssl5.2" - @echo "openssl5.1 - build 5.1/openssl.so" - @echo "openssl5.2 - build 5.2/openssl.so" - @echo "openssl5.3 - build 5.3/openssl.so" - @echo "install - invokes install5.1 and install5.2" - @echo "install5.1 - install openssl Lua 5.1 modules" - @echo "install5.2 - install openssl Lua 5.2 modules" - @echo "install5.3 - install openssl Lua 5.3 modules" - @echo "uninstall - invokes uninstall5.1 and uninstall5.2" + @echo " all - build all API targets" + @echo " all5.1 - build 5.1/openssl.so" + @echo " all5.2 - build 5.2/openssl.so" + @echo " all5.3 - build 5.3/openssl.so" + @echo " install - install all API targets" + @echo " install5.1 - install openssl Lua 5.1 modules" + @echo " install5.2 - install openssl Lua 5.2 modules" + @echo " install5.3 - install openssl Lua 5.3 modules" + @echo " uninstall - uninstall all API targets" @echo "uninstall5.1 - uninstall openssl Lua 5.1 modules" @echo "uninstall5.2 - uninstall openssl Lua 5.2 modules" @echo "uninstall5.3 - uninstall openssl Lua 5.3 modules" - @echo " clean - rm binary targets, object files, debugging symbols, etc" - @echo " clean~ - clean + rm *~" - @echo " help - echo this help message" + @echo " clean - rm binary targets, object files, debugging symbols, etc" + @echo " clean~ - clean + rm *~" + @echo " help - echo this help message" @echo "" @echo "Some important Make variables:" @echo "" + @echo ' LUA_APIS - default Lua APIs to target ($(LUA_APIS))' @echo " prefix - path to install root ($(value prefix))" @echo ' lua51path - install path for Lua 5.1 modules ($(value lua51path))' @echo 'lua51cpath - install path for Lua 5.1 C modules ($(value lua51cpath))' @@ -247,6 +213,10 @@ $(d)/help: @echo ' lua53path - install path for Lua 5.3 modules ($(value lua53path))' @echo 'lua53cpath - install path for Lua 5.3 C modules ($(value lua53cpath))' @echo "" + @echo 'LUA51_CPPFLAGS - cpp flags for Lua 5.1 headers ($(LUA51_CPPFLAGS))' + @echo 'LUA52_CPPFLAGS - cpp flags for Lua 5.2 headers ($(LUA52_CPPFLAGS))' + @echo 'LUA53_CPPFLAGS - cpp flags for Lua 5.3 headers ($(LUA53_CPPFLAGS))' + @echo "" @echo "(NOTE: all the common GNU-style paths are supported, including" @echo "prefix, bindir, libdir, datadir, includedir, and DESTDIR.)" @echo "" diff --git a/src/compat52.h b/src/compat52.h deleted file mode 100644 index 0057b3c..0000000 --- a/src/compat52.h +++ /dev/null @@ -1,160 +0,0 @@ -/* ========================================================================== - * compat52.h - Routines for Lua 5.2 compatibility - * -------------------------------------------------------------------------- - * Copyright (c) 2012 William Ahern - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * ========================================================================== - */ -#if LUA_VERSION_NUM < 502 - -#define LUA_OK 0 - - -static void luaL_setmetatable(lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} /* luaL_setmetatable() */ - - -static int lua_absindex(lua_State *L, int idx) { - return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1; -} /* lua_absindex() */ - - -static void *luaL_testudata(lua_State *L, int arg, const char *tname) { - void *p = lua_touserdata(L, arg); - int eq; - - if (!p || !lua_getmetatable(L, arg)) - return 0; - - luaL_getmetatable(L, tname); - eq = lua_rawequal(L, -2, -1); - lua_pop(L, 2); - - return (eq)? p : 0; -} /* luaL_testudate() */ - - -static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { - int i, t = lua_absindex(L, -1 - nup); - - for (; l->name; l++) { - for (i = 0; i < nup; i++) - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); - lua_setfield(L, t, l->name); - } - - lua_pop(L, nup); -} /* luaL_setfuncs() */ - - -#define luaL_newlibtable(L, l) \ - lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1) - -#define luaL_newlib(L, l) \ - (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0)) - - -static void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) { - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); - lua_call(L, 1, 1); - - lua_getglobal(L, "package"); - lua_getfield(L, -1, "loaded"); - lua_pushvalue(L, -3); - lua_setfield(L, -2, modname); - - lua_pop(L, 2); - - if (glb) { - lua_pushvalue(L, -1); - lua_setglobal(L, modname); - } -} /* luaL_requiref() */ - - -#define lua_resume(L, from, nargs) lua_resume((L), (nargs)) - - -static void lua_rawgetp(lua_State *L, int index, const void *p) { - index = lua_absindex(L, index); - lua_pushlightuserdata(L, (void *)p); - lua_rawget(L, index); -} /* lua_rawgetp() */ - -static void lua_rawsetp(lua_State *L, int index, const void *p) { - index = lua_absindex(L, index); - lua_pushlightuserdata(L, (void *)p); - lua_pushvalue(L, -2); - lua_rawset(L, index); - lua_pop(L, 1); -} /* lua_rawsetp() */ - - -#ifndef LUA_UNSIGNED -#define LUA_UNSIGNED unsigned -#endif - -typedef LUA_UNSIGNED lua_Unsigned; - - -static void lua_pushunsigned(lua_State *L, lua_Unsigned n) { - lua_pushnumber(L, (lua_Number)n); -} /* lua_pushunsigned() */ - -static lua_Unsigned luaL_checkunsigned(lua_State *L, int arg) { - return (lua_Unsigned)luaL_checknumber(L, arg); -} /* luaL_checkunsigned() */ - - -static lua_Unsigned luaL_optunsigned(lua_State *L, int arg, lua_Unsigned def) { - return (lua_Unsigned)luaL_optnumber(L, arg, (lua_Number)def); -} /* luaL_optunsigned() */ - - -#ifndef LUA_FILEHANDLE /* Not defined by earlier LuaJIT releases */ -#define LUA_FILEHANDLE "FILE*" -#endif - -/* - * Lua 5.1 userdata is a simple FILE *, while LuaJIT is a struct with the - * first member a FILE *, similar to Lua 5.2. - */ -typedef struct luaL_Stream { - FILE *f; -} luaL_Stream; - - -#define lua_rawlen(...) lua_objlen(__VA_ARGS__) - - -#define lua_pushstring(...) lua52_pushstring(__VA_ARGS__) - -static const char *lua52_pushstring(lua_State *L, const char *s) { - (lua_pushstring)(L, s); - return lua_tostring(L, -1); -} /* lua52_pushstring() */ - - -#endif /* LUA_VERSION_NUM < 502 */ diff --git a/src/openssl.c b/src/openssl.c index 8217deb..a3e5637 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -69,14 +69,13 @@ #include <openssl/hmac.h> #include <openssl/rand.h> #include <openssl/des.h> +#include <openssl/ocsp.h> #include <lua.h> #include <lualib.h> #include <lauxlib.h> -#if LUA_VERSION_NUM < 502 -#include "compat52.h" -#endif +#include "../vendor/compat53/c-api/compat-5.3.h" #define GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) #define GNUC_PREREQ(M, m, p) (__GNUC__ > 0 && GNUC_2VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) >= GNUC_2VER((M), (m), (p))) @@ -270,6 +269,10 @@ #define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS #endif +#ifndef HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK +#define HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK OPENSSL_PREREQ(1,0,0) +#endif + #ifndef HAVE_SSL_CTX_SET1_CERT_STORE #define HAVE_SSL_CTX_SET1_CERT_STORE (HAVE_SSL_CTX_set1_cert_store || 0) /* backwards compatible with old macro name */ #endif @@ -282,6 +285,14 @@ #define HAVE_SSL_CTX_CERT_STORE (!OPENSSL_PREREQ(1,1,0)) #endif +#ifndef HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE +#define HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE +#define HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE OPENSSL_PREREQ(1,1,0) +#endif + #ifndef HAVE_SSL_GET0_ALPN_SELECTED #define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS #endif @@ -302,6 +313,14 @@ #define HAVE_SSL_SET1_PARAM OPENSSL_PREREQ(1,0,2) #endif +#ifndef HAVE_SSL_GET_CLIENT_RANDOM +#define HAVE_SSL_GET_CLIENT_RANDOM OPENSSL_PREREQ(1,1,0) +#endif + +#ifndef HAVE_SSL_GET_TLSEXT_STATUS_TYPE +#define HAVE_SSL_GET_TLSEXT_STATUS_TYPE OPENSSL_PREREQ(1,1,0) +#endif + #ifndef HAVE_SSL_UP_REF #define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0) #endif @@ -314,6 +333,10 @@ #define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) #endif +#ifndef HAVE_X509_GET_SIGNATURE_NID +#define HAVE_X509_GET_SIGNATURE_NID OPENSSL_PREREQ(1,0,2) +#endif + #ifndef HAVE_X509_STORE_REFERENCES #define HAVE_X509_STORE_REFERENCES (!OPENSSL_PREREQ(1,1,0)) #endif @@ -392,6 +415,8 @@ #define DIGEST_CLASS "EVP_MD_CTX*" #define HMAC_CLASS "HMAC_CTX*" #define CIPHER_CLASS "EVP_CIPHER_CTX*" +#define OCSP_RESPONSE_CLASS "OCSP_RESPONSE*" +#define OCSP_BASICRESP_CLASS "OCSP_BASICRESP*" #if __GNUC__ @@ -669,6 +694,44 @@ static void *loadfield_udata(lua_State *L, int index, const char *k, const char } /* loadfield_udata() */ +/* Forward declaration */ +static SSL *ssl_push(lua_State *, SSL *); + +/* push an ssl object into lua in a way that is safe from OOM + * Lua 5.1 does not support normally returning values from lua_cpcall + * to return a value, we instead return it via an error object + */ +static int ssl_pushsafe_helper(lua_State *L) { + ssl_push(L, lua_touserdata(L, 1)); +#if LUA_VERSION_NUM <= 501 + return lua_error(L); +#else + return 1; +#endif +} + +static int ssl_pushsafe(lua_State *L, SSL *ssl) { + int status; +#if LUA_VERSION_NUM <= 501 + status = lua_cpcall(L, ssl_pushsafe_helper, ssl); + if (status == LUA_ERRRUN) + status = LUA_OK; + else if (status == LUA_OK) + /* this should be impossible */ + status = LUA_ERRRUN; + else + lua_pop(L, 1); +#else + lua_pushcfunction(L, ssl_pushsafe_helper); + lua_pushlightuserdata(L, ssl); + status = lua_pcall(L, 1, 1, 0); + if (status != LUA_OK) + lua_pop(L, 1); +#endif + return status; +} + + /* * Auxiliary C routines * @@ -920,7 +983,7 @@ static void auxL_pushinteger(lua_State *L, auxL_Integer i) { } } /* auxL_pushinteger() */ -NOTUSED static void auxL_pushunsigned(lua_State *L, auxL_Unsigned i) { +static void auxL_pushunsigned(lua_State *L, auxL_Unsigned i) { if (i <= lua_IntegerMax) { lua_pushinteger(L, i); } else if (i == (auxL_Unsigned)(lua_Number)i) { @@ -1571,6 +1634,18 @@ static void compat_RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { } /* compat_RSA_set0_key() */ #endif +#if !HAVE_SSL_GET_CLIENT_RANDOM +#define SSL_get_client_random(...) compat_SSL_get_client_random(__VA_ARGS__) +static size_t compat_SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen) { + if (outlen == 0) + return sizeof(ssl->s3->client_random); + if (outlen > sizeof(ssl->s3->client_random)) + outlen = sizeof(ssl->s3->client_random); + memcpy(out, ssl->s3->client_random, outlen); + return outlen; +} +#endif + #if !HAVE_SSL_CLIENT_VERSION #define SSL_client_version(...) compat_SSL_client_version(__VA_ARGS__) @@ -1627,6 +1702,10 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) { #define X509_get0_ext(crt, i) X509_get_ext((crt), (i)) #endif +#if !HAVE_X509_GET_SIGNATURE_NID +#define X509_get_signature_nid(crt) OBJ_obj2nid((crt)->sig_alg->algorithm) +#endif + #if !HAVE_X509_CRL_GET0_EXT #define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i)) #endif @@ -1914,6 +1993,7 @@ struct ex_data { enum { EX_SSL_CTX_ALPN_SELECT_CB, + EX_SSL_CTX_TLSEXT_SERVERNAME_CB, }; static struct ex_type { @@ -1923,6 +2003,7 @@ static struct ex_type { int (*set_ex_data)(); } ex_type[] = { [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data }, + [EX_SSL_CTX_TLSEXT_SERVERNAME_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data }, }; #if OPENSSL_PREREQ(1,1,0) @@ -3074,6 +3155,7 @@ static int pk_new(lua_State *L) { unsigned exp = 65537; int curve = NID_X9_62_prime192v1; const char *id; + const char *dhparam = NULL; lua_Number n; if (!lua_istable(L, 1)) @@ -3115,6 +3197,9 @@ static int pk_new(lua_State *L) { luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id)); } + /* dhparam field can contain a PEM encoded string. */ + loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam); + creat: if (!(*ud = EVP_PKEY_new())) return auxL_error(L, auxL_EOPENSSL, "pkey.new"); @@ -3152,9 +3237,23 @@ creat: case EVP_PKEY_DH: { DH *dh; - if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) + /* DH Parameter Generation can take a long time, therefore we look + * at the "dhparam" field, provided by the user. + * The "dhparam" field takes precedence over "bits" + */ + if (dhparam) { + BIO *bio = BIO_new_mem_buf((void*)dhparam, strlen(dhparam)); + if (!bio) + return auxL_error(L, auxL_EOPENSSL, "pkey.new"); + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (!dh) + return auxL_error(L, auxL_EOPENSSL, "pkey.new"); + } else if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) return auxL_error(L, auxL_EOPENSSL, "pkey.new"); + if (!DH_generate_key(dh)) { DH_free(dh); return auxL_error(L, auxL_EOPENSSL, "pkey.new"); @@ -3420,7 +3519,7 @@ static int pk_decrypt(lua_State *L) { if (lua_istable(L, 3)) { if (base_type == EVP_PKEY_RSA) { lua_getfield(L, 3, "rsaPadding"); - rsaPadding = luaL_optint(L, -1, rsaPadding); + rsaPadding = luaL_optinteger(L, -1, rsaPadding); lua_pop(L, 1); } } @@ -3479,7 +3578,7 @@ static int pk_encrypt(lua_State *L) { if (lua_istable(L, 3)) { if (base_type == EVP_PKEY_RSA) { lua_getfield(L, 3, "rsaPadding"); - rsaPadding = luaL_optint(L, -1, rsaPadding); + rsaPadding = luaL_optinteger(L, -1, rsaPadding); lua_pop(L, 1); } } @@ -4401,7 +4500,7 @@ static int ecg_new(lua_State *L) { return 1; } case LUA_TNUMBER: { - int nid = luaL_checkint(L, 2); + int nid = luaL_checkinteger(L, 2); if (!ecg_push_by_nid(L, nid)) goto sslerr; @@ -4970,6 +5069,25 @@ static _Bool xe_new_isder(const char *value, _Bool *crit) { return 0; } /* xs_new_isder() */ +static CONF* loadconf(lua_State *L, int idx) { + CONF *conf; + size_t len; + const char *cdata = luaL_checklstring(L, idx, &len); + BIO *bio = getbio(L); + if (BIO_write(bio, cdata, len) < 0) + return NULL; + + if (!(conf = NCONF_new(NULL))) + return NULL; + + if (!NCONF_load_bio(conf, bio, NULL)) { + NCONF_free(conf); + return NULL; + } + + return conf; +} + static int xe_new(lua_State *L) { const char *name = luaL_checkstring(L, 1); const char *value = luaL_checkstring(L, 2); @@ -4978,42 +5096,87 @@ static int xe_new(lua_State *L) { CONF *conf = NULL; X509V3_CTX cbuf = { 0 }, *ctx = NULL; X509_EXTENSION **ud; + _Bool crit; lua_settop(L, 3); ud = prepsimple(L, X509_EXT_CLASS); - if (!lua_isnil(L, 3)) { + if (xe_new_isder(value, &crit)) { size_t len; - const char *cdata = luaL_checklstring(L, 3, &len); - _Bool crit; + const char *cdata = lua_tolstring(L, 3, &len); + if (!(obj = OBJ_txt2obj(name, 0))) + goto error; + if (!(oct = ASN1_STRING_new())) + goto error; + if (!ASN1_STRING_set(oct, cdata, len)) + goto error; + if (!(*ud = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct))) + goto error; - if (xe_new_isder(value, &crit)) { - if (!(obj = OBJ_txt2obj(name, 0))) - goto error; - if (!(oct = ASN1_STRING_new())) - goto error; - if (!ASN1_STRING_set(oct, cdata, len)) - goto error; - if (!(*ud = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct))) + ASN1_OBJECT_free(obj); + ASN1_STRING_free(oct); + + return 1; + } + + switch (lua_type(L, 3)) { + case LUA_TNONE: + case LUA_TNIL: + break; + case LUA_TSTRING: { + if (!(conf = loadconf(L, 3))) + goto error; + + ctx = &cbuf; + X509V3_set_nconf(ctx, conf); + break; + } + case LUA_TTABLE: { + X509 *issuer = NULL; + X509 *subject = NULL; + X509_REQ *request = NULL; + X509_CRL *crl = NULL; + int flags = 0; + + ctx = &cbuf; + + if (lua_getfield(L, 3, "db") != LUA_TNIL) { + if (!(conf = loadconf(L, -1))) goto error; + X509V3_set_nconf(ctx, conf); + } + lua_pop(L, 1); - ASN1_OBJECT_free(obj); - ASN1_STRING_free(oct); + if (lua_getfield(L, 3, "issuer") != LUA_TNIL) { + issuer = checksimple(L, -1, X509_CERT_CLASS); + } + lua_pop(L, 1); - return 1; + if (lua_getfield(L, 3, "subject") != LUA_TNIL) { + subject = checksimple(L, -1, X509_CERT_CLASS); } + lua_pop(L, 1); - BIO *bio = getbio(L); - if (BIO_puts(bio, cdata) < 0) - goto error; + if (lua_getfield(L, 3, "request") != LUA_TNIL) { + request = checksimple(L, -1, X509_CSR_CLASS); + } + lua_pop(L, 1); - if (!(conf = NCONF_new(NULL))) - goto error; - if (!NCONF_load_bio(conf, bio, NULL)) - goto error; + if (lua_getfield(L, 3, "crl") != LUA_TNIL) { + crl = checksimple(L, -1, X509_CRL_CLASS); + } + lua_pop(L, 1); - ctx = &cbuf; - X509V3_set_nconf(ctx, conf); + if (lua_getfield(L, 3, "flags") != LUA_TNIL) { + flags = luaL_checkinteger(L, -1); + } + lua_pop(L, 1); + + X509V3_set_ctx(ctx, issuer, subject, request, crl, flags); + break; + } + default: + return luaL_argerror(L, 3, "invalid extra parameter (expected string, table or nil)"); } /* @@ -5257,7 +5420,7 @@ static int xc_getVersion(lua_State *L) { static int xc_setVersion(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); - int version = luaL_checkint(L, 2); + int version = luaL_checkinteger(L, 2); if (!X509_set_version(crt, version - 1)) return luaL_error(L, "x509.cert:setVersion: %d: invalid version", version); @@ -5804,11 +5967,11 @@ static int xc_setBasicConstraint(lua_State *L) { lua_pop(L, 1); lua_getfield(L, 2, "pathLen"); - pathLen = luaL_optint(L, -1, pathLen); + pathLen = luaL_optinteger(L, -1, pathLen); lua_pop(L, 1); lua_getfield(L, 2, "pathLenConstraint"); - pathLen = luaL_optint(L, -1, pathLen); + pathLen = luaL_optinteger(L, -1, pathLen); lua_pop(L, 1); if (!(bs = BASIC_CONSTRAINTS_new())) @@ -5825,7 +5988,7 @@ static int xc_setBasicConstraint(lua_State *L) { case 1: /* FALL THROUGH */ case 2: - pathLen = luaL_checkint(L, 3); + pathLen = luaL_checkinteger(L, 3); break; } @@ -5947,6 +6110,40 @@ static int xc_getExtensionCount(lua_State *L) { } /* xc_getExtensionCount() */ +static int sk_openssl_string__gc(lua_State *L) { + STACK_OF(OPENSSL_STRING) **res = lua_touserdata(L, 1); + + if (*res) { + sk_OPENSSL_STRING_free(*res); + *res = NULL; + } + + return 0; +} /* sk_openssl_string__gc() */ + + +static int xc_getOCSP(lua_State *L) { + X509 *crt = checksimple(L, 1, X509_CERT_CLASS); + STACK_OF(OPENSSL_STRING) **res = prepsimple(L, NULL, &sk_openssl_string__gc); + int num, i; + + *res = X509_get1_ocsp(crt); + if (!*res) + return 0; + + num = sk_OPENSSL_STRING_num(*res); + luaL_checkstack(L, num, "too many authorityInfoAccess"); + for (i = 0; i < num; i++) { + lua_pushstring(L, sk_OPENSSL_STRING_value(*res, i)); + } + + sk_OPENSSL_STRING_free(*res); + *res = NULL; + + return num; +} /* xc_getOCSP */ + + static int xc_isIssuedBy(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); X509 *issuer = checksimple(L, 2, X509_CERT_CLASS); @@ -6029,23 +6226,17 @@ static int xc_getPublicKeyDigest(lua_State *L) { } /* xc_getPublicKeyDigest() */ -#if 0 -/* - * TODO: X509_get_signature_type always seems to return NID_undef. Are we - * using it wrong or is it broken? - */ static int xc_getSignatureName(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); int nid; - if (NID_undef == (nid = X509_get_signature_type(crt))) + if (NID_undef == (nid = X509_get_signature_nid(crt))) return 0; auxL_pushnid(L, nid); return 1; } /* xc_getSignatureName() */ -#endif static int xc_sign(lua_State *L) { @@ -6188,13 +6379,12 @@ static const auxL_Reg xc_methods[] = { { "addExtension", &xc_addExtension }, { "getExtension", &xc_getExtension }, { "getExtensionCount", &xc_getExtensionCount }, + { "getOCSP", &xc_getOCSP }, { "isIssuedBy", &xc_isIssuedBy }, { "getPublicKey", &xc_getPublicKey }, { "setPublicKey", &xc_setPublicKey }, { "getPublicKeyDigest", &xc_getPublicKeyDigest }, -#if 0 { "getSignatureName", &xc_getSignatureName }, -#endif { "sign", &xc_sign }, { "text", &xc_text }, { "tostring", &xc__tostring }, @@ -6286,7 +6476,7 @@ static int xr_getVersion(lua_State *L) { static int xr_setVersion(lua_State *L) { X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); - int version = luaL_checkint(L, 2); + int version = luaL_checkinteger(L, 2); if (!X509_REQ_set_version(csr, version - 1)) return luaL_error(L, "x509.csr:setVersion: %d: invalid version", version); @@ -6591,7 +6781,7 @@ static int xx_getVersion(lua_State *L) { static int xx_setVersion(lua_State *L) { X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); - int version = luaL_checkint(L, 2); + int version = luaL_checkinteger(L, 2); if (!X509_CRL_set_version(crl, version - 1)) return luaL_error(L, "x509.crl:setVersion: %d: invalid version", version); @@ -6642,7 +6832,7 @@ static int xx_getNextUpdate(lua_State *L) { updateby = timeutc(time); if (isfinite(updateby)) - lua_pushnumber(L, 1); + lua_pushnumber(L, updateby); else lua_pushnil(L); @@ -6832,6 +7022,19 @@ static int xx_sign(lua_State *L) { } /* xx_sign() */ +static int xx_verify(lua_State *L) { + X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); + EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS); + + if (!X509_CRL_verify(crl, key)) + return auxL_error(L, auxL_EOPENSSL, "x509.crl:verify"); + + lua_pushboolean(L, 1); + + return 1; +} /* xx_verify() */ + + static int xx_text(lua_State *L) { X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); @@ -6901,6 +7104,7 @@ static const auxL_Reg xx_methods[] = { { "getExtension", &xx_getExtension }, { "getExtensionCount", &xx_getExtensionCount }, { "sign", &xx_sign }, + { "verify", &xx_verify }, { "text", &xx_text }, { "tostring", &xx__tostring }, { NULL, NULL }, @@ -7180,7 +7384,7 @@ static int xs_verify(lua_State *L) { X509 *crt = checksimple(L, 2, X509_CERT_CLASS); STACK_OF(X509) *chain = NULL, **proof; X509_STORE_CTX *ctx = NULL; - int nr = 0, ok, why; + int ok, why; /* pre-allocate space for a successful return */ lua_settop(L, 3); @@ -7215,27 +7419,24 @@ static int xs_verify(lua_State *L) { case 1: /* verified */ if (!(*proof = X509_STORE_CTX_get1_chain(ctx))) goto eossl; + X509_STORE_CTX_free(ctx); lua_pushboolean(L, 1); lua_pushvalue(L, -2); - nr = 2; - break; + return 2; case 0: /* not verified */ why = X509_STORE_CTX_get_error(ctx); + X509_STORE_CTX_free(ctx); lua_pushboolean(L, 0); lua_pushstring(L, X509_verify_cert_error_string(why)); - nr = 2; - break; + return 2; default: goto eossl; } - X509_STORE_CTX_free(ctx); - - return nr; eossl: if (ctx) X509_STORE_CTX_free(ctx); @@ -7428,6 +7629,57 @@ static int p12_interpose(lua_State *L) { } /* p12_interpose() */ +static int p12_parse(lua_State *L) { + /* parse a p12 binary string and return the parts */ + PKCS12 *p12; + + /* gather input parameters */ + size_t len; + const char *blob = luaL_checklstring(L, 1, &len); + const char *passphrase = luaL_optstring(L, 2, NULL); + + /* prepare return values */ + EVP_PKEY **ud_pkey = prepsimple(L, PKEY_CLASS); + X509 **ud_cert = prepsimple(L, X509_CERT_CLASS); + STACK_OF(X509) **ud_chain = prepsimple(L, X509_CHAIN_CLASS); + /* Note: *ud_chain must be initialised to NULL, which prepsimple does. */ + + /* read PKCS#12 data into OpenSSL memory buffer */ + BIO *bio = BIO_new_mem_buf((void*)blob, len); + if (!bio) + return auxL_error(L, auxL_EOPENSSL, "pkcs12.parse"); + p12 = d2i_PKCS12_bio(bio, NULL); + BIO_free(bio); + if (!p12) + return auxL_error(L, auxL_EOPENSSL, "pkcs12.parse"); + + /* the p12 pointer holds the data we're interested in */ + int rc = PKCS12_parse(p12, passphrase, ud_pkey, ud_cert, ud_chain); + PKCS12_free(p12); + if (!rc) + auxL_error(L, auxL_EOPENSSL, "pkcs12.parse"); + + /* replace the return values by nil if the ud pointers are NULL */ + if (*ud_pkey == NULL) { + lua_pushnil(L); + lua_replace(L, -4); + } + + if (*ud_cert == NULL) { + lua_pushnil(L); + lua_replace(L, -3); + } + + /* other certificates (a chain, STACK_OF(X509) *) */ + if (*ud_chain == NULL) { + lua_pop(L, 1); + lua_pushnil(L); + } + + return 3; +} /* p12_parse() */ + + static int p12__tostring(lua_State *L) { PKCS12 *p12 = checksimple(L, 1, PKCS12_CLASS); BIO *bio = getbio(L); @@ -7471,6 +7723,7 @@ static const auxL_Reg p12_metatable[] = { static const auxL_Reg p12_globals[] = { { "new", &p12_new }, { "interpose", &p12_interpose }, + { "parse", &p12_parse }, { NULL, NULL }, }; @@ -7690,8 +7943,8 @@ static int sx_getParam(lua_State *L) { static int sx_setVerify(lua_State *L) { SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); - int mode = luaL_optint(L, 2, -1); - int depth = luaL_optint(L, 3, -1); + int mode = luaL_optinteger(L, 2, -1); + int depth = luaL_optinteger(L, 3, -1); if (mode != -1) SSL_CTX_set_verify(ctx, mode, 0); @@ -7855,9 +8108,8 @@ static int sx_setAlpnProtos(lua_State *L) { } /* sx_setAlpnProtos() */ #endif -#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB -static SSL *ssl_push(lua_State *, SSL *); +#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) { SSL_CTX *ctx = _ctx; lua_State *L = NULL; @@ -7875,12 +8127,12 @@ static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned cha otop = lua_gettop(L) - n; - /* TODO: Install temporary panic handler to catch OOM errors */ - /* pass SSL object as 1st argument */ - ssl_push(L, ssl); + if (ssl_pushsafe(L, ssl)) + goto fatal; lua_insert(L, otop + 3); + /* TODO: Install temporary panic handler to catch OOM errors */ /* pass table of protocol names as 2nd argument */ pushprotos(L, in, inlen); lua_insert(L, otop + 4); @@ -7952,6 +8204,116 @@ static int sx_setAlpnSelect(lua_State *L) { #endif +#if HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK +static int sx_setHostNameCallback_cb(SSL *ssl, int *ad, void *_ctx) { + SSL_CTX *ctx = _ctx; + lua_State *L = NULL; + size_t n; + int otop, status, ret = SSL_TLSEXT_ERR_ALERT_FATAL; + + *ad = SSL_AD_INTERNAL_ERROR; + + /* expect at least one value: closure */ + if ((n = ex_getdata(&L, EX_SSL_CTX_TLSEXT_SERVERNAME_CB, ctx)) < 1) + return SSL_TLSEXT_ERR_ALERT_FATAL; + + otop = lua_gettop(L) - n; + + /* pass SSL object as 1st argument */ + if (ssl_pushsafe(L, ssl)) + goto done; + + lua_insert(L, otop + 2); + + if (LUA_OK != (status = lua_pcall(L, 1 + (n - 1), 2, 0))) + goto done; + + /* callback should return a boolean for OK/NOACK + * or nil + an integer for a controlled error + * everything else will be a fatal internal error + */ + if (lua_isboolean(L, -2)) { + ret = lua_toboolean(L, -2) ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK; + } else { + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + if (lua_isnil(L, -2) && lua_isinteger(L, -1)) + *ad = lua_tointeger(L, -1); + } + +done: + lua_settop(L, otop); + + return ret; +} /* sx_setHostNameCallback_cb() */ + + +static int sx_setHostNameCallback(lua_State *L) { + SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); + int error; + + luaL_checktype(L, 2, LUA_TFUNCTION); + + if ((error = ex_setdata(L, EX_SSL_CTX_TLSEXT_SERVERNAME_CB, ctx, lua_gettop(L) - 1))) { + if (error > 0) { + return luaL_error(L, "unable to set hostname selection callback: %s", aux_strerror(error)); + } else if (error == auxL_EOPENSSL && !ERR_peek_error()) { + return luaL_error(L, "unable to set hostname selection callback: Unknown internal error"); + } else { + return auxL_error(L, error, "ssl.context:setHostNameCallback"); + } + } + SSL_CTX_set_tlsext_servername_callback(ctx, sx_setHostNameCallback_cb); + SSL_CTX_set_tlsext_servername_arg(ctx, ctx); + + lua_pushboolean(L, 1); + + return 1; +} /* sx_setHostNameCallback() */ +#endif + + +int TLSEXT_STATUSTYPEs[] = { TLSEXT_STATUSTYPE_ocsp }; +const char *TLSEXT_STATUSTYPEs_names[] = { "ocsp", NULL }; +#define checkTLSEXT_STATUSTYPE(L, idx) \ + (TLSEXT_STATUSTYPEs[luaL_checkoption((L), (idx), NULL, TLSEXT_STATUSTYPEs_names)]) + + +#if HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE +static int sx_setTLSextStatusType(lua_State *L) { + SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); + int type = checkTLSEXT_STATUSTYPE(L, 2); + + if(!SSL_CTX_set_tlsext_status_type(ctx, type)) + return auxL_error(L, auxL_EOPENSSL, "ssl.context:setTLSextStatusType"); + + lua_pushboolean(L, 1); + + return 1; +} /* sx_setTLSextStatusType() */ +#endif + + +#if HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE +static int sx_getTLSextStatusType(lua_State *L) { + SSL_CTX *ctx = checksimple(L, 1, SSL_CLASS); + + int type = SSL_CTX_get_tlsext_status_type(ctx); + switch(type) { + case -1: + lua_pushnil(L); + break; + case TLSEXT_STATUSTYPE_ocsp: + lua_pushliteral(L, "ocsp"); + break; + default: + luaL_error(L, "unknown TLS extension %d", type); + } + + return 1; +} /* sx_getTLSextStatusType() */ +#endif + + static int sx__gc(lua_State *L) { SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); @@ -7987,6 +8349,15 @@ static const auxL_Reg sx_methods[] = { #if HAVE_SSL_CTX_SET_ALPN_SELECT_CB { "setAlpnSelect", &sx_setAlpnSelect }, #endif +#if HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK + { "setHostNameCallback", &sx_setHostNameCallback }, +#endif +#if HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE + { "setTLSextStatusType", &sx_setTLSextStatusType }, +#endif +#if HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE + { "getTLSextStatusType", &sx_getTLSextStatusType }, +#endif { NULL, NULL }, }; @@ -8098,6 +8469,18 @@ static int ssl_interpose(lua_State *L) { } /* ssl_interpose() */ +static int ssl_setContext(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + SSL_CTX *ctx = checksimple(L, 2, SSL_CTX_CLASS); + + if (!SSL_set_SSL_CTX(ssl, ctx)) + return auxL_error(L, auxL_EOPENSSL, "ssl.setContext"); + + lua_pushboolean(L, 1); + + return 1; +} /* ssl_setContext() */ + static int ssl_setOptions(lua_State *L) { SSL *ssl = checksimple(L, 1, SSL_CLASS); auxL_Integer options = auxL_checkinteger(L, 2); @@ -8159,6 +8542,33 @@ static int ssl_getParam(lua_State *L) { } /* ssl_getParam() */ +static int ssl_setVerify(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + int mode = luaL_optinteger(L, 2, -1); + int depth = luaL_optinteger(L, 3, -1); + + if (mode != -1) + SSL_set_verify(ssl, mode, 0); + + if (depth != -1) + SSL_set_verify_depth(ssl, depth); + + lua_pushboolean(L, 1); + + return 1; +} /* ssl_setVerify() */ + + +static int ssl_getVerify(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + + lua_pushinteger(L, SSL_get_verify_mode(ssl)); + lua_pushinteger(L, SSL_get_verify_depth(ssl)); + + return 2; +} /* ssl_getVerify() */ + + static int ssl_getVerifyResult(lua_State *L) { SSL *ssl = checksimple(L, 1, SSL_CLASS); long res = SSL_get_verify_result(ssl); @@ -8168,6 +8578,44 @@ static int ssl_getVerifyResult(lua_State *L) { } /* ssl_getVerifyResult() */ +static int ssl_setCertificate(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + X509 *crt = X509_dup(checksimple(L, 2, X509_CERT_CLASS)); + int ok; + + ok = SSL_use_certificate(ssl, crt); + X509_free(crt); + + if (!ok) + return auxL_error(L, auxL_EOPENSSL, "ssl:setCertificate"); + + lua_pushboolean(L, 1); + + return 1; +} /* ssl_setCertificate() */ + + +static int ssl_setPrivateKey(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS); + /* + * NOTE: No easy way to dup the key, but a shared reference should + * be okay as keys are less mutable than certificates. + * + * FIXME: SSL_use_PrivateKey will return true even if the + * EVP_PKEY object has no private key. Instead, we'll just get a + * segfault during the SSL handshake. We need to check that a + * private key is actually defined in the object. + */ + if (!SSL_use_PrivateKey(ssl, key)) + return auxL_error(L, auxL_EOPENSSL, "ssl:setPrivateKey"); + + lua_pushboolean(L, 1); + + return 1; +} /* ssl_setPrivateKey() */ + + static int ssl_getPeerCertificate(lua_State *L) { SSL *ssl = checksimple(L, 1, SSL_CLASS); X509 **x509 = prepsimple(L, X509_CERT_CLASS); @@ -8284,6 +8732,31 @@ static int ssl_getVersion(lua_State *L) { } /* ssl_getVersion() */ +static int ssl_getClientRandom(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + luaL_Buffer B; + size_t len; + unsigned char *out; + + len = SSL_get_client_random(ssl, NULL, 0); +#if LUA_VERSION_NUM < 502 + if (LUAL_BUFFERSIZE < len) + luaL_error(L, "ssl:getClientRandom: LUAL_BUFFERSIZE(%d) < SSL_get_client_random(ssl, NULL, 0)", (int)LUAL_BUFFERSIZE, (int)len); + luaL_buffinit(L, &B); + out = (unsigned char*)luaL_prepbuffer(&B); + len = SSL_get_client_random(ssl, out, len); + luaL_addsize(&B, len); + luaL_pushresult(&B); +#else + out = (unsigned char*)luaL_buffinitsize(L, &B, len); + len = SSL_get_client_random(ssl, out, len); + luaL_pushresultsize(&B, len); +#endif + + return 1; +} /* ssl_getClientRandom() */ + + static int ssl_getClientVersion(lua_State *L) { SSL *ssl = checksimple(L, 1, SSL_CLASS); int format = luaL_checkoption(L, 2, "d", (const char *[]){ "d", ".", "f", NULL }); @@ -8354,6 +8827,87 @@ static int ssl_setAlpnProtos(lua_State *L) { #endif +static int ssl_setTLSextStatusType(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + int type = checkTLSEXT_STATUSTYPE(L, 2); + + if(!SSL_set_tlsext_status_type(ssl, type)) + return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusType"); + + lua_pushboolean(L, 1); + + return 1; +} /* ssl_setTLSextStatusType() */ + + +#if HAVE_SSL_GET_TLSEXT_STATUS_TYPE +static int ssl_getTLSextStatusType(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + + int type = SSL_get_tlsext_status_type(ssl); + switch(type) { + case -1: + lua_pushnil(L); + break; + case TLSEXT_STATUSTYPE_ocsp: + lua_pushliteral(L, "ocsp"); + break; + default: + luaL_error(L, "unknown TLS extension %d", type); + } + + return 1; +} /* ssl_getTLSextStatusType() */ +#endif + + +static int ssl_setTLSextStatusOCSPResp(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + OCSP_RESPONSE *or = testsimple(L, 2, OCSP_RESPONSE_CLASS); + + unsigned char *resp = NULL; + long resp_len; + + if (or) { + resp_len = i2d_OCSP_RESPONSE(or, &resp); + if (resp_len <= 0) + return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusOCSPResp"); + } else { + resp_len = 0; + } + + if (!SSL_set_tlsext_status_ocsp_resp(ssl, resp, resp_len)) + return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusOCSPResp"); + + lua_pushboolean(L, 1); + + return 1; +} /* ssl_setTLSextStatusOCSPResp() */ + + +static int ssl_getTLSextStatusOCSPResp(lua_State *L) { + SSL *ssl = checksimple(L, 1, SSL_CLASS); + + OCSP_RESPONSE **ud = prepsimple(L, OCSP_RESPONSE_CLASS); + const unsigned char *resp; + long resp_len; + + resp_len = SSL_get_tlsext_status_ocsp_resp(ssl, &resp); + if (resp == NULL) { + lua_pushnil(L); + return 1; + } + if (resp_len == -1) + return auxL_error(L, auxL_EOPENSSL, "ssl:getTLSextStatusOCSPResp"); + + *ud = d2i_OCSP_RESPONSE(NULL, &resp, resp_len); + if(*ud == NULL) + return auxL_error(L, auxL_EOPENSSL, "ssl:getTLSextStatusOCSPResp"); + + return 1; +} /* ssl_getTLSextStatusOCSPResp() */ + + static int ssl__gc(lua_State *L) { SSL **ud = luaL_checkudata(L, 1, SSL_CLASS); @@ -8367,12 +8921,17 @@ static int ssl__gc(lua_State *L) { static const auxL_Reg ssl_methods[] = { + { "setContext", &ssl_setContext }, { "setOptions", &ssl_setOptions }, { "getOptions", &ssl_getOptions }, { "clearOptions", &ssl_clearOptions }, { "setParam", &ssl_setParam }, { "getParam", &ssl_getParam }, + { "setVerify", &ssl_setVerify }, + { "getVerify", &ssl_getVerify }, { "getVerifyResult", &ssl_getVerifyResult }, + { "setCertificate", &ssl_setCertificate }, + { "setPrivateKey", &ssl_setPrivateKey }, { "getPeerCertificate", &ssl_getPeerCertificate }, { "getPeerChain", &ssl_getPeerChain }, { "getCipherInfo", &ssl_getCipherInfo }, @@ -8382,6 +8941,7 @@ static const auxL_Reg ssl_methods[] = { { "getHostName", &ssl_getHostName }, { "setHostName", &ssl_setHostName }, { "getVersion", &ssl_getVersion }, + { "getClientRandom", &ssl_getClientRandom }, { "getClientVersion", &ssl_getClientVersion }, #if HAVE_SSL_GET0_ALPN_SELECTED { "getAlpnSelected", &ssl_getAlpnSelected }, @@ -8389,6 +8949,12 @@ static const auxL_Reg ssl_methods[] = { #if HAVE_SSL_SET_ALPN_PROTOS { "setAlpnProtos", &ssl_setAlpnProtos }, #endif + { "setTLSextStatusType", &ssl_setTLSextStatusType }, +#if HAVE_SSL_GET_TLSEXT_STATUS_TYPE + { "getTLSextStatusType", &ssl_getTLSextStatusType }, +#endif + { "setTLSextStatusOCSPResp", &ssl_setTLSextStatusOCSPResp }, + { "getTLSextStatusOCSPResp", &ssl_getTLSextStatusOCSPResp }, { NULL, NULL }, }; @@ -9126,6 +9692,166 @@ int luaopen__openssl_cipher(lua_State *L) { /* + * OCSP_RESPONSE - openssl.ocsp.response + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static int or_tostring(lua_State *L) { + OCSP_RESPONSE *resp = checksimple(L, 1, OCSP_RESPONSE_CLASS); + BIO *bio = getbio(L); + size_t len; + char *bytes; + + if (!OCSP_RESPONSE_print(bio, resp, 0)) + return auxL_error(L, auxL_EOPENSSL, "OCSP_RESPONSE:tostring"); + + len = BIO_get_mem_data(bio, &bytes); + lua_pushlstring(L, bytes, len); + + return 1; +} /* or__tostring() */ + + +static int or_toPEM(lua_State *L) { + OCSP_RESPONSE *resp = checksimple(L, 1, OCSP_RESPONSE_CLASS); + BIO *bio = getbio(L); + size_t len; + char *bytes; + + if (!PEM_write_bio_OCSP_RESPONSE(bio, resp)) + return auxL_error(L, auxL_EOPENSSL, "OCSP_RESPONSE:toPEM"); + + len = BIO_get_mem_data(bio, &bytes); + lua_pushlstring(L, bytes, len); + + return 1; +} /* or_toPEM() */ + + +static int or_getBasic(lua_State *L) { + OCSP_RESPONSE *resp = checksimple(L, 1, OCSP_RESPONSE_CLASS); + + OCSP_BASICRESP **basic = prepsimple(L, OCSP_BASICRESP_CLASS); + + *basic = OCSP_response_get1_basic(resp); + if (!*basic) + return auxL_error(L, auxL_EOPENSSL, "OCSP_RESPONSE:getBasic"); + + return 1; +} /* or_getBasic() */ + + +static int or__gc(lua_State *L) { + OCSP_RESPONSE **ud = luaL_checkudata(L, 1, OCSP_RESPONSE_CLASS); + + if (*ud) { + OCSP_RESPONSE_free(*ud); + *ud = NULL; + } + + return 0; +} /* or__gc() */ + +static const auxL_Reg or_methods[] = { + { "tostring", &or_tostring }, + { "toPEM", &or_toPEM }, + { "getBasic", &or_getBasic }, + { NULL, NULL }, +}; + +static const auxL_Reg or_metatable[] = { + { "__tostring", &or_tostring }, + { "__gc", &or__gc }, + { NULL, NULL }, +}; + +static const auxL_Reg or_globals[] = { + { NULL, NULL }, +}; + +int luaopen__openssl_ocsp_response(lua_State *L) { + initall(L); + + auxL_newlib(L, or_globals, 0); + + return 1; +} /* luaopen__openssl_ocsp_response() */ + + +/* + * OCSP_BASICRESP - openssl.ocsp.basic + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static int ob_verify(lua_State *L) { + OCSP_BASICRESP *basic = checksimple(L, 1, OCSP_BASICRESP_CLASS); + STACK_OF(X509) *certs = testsimple(L, 2, X509_CHAIN_CLASS); + X509_STORE *store = testsimple(L, 3, X509_STORE_CLASS); + unsigned long flags = luaL_optinteger(L, 4, 0); + + int res = OCSP_basic_verify(basic, certs, store, flags); + if (res == -1) + return auxL_error(L, auxL_EOPENSSL, "OCSP_BASICRESP:verify"); + + lua_pushboolean(L, res); + if (res) { + return 1; + } else { + auxL_pusherror(L, auxL_EOPENSSL, NULL); + return 2; + } +} /* ob_verify() */ + + +static int ob__gc(lua_State *L) { + OCSP_BASICRESP **ud = luaL_checkudata(L, 1, OCSP_BASICRESP_CLASS); + + if (*ud) { + OCSP_BASICRESP_free(*ud); + *ud = NULL; + } + + return 0; +} /* or__gc() */ + + +static const auxL_Reg ob_methods[] = { + { "verify", &ob_verify }, + { NULL, NULL }, +}; + +static const auxL_Reg ob_metatable[] = { + { "__gc", &ob__gc }, + { NULL, NULL }, +}; + +static const auxL_Reg ob_globals[] = { + { NULL, NULL }, +}; + +static const auxL_IntegerReg ob_verify_flags[] = { + { "NOSIGS", OCSP_NOSIGS}, + { "NOVERIFY", OCSP_NOVERIFY}, + { "NOCHAIN", OCSP_NOCHAIN}, + { "NOCHECKS", OCSP_NOCHECKS}, + { "NOEXPLICIT", OCSP_NOEXPLICIT}, + { "TRUSTOTHER", OCSP_TRUSTOTHER}, + { "NOINTERN", OCSP_NOINTERN}, + { "TRUSTOTHER", OCSP_TRUSTOTHER}, + { NULL, 0 }, +}; + +int luaopen__openssl_ocsp_basic(lua_State *L) { + initall(L); + + auxL_newlib(L, ob_globals, 0); + auxL_setintegers(L, ob_verify_flags); + + return 1; +} /* luaopen__openssl_ocsp_basic() */ + + +/* * Rand - openssl.rand * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -9322,7 +10048,7 @@ static int rand_add(lua_State *L) { static int rand_bytes(lua_State *L) { - int size = luaL_checkint(L, 1); + int size = luaL_checkinteger(L, 1); luaL_Buffer B; int count = 0, n; @@ -9438,11 +10164,7 @@ static int rand_uniform(lua_State *L) { } else { unsigned long long N, m; - if (sizeof (lua_Unsigned) >= sizeof r) { - N = luaL_checkunsigned(L, 1); - } else { - N = luaL_checknumber(L, 1); - } + N = auxL_checkunsigned(L, 1); luaL_argcheck(L, N > 1, 1, lua_pushfstring(L, "[0, %d): interval is empty", (int)N)); @@ -9455,11 +10177,7 @@ static int rand_uniform(lua_State *L) { r = r % N; } - if (sizeof (lua_Unsigned) >= sizeof r) { - lua_pushunsigned(L, r); - } else { - lua_pushnumber(L, r); - } + auxL_pushunsigned(L, r); return 1; } /* rand_uniform() */ @@ -9690,5 +10408,7 @@ static void initall(lua_State *L) { auxL_addclass(L, DIGEST_CLASS, md_methods, md_metatable, 0); auxL_addclass(L, HMAC_CLASS, hmac_methods, hmac_metatable, 0); auxL_addclass(L, CIPHER_CLASS, cipher_methods, cipher_metatable, 0); + auxL_addclass(L, OCSP_RESPONSE_CLASS, or_methods, or_metatable, 0); + auxL_addclass(L, OCSP_BASICRESP_CLASS, ob_methods, ob_metatable, 0); } /* initall() */ diff --git a/src/openssl.ocsp.basic.lua b/src/openssl.ocsp.basic.lua new file mode 100644 index 0000000..355faf7 --- /dev/null +++ b/src/openssl.ocsp.basic.lua @@ -0,0 +1,3 @@ +local ob = require "_openssl.ocsp.basic" + +return ob diff --git a/src/openssl.ocsp.response.lua b/src/openssl.ocsp.response.lua new file mode 100644 index 0000000..2226096 --- /dev/null +++ b/src/openssl.ocsp.response.lua @@ -0,0 +1,3 @@ +local ocsp_response = require "_openssl.ocsp.response" + +return ocsp_response |