diff --git a/nse_ssl_cert.cc b/nse_ssl_cert.cc index 77aeab1..183c4f2 100644 --- a/nse_ssl_cert.cc +++ b/nse_ssl_cert.cc @@ -101,6 +101,7 @@ #include #include #include +#include extern "C" { @@ -395,26 +396,36 @@ static const char *pkey_type_to_string(int type) } } -int l_get_ssl_certificate(lua_State *L) +static const char* verify_ssl_certificate(X509* cert, STACK_OF(X509)* chain) { - SSL *ssl; - struct cert_userdata *udata; - X509 *cert; - X509_NAME *subject, *issuer; - EVP_PKEY *pubkey; + const char* error = NULL; + X509_STORE* store = X509_STORE_new(); + X509_LOOKUP* lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + X509_STORE_CTX *storeCtx = X509_STORE_CTX_new(); + X509_STORE_CTX_init(storeCtx, store, cert, chain); - ssl = nse_nsock_get_ssl(L); - cert = SSL_get_peer_certificate(ssl); - if (cert == NULL) { - lua_pushnil(L); - return 1; + if (X509_verify_cert(storeCtx) != 1) { + error = X509_verify_cert_error_string(storeCtx->error); } + X509_STORE_CTX_free(storeCtx); - udata = (struct cert_userdata *) lua_newuserdata(L, sizeof(*udata)); - udata->cert = cert; + if(store != NULL) { + X509_STORE_free(store); + store = NULL; + } - lua_newtable(L); + return error; +} +static void push_cert_to_lua_table(lua_State *L, X509* cert) +{ + X509_NAME *subject, *issuer; + EVP_PKEY *pubkey; + subject = X509_get_subject_name(cert); if (subject != NULL) { x509_name_to_table(L, subject); @@ -441,6 +452,51 @@ int l_get_ssl_certificate(lua_State *L) lua_setfield(L, -2, "bits"); lua_setfield(L, -2, "pubkey"); EVP_PKEY_free(pubkey); +} + + +int l_get_ssl_certificate(lua_State *L) +{ + SSL *ssl; + struct cert_userdata *udata; + X509 *cert; + STACK_OF(X509) *chain; + const char *cert_error; + + ssl = nse_nsock_get_ssl(L); + cert = SSL_get_peer_certificate(ssl); + if (cert == NULL) { + lua_pushnil(L); + return 1; + } + + chain = SSL_get_peer_cert_chain(ssl); + if (chain == NULL) { + lua_pushnil(L); + return 1; + } + + udata = (struct cert_userdata *) lua_newuserdata(L, sizeof(*udata)); + udata->cert = cert; + + lua_newtable(L); + + if ( ( cert_error = verify_ssl_certificate(cert, chain) ) != NULL ) { + lua_pushstring(L, cert_error); + lua_setfield(L, -2, "warning"); + } + + push_cert_to_lua_table(L, cert); + + lua_newtable(L); + for( int i = 0; i 1 then + o.chain = { subject = {}, issuer = {} } + for k, v in ipairs(cert.chain) do + o.chain.subject[k] = name_to_table(v.subject) + o.chain.issuer[k] = name_to_table(v.issuer) + end + end o.pubkey = cert.pubkey o.validity = {} for k, v in pairs(cert.validity) do @@ -205,12 +214,24 @@ end local function output_str(cert) local lines = {} + if ( cert.warning ) then + lines[#lines + 1] = "Certificate Warning: " .. cert.warning + end + lines[#lines + 1] = "Subject: " .. stringify_name(cert.subject) if nmap.verbosity() > 0 then lines[#lines + 1] = "Issuer: " .. stringify_name(cert.issuer) end + if nmap.verbosity() > 0 and #cert.chain > 1 then + lines[#lines + 1] = "Chain: " + for i, c in ipairs(cert.chain) do + lines[#lines + 1] = (" [%d] Subject: %s "):format(i - 1, stringify_name(c.subject)) + lines[#lines + 1] = " Issuer: " .. stringify_name(c.issuer) + end + end + if nmap.verbosity() > 0 then lines[#lines + 1] = "Public Key type: " .. cert.pubkey.type lines[#lines + 1] = "Public Key bits: " .. cert.pubkey.bits