diff options
-rwxr-xr-x | examples/self.x509 | 4 | ||||
-rw-r--r-- | src/GNUmakefile | 1 | ||||
-rw-r--r-- | src/openssl.c | 220 | ||||
-rw-r--r-- | src/openssl.pkcs12.lua | 1 |
4 files changed, 220 insertions, 6 deletions
diff --git a/examples/self.x509 b/examples/self.x509 index 31d6058..b2d14f9 100755 --- a/examples/self.x509 +++ b/examples/self.x509 @@ -49,6 +49,4 @@ crt:setBasicConstraintsCritical(true) crt:setPublicKey(key) crt:sign(key) --- pretty-print using openssl command-line utility. -io.popen("openssl x509 -text -noout", "w"):write(tostring(crt)) - +print(crt:text()) diff --git a/src/GNUmakefile b/src/GNUmakefile index c3cddf0..f988855 100644 --- a/src/GNUmakefile +++ b/src/GNUmakefile @@ -97,6 +97,7 @@ MODS$(1)_$(d) = \ $$(DESTDIR)$(3)/openssl/x509/crl.lua \ $$(DESTDIR)$(3)/openssl/x509/extension.lua \ $$(DESTDIR)$(3)/openssl/x509/store.lua \ + $$(DESTDIR)$(3)/openssl/pkcs12.lua \ $$(DESTDIR)$(3)/openssl/ssl/context.lua \ $$(DESTDIR)$(3)/openssl/ssl.lua \ $$(DESTDIR)$(3)/openssl/digest.lua \ diff --git a/src/openssl.c b/src/openssl.c index b72b28e..7bd9c61 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -27,6 +27,7 @@ #define LUAOSSL_H #include <limits.h> /* INT_MAX INT_MIN */ +#include <stdint.h> /* uintptr_t */ #include <string.h> /* memset(3) strerror_r(3) */ #include <strings.h> /* strcasecmp(3) */ #include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */ @@ -64,6 +65,7 @@ #include <openssl/asn1.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include <openssl/pkcs12.h> #include <openssl/evp.h> #include <openssl/pem.h> #include <openssl/ssl.h> @@ -89,6 +91,7 @@ #define X509_CRL_CLASS "X509_CRL*" #define X509_STORE_CLASS "X509_STORE*" #define X509_STCTX_CLASS "X509_STORE_CTX*" +#define PKCS12_CLASS "PKCS12*" #define SSL_CTX_CLASS "SSL_CTX*" #define SSL_CLASS "SSL*" #define DIGEST_CLASS "EVP_MD_CTX" /* not a pointer */ @@ -364,6 +367,18 @@ static _Bool loadfield(lua_State *L, int index, const char *k, int type, void *p } /* loadfield() */ +static void *loadfield_udata(lua_State *L, int index, const char *k, const char *tname) { + if (!getfield(L, index, k)) + return NULL; + + void **p = luaL_checkudata(L, -1, tname); + + lua_pop(L, 1); /* table keeps reference */ + + return *p; +} /* loadfield_udata() */ + + static const char *pushnid(lua_State *L, int nid) { const char *txt; ASN1_OBJECT *obj; @@ -1029,7 +1044,7 @@ done: static int pk_interpose(lua_State *L) { - return interpose(L, X509_NAME_CLASS); + return interpose(L, PKEY_CLASS); } /* pk_interpose() */ @@ -2695,6 +2710,66 @@ static int xc_sign(lua_State *L) { } /* xc_sign() */ +static int xc_text(lua_State *L) { + static const struct { const char *kw; unsigned int flag; } map[] = { + { "no_header", X509_FLAG_NO_HEADER }, + { "no_version", X509_FLAG_NO_VERSION }, + { "no_serial", X509_FLAG_NO_SERIAL }, + { "no_signame", X509_FLAG_NO_SIGNAME }, + { "no_validity", X509_FLAG_NO_VALIDITY }, + { "no_subject", X509_FLAG_NO_SUBJECT }, + { "no_issuer", X509_FLAG_NO_ISSUER }, + { "no_pubkey", X509_FLAG_NO_PUBKEY }, + { "no_extensions", X509_FLAG_NO_EXTENSIONS }, + { "no_sigdump", X509_FLAG_NO_SIGDUMP }, + { "no_aux", X509_FLAG_NO_AUX }, + { "no_attributes", X509_FLAG_NO_ATTRIBUTES }, + { "ext_default", X509V3_EXT_DEFAULT }, + { "ext_error", X509V3_EXT_ERROR_UNKNOWN }, + { "ext_parse", X509V3_EXT_PARSE_UNKNOWN }, + { "ext_dump", X509V3_EXT_DUMP_UNKNOWN } + }; + + lua_settop(L, 2); + + X509 *crt = checksimple(L, 1, X509_CERT_CLASS); + + unsigned int flags = 0; + const char *kw; + int found; + unsigned int i; + + BIO *bio = getbio(L); + char *data; + long len; + + if (!lua_isnil(L, 2)) { + lua_pushnil(L); + while (lua_next(L, 2)) { + kw = luaL_checkstring(L, -1); + found = 0; + for (i = 0; i < countof(map); i++) + if (!strcmp(kw, map[i].kw)) { + flags |= map[i].flag; + found = 1; + } + if (!found) + luaL_argerror(L, 2, lua_pushfstring(L, "invalid flag: %s", kw)); + lua_pop(L, 1); + } + } + + if (!X509_print_ex(bio, crt, 0, flags)) + return throwssl(L, "x509.cert:text"); + + len = BIO_get_mem_data(bio, &data); + + lua_pushlstring(L, data, len); + + return 1; +} /* xc_text() */ + + static int xc__tostring(lua_State *L) { X509 *crt = checksimple(L, 1, X509_CERT_CLASS); int type = optencoding(L, 2, "pem", X509_PEM|X509_DER); @@ -2762,6 +2837,7 @@ static const luaL_Reg xc_methods[] = { { "getPublicKey", &xc_getPublicKey }, { "setPublicKey", &xc_setPublicKey }, { "sign", &xc_sign }, + { "text", &xc_text }, { "tostring", &xc__tostring }, { NULL, NULL }, }; @@ -3049,7 +3125,7 @@ static int xx_getLastUpdate(lua_State *L) { updated = timeutc(time); if (isfinite(updated)) - lua_pushnumber(L, 1); + lua_pushnumber(L, updated); else lua_pushnil(L); @@ -3210,6 +3286,24 @@ static int xx_sign(lua_State *L) { } /* xx_sign() */ +static int xx_text(lua_State *L) { + X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); + + BIO *bio = getbio(L); + char *data; + long len; + + if (!X509_CRL_print(bio, crl)) + return throwssl(L, "x509.crl:text"); + + len = BIO_get_mem_data(bio, &data); + + lua_pushlstring(L, data, len); + + return 1; +} /* xx_text() */ + + static int xx__tostring(lua_State *L) { X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); int type = optencoding(L, 2, "pem", X509_PEM|X509_DER); @@ -3256,6 +3350,7 @@ static const luaL_Reg xx_methods[] = { { "setIssuer", &xx_setIssuer }, { "add", &xx_add }, { "sign", &xx_sign }, + { "text", &xx_text }, { "tostring", &xx__tostring }, { NULL, NULL }, }; @@ -3670,6 +3765,124 @@ int luaopen__openssl_x509_store_context(lua_State *L) { /* + * PKCS12 - openssl.pkcs12 + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +static int p12_new(lua_State *L) { + char *pass = NULL; + loadfield(L, 1, "password", LUA_TSTRING, &pass); + + EVP_PKEY *key = loadfield_udata(L, 1, "key", PKEY_CLASS); + STACK_OF(X509) *certs = loadfield_udata(L, 1, "certs", X509_CHAIN_CLASS); + + PKCS12 **ud = prepsimple(L, PKCS12_CLASS); + + int i; + int no_kcert = 0; + X509 *cert = NULL; + X509 *kcert = NULL; + STACK_OF(X509) *ca; + + if (!(ca = sk_X509_new_null())) + goto error; + + for (i = 0; i < sk_X509_num(certs); i++) { + cert = sk_X509_value(certs, i); + if (key && X509_check_private_key(cert, key)) { + if (!(kcert = X509_dup(cert))) + goto error; + X509_keyid_set1(kcert, NULL, 0); + X509_alias_set1(kcert, NULL, 0); + } + else sk_X509_push(ca, cert); + } + if (key && !kcert) { + no_kcert = 1; + goto error; + } + + if (!(*ud = PKCS12_create(pass, NULL, key, kcert, ca, 0, 0, 0, 0, 0))) + goto error; + + if (kcert) + X509_free(kcert); + sk_X509_free(ca); + + return 1; + +error: + if (kcert) + X509_free(kcert); + if (ca) + sk_X509_free(ca); + + if (no_kcert) + luaL_argerror(L, 1, lua_pushfstring(L, "certificate matching the key not found")); + + return throwssl(L, "pkcs12.new"); +} /* p12_new() */ + + +static int p12_interpose(lua_State *L) { + return interpose(L, PKCS12_CLASS); +} /* p12_interpose() */ + + +static int p12__tostring(lua_State *L) { + PKCS12 *p12 = checksimple(L, 1, PKCS12_CLASS); + BIO *bio = getbio(L); + char *data; + long len; + + if (!i2d_PKCS12_bio(bio, p12)) + return throwssl(L, "pkcs12:__tostring"); + + len = BIO_get_mem_data(bio, &data); + + lua_pushlstring(L, data, len); + + return 1; +} /* p12__tostring() */ + + +static int p12__gc(lua_State *L) { + PKCS12 **ud = luaL_checkudata(L, 1, PKCS12_CLASS); + + PKCS12_free(*ud); + *ud = NULL; + + return 0; +} /* p12__gc() */ + + +static const luaL_Reg p12_methods[] = { + { "tostring", &p12__tostring }, + { NULL, NULL }, +}; + +static const luaL_Reg p12_metatable[] = { + { "__tostring", &p12__tostring }, + { "__gc", &p12__gc }, + { NULL, NULL }, +}; + +static const luaL_Reg p12_globals[] = { + { "new", &p12_new }, + { "interpose", &p12_interpose }, + { NULL, NULL }, +}; + +int luaopen__openssl_pkcs12(lua_State *L) { + initall(L); + + luaL_newlib(L, p12_globals); + + return 1; +} /* luaopen__openssl_pkcs12() */ + + +/* * SSL_CTX - openssl.ssl.context * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -4213,7 +4426,7 @@ static int cipher_new(lua_State *L) { static int cipher_interpose(lua_State *L) { - return interpose(L, HMAC_CLASS); + return interpose(L, CIPHER_CLASS); } /* cipher_interpose() */ @@ -4867,6 +5080,7 @@ static void initall(lua_State *L) { addclass(L, X509_CRL_CLASS, xx_methods, xx_metatable); addclass(L, X509_CHAIN_CLASS, xl_methods, xl_metatable); addclass(L, X509_STORE_CLASS, xs_methods, xs_metatable); + addclass(L, PKCS12_CLASS, p12_methods, p12_metatable); addclass(L, SSL_CTX_CLASS, sx_methods, sx_metatable); addclass(L, SSL_CLASS, ssl_methods, ssl_metatable); addclass(L, DIGEST_CLASS, md_methods, md_metatable); diff --git a/src/openssl.pkcs12.lua b/src/openssl.pkcs12.lua new file mode 100644 index 0000000..d8f70c2 --- /dev/null +++ b/src/openssl.pkcs12.lua @@ -0,0 +1 @@ +return require('_openssl.pkcs12') |