aboutsummaryrefslogtreecommitdiffstats
path: root/src/openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openssl.c')
-rw-r--r--src/openssl.c575
1 files changed, 476 insertions, 99 deletions
diff --git a/src/openssl.c b/src/openssl.c
index 9fc5b97..1b11207 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -75,7 +75,7 @@
#include <lualib.h>
#include <lauxlib.h>
-#include "compat52.h"
+#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)))
@@ -83,11 +83,16 @@
#define MSC_2VER(M, m, p) ((((M) + 6) * 10000000) + ((m) * 1000000) + (p))
#define MSC_PREREQ(M, m, p) (_MSC_FULL_VER > 0 && _MSC_FULL_VER >= MSC_2VER((M), (m), (p)))
-#define OPENSSL_PREREQ(M, m, p) \
- (OPENSSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)) && !defined LIBRESSL_VERSION_NUMBER)
-
+#ifdef LIBRESSL_VERSION_NUMBER
+#define OPENSSL_PREREQ(M, m, p) (0)
#define LIBRESSL_PREREQ(M, m, p) \
(LIBRESSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)))
+#else
+#define OPENSSL_PREREQ(M, m, p) \
+ (OPENSSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)))
+#define LIBRESSL_PREREQ(M, m, p) (0)
+#endif
+
#ifndef __has_builtin
#define __has_builtin(x) 0
@@ -146,7 +151,11 @@
#endif
#ifndef HAVE_DTLSV1_CLIENT_METHOD
-#define HAVE_DTLSV1_CLIENT_METHOD (!defined OPENSSL_NO_DTLS1)
+#ifdef OPENSSL_NO_DTLS1
+#define HAVE_DTLSV1_CLIENT_METHOD (0)
+#else
+#define HAVE_DTLSV1_CLIENT_METHOD (1)
+#endif
#endif
#ifndef HAVE_DTLSV1_SERVER_METHOD
@@ -154,7 +163,11 @@
#endif
#ifndef HAVE_DTLS_CLIENT_METHOD
-#define HAVE_DTLS_CLIENT_METHOD (OPENSSL_PREREQ(1,0,2) && !defined OPENSSL_NO_DTLS1)
+#ifdef OPENSSL_NO_DTLS1
+#define HAVE_DTLS_CLIENT_METHOD (0)
+#else
+#define HAVE_DTLS_CLIENT_METHOD OPENSSL_PREREQ(1,0,2)
+#endif
#endif
#ifndef HAVE_DTLS_SERVER_METHOD
@@ -162,7 +175,11 @@
#endif
#ifndef HAVE_DTLSV1_2_CLIENT_METHOD
-#define HAVE_DTLSV1_2_CLIENT_METHOD (OPENSSL_PREREQ(1,0,2) && !defined OPENSSL_NO_DTLS1)
+#ifdef OPENSSL_NO_DTLS1
+#define HAVE_DTLSV1_2_CLIENT_METHOD (0)
+#else
+#define HAVE_DTLSV1_2_CLIENT_METHOD OPENSSL_PREREQ(1,0,2)
+#endif
#endif
#ifndef HAVE_DTLSV1_2_SERVER_METHOD
@@ -229,10 +246,6 @@
#define HAVE_RSA_GET0_KEY OPENSSL_PREREQ(1,1,0)
#endif
-#ifndef HAVE_RSA_PKCS1_PSS_PADDING
-#define HAVE_RSA_PKCS1_PSS_PADDING (defined RSA_PKCS1_PSS_PADDING || OPENSSL_PREREQ(1,0,0) || LIBRESSL_PREREQ(2,0,0))
-#endif
-
#ifndef HAVE_RSA_SET0_CRT_PARAMS
#define HAVE_RSA_SET0_CRT_PARAMS OPENSSL_PREREQ(1,1,0)
#endif
@@ -253,6 +266,14 @@
#define HAVE_SSL_CTX_GET0_PARAM OPENSSL_PREREQ(1,0,2)
#endif
+#ifndef HAVE_SSL_CTX_SET_CURVES_LIST
+#define HAVE_SSL_CTX_SET_CURVES_LIST (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,5,1))
+#endif
+
+#ifndef HAVE_SSL_CTX_SET_ECDH_AUTO
+#define HAVE_SSL_CTX_SET_ECDH_AUTO ((OPENSSL_PREREQ(1,0,2) && !OPENSSL_PREREQ(1,1,0)) || LIBRESSL_PREREQ(2,1,2))
+#endif
+
#ifndef HAVE_SSL_CTX_SET_ALPN_PROTOS
#define HAVE_SSL_CTX_SET_ALPN_PROTOS (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,1,3))
#endif
@@ -261,6 +282,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
@@ -293,6 +318,10 @@
#define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS
#endif
+#ifndef HAVE_SSL_SET_CURVES_LIST
+#define HAVE_SSL_SET_CURVES_LIST (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,5,1))
+#endif
+
#ifndef HAVE_SSL_SET1_PARAM
#define HAVE_SSL_SET1_PARAM OPENSSL_PREREQ(1,0,2)
#endif
@@ -309,12 +338,32 @@
#define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0)
#endif
-#ifndef HAVE_SSLV2_CLIENT_METHOD
-#define HAVE_SSLV2_CLIENT_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2)
+#ifndef HAVE_SSL_OP_NO_SSL_MASK
+#define HAVE_SSL_OP_NO_SSL_MASK OPENSSL_PREREQ(1,0,2)
#endif
-#ifndef HAVE_SSLV2_SERVER_METHOD
-#define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2)
+#ifndef HAVE_SSL_OP_NO_DTLS_MASK
+#define HAVE_SSL_OP_NO_DTLS_MASK OPENSSL_PREREQ(1,1,0)
+#endif
+
+#ifndef HAVE_STACK_OPENSSL_STRING_FUNCS
+#define HAVE_STACK_OPENSSL_STRING_FUNCS (OPENSSL_PREREQ(1,0,0) || LIBRESSL_PREREQ(2,0,0))
+#endif
+
+#ifndef HAVE_X509_CRL_GET0_LASTUPDATE
+#define HAVE_X509_CRL_GET0_LASTUPDATE OPENSSL_PREREQ(1,1,0)
+#endif
+
+#ifndef HAVE_X509_CRL_GET0_NEXTUPDATE
+#define HAVE_X509_CRL_GET0_NEXTUPDATE OPENSSL_PREREQ(1,1,0)
+#endif
+
+#ifndef HAVE_X509_CRL_SET1_LASTUPDATE
+#define HAVE_X509_CRL_SET1_LASTUPDATE OPENSSL_PREREQ(1,1,0)
+#endif
+
+#ifndef HAVE_X509_CRL_SET1_NEXTUPDATE
+#define HAVE_X509_CRL_SET1_NEXTUPDATE OPENSSL_PREREQ(1,1,0)
#endif
#ifndef HAVE_X509_GET_SIGNATURE_NID
@@ -358,7 +407,11 @@
#endif
#ifndef STRERROR_R_CHAR_P
-#define STRERROR_R_CHAR_P (defined __GLIBC__ && (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)))
+#ifdef __GLIBC__
+#define STRERROR_R_CHAR_P (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))
+#else
+#define STRERROR_R_CHAR_P (0)
+#endif
#endif
#ifndef LIST_HEAD
@@ -678,6 +731,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
*
@@ -1623,6 +1714,22 @@ static int compat_SSL_up_ref(SSL *ssl) {
} /* compat_SSL_up_ref() */
#endif
+#if !HAVE_SSL_OP_NO_SSL_MASK
+/* SSL_OP_NO_SSL_MASK was introduced in 1.0.2
+ 1.0.1 had up to TLSv1_2
+ 0.9.8-1.0.0 had up to TLSv1
+*/
+#ifdef SSL_OP_NO_TLSv1_2
+#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
+#else
+#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1)
+#endif
+#endif
+
+#if !HAVE_SSL_OP_NO_DTLS_MASK && HAVE_DTLS_CLIENT_METHOD
+#define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2)
+#endif
+
#if !HAVE_SSL_CTX_GET0_PARAM
#define SSL_CTX_get0_param(ctx) compat_SSL_CTX_get0_param((ctx))
@@ -1639,6 +1746,12 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) {
} /* compat_SSL_CTX_set1_param() */
#endif
+#if !HAVE_STACK_OPENSSL_STRING_FUNCS
+#define sk_OPENSSL_STRING_num(s) sk_num(s)
+#define sk_OPENSSL_STRING_value(s, i) sk_value((s), (i))
+#define sk_OPENSSL_STRING_free(s) X509_email_free(s)
+#endif
+
#if !HAVE_X509_GET0_EXT
#define X509_get0_ext(crt, i) X509_get_ext((crt), (i))
#endif
@@ -1651,6 +1764,22 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) {
#define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i))
#endif
+#if !HAVE_X509_CRL_GET0_LASTUPDATE
+#define X509_CRL_get0_lastUpdate(crl) ((const ASN1_TIME*)X509_CRL_get_lastUpdate(crl))
+#endif
+
+#if !HAVE_X509_CRL_GET0_NEXTUPDATE
+#define X509_CRL_get0_nextUpdate(crl) ((const ASN1_TIME*)X509_CRL_get_nextUpdate(crl))
+#endif
+
+#if !HAVE_X509_CRL_SET1_LASTUPDATE
+#define X509_CRL_set1_lastUpdate(crl, s) X509_CRL_set_lastUpdate((crl), (ASN1_TIME*)(s))
+#endif
+
+#if !HAVE_X509_CRL_SET1_NEXTUPDATE
+#define X509_CRL_set1_nextUpdate(crl, s) X509_CRL_set_nextUpdate((crl), (ASN1_TIME*)(s))
+#endif
+
#if !HAVE_X509_EXTENSION_GET0_OBJECT
#define X509_EXTENSION_get0_object(ext) X509_EXTENSION_get_object((ext))
#endif
@@ -1784,6 +1913,7 @@ static int compat_init(void) {
if (done)
goto epilog;
+#if defined compat_X509_STORE_free
/*
* We need to unconditionally install at least one external
* application data callback. Because these can never be
@@ -1792,7 +1922,6 @@ static int compat_init(void) {
if ((error = dl_anchor()))
goto epilog;
-#if defined compat_X509_STORE_free
/*
* Test if X509_STORE_free obeys reference counts by installing an
* onfree callback.
@@ -1929,6 +2058,7 @@ struct ex_data {
enum {
EX_SSL_CTX_ALPN_SELECT_CB,
+ EX_SSL_CTX_TLSEXT_SERVERNAME_CB,
};
static struct ex_type {
@@ -1938,6 +2068,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)
@@ -3081,7 +3212,8 @@ static int pk_new(lua_State *L) {
if (lua_istable(L, 1) || lua_isnil(L, 1)) {
int type = EVP_PKEY_RSA;
unsigned bits = 1024;
- unsigned exp = 65537;
+ BIGNUM *exp = NULL;
+ int generator = 2;
int curve = NID_X9_62_prime192v1;
const char *id;
const char *dhparam = NULL;
@@ -3111,23 +3243,46 @@ static int pk_new(lua_State *L) {
luaL_argcheck(L, type != NID_undef, 1, lua_pushfstring(L, "%s: invalid key type", id));
}
- if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
- luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
- bits = (unsigned)n;
- }
+ switch(type) {
+ case EVP_PKEY_RSA:
+ if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
+ luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
+ bits = (unsigned)n;
+ }
- if (loadfield(L, 1, "exp", LUA_TNUMBER, &n)) {
- luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n));
- exp = (unsigned)n;
- }
+ if (!getfield(L, 1, "exp")) {
+ exp = checkbig(L, -1);
+ } else {
+ /* default to 65537 */
+ exp = bn_push(L);
+ if (!BN_add_word(exp, 65537))
+ return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+ }
+ break;
+ case EVP_PKEY_DH:
+ /* dhparam field can contain a PEM encoded string.
+ The "dhparam" field takes precedence over "bits" */
+ if (loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam))
+ break;
- if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) {
- if (!auxS_txt2nid(&curve, id))
- luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id));
- }
+ if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
+ luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
+ bits = (unsigned)n;
+ }
- /* dhparam field can contain a PEM encoded string. */
- loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam);
+ /* compat: DH used to use the 'exp' field for the generator */
+ if (loadfield(L, 1, "generator", LUA_TNUMBER, &n) || loadfield(L, 1, "exp", LUA_TNUMBER, &n)) {
+ luaL_argcheck(L, n > 0 && n <= INT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n));
+ generator = (int)n;
+ }
+ break;
+ case EVP_PKEY_EC:
+ if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) {
+ if (!auxS_txt2nid(&curve, id))
+ luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id));
+ }
+ break;
+ }
creat:
if (!(*ud = EVP_PKEY_new()))
@@ -3137,9 +3292,14 @@ creat:
case EVP_PKEY_RSA: {
RSA *rsa;
- if (!(rsa = RSA_generate_key(bits, exp, 0, 0)))
+ if (!(rsa = RSA_new()))
return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+ if (!RSA_generate_key_ex(rsa, bits, exp, 0)) {
+ RSA_free(rsa);
+ return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+ }
+
EVP_PKEY_set1_RSA(*ud, rsa);
RSA_free(rsa);
@@ -3149,9 +3309,14 @@ creat:
case EVP_PKEY_DSA: {
DSA *dsa;
- if (!(dsa = DSA_generate_parameters(bits, 0, 0, 0, 0, 0, 0)))
+ if (!(dsa = DSA_new()))
return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+ if (!DSA_generate_parameters_ex(dsa, bits, 0, 0, 0, 0, 0)) {
+ DSA_free(dsa);
+ return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+ }
+
if (!DSA_generate_key(dsa)) {
DSA_free(dsa);
return auxL_error(L, auxL_EOPENSSL, "pkey.new");
@@ -3179,8 +3344,15 @@ creat:
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");
+ } else {
+ if (!(dh = DH_new()))
+ return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+
+ if (!DH_generate_parameters_ex(dh, bits, generator, 0)) {
+ DH_free(dh);
+ return auxL_error(L, auxL_EOPENSSL, "pkey.new");
+ }
+ }
if (!DH_generate_key(dh)) {
@@ -4319,7 +4491,7 @@ static const auxL_IntegerReg pk_rsa_pad_opts[] = {
{ "RSA_NO_PADDING", RSA_NO_PADDING }, // no padding
{ "RSA_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING }, // OAEP padding (encrypt and decrypt only)
{ "RSA_X931_PADDING", RSA_X931_PADDING }, // (signature operations only)
-#if HAVE_RSA_PKCS1_PSS_PADDING
+#if RSA_PKCS1_PSS_PADDING
{ "RSA_PKCS1_PSS_PADDING", RSA_PKCS1_PSS_PADDING }, // (sign and verify only)
#endif
{ NULL, 0 },
@@ -5523,17 +5695,17 @@ static _Bool scan(int *i, char **cp, int n, int signok) {
} /* scan() */
-static double timeutc(ASN1_TIME *time) {
+static double timeutc(const ASN1_TIME *time) {
char buf[32] = "", *cp;
struct tm tm = { 0 };
int gmtoff = 0, year, i;
- if (!ASN1_TIME_check(time))
+ if (!ASN1_TIME_check((ASN1_STRING *)time))
return 0;
cp = strncpy(buf, (const char *)ASN1_STRING_get0_data((ASN1_STRING *)time), sizeof buf - 1);
- if (ASN1_STRING_type(time) == V_ASN1_GENERALIZEDTIME) {
+ if (ASN1_STRING_type((ASN1_STRING *)time) == V_ASN1_GENERALIZEDTIME) {
if (!scan(&year, &cp, 4, 1))
goto badfmt;
} else {
@@ -5595,7 +5767,7 @@ badfmt:
static int xc_getLifetime(lua_State *L) {
X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
double begin = INFINITY, end = INFINITY;
- ASN1_TIME *time;
+ const ASN1_TIME *time;
if ((time = X509_get_notBefore(crt)))
begin = timeutc(time);
@@ -6684,10 +6856,21 @@ static int xx_new(lua_State *L) {
if (!ok)
return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
} else {
+ ASN1_TIME *tm;
+
if (!(*ud = X509_CRL_new()))
return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
- X509_gmtime_adj(X509_CRL_get_lastUpdate(*ud), 0);
+ /* initialize last updated time to now */
+ if (!(tm = ASN1_TIME_set(NULL, time(NULL))))
+ return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
+
+ if (!X509_CRL_set1_lastUpdate(*ud, tm)) {
+ ASN1_TIME_free(tm);
+ return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
+ }
+
+ ASN1_TIME_free(tm);
}
return 1;
@@ -6724,9 +6907,9 @@ static int xx_setVersion(lua_State *L) {
static int xx_getLastUpdate(lua_State *L) {
X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
double updated = INFINITY;
- ASN1_TIME *time;
+ const ASN1_TIME *time;
- if ((time = X509_CRL_get_lastUpdate(crl)))
+ if ((time = X509_CRL_get0_lastUpdate(crl)))
updated = timeutc(time);
if (isfinite(updated))
@@ -6741,23 +6924,30 @@ static int xx_getLastUpdate(lua_State *L) {
static int xx_setLastUpdate(lua_State *L) {
X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
double updated = luaL_checknumber(L, 2);
+ ASN1_TIME *time;
- /* lastUpdate always present */
- if (!ASN1_TIME_set(X509_CRL_get_lastUpdate(crl), updated))
- return auxL_error(L, auxL_EOPENSSL, "x509.crl:setLastUpdate");
+ if (!(time = ASN1_TIME_set(NULL, updated)))
+ goto error;
+
+ if (!X509_CRL_set1_lastUpdate(crl, time))
+ goto error;
lua_pushboolean(L, 1);
return 1;
+error:
+ ASN1_TIME_free(time);
+
+ return auxL_error(L, auxL_EOPENSSL, "x509.crl:setLastUpdate");
} /* xx_setLastUpdate() */
static int xx_getNextUpdate(lua_State *L) {
X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
double updateby = INFINITY;
- ASN1_TIME *time;
+ const ASN1_TIME *time;
- if ((time = X509_CRL_get_nextUpdate(crl)))
+ if ((time = X509_CRL_get0_nextUpdate(crl)))
updateby = timeutc(time);
if (isfinite(updateby))
@@ -6772,30 +6962,19 @@ static int xx_getNextUpdate(lua_State *L) {
static int xx_setNextUpdate(lua_State *L) {
X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
double updateby = luaL_checknumber(L, 2);
- ASN1_TIME *time = NULL;
-
- if (X509_CRL_get_nextUpdate(crl)) {
- if (!ASN1_TIME_set(X509_CRL_get_nextUpdate(crl), updateby))
- goto error;
- } else {
- if (!(time = ASN1_TIME_new()))
- goto error;
-
- if (!(ASN1_TIME_set(time, updateby)))
- goto error;
+ ASN1_TIME *time;
- if (!X509_CRL_set_nextUpdate(crl, time))
- goto error;
+ if (!(time = ASN1_TIME_set(NULL, updateby)))
+ goto error;
- time = NULL;
- }
+ if (!X509_CRL_set1_nextUpdate(crl, time))
+ goto error;
lua_pushboolean(L, 1);
return 1;
error:
- if (time)
- ASN1_TIME_free(time);
+ ASN1_TIME_free(time);
return auxL_error(L, auxL_EOPENSSL, "x509.crl:setNextUpdate");
} /* xx_setNextUpdate() */
@@ -7670,11 +7849,6 @@ int luaopen__openssl_pkcs12(lua_State *L) {
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-/*
- * NOTE: TLS methods and flags were added in tandem. For example, if the
- * macro SSL_OP_NO_TLSv1_1 is defined we know TLSv1_1_server_method is also
- * declared and defined.
- */
static int sx_new(lua_State *L) {
static const char *const opts[] = {
[0] = "SSL",
@@ -7690,81 +7864,109 @@ static int sx_new(lua_State *L) {
[14] = "DTLSv1_2", [15] = "DTLSv1.2",
NULL
};
- /* later versions of SSL declare a const qualifier on the return type */
- __typeof__(&TLSv1_client_method) method = &TLSv1_client_method;
+ int method_enum;
_Bool srv;
SSL_CTX **ud;
int options = 0;
lua_settop(L, 2);
+ method_enum = auxL_checkoption(L, 1, "TLS", opts, 1);
srv = lua_toboolean(L, 2);
- switch (auxL_checkoption(L, 1, "TLS", opts, 1)) {
+ switch (method_enum) {
case 0: /* SSL */
- method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
options = SSL_OP_NO_SSLv2;
break;
case 1: /* TLS */
- method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
options = SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
break;
-#if HAVE_SSLV2_CLIENT_METHOD && HAVE_SSLV2_SERVER_METHOD
case 2: /* SSLv2 */
- method = (srv)? &SSLv2_server_method : &SSLv2_client_method;
+ options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_SSLv2;
break;
-#endif
-#ifndef OPENSSL_NO_SSL3
case 3: /* SSLv3 */
- method = (srv)? &SSLv3_server_method : &SSLv3_client_method;
+ options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_SSLv3;
break;
-#endif
case 4: /* SSLv23 */
- method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
break;
case 5: /* TLSv1 */
case 6: /* TLSv1.0 */
- method = (srv)? &TLSv1_server_method : &TLSv1_client_method;
+ options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_TLSv1;
break;
#if defined SSL_OP_NO_TLSv1_1
case 7: /* TLSv1_1 */
case 8: /* TLSv1.1 */
- method = (srv)? &TLSv1_1_server_method : &TLSv1_1_client_method;
+ options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_TLSv1_1;
break;
#endif
#if defined SSL_OP_NO_TLSv1_2
case 9: /* TLSv1_2 */
case 10: /* TLSv1.2 */
- method = (srv)? &TLSv1_2_server_method : &TLSv1_2_client_method;
+ options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_TLSv1_2;
break;
#endif
#if HAVE_DTLS_CLIENT_METHOD
case 11: /* DTLS */
- method = (srv)? &DTLS_server_method : &DTLS_client_method;
break;
-#endif
-#if HAVE_DTLSV1_CLIENT_METHOD
+#ifdef SSL_OP_NO_DTLSv1
case 12: /* DTLSv1 */
case 13: /* DTLSv1.0 */
- method = (srv)? &DTLSv1_server_method : &DTLSv1_client_method;
+ options = SSL_OP_NO_DTLS_MASK & ~SSL_OP_NO_DTLSv1;
break;
#endif
-#if HAVE_DTLSV1_2_CLIENT_METHOD
+#ifdef SSL_OP_NO_DTLSv1_2
case 14: /* DTLSv1_2 */
case 15: /* DTLSv1.2 */
- method = (srv)? &DTLSv1_server_method : &DTLSv1_client_method;
+ options = SSL_OP_NO_DTLS_MASK & ~SSL_OP_NO_DTLSv1_2;
break;
#endif
+#endif
default:
return luaL_argerror(L, 1, "invalid option");
}
ud = prepsimple(L, SSL_CTX_CLASS);
- if (!(*ud = SSL_CTX_new(method())))
+ switch (method_enum) {
+ case 0: /* SSL */
+ case 1: /* TLS */
+ case 2: /* SSLv2 */
+ case 3: /* SSLv3 */
+ case 4: /* SSLv23 */
+ case 5: /* TLSv1 */
+ case 6: /* TLSv1.0 */
+ case 7: /* TLSv1_1 */
+ case 8: /* TLSv1.1 */
+ case 9: /* TLSv1_2 */
+ case 10: /* TLSv1.2 */
+ *ud = SSL_CTX_new(srv?SSLv23_server_method():SSLv23_client_method());
+ break;
+#if HAVE_DTLS_CLIENT_METHOD
+ case 11: /* DTLS */
+ case 12: /* DTLSv1 */
+ case 13: /* DTLSv1.0 */
+ case 14: /* DTLSv1_2 */
+ case 15: /* DTLSv1.2 */
+ *ud = SSL_CTX_new(srv?DTLS_server_method():DTLS_client_method());
+ break;
+#endif
+ default:
+ NOTREACHED;
+ }
+
+ if (!*ud)
return auxL_error(L, auxL_EOPENSSL, "ssl.context.new");
SSL_CTX_set_options(*ud, options);
+#if HAVE_SSL_CTX_SET_ECDH_AUTO
+ /* OpenSSL 1.0.2 introduced SSL_CTX_set_ecdh_auto to automatically select
+ * from the curves set via SSL_CTX_set1_curves_list. However as of OpenSSL
+ * 1.1.0, the functionality was turned on permanently and the option
+ * removed. */
+ if (!SSL_CTX_set_ecdh_auto(*ud, 1))
+ return auxL_error(L, auxL_EOPENSSL, "ssl.context.new");
+#endif
+
return 1;
} /* sx_new() */
@@ -7940,6 +8142,21 @@ static int sx_setCipherList(lua_State *L) {
} /* sx_setCipherList() */
+#if HAVE_SSL_CTX_SET_CURVES_LIST
+static int sx_setCurvesList(lua_State *L) {
+ SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
+ const char *curves = luaL_checkstring(L, 2);
+
+ if (!SSL_CTX_set1_curves_list(ctx, curves))
+ return auxL_error(L, auxL_EOPENSSL, "ssl.context:setCurvesList");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* sx_setCurvesList() */
+#endif
+
+
static int sx_setEphemeralKey(lua_State *L) {
SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS);
@@ -8013,9 +8230,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;
@@ -8033,12 +8249,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);
@@ -8110,6 +8326,74 @@ 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) \
@@ -8122,7 +8406,7 @@ static int sx_setTLSextStatusType(lua_State *L) {
int type = checkTLSEXT_STATUSTYPE(L, 2);
if(!SSL_CTX_set_tlsext_status_type(ctx, type))
- return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusType");
+ return auxL_error(L, auxL_EOPENSSL, "ssl.context:setTLSextStatusType");
lua_pushboolean(L, 1);
@@ -8177,6 +8461,9 @@ static const auxL_Reg sx_methods[] = {
{ "setCertificate", &sx_setCertificate },
{ "setPrivateKey", &sx_setPrivateKey },
{ "setCipherList", &sx_setCipherList },
+#if HAVE_SSL_CTX_SET_CURVES_LIST
+ { "setCurvesList", &sx_setCurvesList },
+#endif
{ "setEphemeralKey", &sx_setEphemeralKey },
#if HAVE_SSL_CTX_SET_ALPN_PROTOS
{ "setAlpnProtos", &sx_setAlpnProtos },
@@ -8184,6 +8471,9 @@ 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
@@ -8374,6 +8664,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);
@@ -8383,6 +8700,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);
@@ -8433,6 +8788,21 @@ static int ssl_getCipherInfo(lua_State *L) {
} /* ssl_getCipherInfo() */
+#if HAVE_SSL_SET_CURVES_LIST
+static int ssl_setCurvesList(lua_State *L) {
+ SSL *ssl = checksimple(L, 1, SSL_CLASS);
+ const char *curves = luaL_checkstring(L, 2);
+
+ if (!SSL_set1_curves_list(ssl, curves))
+ return auxL_error(L, auxL_EOPENSSL, "ssl:setCurvesList");
+
+ lua_pushboolean(L, 1);
+
+ return 1;
+} /* ssl_setCurvesList() */
+#endif
+
+
static int ssl_getHostName(lua_State *L) {
SSL *ssl = checksimple(L, 1, SSL_CLASS);
const char *host;
@@ -8679,10 +9049,17 @@ static const auxL_Reg ssl_methods[] = {
{ "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 },
+#if HAVE_SSL_SET_CURVES_LIST
+ { "setCurvesList", &ssl_setCurvesList },
+#endif
{ "getHostName", &ssl_getHostName },
{ "setHostName", &ssl_setHostName },
{ "getVersion", &ssl_getVersion },