From 3d7180c36adb6b9be8f4bb9825d3e35eef146bf5 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 27 Feb 2017 15:23:05 +1100
Subject: extension.new: Factor out conf loading to own function

---
 src/openssl.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index fa7dd79..900b909 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -4958,6 +4958,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);
@@ -4991,13 +5010,7 @@ static int xe_new(lua_State *L) {
 			return 1;
 		}
 
-		BIO *bio = getbio(L);
-		if (BIO_puts(bio, cdata) < 0)
-			goto error;
-
-		if (!(conf = NCONF_new(NULL)))
-			goto error;
-		if (!NCONF_load_bio(conf, bio, NULL))
+		if (!(conf = loadconf(L, 3)))
 			goto error;
 
 		ctx = &cbuf;
-- 
cgit v1.2.3-59-g8ed1b


From 25337767bfb8d8d40c142e4acc6bc11116b15266 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 27 Feb 2017 15:24:28 +1100
Subject: extension.new: Swap to switch/case based argument checking

---
 src/openssl.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 900b909..9ea9469 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -4989,9 +4989,13 @@ static int xe_new(lua_State *L) {
 	lua_settop(L, 3);
 	ud = prepsimple(L, X509_EXT_CLASS);
 
-	if (!lua_isnil(L, 3)) {
+	switch (lua_type(L, 3)) {
+	case LUA_TNONE:
+	case LUA_TNIL:
+		break;
+	case LUA_TSTRING: {
 		size_t len;
-		const char *cdata = luaL_checklstring(L, 3, &len);
+		const char *cdata = lua_tolstring(L, 3, &len);
 		_Bool crit;
 
 		if (xe_new_isder(value, &crit)) {
@@ -5015,6 +5019,10 @@ static int xe_new(lua_State *L) {
 
 		ctx = &cbuf;
 		X509V3_set_nconf(ctx, conf);
+		break;
+	}
+	default:
+		return luaL_argerror(L, 3, "invalid extra parameter (expected string or nil)");
 	}
 
 	/*
-- 
cgit v1.2.3-59-g8ed1b


From 419494337e30fa3fa539990e8ae7c314ce01eaab Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 27 Feb 2017 15:25:10 +1100
Subject: Add lua_getfield compatibility macro that returns the type (as it
 does in 5.3)

---
 src/compat52.h | 8 ++++++++
 src/openssl.c  | 2 --
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/compat52.h b/src/compat52.h
index 0057b3c..22541f7 100644
--- a/src/compat52.h
+++ b/src/compat52.h
@@ -23,6 +23,14 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  * ==========================================================================
  */
+
+
+#if LUA_VERSION_NUM < 503
+
+#define lua_getfield(L, i, f) (lua_getfield(L, (i), (f)), lua_type(L, -1))
+
+#endif
+
 #if LUA_VERSION_NUM < 502
 
 #define LUA_OK 0
diff --git a/src/openssl.c b/src/openssl.c
index 9ea9469..1307852 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -74,9 +74,7 @@
 #include <lualib.h>
 #include <lauxlib.h>
 
-#if LUA_VERSION_NUM < 502
 #include "compat52.h"
-#endif
 
 #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)))
-- 
cgit v1.2.3-59-g8ed1b


From 42018dfc1c1a3baee7b7e2aaa3cf21554341a61e Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 27 Feb 2017 15:25:43 +1100
Subject: extension.new: Add table form for extra argument

---
 src/openssl.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/openssl.c b/src/openssl.c
index 1307852..5835a0a 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -5019,8 +5019,52 @@ static int xe_new(lua_State *L) {
 		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);
+
+		if (lua_getfield(L, 3, "issuer") != LUA_TNIL) {
+			issuer = checksimple(L, -1, X509_CERT_CLASS);
+		}
+		lua_pop(L, 1);
+
+		if (lua_getfield(L, 3, "subject") != LUA_TNIL) {
+			subject = checksimple(L, -1, X509_CERT_CLASS);
+		}
+		lua_pop(L, 1);
+
+		if (lua_getfield(L, 3, "request") != LUA_TNIL) {
+			request = checksimple(L, -1, X509_CSR_CLASS);
+		}
+		lua_pop(L, 1);
+
+		if (lua_getfield(L, 3, "crl") != LUA_TNIL) {
+			crl = checksimple(L, -1, X509_CRL_CLASS);
+		}
+		lua_pop(L, 1);
+
+		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 or nil)");
+		return luaL_argerror(L, 3, "invalid extra parameter (expected string, table or nil)");
 	}
 
 	/*
-- 
cgit v1.2.3-59-g8ed1b


From a0846fc69bb3e56bf3647f97c8e3ff1df8eacb2e Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 3 Apr 2017 16:20:54 +1000
Subject: Move value='DER' check out of type dispatch in xe_new

---
 src/openssl.c | 39 +++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 5835a0a..a11e6ae 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -4983,35 +4983,34 @@ 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);
 
-	switch (lua_type(L, 3)) {
-	case LUA_TNONE:
-	case LUA_TNIL:
-		break;
-	case LUA_TSTRING: {
+	if (xe_new_isder(value, &crit)) {
 		size_t len;
 		const char *cdata = lua_tolstring(L, 3, &len);
-		_Bool crit;
-
-		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)))
-				goto error;
+		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;
 
-			ASN1_OBJECT_free(obj);
-			ASN1_STRING_free(oct);
+		ASN1_OBJECT_free(obj);
+		ASN1_STRING_free(oct);
 
-			return 1;
-		}
+		return 1;
+	}
 
+	switch (lua_type(L, 3)) {
+	case LUA_TNONE:
+	case LUA_TNIL:
+		break;
+	case LUA_TSTRING: {
 		if (!(conf = loadconf(L, 3)))
 			goto error;
 
-- 
cgit v1.2.3-59-g8ed1b


From 25ad97c7be75b2d6e7ae677506b1b47ce760d46a Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 3 Apr 2017 16:43:12 +1000
Subject: Document table form of extension.new() data argument

---
 doc/luaossl.tex | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/doc/luaossl.tex b/doc/luaossl.tex
index 7db7463..5165b18 100644
--- a/doc/luaossl.tex
+++ b/doc/luaossl.tex
@@ -389,7 +389,19 @@ Binds the X.509 extension OpenSSL object.
 
 \subsubsection[\fn{extension.new}]{\fn{extension.new($name$, $value$ [, $data$])}}
 
-Returns a new X.509 extension. If $value$ is the string ``DER'' or ``critical,DER'', then $data$ is an ASN.1-encoded octet string. Otherwise, $name$ and $value$ are plain text strings in \href{https://www.openssl.org/docs/apps/x509v3_config.html#ARBITRARY_EXTENSIONS}{OpenSSL's arbitrary extension format}; and if specified, $data$ is an OpenSSL configuration string defining any referenced identifiers in $value$.
+Returns a new X.509 extension.
+If $value$ is the string ``DER'' or ``critical,DER'', then $data$ is an ASN.1-encoded octet string.
+Otherwise, $name$ and $value$ are plain text strings in \href{https://www.openssl.org/docs/apps/x509v3_config.html#ARBITRARY_EXTENSIONS}{OpenSSL's arbitrary extension format}; and if specified, $data$ is either an OpenSSL configuration string defining any referenced identifiers in $value$, or a table with members:
+
+\begin{ctabular}{ l | l | p{8cm} }
+field & type:default & description\\\hline
+.db & string:$nil$ & OpenSSL configuration string\\
+.issuer & \module{openssl.x509}:$nil$ & issuer certificate\\
+.subject & \module{openssl.x509}:$nil$ & subject certificate\\
+.request & \module{openssl.x509.csr}:$nil$ & certificate signing request\\
+.crl & \module{openssl.x509.crl}:$nil$ & certificate revocation list\\
+.flags & integer:$0$ & a bitwise combination of flags
+\end{ctabular}
 
 \subsubsection[\fn{extension.interpose}]{\fn{extension.interpose($name$, $function$)}}
 
-- 
cgit v1.2.3-59-g8ed1b