From 36277465de786618aa94bc2d33c0ffce5e2102a3 Mon Sep 17 00:00:00 2001 From: Ash Berlin Date: Sun, 10 Apr 2016 22:15:33 +0100 Subject: Support for getting and setting SAN on a CSR Extensions in a CSR are a bit more complex than in a CRL or a certificate itself so we don't quite use the same interface. --- doc/luaossl.tex | 8 ++++++ src/openssl.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/doc/luaossl.tex b/doc/luaossl.tex index 433dd03..7db7463 100644 --- a/doc/luaossl.tex +++ b/doc/luaossl.tex @@ -597,6 +597,14 @@ Returns the subject distinguished name as an \module{x509.name} object. Sets the subject distinguished name. $name$ should be an \module{x509.name} object. +\subsubsection[\fn{csr:getSubjectAlt}]{\fn{csr:getSubjectAlt()}} + +Returns the subject alternative name as an \module{x509.altname} object. + +\subsubsection[\fn{csr:setSubjectAlt}]{\fn{csr:setSubjectAlt($name$)}} + +Sets the subject alternative names. $name$ should be an \module{x509.altname} object. + \subsubsection[\fn{csr:getPublicKey}]{\fn{csr:getPublicKey()}} Returns the public key component as an \module{openssl.pkey} object. diff --git a/src/openssl.c b/src/openssl.c index 2893d04..f8c5047 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -5488,6 +5488,85 @@ static int xr_setPublicKey(lua_State *L) { } /* xr_setPublicKey() */ +static int xr_setExtensionByNid(lua_State *L, X509_REQ *csr, int target_nid, void* value) { + STACK_OF(X509_EXTENSION) *sk = NULL; + X509_ATTRIBUTE *attr; + int has_attrs=0, idx, *pnid; + + // Replace existing if it's there. Extensions are stored in a CSR in an interesting way: + // + // They are stored as a list under either (most likely) the "official" + // NID_ext_req or under NID_ms_ext_req which means everything is stored + // under a list in a single "attribute" so we can't use X509_REQ_add1_attr + // or similar. + // + // Instead we have to get the extensions, find and replace the SAN if it's + // in there, then *replace* the extensions in the list of attributes. (If + // we just try to add it the old ones are found first and don't take + // priority) + + has_attrs = X509_REQ_get_attr_count(csr); + sk = X509_REQ_get_extensions(csr); + + if (!X509V3_add1_i2d(&sk, target_nid, value, 0, X509V3_ADD_REPLACE)) + goto error; + + if (X509_REQ_add_extensions(csr, sk) == 0) + goto error; + + // Delete the old extensions attribute, so that the one we just added takes priority + if (has_attrs) { + for (pnid = X509_REQ_get_extension_nids(); *pnid != NID_undef; pnid++) { + idx = X509_REQ_get_attr_by_NID(csr, *pnid, -1); + if (idx == -1) + continue; + if (!(attr = X509_REQ_delete_attr(csr, idx))) + goto error; + X509_ATTRIBUTE_free(attr); + break; + } + if (!attr) + goto error; + } + + // We have to mark the encoded form as invalid, otherwise when we write it + // out again it will use the loaded version + csr->req_info->enc.modified = 1; + + sk_X509_EXTENSION_pop_free(sk, X509_EXTENSION_free); + lua_pushboolean(L, 1); + return 1; +error: + if (sk) + sk_X509_EXTENSION_pop_free(sk, X509_EXTENSION_free); + return auxL_error(L, auxL_EOPENSSL, "x509.csr.setExtensionByNid"); +} /* xr_setExtensionByNid() */ + + +static int xr_setSubjectAlt(lua_State *L) { + X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); + GENERAL_NAMES *gens = checksimple(L, 2, X509_GENS_CLASS); + return xr_setExtensionByNid(L, csr, NID_subject_alt_name, gens); +} /* xr_setSubjectAlt */ + + +static int xr_getSubjectAlt(lua_State *L) { + X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); + GENERAL_NAMES *gens; + STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(csr); + + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + if (!gens) goto error; + + gn_dup(L, gens); + return 1; +error: + return 0; +} /* xr_getSubjectAlt() */ + + + static int xr_sign(lua_State *L) { X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS); @@ -5545,6 +5624,8 @@ static const auxL_Reg xr_methods[] = { { "setSubject", &xr_setSubject }, { "getPublicKey", &xr_getPublicKey }, { "setPublicKey", &xr_setPublicKey }, + { "getSubjectAlt", &xr_getSubjectAlt }, + { "setSubjectAlt", &xr_setSubjectAlt }, { "sign", &xr_sign }, { "tostring", &xr__tostring }, { NULL, NULL }, -- cgit v1.2.3-59-g8ed1b