Index: nse_nsock.cc =================================================================== --- nse_nsock.cc (revision 15706) +++ nse_nsock.cc (working copy) @@ -530,8 +530,8 @@ static int l_nsock_connect(lua_State * L) { - enum type {TCP, UDP, SSL}; - static const char * const op[] = {"tcp", "udp", "ssl", NULL}; + enum type {TCP, UDP, SSL, RESSL}; + static const char * const op[] = {"tcp", "udp", "ssl", "ressl", NULL}; l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock"); const char *addr = luaL_checkstring(L, 2); @@ -596,6 +596,10 @@ udata->timeout, &udata->yield, dest->ai_addr, dest->ai_addrlen, IPPROTO_TCP, port, udata->ssl_session); break; + case RESSL: + nsock_reconnect_ssl(nsp, udata->nsiod, l_nsock_connect_handler, + udata->timeout, &udata->yield, udata->ssl_session); + break; } freeaddrinfo(dest); Index: scripts/ssl-cert.nse =================================================================== --- scripts/ssl-cert.nse (revision 15706) +++ scripts/ssl-cert.nse (working copy) @@ -1,168 +1,220 @@ -description = [[ -Retrieves a server's SSL certificate. The amount of information printed -about the certificate depends on the verbosity level. With no extra -verbosity, the script prints the validity period and the commonName, -organizationName, stateOrProvinceName, and countryName of the subject. - - -443/tcp open https -| ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ -/stateOrProvinceName=California/countryName=US -| Not valid before: 2009-05-28 00:00:00 -|_ Not valid after: 2010-05-01 23:59:59 - - -With -v it adds the issuer name and fingerprints. - - -443/tcp open https -| ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ -/stateOrProvinceName=California/countryName=US -| Issuer: commonName=VeriSign Class 3 Extended Validation SSL CA\ -/organizationName=VeriSign, Inc./countryName=US -| Not valid before: 2009-05-28 00:00:00 -| Not valid after: 2010-05-01 23:59:59 -| MD5: c5b8 7ddd ccc7 537f 8861 b476 078d e8fd -|_ SHA-1: dc5a cb8b 9eb9 b5de 7117 c536 8c15 0e75 ba88 702e - - -With -vv it adds the PEM-encoded contents of the entire -certificate. - - -443/tcp open https -| ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ -/stateOrProvinceName=California/countryName=US/serialNumber=3014267\ -/1.3.6.1.4.1.311.60.2.1.3=US/streetAddress=2211 N 1st St\ -/1.3.6.1.4.1.311.60.2.1.2=Delaware/postalCode=95131-2021\ -/localityName=San Jose/organizationalUnitName=Information Systems\ -/2.5.4.15=V1.0, Clause 5.(b) -| Issuer: commonName=VeriSign Class 3 Extended Validation SSL CA\ -/organizationName=VeriSign, Inc./countryName=US\ -/organizationalUnitName=Terms of use at https://www.verisign.com/rpa (c)06 -| Not valid before: 2009-05-28 00:00:00 -| Not valid after: 2010-05-01 23:59:59 -| MD5: c5b8 7ddd ccc7 537f 8861 b476 078d e8fd -| SHA-1: dc5a cb8b 9eb9 b5de 7117 c536 8c15 0e75 ba88 702e -| -----BEGIN CERTIFICATE----- -| MIIFxzCCBK+gAwIBAgIQX02QuADDB7CVjZdooVge+zANBgkqhkiG9w0BAQUFADCB -... - -]] - ---- --- @output --- 443/tcp open https --- | ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ --- /stateOrProvinceName=California/countryName=US --- | Not valid before: 2009-05-28 00:00:00 --- |_ Not valid after: 2010-05-01 23:59:59 - -author = "David Fifield " - -license = "Same as Nmap--See http://nmap.org/book/man-legal.html" - -categories = { "safe", "discovery" } - -require("nmap") -require("nsedebug") -require("stdnse") - -local stringify_name -local date_to_string -local table_find - -local LIKELY_SSL_PORTS = { 443, 465, 989, 990, 992, 993, 994, 995, 587, 8443 } - -portrule = function(host, port) - return port.version.service_tunnel == "ssl" - or table_find(LIKELY_SSL_PORTS, port.number) -end - -action = function(host, port) - local s = nmap.new_socket() - local status, error = s:connect(host.ip, port.number, "ssl") - if not status then - if nmap.verbosity() > 0 then - return error - else - return nil - end - end - local cert = s:get_ssl_certificate() - s:close() - - local lines = {} - lines[#lines + 1] = "Subject: " .. stringify_name(cert.subject) - - if nmap.verbosity() > 0 then - lines[#lines + 1] = "Issuer: " .. stringify_name(cert.issuer) - end - - lines[#lines + 1] = "Not valid before: " .. - date_to_string(cert.validity.notBefore) - lines[#lines + 1] = "Not valid after: " .. - date_to_string(cert.validity.notAfter) - - lines[#lines + 1] = "MD5: " .. stdnse.tohex(cert:digest("md5"), { separator = " ", group = 4 }) - lines[#lines + 1] = "SHA-1: " .. stdnse.tohex(cert:digest("sha1"), { separator = " ", group = 4 }) - - if nmap.verbosity() > 1 then - lines[#lines + 1] = cert.pem - end - - return stdnse.strjoin("\n", lines) -end - --- Find the index of a value in an array. -function table_find(t, value) - local i, v - for i, v in ipairs(t) do - if v == value then - return i - end - end - return nil -end - --- These are the subject/issuer name fields that will be shown, in this order, --- without a high verbosity. -local NON_VERBOSE_FIELDS = { "commonName", "organizationName", - "stateOrProvinceName", "countryName" } - -function stringify_name(name) - local fields = {} - local _, k, v - if not name then - return nil - end - for _, k in ipairs(NON_VERBOSE_FIELDS) do - v = name[k] - if v then - fields[#fields + 1] = string.format("%s=%s", k, v) - end - end - if nmap.verbosity() > 1 then - for k, v in pairs(name) do - -- Don't include a field twice. - if not table_find(NON_VERBOSE_FIELDS, k) then - if type(k) == "table" then - k = stdnse.strjoin(".", k) - end - fields[#fields + 1] = string.format("%s=%s", k, v) - end - end - end - return stdnse.strjoin("/", fields) -end - -function date_to_string(date) - if not date then - return "MISSING" - end - if type(date) == "string" then - return string.format("Can't parse; string is \"%s\"", date) - else - return os.date("%Y-%m-%d %H:%M:%S", os.time(date)) - end -end +description = [[ +Retrieves a server's SSL certificate. The amount of information printed +about the certificate depends on the verbosity level. With no extra +verbosity, the script prints the validity period and the commonName, +organizationName, stateOrProvinceName, and countryName of the subject. + + +443/tcp open https +| ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ +/stateOrProvinceName=California/countryName=US +| Not valid before: 2009-05-28 00:00:00 +|_ Not valid after: 2010-05-01 23:59:59 + + +With -v it adds the issuer name and fingerprints. + + +443/tcp open https +| ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ +/stateOrProvinceName=California/countryName=US +| Issuer: commonName=VeriSign Class 3 Extended Validation SSL CA\ +/organizationName=VeriSign, Inc./countryName=US +| Not valid before: 2009-05-28 00:00:00 +| Not valid after: 2010-05-01 23:59:59 +| MD5: c5b8 7ddd ccc7 537f 8861 b476 078d e8fd +|_ SHA-1: dc5a cb8b 9eb9 b5de 7117 c536 8c15 0e75 ba88 702e + + +With -vv it adds the PEM-encoded contents of the entire +certificate. + + +443/tcp open https +| ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ +/stateOrProvinceName=California/countryName=US/serialNumber=3014267\ +/1.3.6.1.4.1.311.60.2.1.3=US/streetAddress=2211 N 1st St\ +/1.3.6.1.4.1.311.60.2.1.2=Delaware/postalCode=95131-2021\ +/localityName=San Jose/organizationalUnitName=Information Systems\ +/2.5.4.15=V1.0, Clause 5.(b) +| Issuer: commonName=VeriSign Class 3 Extended Validation SSL CA\ +/organizationName=VeriSign, Inc./countryName=US\ +/organizationalUnitName=Terms of use at https://www.verisign.com/rpa (c)06 +| Not valid before: 2009-05-28 00:00:00 +| Not valid after: 2010-05-01 23:59:59 +| MD5: c5b8 7ddd ccc7 537f 8861 b476 078d e8fd +| SHA-1: dc5a cb8b 9eb9 b5de 7117 c536 8c15 0e75 ba88 702e +| -----BEGIN CERTIFICATE----- +| MIIFxzCCBK+gAwIBAgIQX02QuADDB7CVjZdooVge+zANBgkqhkiG9w0BAQUFADCB +... + +]] + +--- +-- @output +-- 443/tcp open https +-- | ssl-cert: Subject: commonName=www.paypal.com/organizationName=PayPal, Inc.\ +-- /stateOrProvinceName=California/countryName=US +-- | Not valid before: 2009-05-28 00:00:00 +-- |_ Not valid after: 2010-05-01 23:59:59 + +author = "David Fifield " + +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" + +categories = { "safe", "discovery" } + +require("nmap") +require("nsedebug") +require("stdnse") + +local stringify_name +local date_to_string +local table_find + +local LIKELY_SSL_PORTS = { 443, 465, 989, 990, 992, 993, 994, 995, 587, 8443 } + +portrule = function(host, port) + return port.version.service_tunnel == "ssl" + or table_find(LIKELY_SSL_PORTS, port.number) +end + +action = function(host, port) + local s = nmap.new_socket() + local status, error = s:connect(host.ip, port.number, "ssl") + + if not status then + status, error = s:connect(host.ip, port.number, "tcp") -- SSL negotiation failed, let try for SMTP + TLS + + if not status then + if nmap.verbosity() > 0 then + return error + else + return nil + end + else + + local i = 0 + repeat + status, resultEHLO = s:receive_lines(1) + i = i + 1 + until string.match(resultEHLO, "^220") or i == 5 + + local query = "EHLO example.org\r\n" + status = s:send(query) + status, resultEHLO = s:receive_lines(1) + + if not (string.match(resultEHLO, "^250")) then + stdnse.print_debug("1","%s",resultEHLO) + stdnse.print_debug("1","EHLO with errors or timeout. Enable --script-trace to see what is happening.") + return error + end + + resultEHLO = "" + + local query = "STARTTLS\r\n" + status = s:send(query) + status, resultEHLO = s:receive_lines(1) + + if not (string.match(resultEHLO, "^220")) then + stdnse.print_debug("1","%s",resultEHLO) + stdnse.print_debug("1","STARTTLS failed or unavailable. Enable --script-trace to see what is happening.") + resultEHLO = "" + + if nmap.verbosity() > 0 then + return error + else + return nil + end + s:close() + end + + status, error = s:connect(host.ip, port.number, "ressl") + if not status then + if nmap.verbosity() > 0 then + return error + else + return nil + end + end + + + end + end + local cert = s:get_ssl_certificate() + s:close() + + local lines = {} + lines[#lines + 1] = "Subject: " .. stringify_name(cert.subject) + + if nmap.verbosity() > 0 then + lines[#lines + 1] = "Issuer: " .. stringify_name(cert.issuer) + end + + lines[#lines + 1] = "Not valid before: " .. + date_to_string(cert.validity.notBefore) + lines[#lines + 1] = "Not valid after: " .. + date_to_string(cert.validity.notAfter) + + lines[#lines + 1] = "MD5: " .. stdnse.tohex(cert:digest("md5"), { separator = " ", group = 4 }) + lines[#lines + 1] = "SHA-1: " .. stdnse.tohex(cert:digest("sha1"), { separator = " ", group = 4 }) + + if nmap.verbosity() > 1 then + lines[#lines + 1] = cert.pem + end + + return stdnse.strjoin("\n", lines) +end + +-- Find the index of a value in an array. +function table_find(t, value) + local i, v + for i, v in ipairs(t) do + if v == value then + return i + end + end + return nil +end + +-- These are the subject/issuer name fields that will be shown, in this order, +-- without a high verbosity. +local NON_VERBOSE_FIELDS = { "commonName", "organizationName", + "stateOrProvinceName", "countryName" } + +function stringify_name(name) + local fields = {} + local _, k, v + if not name then + return nil + end + for _, k in ipairs(NON_VERBOSE_FIELDS) do + v = name[k] + if v then + fields[#fields + 1] = string.format("%s=%s", k, v) + end + end + if nmap.verbosity() > 1 then + for k, v in pairs(name) do + -- Don't include a field twice. + if not table_find(NON_VERBOSE_FIELDS, k) then + if type(k) == "table" then + k = stdnse.strjoin(".", k) + end + fields[#fields + 1] = string.format("%s=%s", k, v) + end + end + end + return stdnse.strjoin("/", fields) +end + +function date_to_string(date) + if not date then + return "MISSING" + end + if type(date) == "string" then + return string.format("Can't parse; string is \"%s\"", date) + else + return os.date("%Y-%m-%d %H:%M:%S", os.time(date)) + end +end