mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Merge from /nmap-exp/david/nmap-mem. This reduces the memory usage of OS
scan by about 95%. (66832396 bytes to 2815061 bytes according to Massif.)
This commit is contained in:
@@ -117,7 +117,7 @@ FingerPrintResults::~FingerPrintResults() {
|
|||||||
|
|
||||||
/* Free OS fingerprints of OS scanning was done */
|
/* Free OS fingerprints of OS scanning was done */
|
||||||
for(i=0; i < numFPs; i++) {
|
for(i=0; i < numFPs; i++) {
|
||||||
freeFingerPrint(FPs[i]);
|
delete(FPs[i]);
|
||||||
FPs[i] = NULL;
|
FPs[i] = NULL;
|
||||||
}
|
}
|
||||||
numFPs = 0;
|
numFPs = 0;
|
||||||
@@ -184,7 +184,8 @@ const char *FingerPrintResults::OmitSubmissionFP() {
|
|||||||
|
|
||||||
/* Goes through fingerprinting results to populate OSR */
|
/* Goes through fingerprinting results to populate OSR */
|
||||||
void FingerPrintResults::populateClassification() {
|
void FingerPrintResults::populateClassification() {
|
||||||
int printno, classno;
|
std::vector<OS_Classification>::iterator osclass;
|
||||||
|
int printno;
|
||||||
|
|
||||||
OSR.OSC_num_perfect_matches = OSR.OSC_num_matches = 0;
|
OSR.OSC_num_perfect_matches = OSR.OSC_num_matches = 0;
|
||||||
OSR.overall_results = OSSCAN_SUCCESS;
|
OSR.overall_results = OSSCAN_SUCCESS;
|
||||||
@@ -198,8 +199,10 @@ void FingerPrintResults::populateClassification() {
|
|||||||
|
|
||||||
for(printno = 0; printno < num_matches; printno++) {
|
for(printno = 0; printno < num_matches; printno++) {
|
||||||
// a single print may have multiple classifications
|
// a single print may have multiple classifications
|
||||||
for(classno = 0; classno < prints[printno]->num_OS_Classifications; classno++) {
|
for (osclass = prints[printno]->OS_class.begin();
|
||||||
if (!classAlreadyExistsInResults(&(prints[printno]->OS_class[classno]))) {
|
osclass != prints[printno]->OS_class.end();
|
||||||
|
osclass++) {
|
||||||
|
if (!classAlreadyExistsInResults(&*osclass)) {
|
||||||
// Then we have to add it ... first ensure we have room
|
// Then we have to add it ... first ensure we have room
|
||||||
if (OSR.OSC_num_matches == MAX_FP_RESULTS) {
|
if (OSR.OSC_num_matches == MAX_FP_RESULTS) {
|
||||||
// Out of space ... if the accuracy of this one is 100%, we have a problem
|
// Out of space ... if the accuracy of this one is 100%, we have a problem
|
||||||
@@ -215,7 +218,7 @@ void FingerPrintResults::populateClassification() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OK, we will add the new class
|
// OK, we will add the new class
|
||||||
OSR.OSC[OSR.OSC_num_matches] = &(prints[printno]->OS_class[classno]);
|
OSR.OSC[OSR.OSC_num_matches] = &*osclass;
|
||||||
OSR.OSC_Accuracy[OSR.OSC_num_matches] = accuracy[printno];
|
OSR.OSC_Accuracy[OSR.OSC_num_matches] = accuracy[printno];
|
||||||
if (accuracy[printno] == 1.0) OSR.OSC_num_perfect_matches++;
|
if (accuracy[printno] == 1.0) OSR.OSC_num_perfect_matches++;
|
||||||
OSR.OSC_num_matches++;
|
OSR.OSC_num_matches++;
|
||||||
|
|||||||
@@ -94,6 +94,8 @@
|
|||||||
#ifndef GLOBAL_STRUCTURES_H
|
#ifndef GLOBAL_STRUCTURES_H
|
||||||
#define GLOBAL_STRUCTURES_H
|
#define GLOBAL_STRUCTURES_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class TargetGroup;
|
class TargetGroup;
|
||||||
class Target;
|
class Target;
|
||||||
|
|
||||||
@@ -155,35 +157,38 @@ struct ftpinfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct AVal {
|
struct AVal {
|
||||||
char *attribute;
|
const char *attribute;
|
||||||
char value[256];
|
const char *value;
|
||||||
struct AVal *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OS_Classification {
|
struct OS_Classification {
|
||||||
char *OS_Vendor;
|
const char *OS_Vendor;
|
||||||
char *OS_Family;
|
const char *OS_Family;
|
||||||
char *OS_Generation; /* Can be NULL if unclassified */
|
const char *OS_Generation; /* Can be NULL if unclassified */
|
||||||
char *Device_Type;
|
const char *Device_Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_OS_CLASSIFICATIONS_PER_FP 10
|
struct FingerTest {
|
||||||
typedef struct FingerTest {
|
|
||||||
char *OS_name;
|
|
||||||
struct OS_Classification OS_class[MAX_OS_CLASSIFICATIONS_PER_FP];
|
|
||||||
int num_OS_Classifications;
|
|
||||||
int line; /* For reference prints, the line # in nmap-os-db */
|
|
||||||
const char *name;
|
const char *name;
|
||||||
struct AVal *results;
|
std::vector<struct AVal> results;
|
||||||
struct FingerTest *next;
|
};
|
||||||
} FingerPrint;
|
|
||||||
|
struct FingerPrint {
|
||||||
|
int line; /* For reference prints, the line # in nmap-os-db */
|
||||||
|
char *OS_name;
|
||||||
|
std::vector<OS_Classification> OS_class;
|
||||||
|
std::vector<FingerTest> tests;
|
||||||
|
};
|
||||||
|
|
||||||
/* This structure contains the important data from the fingerprint
|
/* This structure contains the important data from the fingerprint
|
||||||
database (nmap-os-db) */
|
database (nmap-os-db) */
|
||||||
typedef struct FingerPrintDB {
|
struct FingerPrintDB {
|
||||||
FingerPrint **prints;
|
|
||||||
FingerPrint *MatchPoints;
|
FingerPrint *MatchPoints;
|
||||||
} FingerPrintDB;
|
std::vector<FingerPrint *> prints;
|
||||||
|
|
||||||
|
FingerPrintDB();
|
||||||
|
~FingerPrintDB();
|
||||||
|
};
|
||||||
|
|
||||||
struct timeout_info {
|
struct timeout_info {
|
||||||
int srtt; /* Smoothed rtt estimate (microseconds) */
|
int srtt; /* Smoothed rtt estimate (microseconds) */
|
||||||
|
|||||||
2
nmap.cc
2
nmap.cc
@@ -1976,7 +1976,7 @@ void nmap_free_mem() {
|
|||||||
free_dns_servers();
|
free_dns_servers();
|
||||||
free_etchosts();
|
free_etchosts();
|
||||||
if (o.reference_FPs) {
|
if (o.reference_FPs) {
|
||||||
free_fingerprint_file(o.reference_FPs);
|
delete o.reference_FPs;
|
||||||
o.reference_FPs = NULL;
|
o.reference_FPs = NULL;
|
||||||
}
|
}
|
||||||
AllProbes::service_scan_free();
|
AllProbes::service_scan_free();
|
||||||
|
|||||||
455
osscan.cc
455
osscan.cc
@@ -100,6 +100,7 @@
|
|||||||
#include "nmap_error.h"
|
#include "nmap_error.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#if TIME_WITH_SYS_TIME
|
#if TIME_WITH_SYS_TIME
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
@@ -112,27 +113,103 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
|
|
||||||
static struct AVal *getattrbyname(struct AVal *AV, const char *name) {
|
/* Store a string uniquely. The first time this function is called with a
|
||||||
if (!AV) return NULL;
|
certain string, it allocates memory and stores a copy of the string in a
|
||||||
do {
|
static pool. Thereafter it will return a pointer to the saved string instead
|
||||||
if (!strcmp(AV->attribute, name))
|
of allocating memory for an identical one. */
|
||||||
return AV;
|
const char *string_pool_insert(const char *s)
|
||||||
AV = AV->next;
|
{
|
||||||
} while(AV);
|
static std::set<std::string> pool;
|
||||||
|
static std::pair<std::set<std::string>::iterator, bool> pair;
|
||||||
|
|
||||||
|
pair = pool.insert(s);
|
||||||
|
|
||||||
|
return pair.first->c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *string_pool_substr(const char *s, const char *t)
|
||||||
|
{
|
||||||
|
return string_pool_insert(std::string(s, t).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *string_pool_substr_strip(const char *s, const char *t) {
|
||||||
|
while (isspace((int) (unsigned char) *s))
|
||||||
|
s++;
|
||||||
|
while (t > s && isspace((int) (unsigned char) *(t - 1)))
|
||||||
|
t--;
|
||||||
|
|
||||||
|
return string_pool_substr(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format a string with sprintf and insert it with string_pool_insert. */
|
||||||
|
const char *string_pool_sprintf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
char *buf;
|
||||||
|
int size, n;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
buf = NULL;
|
||||||
|
size = 32;
|
||||||
|
/* Loop until we allocate a string big enough for the sprintf. */
|
||||||
|
for (;;) {
|
||||||
|
buf = (char *) realloc(buf, size);
|
||||||
|
assert(buf != NULL);
|
||||||
|
va_start(ap, fmt);
|
||||||
|
n = Vsnprintf(buf, size, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (n < 0)
|
||||||
|
size = size * 2;
|
||||||
|
else if (n >= size)
|
||||||
|
size = n + 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = string_pool_insert(buf);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
FingerPrintDB::FingerPrintDB() : MatchPoints(NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
FingerPrintDB::~FingerPrintDB() {
|
||||||
|
std::vector<FingerPrint *>::iterator current;
|
||||||
|
|
||||||
|
if (MatchPoints != NULL)
|
||||||
|
delete MatchPoints;
|
||||||
|
for (current = prints.begin(); current != prints.end(); current++)
|
||||||
|
delete *current;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct AVal *getattrbyname(const FingerTest *test, const char *name) {
|
||||||
|
std::vector<struct AVal>::const_iterator i;
|
||||||
|
|
||||||
|
if (test == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (i = test->results.begin(); i != test->results.end(); i++) {
|
||||||
|
if (strcmp(i->attribute, name) == 0)
|
||||||
|
return &*i;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct AVal *gettestbyname(FingerPrint *FP, const char *name) {
|
static FingerTest *gettestbyname(FingerPrint *FP, const char *name) {
|
||||||
|
std::vector<FingerTest>::iterator i;
|
||||||
|
|
||||||
if (!FP) return NULL;
|
if (!FP) return NULL;
|
||||||
do {
|
for (i = FP->tests.begin(); i != FP->tests.end(); i++) {
|
||||||
if (!strcmp(FP->name, name))
|
if (strcmp(i->name, name) == 0)
|
||||||
return FP->results;
|
return &*i;
|
||||||
FP = FP->next;
|
};
|
||||||
} while(FP);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +226,13 @@ static struct AVal *gettestbyname(FingerPrint *FP, const char *name) {
|
|||||||
case, you may also pass in the group name (SEQ, T1, etc) to have
|
case, you may also pass in the group name (SEQ, T1, etc) to have
|
||||||
that extra info printed. If you pass 0 for verbose, you might as
|
that extra info printed. If you pass 0 for verbose, you might as
|
||||||
well pass NULL for testGroupName as it won't be used. */
|
well pass NULL for testGroupName as it won't be used. */
|
||||||
static int AVal_match(struct AVal *reference, struct AVal *fprint, struct AVal *points,
|
static int AVal_match(FingerTest *reference, FingerTest *fprint, FingerTest *points,
|
||||||
unsigned long *num_subtests,
|
unsigned long *num_subtests,
|
||||||
unsigned long *num_subtests_succeeded, int shortcut,
|
unsigned long *num_subtests_succeeded, int shortcut,
|
||||||
int verbose, const char *testGroupName) {
|
int verbose, const char *testGroupName) {
|
||||||
struct AVal *current_ref;
|
std::vector<struct AVal>::iterator current_ref;
|
||||||
struct AVal *current_fp;
|
const struct AVal *current_fp;
|
||||||
struct AVal *current_points;
|
const struct AVal *current_points;
|
||||||
unsigned int number, number1;
|
unsigned int number, number1;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */
|
char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */
|
||||||
@@ -166,8 +243,9 @@ static int AVal_match(struct AVal *reference, struct AVal *fprint, struct AVal *
|
|||||||
int subtests = 0, subtests_succeeded=0;
|
int subtests = 0, subtests_succeeded=0;
|
||||||
int pointsThisTest = 1;
|
int pointsThisTest = 1;
|
||||||
|
|
||||||
|
for (current_ref = reference->results.begin();
|
||||||
for(current_ref = reference; current_ref; current_ref = current_ref->next) {
|
current_ref != reference->results.end();
|
||||||
|
current_ref++) {
|
||||||
current_fp = getattrbyname(fprint, current_ref->attribute);
|
current_fp = getattrbyname(fprint, current_ref->attribute);
|
||||||
if (!current_fp) continue;
|
if (!current_fp) continue;
|
||||||
/* OK, we compare an attribute value in current_fp->value to a
|
/* OK, we compare an attribute value in current_fp->value to a
|
||||||
@@ -255,16 +333,17 @@ static int AVal_match(struct AVal *reference, struct AVal *fprint, struct AVal *
|
|||||||
a special "fingerprints" which tells how many points each test is worth. */
|
a special "fingerprints" which tells how many points each test is worth. */
|
||||||
double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
|
double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
|
||||||
FingerPrint *MatchPoints, int verbose) {
|
FingerPrint *MatchPoints, int verbose) {
|
||||||
FingerPrint *currentReferenceTest;
|
std::vector<FingerTest>::iterator currentReferenceTest;
|
||||||
struct AVal *currentObservedTest;
|
FingerTest *currentObservedTest;
|
||||||
struct AVal *currentTestMatchPoints;
|
FingerTest *currentTestMatchPoints;
|
||||||
unsigned long num_subtests = 0, num_subtests_succeeded = 0;
|
unsigned long num_subtests = 0, num_subtests_succeeded = 0;
|
||||||
unsigned long new_subtests, new_subtests_succeeded;
|
unsigned long new_subtests, new_subtests_succeeded;
|
||||||
assert(referenceFP);
|
assert(referenceFP);
|
||||||
assert(observedFP);
|
assert(observedFP);
|
||||||
|
|
||||||
for(currentReferenceTest = referenceFP; currentReferenceTest;
|
for (currentReferenceTest = referenceFP->tests.begin();
|
||||||
currentReferenceTest = currentReferenceTest->next) {
|
currentReferenceTest != referenceFP->tests.end();
|
||||||
|
currentReferenceTest++) {
|
||||||
currentObservedTest = gettestbyname(observedFP, currentReferenceTest->name);
|
currentObservedTest = gettestbyname(observedFP, currentReferenceTest->name);
|
||||||
if (currentObservedTest) {
|
if (currentObservedTest) {
|
||||||
new_subtests = new_subtests_succeeded = 0;
|
new_subtests = new_subtests_succeeded = 0;
|
||||||
@@ -274,7 +353,7 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
|
|||||||
fatal("%s: Failed to locate test %s in MatchPoints directive of fingerprint file", __func__, currentReferenceTest->name);
|
fatal("%s: Failed to locate test %s in MatchPoints directive of fingerprint file", __func__, currentReferenceTest->name);
|
||||||
} else currentTestMatchPoints = NULL;
|
} else currentTestMatchPoints = NULL;
|
||||||
|
|
||||||
AVal_match(currentReferenceTest->results, currentObservedTest, currentTestMatchPoints,
|
AVal_match(&*currentReferenceTest, currentObservedTest, currentTestMatchPoints,
|
||||||
&new_subtests, &new_subtests_succeeded, 0, verbose, currentReferenceTest->name);
|
&new_subtests, &new_subtests_succeeded, 0, verbose, currentReferenceTest->name);
|
||||||
num_subtests += new_subtests;
|
num_subtests += new_subtests;
|
||||||
num_subtests_succeeded += new_subtests_succeeded;
|
num_subtests_succeeded += new_subtests_succeeded;
|
||||||
@@ -293,14 +372,11 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
|
|||||||
the maximum that fits in a FingerPrintResults class. */
|
the maximum that fits in a FingerPrintResults class. */
|
||||||
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
||||||
FingerPrintDB *DB, double accuracy_threshold) {
|
FingerPrintDB *DB, double accuracy_threshold) {
|
||||||
|
|
||||||
int i;
|
|
||||||
double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be
|
double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be
|
||||||
at least this big
|
at least this big
|
||||||
to be added to the
|
to be added to the
|
||||||
list */
|
list */
|
||||||
FingerPrint **reference_FPs = DB->prints;
|
std::vector<FingerPrint *>::iterator current_os;
|
||||||
FingerPrint *current_os;
|
|
||||||
double acc;
|
double acc;
|
||||||
int state;
|
int state;
|
||||||
int skipfp;
|
int skipfp;
|
||||||
@@ -315,18 +391,17 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
|||||||
|
|
||||||
FPR->overall_results = OSSCAN_SUCCESS;
|
FPR->overall_results = OSSCAN_SUCCESS;
|
||||||
|
|
||||||
for(i = 0; reference_FPs[i]; i++) {
|
for (current_os = DB->prints.begin(); current_os != DB->prints.end(); current_os++) {
|
||||||
current_os = reference_FPs[i];
|
|
||||||
skipfp = 0;
|
skipfp = 0;
|
||||||
|
|
||||||
acc = compare_fingerprints(current_os, FP, DB->MatchPoints, 0);
|
acc = compare_fingerprints(*current_os, FP, DB->MatchPoints, 0);
|
||||||
|
|
||||||
/* error("Comp to %s: %li/%li=%f", o.reference_FPs1[i]->OS_name, num_subtests_succeeded, num_subtests, acc); */
|
/* error("Comp to %s: %li/%li=%f", o.reference_FPs1[i]->OS_name, num_subtests_succeeded, num_subtests, acc); */
|
||||||
if (acc >= FPR_entrance_requirement || acc == 1.0) {
|
if (acc >= FPR_entrance_requirement || acc == 1.0) {
|
||||||
|
|
||||||
state = 0;
|
state = 0;
|
||||||
for(idx=0; idx < FPR->num_matches; idx++) {
|
for(idx=0; idx < FPR->num_matches; idx++) {
|
||||||
if (strcmp(FPR->prints[idx]->OS_name, current_os->OS_name) == 0) {
|
if (strcmp(FPR->prints[idx]->OS_name, (*current_os)->OS_name) == 0) {
|
||||||
if (FPR->accuracy[idx] >= acc) {
|
if (FPR->accuracy[idx] >= acc) {
|
||||||
skipfp = 1; /* Skip it -- a higher version is already in list */
|
skipfp = 1; /* Skip it -- a higher version is already in list */
|
||||||
} else {
|
} else {
|
||||||
@@ -370,7 +445,7 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
|||||||
/* OK, I insert the sucker into the next slot ... */
|
/* OK, I insert the sucker into the next slot ... */
|
||||||
tmp_acc = FPR->accuracy[idx+1];
|
tmp_acc = FPR->accuracy[idx+1];
|
||||||
tmp_FP = FPR->prints[idx+1];
|
tmp_FP = FPR->prints[idx+1];
|
||||||
FPR->prints[idx+1] = current_os;
|
FPR->prints[idx+1] = *current_os;
|
||||||
FPR->accuracy[idx+1] = acc;
|
FPR->accuracy[idx+1] = acc;
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
@@ -396,21 +471,6 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeFingerPrint(FingerPrint *FP) {
|
|
||||||
FingerPrint *currentFP;
|
|
||||||
FingerPrint *nextFP;
|
|
||||||
|
|
||||||
if (!FP) return;
|
|
||||||
|
|
||||||
for(currentFP = FP; currentFP; currentFP = nextFP) {
|
|
||||||
nextFP = currentFP->next;
|
|
||||||
if (currentFP->results)
|
|
||||||
free(currentFP->results);
|
|
||||||
free(currentFP);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *dist_method_fp_string(enum dist_calc_method method)
|
static const char *dist_method_fp_string(enum dist_calc_method method)
|
||||||
{
|
{
|
||||||
const char *s = "";
|
const char *s = "";
|
||||||
@@ -482,50 +542,76 @@ static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP,
|
|||||||
macbuf, (int) timep, NMAP_PLATFORM);
|
macbuf, (int) timep, NMAP_PLATFORM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Puts a textual representation of the chain of AVals beginning with AV in s.
|
/* Puts a textual representation of the test in s.
|
||||||
No more than n bytes will be written. Unless n is 0, the string is always
|
No more than n bytes will be written. Unless n is 0, the string is always
|
||||||
null-terminated. Returns the number of bytes written, excluding the
|
null-terminated. Returns the number of bytes written, excluding the
|
||||||
terminator. */
|
terminator. */
|
||||||
static int AVal2str(const struct AVal *AV, char *s, size_t n) {
|
static int test2str(const FingerTest *test, char *s, size_t n) {
|
||||||
|
std::vector<struct AVal>::const_iterator av;
|
||||||
char *p;
|
char *p;
|
||||||
char *end;
|
char *end;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (AV == NULL) {
|
if (n == 0)
|
||||||
if (n > 0)
|
|
||||||
*s = '\0';
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
p = s;
|
p = s;
|
||||||
end = s + n - 1;
|
end = s + n - 1;
|
||||||
for ( ; AV != NULL; AV = AV->next) {
|
|
||||||
if (p >= end)
|
len = strlen(test->name);
|
||||||
break;
|
if (p + len > end)
|
||||||
/* Put a separator in front of every attribute-value pair but the first. */
|
goto error;
|
||||||
if (p != s)
|
|
||||||
*p++ = '%';
|
memcpy(p, test->name, len);
|
||||||
len = MIN((ptrdiff_t) strlen(AV->attribute), end - p);
|
|
||||||
memcpy(p, AV->attribute, len);
|
|
||||||
p += len;
|
p += len;
|
||||||
if (p >= end)
|
if (p + 1 > end)
|
||||||
break;
|
goto error;
|
||||||
|
*p++ = '(';
|
||||||
|
|
||||||
|
for (av = test->results.begin(); av != test->results.end(); av++) {
|
||||||
|
if (av != test->results.begin()) {
|
||||||
|
if (p + 1 > end)
|
||||||
|
goto error;
|
||||||
|
*p++ = '%';
|
||||||
|
}
|
||||||
|
len = strlen(av->attribute);
|
||||||
|
if (p + len > end)
|
||||||
|
goto error;
|
||||||
|
memcpy(p, av->attribute, len);
|
||||||
|
p += len;
|
||||||
|
if (p + 1 > end)
|
||||||
|
goto error;
|
||||||
*p++ = '=';
|
*p++ = '=';
|
||||||
len = MIN((ptrdiff_t) strlen(AV->value), end - p);
|
len = strlen(av->value);
|
||||||
memcpy(p, AV->value, len);
|
if (p + len > end)
|
||||||
|
goto error;
|
||||||
|
memcpy(p, av->value, len);
|
||||||
p += len;
|
p += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p + 1 > end)
|
||||||
|
goto error;
|
||||||
|
*p++ = ')';
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
return p - s;
|
return p - s;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (n > 0)
|
||||||
|
*s = '\0';
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct AVal *str2AVal(char *str) {
|
static std::vector<struct AVal> str2AVal(char *str) {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
char *q = str, *p=str;
|
char *q = str, *p=str;
|
||||||
struct AVal *AVs;
|
std::vector<struct AVal> AVs;
|
||||||
if (!*str) return NULL;
|
|
||||||
|
if (!*str)
|
||||||
|
return std::vector<struct AVal>();
|
||||||
|
|
||||||
/* count the AVals */
|
/* count the AVals */
|
||||||
while((q = strchr(q, '%'))) {
|
while((q = strchr(q, '%'))) {
|
||||||
@@ -533,14 +619,16 @@ static struct AVal *str2AVal(char *str) {
|
|||||||
q++;
|
q++;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVs = (struct AVal *) safe_zalloc(count * sizeof(struct AVal));
|
AVs.reserve(count);
|
||||||
for(i=0; i < count; i++) {
|
for(i=0; i < count; i++) {
|
||||||
|
struct AVal av;
|
||||||
|
|
||||||
q = strchr(p, '=');
|
q = strchr(p, '=');
|
||||||
if (!q) {
|
if (!q) {
|
||||||
fatal("Parse error with AVal string (%s) in nmap-os-db file", str);
|
fatal("Parse error with AVal string (%s) in nmap-os-db file", str);
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
AVs[i].attribute = strdup(p);
|
av.attribute = string_pool_insert(p);
|
||||||
p = q+1;
|
p = q+1;
|
||||||
if (i != count - 1) {
|
if (i != count - 1) {
|
||||||
q = strchr(p, '%');
|
q = strchr(p, '%');
|
||||||
@@ -548,31 +636,33 @@ static struct AVal *str2AVal(char *str) {
|
|||||||
fatal("Parse error with AVal string (%s) in nmap-os-db file", str);
|
fatal("Parse error with AVal string (%s) in nmap-os-db file", str);
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
AVs[i].next = &AVs[i+1];
|
|
||||||
}
|
}
|
||||||
Strncpy(AVs[i].value, p, sizeof(AVs[i].value));
|
av.value = string_pool_insert(p);
|
||||||
p = q + 1;
|
p = q + 1;
|
||||||
|
AVs.push_back(av);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AVs;
|
return AVs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare two AVal chains literally, without evaluating the value of either one
|
/* Compare two AVal chains literally, without evaluating the value of either one
|
||||||
as an expression. This is used by mergeFPs. Unlike with AVal_match, it is
|
as an expression. This is used by mergeFPs. Unlike with AVal_match, it is
|
||||||
always the case that AVal_match_literal(a, b) == AVal_match_literal(b, a). */
|
always the case that AVal_match_literal(a, b) == AVal_match_literal(b, a). */
|
||||||
static bool AVal_match_literal(struct AVal *a, struct AVal *b) {
|
static bool test_match_literal(const FingerTest *a, const FingerTest *b) {
|
||||||
struct AVal *av_a, *av_b;
|
std::vector<struct AVal>::const_iterator i;
|
||||||
|
const struct AVal *av;
|
||||||
|
|
||||||
/* Check that b contains all the AVals in a, with the same values. */
|
/* Check that b contains all the AVals in a, with the same values. */
|
||||||
for (av_a = a; av_a != NULL; av_a = av_a->next) {
|
for (i = a->results.begin(); i != a->results.end(); i++) {
|
||||||
av_b = getattrbyname(b, av_a->attribute);
|
av = getattrbyname(b, i->attribute);
|
||||||
if (av_b == NULL || strcmp(av_a->value, av_b->value) != 0)
|
if (av == NULL || strcmp(i->value, av->value) != 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that a contains all the AVals in b, with the same values. */
|
/* Check that a contains all the AVals in b, with the same values. */
|
||||||
for (av_b = a; av_b != NULL; av_b = av_b->next) {
|
for (i = b->results.begin(); i != b->results.end(); i++) {
|
||||||
av_a = getattrbyname(a, av_b->attribute);
|
av = getattrbyname(a, i->attribute);
|
||||||
if (av_a == NULL || strcmp(av_a->value, av_b->value) != 0)
|
if (av == NULL || strcmp(i->value, av->value) != 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,7 +723,7 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
|
|||||||
char *end = str + sizeof(str) - 1; /* Last byte allowed to write into */
|
char *end = str + sizeof(str) - 1; /* Last byte allowed to write into */
|
||||||
std::list<const FingerTest *> tests;
|
std::list<const FingerTest *> tests;
|
||||||
std::list<const FingerTest *>::iterator iter;
|
std::list<const FingerTest *>::iterator iter;
|
||||||
const FingerTest *ft;
|
std::vector<FingerTest>::iterator ft;
|
||||||
|
|
||||||
if (numFPs <= 0)
|
if (numFPs <= 0)
|
||||||
return "(None)";
|
return "(None)";
|
||||||
@@ -642,8 +732,8 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
|
|||||||
|
|
||||||
/* Copy the tests from each fingerprint into a flat list. */
|
/* Copy the tests from each fingerprint into a flat list. */
|
||||||
for (i = 0; i < numFPs; i++) {
|
for (i = 0; i < numFPs; i++) {
|
||||||
for (ft = FPs[i]; ft != NULL; ft = ft->next)
|
for (ft = FPs[i]->tests.begin(); ft != FPs[i]->tests.end(); ft++)
|
||||||
tests.push_back(ft);
|
tests.push_back(&*ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the tests in the proper order and ensure that tests with identical
|
/* Put the tests in the proper order and ensure that tests with identical
|
||||||
@@ -660,7 +750,7 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
|
|||||||
while (tmp_i != tests.end() && strcmp((*iter)->name, (*tmp_i)->name) == 0) {
|
while (tmp_i != tests.end() && strcmp((*iter)->name, (*tmp_i)->name) == 0) {
|
||||||
next = tmp_i;
|
next = tmp_i;
|
||||||
next++;
|
next++;
|
||||||
if (AVal_match_literal((*iter)->results, (*tmp_i)->results)) {
|
if (test_match_literal(*iter, *tmp_i)) {
|
||||||
/* This is a duplicate test. Remove it. */
|
/* This is a duplicate test. Remove it. */
|
||||||
tests.erase(tmp_i);
|
tests.erase(tmp_i);
|
||||||
}
|
}
|
||||||
@@ -670,17 +760,16 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
|
|||||||
|
|
||||||
/* A safety check to make sure that no tests were lost in merging. */
|
/* A safety check to make sure that no tests were lost in merging. */
|
||||||
for (i = 0; i < numFPs; i++) {
|
for (i = 0; i < numFPs; i++) {
|
||||||
for (ft = FPs[i]; ft != NULL; ft = ft->next) {
|
for (ft = FPs[i]->tests.begin(); ft != FPs[i]->tests.end(); ft++) {
|
||||||
for (iter = tests.begin(); iter != tests.end(); iter++) {
|
for (iter = tests.begin(); iter != tests.end(); iter++) {
|
||||||
if (strcmp((*iter)->name, ft->name) == 0
|
if (strcmp((*iter)->name, ft->name) == 0 && test_match_literal(*iter, &*ft)) {
|
||||||
&& AVal_match_literal((*iter)->results, ft->results)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (iter == tests.end()) {
|
if (iter == tests.end()) {
|
||||||
char buf[200];
|
char buf[200];
|
||||||
AVal2str(ft->results, buf, sizeof(buf));
|
test2str(&*ft, buf, sizeof(buf));
|
||||||
fatal("The test %s(%s) was somehow lost in %s.\n", ft->name, buf, __func__);
|
fatal("The test %s was somehow lost in %s.\n", buf, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -698,29 +787,21 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
|
|||||||
|
|
||||||
/* Append the string representation of each test to the result string. */
|
/* Append the string representation of each test to the result string. */
|
||||||
for (iter = tests.begin(); iter != tests.end(); iter++) {
|
for (iter = tests.begin(); iter != tests.end(); iter++) {
|
||||||
size_t len;
|
int len;
|
||||||
|
|
||||||
ft = *iter;
|
len = test2str(*iter, p, end - p + 1);
|
||||||
len = MIN((ptrdiff_t) strlen(ft->name), (end - p));
|
if (len == -1)
|
||||||
memcpy(p, ft->name, len);
|
|
||||||
p += len;
|
|
||||||
if (p >= end)
|
|
||||||
break;
|
break;
|
||||||
*p++ = '(';
|
|
||||||
len = AVal2str(ft->results, p, end - p + 1);
|
|
||||||
p += len;
|
p += len;
|
||||||
if (p >= end)
|
|
||||||
break;
|
|
||||||
*p++ = ')';
|
|
||||||
if (!wrapit) {
|
if (!wrapit) {
|
||||||
if (p >= end)
|
if (p + 1 > end)
|
||||||
break;
|
break;
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we bailed out of the loop early it was because we ran out of space. */
|
/* If we bailed out of the loop early it was because we ran out of space. */
|
||||||
if (iter != tests.end() || p > end)
|
if (iter != tests.end())
|
||||||
fatal("Merged fingerprint too long in %s.\n", __func__);
|
fatal("Merged fingerprint too long in %s.\n", __func__);
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
@@ -755,86 +836,51 @@ return str;
|
|||||||
|
|
||||||
const char *fp2ascii(FingerPrint *FP) {
|
const char *fp2ascii(FingerPrint *FP) {
|
||||||
static char str[2048];
|
static char str[2048];
|
||||||
FingerPrint *current;
|
std::vector<FingerTest>::iterator iter;
|
||||||
struct AVal *AV;
|
|
||||||
char *p = str;
|
char *p = str;
|
||||||
memset(str, 0, sizeof(str));
|
|
||||||
|
|
||||||
if (!FP) return "(None)";
|
if (!FP) return "(None)";
|
||||||
|
|
||||||
for(current = FP; current ; current = current->next) {
|
for (iter = FP->tests.begin(); iter != FP->tests.end(); iter++) {
|
||||||
Strncpy(p, current->name, sizeof(str) - (p-str));
|
int len;
|
||||||
p += strlen(p);
|
|
||||||
assert(p-str < (int) sizeof(str) - 30);
|
len = test2str(&*iter, p, sizeof(str) - (p - str));
|
||||||
*p++='(';
|
if (len == -1)
|
||||||
for(AV = current->results; AV; AV = AV->next) {
|
break;
|
||||||
Strncpy(p, AV->attribute, sizeof(str) - (p-str));
|
p += len;
|
||||||
p += strlen(p);
|
if (p + 1 > str + sizeof(str))
|
||||||
assert(p-str < (int) sizeof(str) - 30);
|
break;
|
||||||
*p++='=';
|
|
||||||
Strncpy(p, AV->value, sizeof(str) - (p-str));
|
|
||||||
p += strlen(p);
|
|
||||||
assert(p-str < (int) sizeof(str) - 30);
|
|
||||||
*p++ = '%';
|
|
||||||
}
|
|
||||||
if(*(p-1) != '(')
|
|
||||||
p--; /* Kill the final & */
|
|
||||||
*p++ = ')';
|
|
||||||
*p++ = '\n';
|
*p++ = '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a zero-terminated copy of the substring that starts at p and ends at
|
|
||||||
q, with leading and trailing whitespace stripped. The returned string is
|
|
||||||
allocated with cp_alloc. */
|
|
||||||
static char *substrstrip(const char *p, const char *q) {
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
assert(p <= q);
|
|
||||||
|
|
||||||
while (isspace((int) (unsigned char) *p))
|
|
||||||
p++;
|
|
||||||
while (q > p && isspace((int) (unsigned char) *(q - 1)))
|
|
||||||
q--;
|
|
||||||
|
|
||||||
s = (char *) cp_alloc(q - p + 1);
|
|
||||||
memcpy(s, p, q - p);
|
|
||||||
s[q - p] = '\0';
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse a 'Class' line found in the fingerprint file into the current
|
/* Parse a 'Class' line found in the fingerprint file into the current
|
||||||
FP. Classno is the number of 'class' lines found so far in the
|
FP. Classno is the number of 'class' lines found so far in the
|
||||||
current fingerprint. The function quits if there is a parse error */
|
current fingerprint. The function quits if there is a parse error */
|
||||||
static void parse_classline(FingerPrint *FP, char *thisline, int lineno,
|
static void parse_classline(FingerPrint *FP, char *thisline, int lineno) {
|
||||||
int *classno) {
|
|
||||||
const char *begin, *end;
|
const char *begin, *end;
|
||||||
struct OS_Classification *os_class;
|
struct OS_Classification os_class;
|
||||||
|
|
||||||
if (!thisline || strncmp(thisline, "Class ", 6) != 0)
|
if (!thisline || strncmp(thisline, "Class ", 6) != 0)
|
||||||
fatal("Bogus line #%d (%s) passed to %s()", lineno, thisline, __func__);
|
fatal("Bogus line #%d (%s) passed to %s()", lineno, thisline, __func__);
|
||||||
|
|
||||||
if (*classno >= MAX_OS_CLASSIFICATIONS_PER_FP)
|
|
||||||
fatal("Too many Class lines in fingerprint (line %d: %s), remove some or increase MAX_OS_CLASSIFICATIONS_PER_FP", lineno, thisline);
|
|
||||||
|
|
||||||
os_class = &FP->OS_class[*classno];
|
|
||||||
|
|
||||||
/* First let's get the vendor name. */
|
/* First let's get the vendor name. */
|
||||||
begin = thisline + 6;
|
begin = thisline + 6;
|
||||||
end = strchr(begin, '|');
|
end = strchr(begin, '|');
|
||||||
if (end == NULL)
|
if (end == NULL)
|
||||||
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
||||||
os_class->OS_Vendor = substrstrip(begin, end);
|
os_class.OS_Vendor = string_pool_substr_strip(begin, end);
|
||||||
|
|
||||||
/* Next comes the OS family. */
|
/* Next comes the OS family. */
|
||||||
begin = end + 1;
|
begin = end + 1;
|
||||||
end = strchr(begin, '|');
|
end = strchr(begin, '|');
|
||||||
if (end == NULL)
|
if (end == NULL)
|
||||||
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
||||||
os_class->OS_Family = substrstrip(begin, end);
|
os_class.OS_Family = string_pool_substr_strip(begin, end);
|
||||||
|
|
||||||
/* And now the the OS generation. */
|
/* And now the the OS generation. */
|
||||||
begin = end + 1;
|
begin = end + 1;
|
||||||
@@ -846,17 +892,16 @@ static void parse_classline(FingerPrint *FP, char *thisline, int lineno,
|
|||||||
while (isspace((int) (unsigned char) *begin))
|
while (isspace((int) (unsigned char) *begin))
|
||||||
begin++;
|
begin++;
|
||||||
if (begin < end)
|
if (begin < end)
|
||||||
os_class->OS_Generation = substrstrip(begin, end);
|
os_class.OS_Generation = string_pool_substr_strip(begin, end);
|
||||||
else
|
else
|
||||||
os_class->OS_Generation = NULL;
|
os_class.OS_Generation = NULL;
|
||||||
|
|
||||||
/* And finally the device type. We look for '\0' instead of '|'. */
|
/* And finally the device type. We look for '\0' instead of '|'. */
|
||||||
begin = end + 1;
|
begin = end + 1;
|
||||||
end = strchr(begin, '\0');
|
end = strchr(begin, '\0');
|
||||||
os_class->Device_Type = substrstrip(begin, end);
|
os_class.Device_Type = string_pool_substr_strip(begin, end);
|
||||||
|
|
||||||
(*classno)++;
|
FP->OS_class.push_back(os_class);
|
||||||
FP->num_OS_Classifications++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parses a single fingerprint from the memory region given. If a
|
/* Parses a single fingerprint from the memory region given. If a
|
||||||
@@ -868,15 +913,12 @@ static void parse_classline(FingerPrint *FP, char *thisline, int lineno,
|
|||||||
it is used by fingerprint utilities that link with Nmap object files. */
|
it is used by fingerprint utilities that link with Nmap object files. */
|
||||||
FingerPrint *parse_single_fingerprint(char *fprint_orig) {
|
FingerPrint *parse_single_fingerprint(char *fprint_orig) {
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
int classno = 0; /* Number of Class lines dealt with so far */
|
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
char *thisline, *nextline;
|
char *thisline, *nextline;
|
||||||
char *fprint = strdup(fprint_orig); /* Make a copy we can futz with */
|
char *fprint = strdup(fprint_orig); /* Make a copy we can futz with */
|
||||||
FingerPrint *FP;
|
FingerPrint *FP;
|
||||||
FingerPrint *current; /* Since a fingerprint is really a linked list of
|
|
||||||
FingerPrint structures */
|
|
||||||
|
|
||||||
current = FP = (FingerPrint *) safe_zalloc(sizeof(FingerPrint));
|
FP = new FingerPrint;
|
||||||
|
|
||||||
thisline = fprint;
|
thisline = fprint;
|
||||||
|
|
||||||
@@ -914,15 +956,12 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
|
|||||||
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
||||||
} else if (strncmp(thisline, "Class ", 6) == 0) {
|
} else if (strncmp(thisline, "Class ", 6) == 0) {
|
||||||
|
|
||||||
parse_classline(FP, thisline, lineno, &classno);
|
parse_classline(FP, thisline, lineno);
|
||||||
|
|
||||||
} else if ((q = strchr(thisline, '('))) {
|
} else if ((q = strchr(thisline, '('))) {
|
||||||
|
FingerTest test;
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
if(current->name) {
|
test.name = string_pool_insert(thisline);
|
||||||
current->next = (FingerPrint *) safe_zalloc(sizeof(FingerPrint));
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
current->name = strdup(thisline);
|
|
||||||
p = q+1;
|
p = q+1;
|
||||||
*q = '(';
|
*q = '(';
|
||||||
q = strchr(p, ')');
|
q = strchr(p, ')');
|
||||||
@@ -930,7 +969,8 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
|
|||||||
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
current->results = str2AVal(p);
|
test.results = str2AVal(p);
|
||||||
|
FP->tests.push_back(test);
|
||||||
} else {
|
} else {
|
||||||
fatal("Parse error line line #%d of fingerprint", lineno);
|
fatal("Parse error line line #%d of fingerprint", lineno);
|
||||||
}
|
}
|
||||||
@@ -946,71 +986,22 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void free_fingerprint_file(FingerPrintDB *DB) {
|
|
||||||
FingerPrint **FPs = DB->prints;
|
|
||||||
FingerPrint **current;
|
|
||||||
FingerPrint *c, *d;
|
|
||||||
struct AVal *avc;
|
|
||||||
struct AVal *avd;
|
|
||||||
|
|
||||||
for(current = FPs; *current != NULL; current++){
|
|
||||||
for(c = *current; c; c=d){
|
|
||||||
d = c->next;
|
|
||||||
if(c->name)
|
|
||||||
free((void*)c->name); //strdup
|
|
||||||
if(c->results){
|
|
||||||
for(avc = c->results; avc; avc = avd) {
|
|
||||||
avd = avc->next;
|
|
||||||
if(avc->attribute)
|
|
||||||
free(avc->attribute);
|
|
||||||
}
|
|
||||||
free(c->results);
|
|
||||||
}
|
|
||||||
free(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(FPs);
|
|
||||||
|
|
||||||
if (DB->MatchPoints) {
|
|
||||||
for(c = DB->MatchPoints; c; c=d){
|
|
||||||
d = c->next;
|
|
||||||
if(c->name)
|
|
||||||
free((void*)c->name); //strdup
|
|
||||||
if(c->results){
|
|
||||||
for(avc = c->results; avc; avc = avd) {
|
|
||||||
avd = avc->next;
|
|
||||||
if(avc->attribute)
|
|
||||||
free(avc->attribute);
|
|
||||||
}
|
|
||||||
free(c->results);
|
|
||||||
}
|
|
||||||
free(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(DB);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FingerPrintDB *parse_fingerprint_file(const char *fname) {
|
FingerPrintDB *parse_fingerprint_file(const char *fname) {
|
||||||
FingerPrintDB *DB = NULL;
|
FingerPrintDB *DB = NULL;
|
||||||
FingerPrint *current;
|
FingerPrint *current;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int max_records = 4096;
|
|
||||||
char line[2048];
|
char line[2048];
|
||||||
int numrecords = 0;
|
|
||||||
int lineno = 0;
|
int lineno = 0;
|
||||||
bool parsingMatchPoints = false;
|
bool parsingMatchPoints = false;
|
||||||
|
|
||||||
int classno = 0; /* Number of Class lines dealt with so far */
|
int classno = 0; /* Number of Class lines dealt with so far */
|
||||||
|
|
||||||
DB = (FingerPrintDB *) safe_zalloc(sizeof(FingerPrintDB));
|
DB = new FingerPrintDB;
|
||||||
|
|
||||||
char *p, *q; /* OH YEAH!!!! */
|
char *p, *q; /* OH YEAH!!!! */
|
||||||
|
|
||||||
if (!DB) fatal("non-allocated DB passed to %s", __func__);
|
if (!DB) fatal("non-allocated DB passed to %s", __func__);
|
||||||
|
|
||||||
DB->prints = (FingerPrint **) safe_zalloc(sizeof(FingerPrint *) * max_records);
|
|
||||||
|
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
if (!fp) fatal("Unable to open Nmap fingerprint file: %s", fname);
|
if (!fp) fatal("Unable to open Nmap fingerprint file: %s", fname);
|
||||||
|
|
||||||
@@ -1033,13 +1024,13 @@ while(fgets(line, sizeof(line), fp)) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = (FingerPrint *) safe_zalloc(sizeof(FingerPrint));
|
current = new FingerPrint;
|
||||||
|
|
||||||
if (parsingMatchPoints) {
|
if (parsingMatchPoints) {
|
||||||
current->OS_name = NULL;
|
current->OS_name = NULL;
|
||||||
DB->MatchPoints = current;
|
DB->MatchPoints = current;
|
||||||
} else {
|
} else {
|
||||||
DB->prints[numrecords] = current;
|
DB->prints.push_back(current);
|
||||||
p = line + 12;
|
p = line + 12;
|
||||||
while(*p && isspace((int) (unsigned char) *p)) p++;
|
while(*p && isspace((int) (unsigned char) *p)) p++;
|
||||||
|
|
||||||
@@ -1069,8 +1060,9 @@ while(fgets(line, sizeof(line), fp)) {
|
|||||||
if (!strncmp(line, "FingerPrint ",12)) {
|
if (!strncmp(line, "FingerPrint ",12)) {
|
||||||
goto fparse;
|
goto fparse;
|
||||||
} else if (strncmp(line, "Class ", 6) == 0) {
|
} else if (strncmp(line, "Class ", 6) == 0) {
|
||||||
parse_classline(current, line, lineno, &classno);
|
parse_classline(current, line, lineno);
|
||||||
} else {
|
} else {
|
||||||
|
FingerTest test;
|
||||||
p = line;
|
p = line;
|
||||||
q = strchr(line, '(');
|
q = strchr(line, '(');
|
||||||
if (!q) {
|
if (!q) {
|
||||||
@@ -1078,11 +1070,7 @@ while(fgets(line, sizeof(line), fp)) {
|
|||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
if(current->name) {
|
test.name = string_pool_insert(p);
|
||||||
current->next = (FingerPrint *) safe_zalloc(sizeof(FingerPrint));
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
current->name = strdup(p);
|
|
||||||
p = q+1;
|
p = q+1;
|
||||||
*q = '(';
|
*q = '(';
|
||||||
q = strchr(p, ')');
|
q = strchr(p, ')');
|
||||||
@@ -1091,17 +1079,12 @@ while(fgets(line, sizeof(line), fp)) {
|
|||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
current->results = str2AVal(p);
|
test.results = str2AVal(p);
|
||||||
|
current->tests.push_back(test);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* printf("Read in fingerprint:\n%s\n", fp2ascii(DB->prints[numrecords])); */
|
|
||||||
if (!parsingMatchPoints)
|
|
||||||
numrecords++;
|
|
||||||
if (numrecords >= max_records)
|
|
||||||
fatal("Too many OS fingerprints -- 0verflow");
|
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
DB->prints[numrecords] = NULL;
|
|
||||||
return DB;
|
return DB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
osscan.h
7
osscan.h
@@ -110,6 +110,13 @@
|
|||||||
/* moved to global_structures.h */
|
/* moved to global_structures.h */
|
||||||
|
|
||||||
/********************** PROTOTYPES ***********************************/
|
/********************** PROTOTYPES ***********************************/
|
||||||
|
|
||||||
|
/* The OS database consists of many small strings, many of which appear
|
||||||
|
thousands of times. It pays to allocate memory only once for each unique
|
||||||
|
string, and have all references point at the one allocated value. */
|
||||||
|
const char *string_pool_insert(const char *s);
|
||||||
|
const char *string_pool_sprintf(const char *fmt, ...);
|
||||||
|
|
||||||
const char *fp2ascii(FingerPrint *FP);
|
const char *fp2ascii(FingerPrint *FP);
|
||||||
|
|
||||||
/* Parses a single fingerprint from the memory region given. If a
|
/* Parses a single fingerprint from the memory region given. If a
|
||||||
|
|||||||
616
osscan2.cc
616
osscan2.cc
File diff suppressed because it is too large
Load Diff
@@ -1493,8 +1493,8 @@ void write_host_status(Target * currenths, int resolve_all) {
|
|||||||
that only unique entries are added. Also note that *numentries is
|
that only unique entries are added. Also note that *numentries is
|
||||||
incremented if the candidate is added. arrsize is the number of
|
incremented if the candidate is added. arrsize is the number of
|
||||||
char * members that fit into arr */
|
char * members that fit into arr */
|
||||||
static int addtochararrayifnew(char *arr[], int *numentries, int arrsize,
|
static int addtochararrayifnew(const char *arr[], int *numentries, int arrsize,
|
||||||
char *candidate) {
|
const char *candidate) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// First lets see if the member already exists
|
// First lets see if the member already exists
|
||||||
@@ -1520,7 +1520,7 @@ static void printosclassificationoutput(const struct
|
|||||||
bool guess) {
|
bool guess) {
|
||||||
int classno, i, familyno;
|
int classno, i, familyno;
|
||||||
int overflow = 0; /* Whether we have too many devices to list */
|
int overflow = 0; /* Whether we have too many devices to list */
|
||||||
char *types[MAX_OS_CLASSMEMBERS];
|
const char *types[MAX_OS_CLASSMEMBERS];
|
||||||
char fullfamily[MAX_OS_CLASSMEMBERS][128]; // "[vendor] [os family]"
|
char fullfamily[MAX_OS_CLASSMEMBERS][128]; // "[vendor] [os family]"
|
||||||
double familyaccuracy[MAX_OS_CLASSMEMBERS]; // highest accuracy for this fullfamily
|
double familyaccuracy[MAX_OS_CLASSMEMBERS]; // highest accuracy for this fullfamily
|
||||||
char familygenerations[MAX_OS_CLASSMEMBERS][48]; // example: "4.X|5.X|6.X"
|
char familygenerations[MAX_OS_CLASSMEMBERS][48]; // example: "4.X|5.X|6.X"
|
||||||
|
|||||||
Reference in New Issue
Block a user