mirror of
https://github.com/nmap/nmap.git
synced 2026-01-27 00:29:03 +00:00
Make gathered CPE codes available to NSE.
CPEs are available at host.os (for the ones from OS fingerprinting) and port.version.cpe (for the version detection ones). This patch also fix a memory leak that David noticed in PortList::setServiceProbeResults().
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] Made gathered CPE codes available to NSE. [Henri]
|
||||
|
||||
o [NSE] Fixed a memory leak in PortList::setServiceProbeResults() noticed and
|
||||
reported by David. The leak was triggered by set_port_version calls from NSE.
|
||||
[Henri]
|
||||
|
||||
o [NSE] Added http-generator.nse by Michael Kohl, which gets version
|
||||
information for web applications that set the "generator" meta
|
||||
element.
|
||||
|
||||
@@ -1630,6 +1630,12 @@ LUALIB_API int luaopen_openssl(lua_State *L) {
|
||||
<option>-O</option> option, then
|
||||
<literal>host.os</literal> is <literal>nil</literal>.
|
||||
</para>
|
||||
<para>
|
||||
Additionally the table can contain CPE codes for the detected
|
||||
operating system. These codes, as described in
|
||||
<ulink url="http://cpe.mitre.org">the official CPE specification
|
||||
</ulink> all start with the <literal>cpe:/</literal> prefix.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -1890,6 +1896,15 @@ LUALIB_API int luaopen_openssl(lua_State *L) {
|
||||
<literal>nil</literal> if <literal>rpc_status</literal> is
|
||||
anything other than <literal>good_prog</literal>.</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry align="left"><literal>cpe</literal></entry>
|
||||
|
||||
<entry>List of CPE codes for the detected service. As described in the
|
||||
<ulink url="http://cpe.mitre.org">official CPE specification</ulink> these strings
|
||||
all start with the <literal>cpe:/</literal> prefix.</entry>
|
||||
</row>
|
||||
|
||||
</tbody></tgroup></table>
|
||||
|
||||
</listitem>
|
||||
|
||||
@@ -32,6 +32,8 @@ static const int NSE_PROTOCOL[] = {IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP};
|
||||
|
||||
void set_version (lua_State *L, const struct serviceDeductions *sd)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
setsfield(L, -1, "name", sd->name);
|
||||
setnfield(L, -1, "name_confidence", sd->name_confidence);
|
||||
setsfield(L, -1, "product", sd->product);
|
||||
@@ -61,6 +63,13 @@ void set_version (lua_State *L, const struct serviceDeductions *sd)
|
||||
setnfield(L, -1, "rpc_lowver", sd->rpc_lowver);
|
||||
setnfield(L, -1, "rpc_highver", sd->rpc_highver);
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
for (i = 0; i < sd->cpe.size(); i++) {
|
||||
lua_pushstring(L, sd->cpe[i]);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
lua_setfield(L, -2, "cpe");
|
||||
}
|
||||
|
||||
/* set some port state information onto the
|
||||
@@ -179,7 +188,8 @@ void set_hostinfo(lua_State *L, Target *currenths) {
|
||||
FPR->overall_results == OSSCAN_SUCCESS && FPR->num_perfect_matches > 0 &&
|
||||
FPR->num_perfect_matches <= 8 )
|
||||
{
|
||||
int i;
|
||||
int i, classno;
|
||||
const OS_Classification_Results *OSR = FPR->getOSClassification();
|
||||
|
||||
lua_newtable(L);
|
||||
// this will run at least one time and at most 8 times, see if condition
|
||||
@@ -187,6 +197,15 @@ void set_hostinfo(lua_State *L, Target *currenths) {
|
||||
lua_pushstring(L, FPR->matches[i]->OS_name);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
|
||||
for (classno = 0; classno < OSR->OSC_num_matches; classno++) {
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < OSR->OSC[classno]->cpe.size(); j++) {
|
||||
lua_pushstring(L, OSR->OSC[classno]->cpe[j]);
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
}
|
||||
lua_setfield(L, -2, "os");
|
||||
}
|
||||
}
|
||||
@@ -508,6 +527,7 @@ static int l_set_port_version (lua_State *L)
|
||||
Target *target;
|
||||
Port *p;
|
||||
Port port;
|
||||
std::vector<const char *> cpe;
|
||||
enum service_tunnel_type tunnel = SERVICE_TUNNEL_NONE;
|
||||
enum serviceprobestate probestate =
|
||||
opversion[luaL_checkoption(L, 3, "hardmatched", ops)];
|
||||
@@ -537,14 +557,23 @@ static int l_set_port_version (lua_State *L)
|
||||
else
|
||||
luaL_argerror(L, 2, "invalid value for port.version.service_tunnel");
|
||||
|
||||
lua_getfield(L, 4, "cpe");
|
||||
if (!lua_istable(L, -1))
|
||||
luaL_error(L, "port.version 'cpe' field must be a table");
|
||||
|
||||
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||
cpe.push_back(lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
if (o.servicescan)
|
||||
target->ports.setServiceProbeResults(p->portno, p->proto,
|
||||
probestate, name, tunnel, product,
|
||||
version, extrainfo, hostname, ostype, devicetype, NULL, NULL, NULL, NULL);
|
||||
version, extrainfo, hostname, ostype, devicetype,
|
||||
(cpe.size() > 0) ? &cpe : NULL, NULL);
|
||||
else
|
||||
target->ports.setServiceProbeResults(p->portno, p->proto,
|
||||
probestate, name, tunnel, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
32
portlist.cc
32
portlist.cc
@@ -115,7 +115,7 @@ Port::Port() {
|
||||
state_reason_init(&reason);
|
||||
}
|
||||
|
||||
void Port::freeService() {
|
||||
void Port::freeService(bool del_service) {
|
||||
if (service != NULL) {
|
||||
std::vector<char *>::iterator it;
|
||||
|
||||
@@ -137,7 +137,10 @@ void Port::freeService() {
|
||||
free(service->service_fp);
|
||||
for (it = service->cpe.begin(); it != service->cpe.end(); it++)
|
||||
free(*it);
|
||||
delete service;
|
||||
service->cpe.clear();
|
||||
|
||||
if (del_service)
|
||||
delete service;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,8 +339,9 @@ void PortList::setServiceProbeResults(u16 portno, int protocol,
|
||||
enum serviceprobestate sres, const char *sname,
|
||||
enum service_tunnel_type tunnel, const char *product, const char *version,
|
||||
const char *extrainfo, const char *hostname, const char *ostype,
|
||||
const char *devicetype, const char *cpe_a, const char *cpe_h, const char *cpe_o,
|
||||
const char *devicetype, const std::vector<const char *> *cpe,
|
||||
const char *fingerprint) {
|
||||
std::vector<char *>::iterator it;
|
||||
Port *port;
|
||||
char *p;
|
||||
|
||||
@@ -370,6 +374,8 @@ void PortList::setServiceProbeResults(u16 portno, int protocol,
|
||||
// port->serviceprobe_results = sres;
|
||||
port->service->service_tunnel = tunnel;
|
||||
|
||||
port->freeService(false);
|
||||
|
||||
if (sname)
|
||||
port->service->name = strdup(sname);
|
||||
else
|
||||
@@ -387,15 +393,15 @@ void PortList::setServiceProbeResults(u16 portno, int protocol,
|
||||
port->service->ostype = cstringSanityCheck(ostype, 32);
|
||||
port->service->devicetype = cstringSanityCheck(devicetype, 32);
|
||||
|
||||
p = cstringSanityCheck(cpe_a, 80);
|
||||
if (p != NULL)
|
||||
port->service->cpe.push_back(p);
|
||||
p = cstringSanityCheck(cpe_h, 80);
|
||||
if (p != NULL)
|
||||
port->service->cpe.push_back(p);
|
||||
p = cstringSanityCheck(cpe_o, 80);
|
||||
if (p != NULL)
|
||||
port->service->cpe.push_back(p);
|
||||
if (cpe) {
|
||||
std::vector<const char *>::const_iterator cit;
|
||||
|
||||
for (cit = cpe->begin(); cit != cpe->end(); cit++) {
|
||||
p = cstringSanityCheck(*cit, 80);
|
||||
if (p != NULL)
|
||||
port->service->cpe.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets the results of an RPC scan. if rpc_status is not
|
||||
@@ -498,7 +504,7 @@ PortList::~PortList() {
|
||||
if(port_list[proto]) {
|
||||
for(i=0; i < port_list_count[proto]; i++) { // free every Port
|
||||
if(port_list[proto][i]) {
|
||||
port_list[proto][i]->freeService();
|
||||
port_list[proto][i]->freeService(true);
|
||||
delete port_list[proto][i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ class Port {
|
||||
|
||||
public:
|
||||
Port();
|
||||
void freeService();
|
||||
void freeService(bool del_service);
|
||||
void getNmapServiceName(char *namebuf, int buflen, const char *rpcinfo) const;
|
||||
|
||||
u16 portno;
|
||||
@@ -267,7 +267,7 @@ class PortList {
|
||||
const char *version, const char *hostname,
|
||||
const char *ostype, const char *devicetype,
|
||||
const char *extrainfo,
|
||||
const char *cpe_a, const char *cpe_h, const char *cpe_o,
|
||||
const std::vector<const char *> *cpe,
|
||||
const char *fingerprint);
|
||||
|
||||
// pass in an allocated struct serviceDeductions (don't worry about initializing, and
|
||||
|
||||
@@ -2536,6 +2536,15 @@ list<ServiceNFO *>::iterator svc;
|
||||
|
||||
for(svc = SG->services_finished.begin(); svc != SG->services_finished.end(); svc++) {
|
||||
if ((*svc)->probe_state != PROBESTATE_FINISHED_NOMATCH) {
|
||||
vector<const char *> cpe;
|
||||
|
||||
if (*(*svc)->cpe_a_matched)
|
||||
cpe.push_back((*svc)->cpe_a_matched);
|
||||
if (*(*svc)->cpe_h_matched)
|
||||
cpe.push_back((*svc)->cpe_h_matched);
|
||||
if (*(*svc)->cpe_o_matched)
|
||||
cpe.push_back((*svc)->cpe_o_matched);
|
||||
|
||||
(*svc)->target->ports.setServiceProbeResults((*svc)->portno, (*svc)->proto,
|
||||
(*svc)->probe_state,
|
||||
(*svc)->probe_matched,
|
||||
@@ -2546,15 +2555,13 @@ list<ServiceNFO *>::iterator svc;
|
||||
*(*svc)->hostname_matched? (*svc)->hostname_matched : NULL,
|
||||
*(*svc)->ostype_matched? (*svc)->ostype_matched : NULL,
|
||||
*(*svc)->devicetype_matched? (*svc)->devicetype_matched : NULL,
|
||||
*(*svc)->cpe_a_matched? (*svc)->cpe_a_matched : NULL,
|
||||
*(*svc)->cpe_h_matched? (*svc)->cpe_h_matched : NULL,
|
||||
*(*svc)->cpe_o_matched? (*svc)->cpe_o_matched : NULL,
|
||||
(cpe.size() > 0) ? &cpe : NULL,
|
||||
shouldWePrintFingerprint(*svc) ? (*svc)->getServiceFingerprint(NULL) : NULL);
|
||||
} else {
|
||||
(*svc)->target->ports.setServiceProbeResults((*svc)->portno, (*svc)->proto,
|
||||
(*svc)->probe_state, NULL,
|
||||
(*svc)->tunnel, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL,
|
||||
(*svc)->getServiceFingerprint(NULL));
|
||||
}
|
||||
}
|
||||
@@ -2600,8 +2607,7 @@ static void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
||||
PROBESTATE_EXCLUDED, NULL,
|
||||
SERVICE_TUNNEL_NONE,
|
||||
"Excluded from version scan", NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
SG->services_remaining.erase(i);
|
||||
SG->services_finished.push_back(svc);
|
||||
|
||||
Reference in New Issue
Block a user