service_scan.cc
=================
Nmap's service-scanner is called by nmap.cc:nmap_main() inside its main loop.
The entry function is:
int service_scan(vector<Target *> &Targets)
which takes the list of recently port-scanned targets as argument.
Initialization
---------------
service_scan() begins with creating an AllProbes instance called AP using
service_scan_init(). AllProbes is a class that essentially contains all
different kinds of probes needed for the scanned services. It fetches them
trough an external file "nmap-service-probes" by calling
parse_nmap_service_probe_file() which is called by parse_nmap_service_probes()
inside service_scan_init(). The probes are pushed inside the AP.probes vector.
Each probe is an object of class ServiceProbe defined at service_scan.h and which
contains service-specific strings (probestring), fallbacks (see "Cheats and
Fallbacks @ Nmap book - chapter 7.3.1), the rarity variable and a vector of
ServiceProbeMatch variables called matches.
After creating AP, a ServiceGroup SG object is created. The class holds
general service information: in particular it holds 3 lists of class ServiceNFO
instances for services finished, in progress and remaining.
// This holds the service information for a group of Targets being
// service scanned.
class ServiceGroup {
public:
ServiceGroup(vector<Target *> &Targets, AllProbes *AP);
~ServiceGroup();
list<ServiceNFO *> services_finished;
// Services finished (discovered or not)
list<ServiceNFO *> services_in_progress; // Services currently being probed
list<ServiceNFO *> services_remaining; // Probes not started yet
unsigned int ideal_parallelism;
// Max (and desired) number of probes out at once.
ScanProgressMeter *SPM;
int num_hosts_timedout; // # of hosts timed out during (or before) scan
};
Class ServiceNFO holds per-port information like fingerprint information to
match the scanned service with the ones in the database. It also includes a
pointer to the Target that it belongs to.
The ServiceGroup constructor creates ServiceNFO instances by parsing the Targets
vector for open or open|filtered ports and pushes them into the
services_remaining vector.
for(targetno = 0 ; targetno < Targets.size(); targetno++) {
nxtport = NULL;
if (Targets[targetno]->timedOut(&now)) {
num_hosts_timedout++;
continue;
}
while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDP,
PORT_OPEN))) {
svc = new ServiceNFO(AP);
svc->target = Targets[targetno];
svc->portno = nxtport->portno;
svc->proto = nxtport->proto;
svc->port = nxtport;
services_remaining.push_back(svc);
}
}
service_scan() then creates an nsock pool and calls launchSomeServiceProbes()
before moving on to nsock_loop. launchSomeServiceProbes() is responsible for
making new connections by registering new (non-blocking) connect(2) events
through nsock. It is additionally called at the end of every callback handler
for service_scan's read, write and connect operations:
static void servicescan_read_handler(nsock_pool nsp, nsock_event nse,
void *mydata);
static void servicescan_write_handler(nsock_pool nsp, nsock_event nse,
void *mydata);
static void servicescan_connect_handler(nsock_pool nsp, nsock_event nse,
void *mydata);
|