diff --git a/nse_ssl_cert.cc b/nse_ssl_cert.cc index 9efba3c..bd59fb7 100644 --- a/nse_ssl_cert.cc +++ b/nse_ssl_cert.cc @@ -132,6 +132,7 @@ #include #include #include +#include extern "C" { @@ -427,6 +428,7 @@ static const char *pkey_type_to_string(int type) } static int parse_ssl_cert(lua_State *L, X509 *cert); +static int parse_ssl_extensions(lua_State *L, X509 *cert); int l_parse_ssl_certificate(lua_State *L) { @@ -462,6 +464,75 @@ int l_get_ssl_certificate(lua_State *L) return parse_ssl_cert(L, cert); } +static int parse_ssl_extensions(lua_State *L, X509 *cert) +{ + const int EXTNAME_LEN = 2048; + STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; + lua_newtable(L); + + int num_of_exts; + if (exts) { + num_of_exts = sk_X509_EXTENSION_num(exts); + } else { + num_of_exts = 0; + } + + if (num_of_exts < 0) { + return 0; + } + + for (int i=0; i < num_of_exts; i++) { + X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i); + if (ex == NULL) { + continue; + } + + ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); + if (obj == NULL) { + continue; + } + + BIO *ext_bio = BIO_new(BIO_s_mem()); + if (ext_bio == NULL) { + continue; + } + + if (!X509V3_EXT_print(ext_bio, ex, 0, 0)) { + M_ASN1_OCTET_STRING_print(ext_bio, ex->value); + } + + BUF_MEM *bptr; + BIO_get_mem_ptr(ext_bio, &bptr); + BIO_set_close(ext_bio, BIO_NOCLOSE); + + // remove newlines + int lastchar = bptr->length; + if (lastchar > 1 && (bptr->data[lastchar-1] == '\n' || bptr->data[lastchar-1] == '\r')) { + bptr->data[lastchar-1] = (char) 0; + } + if (lastchar > 0) { + bptr->data[lastchar] = (char) 0; + } + + unsigned nid = OBJ_obj2nid(obj); + if (nid == NID_undef) { + char extname[EXTNAME_LEN]; + OBJ_obj2txt(extname, EXTNAME_LEN, (const ASN1_OBJECT *) obj, 1); + lua_pushstring(L, bptr->data); + lua_setfield(L, -2, extname); + } else { + const char *c_ext_name = OBJ_nid2ln(nid); + if (c_ext_name != NULL) { + lua_pushstring(L, bptr->data); + lua_setfield(L, -2, c_ext_name); + } + } + BIO_free(ext_bio); + } + lua_setfield(L, -2, "exts"); + return 1; +} + static int parse_ssl_cert(lua_State *L, X509 *cert) { struct cert_userdata *udata; @@ -504,6 +575,9 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) lua_setfield(L, -2, "pubkey"); EVP_PKEY_free(pubkey); + parse_ssl_extensions(L, cert); + + /* At this point the certificate-specific table of attributes is at the top of the stack. We give it a metatable with an __index entry that points into the global shared table of certificate functions. */ diff --git a/scripts/ssl-cert.nse b/scripts/ssl-cert.nse index b878a80..67fac79 100644 --- a/scripts/ssl-cert.nse +++ b/scripts/ssl-cert.nse @@ -209,6 +209,10 @@ local function output_str(cert) local lines = {} lines[#lines + 1] = "Subject: " .. stringify_name(cert.subject) + local SNA = cert.exts['X509v3 Subject Alternative Name'] + if SNA ~= nil then + lines[#lines + 1] = "Subject Alternative Names: " .. cert.exts['X509v3 Subject Alternative Name'] + end if nmap.verbosity() > 0 then lines[#lines + 1] = "Issuer: " .. stringify_name(cert.issuer)