Whitespace and formatting in osscan.cc.

This commit is contained in:
david 2011-07-19 22:00:13 +00:00
parent 9a64d66a1e
commit 1646813162

663
osscan.cc
View file

@ -229,9 +229,9 @@ const FingerTest *FingerPrint::gettestbyname(const char *name) const {
that extra info printed. If you pass 0 for verbose, you might as
well pass NULL for testGroupName as it won't be used. */
static int AVal_match(const FingerTest *reference, const FingerTest *fprint, const FingerTest *points,
unsigned long *num_subtests,
unsigned long *num_subtests_succeeded, int shortcut,
int verbose, const char *testGroupName) {
unsigned long *num_subtests,
unsigned long *num_subtests_succeeded, int shortcut,
int verbose, const char *testGroupName) {
std::vector<struct AVal>::const_iterator current_ref;
const struct AVal *current_fp;
const struct AVal *current_points;
@ -248,93 +248,166 @@ static int AVal_match(const FingerTest *reference, const FingerTest *fprint, con
for (current_ref = reference->results.begin();
current_ref != reference->results.end();
current_ref++) {
current_fp = fprint->getattrbyname(current_ref->attribute);
if (!current_fp) continue;
/* OK, we compare an attribute value in current_fp->value to a
current_fp = fprint->getattrbyname(current_ref->attribute);
if (!current_fp)
continue;
/* OK, we compare an attribute value in current_fp->value to a
potentially large expression in current_ref->value. The syntax
uses < (less than), > (greather than), + (non-zero), | (or), -
(range), and & (and). No parenthesis are allowed */
numtrue = andexp = orexp = 0; testfailed = 0;
Strncpy(valcpy, current_ref->value, sizeof(valcpy));
p = valcpy;
if (strchr(current_ref->value, '|')) {
orexp = 1; expchar = '|';
} else {
andexp = 1; expchar = '&';
}
do {
q = strchr(p, expchar);
if (q) *q = '\0';
if (q)
*q = '\0';
if (strcmp(p, "+") == 0) {
if (!*current_fp->value) { if (andexp) { testfailed=1; break; } }
else {
val = strtol(current_fp->value, &endptr, 16);
if (val == 0 || *endptr) { if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
}
if (!*current_fp->value) {
if (andexp) {
testfailed = 1;
break;
}
} else {
val = strtol(current_fp->value, &endptr, 16);
if (val == 0 || *endptr) {
if (andexp) {
testfailed = 1;
break;
}
} else {
numtrue++;
if (orexp)
break;
}
}
} else if (*p == '<' && isxdigit((int) (unsigned char) p[1])) {
if (!*current_fp->value) { if (andexp) { testfailed=1; break; } }
number = strtol(p + 1, &endptr, 16);
val = strtol(current_fp->value, &endptr, 16);
if (val >= number || *endptr) { if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
if (!*current_fp->value) {
if (andexp) {
testfailed = 1;
break;
}
}
number = strtol(p + 1, &endptr, 16);
val = strtol(current_fp->value, &endptr, 16);
if (val >= number || *endptr) {
if (andexp) {
testfailed = 1;
break;
}
} else {
numtrue++;
if (orexp)
break;
}
} else if (*p == '>' && isxdigit((int) (unsigned char) p[1])) {
if (!*current_fp->value) { if (andexp) { testfailed=1; break; } }
number = strtol(p + 1, &endptr, 16);
val = strtol(current_fp->value, &endptr, 16);
if (val <= number || *endptr) { if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
if (!*current_fp->value) {
if (andexp) {
testfailed = 1;
break;
}
}
number = strtol(p + 1, &endptr, 16);
val = strtol(current_fp->value, &endptr, 16);
if (val <= number || *endptr) {
if (andexp) {
testfailed = 1;
break;
}
} else {
numtrue++;
if (orexp)
break;
}
} else if (((q1 = strchr(p, '-')) != NULL) && isxdigit((int) (unsigned char) p[0]) && isxdigit((int) (unsigned char) q1[1])) {
if (!*current_fp->value) { if (andexp) { testfailed=1; break; } }
*q1 = '\0'; number = strtol(p, NULL, 16);
number1 = strtol(q1 + 1, NULL, 16);
if(number1 < number && o.debugging) {
error("Range error in reference aval: %s=%s", current_ref->attribute, current_ref->value);
if (!*current_fp->value) {
if (andexp) {
testfailed = 1;
break;
}
}
*q1 = '\0';
number = strtol(p, NULL, 16);
number1 = strtol(q1 + 1, NULL, 16);
if (number1 < number && o.debugging) {
error("Range error in reference aval: %s=%s", current_ref->attribute, current_ref->value);
}
val = strtol(current_fp->value, &endptr, 16);
if (val < number || val > number1 || *endptr) {
if (andexp) {
testfailed = 1;
break;
}
} else {
numtrue++;
if (orexp)
break;
}
} else {
if (strcmp(p, current_fp->value)) {
if (andexp) {
testfailed = 1;
break;
}
} else {
numtrue++;
if (orexp)
break;
}
}
val = strtol(current_fp->value, &endptr, 16);
if (val < number || val > number1 || *endptr) { if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
} else {
if (strcmp(p, current_fp->value))
{ if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
if (q)
p = q + 1;
} while (q);
if (numtrue == 0)
testfailed = 1;
if (points) {
current_points = points->getattrbyname(current_ref->attribute);
if (!current_points)
fatal("%s: Failed to find point amount for test %s.%s", __func__, testGroupName? testGroupName : "", current_ref->attribute);
errno = 0;
pointsThisTest = strtol(current_points->value, &endptr, 10);
if (errno != 0 || *endptr != '\0' || pointsThisTest < 0)
fatal("%s: Got bogus point amount (%s) for test %s.%s", __func__, current_points->value, testGroupName? testGroupName : "", current_ref->attribute);
}
subtests += pointsThisTest;
if (testfailed) {
if (shortcut) {
if (num_subtests)
*num_subtests += subtests;
return 0;
}
if (q) p = q + 1;
} while(q);
if (numtrue == 0) testfailed=1;
if (points) {
current_points = points->getattrbyname(current_ref->attribute);
if (!current_points) fatal("%s: Failed to find point amount for test %s.%s", __func__, testGroupName? testGroupName : "", current_ref->attribute);
errno = 0;
pointsThisTest = strtol(current_points->value, &endptr, 10);
if (errno != 0 || *endptr != '\0' || pointsThisTest < 0)
fatal("%s: Got bogus point amount (%s) for test %s.%s", __func__, current_points->value, testGroupName? testGroupName : "", current_ref->attribute);
}
subtests += pointsThisTest;
if (testfailed) {
if (shortcut) {
if (num_subtests) *num_subtests += subtests;
return 0;
}
if (verbose)
log_write(LOG_PLAIN, "%s.%s: \"%s\" NOMATCH \"%s\" (%d %s)\n", testGroupName,
current_ref->attribute, current_fp->value,
current_ref->value, pointsThisTest, (pointsThisTest == 1)? "point" : "points");
} else subtests_succeeded += pointsThisTest;
/* Whew, we made it past one Attribute alive , on to the next! */
if (verbose)
log_write(LOG_PLAIN, "%s.%s: \"%s\" NOMATCH \"%s\" (%d %s)\n", testGroupName,
current_ref->attribute, current_fp->value,
current_ref->value, pointsThisTest, (pointsThisTest == 1) ? "point" : "points");
} else {
subtests_succeeded += pointsThisTest;
}
/* Whew, we made it past one Attribute alive , on to the next! */
}
if (num_subtests) *num_subtests += subtests;
if (num_subtests_succeeded) *num_subtests_succeeded += subtests_succeeded;
return (subtests == subtests_succeeded)? 1 : 0;
if (num_subtests)
*num_subtests += subtests;
if (num_subtests_succeeded)
*num_subtests_succeeded += subtests_succeeded;
return (subtests == subtests_succeeded) ? 1 : 0;
}
/* Compares 2 fingerprints -- a referenceFP (can have expression
attributes) with an observed fingerprint (no expressions). If
verbose is nonzero, differences will be printed. The comparison
accuracy (between 0 and 1) is returned). If MatchPoints is not NULL, it is
accuracy (between 0 and 1) is returned). If MatchPoints is not NULL, it is
a special "fingerprints" which tells how many points each test is worth. */
double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
FingerPrint *MatchPoints, int verbose) {
FingerPrint *MatchPoints, int verbose) {
std::vector<FingerTest>::iterator currentReferenceTest;
const FingerTest *currentObservedTest;
const FingerTest *currentTestMatchPoints;
@ -350,20 +423,22 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
if (currentObservedTest) {
new_subtests = new_subtests_succeeded = 0;
if (MatchPoints) {
currentTestMatchPoints = MatchPoints->gettestbyname(currentReferenceTest->name);
if (!currentTestMatchPoints)
fatal("%s: Failed to locate test %s in MatchPoints directive of fingerprint file", __func__, currentReferenceTest->name);
} else currentTestMatchPoints = NULL;
currentTestMatchPoints = MatchPoints->gettestbyname(currentReferenceTest->name);
if (!currentTestMatchPoints)
fatal("%s: Failed to locate test %s in MatchPoints directive of fingerprint file", __func__, currentReferenceTest->name);
} else {
currentTestMatchPoints = NULL;
}
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_succeeded += new_subtests_succeeded;
}
}
assert(num_subtests_succeeded <= num_subtests);
return (num_subtests)? (num_subtests_succeeded / (double) num_subtests) : 0;
return (num_subtests) ? (num_subtests_succeeded / (double) num_subtests) : 0;
}
/* Takes a fingerprint and looks for matches inside the passed in
@ -372,12 +447,12 @@ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP,
will be reverse-sorted by accuracy. No results below
accuracy_threshhold will be included. The max matches returned is
the maximum that fits in a FingerPrintResults class. */
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
FingerPrintDB *DB, double accuracy_threshold) {
double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be
at least this big
to be added to the
list */
void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
FingerPrintDB *DB, double accuracy_threshold) {
double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be
at least this big
to be added to the
list */
std::vector<FingerPrint *>::iterator current_os;
double acc;
int state;
@ -385,14 +460,14 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
int max_prints = sizeof(FPR->prints) / sizeof(FingerPrint *);
int idx;
double tmp_acc=0.0, tmp_acc2; /* These are temp buffers for list swaps */
FingerPrint *tmp_FP=NULL, *tmp_FP2;
FingerPrint *tmp_FP = NULL, *tmp_FP2;
assert(FP);
assert(FPR);
assert(accuracy_threshold >= 0 && accuracy_threshold <= 1);
FPR->overall_results = OSSCAN_SUCCESS;
for (current_os = DB->prints.begin(); current_os != DB->prints.end(); current_os++) {
skipfp = 0;
@ -402,67 +477,68 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
if (acc >= FPR_entrance_requirement || acc == 1.0) {
state = 0;
for(idx=0; idx < FPR->num_matches; idx++) {
if (strcmp(FPR->prints[idx]->OS_name, (*current_os)->OS_name) == 0) {
if (FPR->accuracy[idx] >= acc) {
skipfp = 1; /* Skip it -- a higher version is already in list */
} else {
/* We must shift the list left to delete this sucker */
memmove(FPR->prints + idx, FPR->prints + idx + 1,
(FPR->num_matches - 1 - idx) * sizeof(FingerPrint *));
memmove(FPR->accuracy + idx, FPR->accuracy + idx + 1,
(FPR->num_matches - 1 - idx) * sizeof(double));
FPR->num_matches--;
FPR->accuracy[FPR->num_matches] = 0;
}
break; /* There can only be 1 in the list with same name */
}
for (idx=0; idx < FPR->num_matches; idx++) {
if (strcmp(FPR->prints[idx]->OS_name, (*current_os)->OS_name) == 0) {
if (FPR->accuracy[idx] >= acc) {
skipfp = 1; /* Skip it -- a higher version is already in list */
} else {
/* We must shift the list left to delete this sucker */
memmove(FPR->prints + idx, FPR->prints + idx + 1,
(FPR->num_matches - 1 - idx) * sizeof(FingerPrint *));
memmove(FPR->accuracy + idx, FPR->accuracy + idx + 1,
(FPR->num_matches - 1 - idx) * sizeof(double));
FPR->num_matches--;
FPR->accuracy[FPR->num_matches] = 0;
}
break; /* There can only be 1 in the list with same name */
}
}
if (!skipfp) {
/* First we check whether we have overflowed with perfect matches */
if (acc == 1) {
/* error("DEBUG: Perfect match #%d/%d", FPR->num_perfect_matches + 1, max_prints); */
if (FPR->num_perfect_matches == max_prints) {
FPR->overall_results = OSSCAN_TOOMANYMATCHES;
return;
}
FPR->num_perfect_matches++;
}
/* Now we add the sucker to the list */
state = 0; /* Have not yet done the insertion */
for(idx=-1; idx < max_prints -1; idx++) {
if (state == 1) {
/* Push tmp_acc and tmp_FP onto the next idx */
tmp_acc2 = FPR->accuracy[idx+1];
tmp_FP2 = FPR->prints[idx+1];
FPR->accuracy[idx+1] = tmp_acc;
FPR->prints[idx+1] = tmp_FP;
tmp_acc = tmp_acc2;
tmp_FP = tmp_FP2;
} else if (FPR->accuracy[idx + 1] < acc) {
/* OK, I insert the sucker into the next slot ... */
tmp_acc = FPR->accuracy[idx+1];
tmp_FP = FPR->prints[idx+1];
FPR->prints[idx+1] = *current_os;
FPR->accuracy[idx+1] = acc;
state = 1;
}
}
if (state != 1) {
fatal("Bogus list insertion state (%d) -- num_matches = %d num_perfect_matches=%d entrance_requirement=%f", state, FPR->num_matches, FPR->num_perfect_matches, FPR_entrance_requirement);
}
FPR->num_matches++;
/* If we are over max_prints, one was shoved off list */
if (FPR->num_matches > max_prints) FPR->num_matches = max_prints;
if (!skipfp) {
/* First we check whether we have overflowed with perfect matches */
if (acc == 1) {
/* error("DEBUG: Perfect match #%d/%d", FPR->num_perfect_matches + 1, max_prints); */
if (FPR->num_perfect_matches == max_prints) {
FPR->overall_results = OSSCAN_TOOMANYMATCHES;
return;
}
FPR->num_perfect_matches++;
}
/* Calculate the new min req. */
if (FPR->num_matches == max_prints) {
FPR_entrance_requirement = FPR->accuracy[max_prints - 1] + 0.00001;
}
/* Now we add the sucker to the list */
state = 0; /* Have not yet done the insertion */
for (idx=-1; idx < max_prints -1; idx++) {
if (state == 1) {
/* Push tmp_acc and tmp_FP onto the next idx */
tmp_acc2 = FPR->accuracy[idx+1];
tmp_FP2 = FPR->prints[idx+1];
FPR->accuracy[idx+1] = tmp_acc;
FPR->prints[idx+1] = tmp_FP;
tmp_acc = tmp_acc2;
tmp_FP = tmp_FP2;
} else if (FPR->accuracy[idx + 1] < acc) {
/* OK, I insert the sucker into the next slot ... */
tmp_acc = FPR->accuracy[idx+1];
tmp_FP = FPR->prints[idx+1];
FPR->prints[idx+1] = *current_os;
FPR->accuracy[idx+1] = acc;
state = 1;
}
}
if (state != 1) {
fatal("Bogus list insertion state (%d) -- num_matches = %d num_perfect_matches=%d entrance_requirement=%f", state, FPR->num_matches, FPR->num_perfect_matches, FPR_entrance_requirement);
}
FPR->num_matches++;
/* If we are over max_prints, one was shoved off list */
if (FPR->num_matches > max_prints)
FPR->num_matches = max_prints;
/* Calculate the new min req. */
if (FPR->num_matches == max_prints) {
FPR_entrance_requirement = FPR->accuracy[max_prints - 1] + 0.00001;
}
}
}
}
@ -503,7 +579,7 @@ static const char *dist_method_fp_string(enum dist_calc_method method)
FPrint is submitted (eg Nmap version, etc). Result is written (up
to ostrlen) to the ostr var passed in */
static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP,
const struct in_addr * const addr, int distance,
const struct in_addr * const addr, int distance,
enum dist_calc_method distance_calculation_method,
const u8 *mac, int openTcpPort,
int closedTcpPort, int closedUdpPort) {
@ -515,33 +591,31 @@ static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP,
ltime = localtime(&timep);
otbuf[0] = '\0';
if(openTcpPort != -1)
Snprintf(otbuf, sizeof(otbuf), "%d", openTcpPort);
if (openTcpPort != -1)
Snprintf(otbuf, sizeof(otbuf), "%d", openTcpPort);
ctbuf[0] = '\0';
if(closedTcpPort != -1)
Snprintf(ctbuf, sizeof(ctbuf), "%d", closedTcpPort);
if (closedTcpPort != -1)
Snprintf(ctbuf, sizeof(ctbuf), "%d", closedTcpPort);
cubuf[0] = '\0';
if(closedUdpPort != -1)
Snprintf(cubuf, sizeof(cubuf), "%d", closedUdpPort);
if (closedUdpPort != -1)
Snprintf(cubuf, sizeof(cubuf), "%d", closedUdpPort);
dsbuf[0] = '\0';
if(distance != -1) {
Snprintf(dsbuf, sizeof(dsbuf), "%%DS=%d", distance);
}
if (distance_calculation_method != DIST_METHOD_NONE) {
Snprintf(dcbuf, sizeof(dcbuf), "%%DC=%s", dist_method_fp_string(distance_calculation_method));
} else {
dcbuf[0] = '\0';
}
if (distance != -1)
Snprintf(dsbuf, sizeof(dsbuf), "%%DS=%d", distance);
if (distance_calculation_method != DIST_METHOD_NONE)
Snprintf(dcbuf, sizeof(dcbuf), "%%DC=%s", dist_method_fp_string(distance_calculation_method));
else
dcbuf[0] = '\0';
macbuf[0] = '\0';
if (mac)
Snprintf(macbuf, sizeof(macbuf), "%%M=%02X%02X%02X", mac[0], mac[1], mac[2]);
Snprintf(ostr, ostrlen, "SCAN(V=%s%%D=%d/%d%%OT=%s%%CT=%s%%CU=%s%%PV=%c%s%s%%G=%c%s%%TM=%X%%P=%s)",
NMAP_VERSION, ltime->tm_mon + 1, ltime->tm_mday,
otbuf, ctbuf, cubuf, isipprivate(addr)?'Y':'N', dsbuf, dcbuf, isGoodFP?'Y':'N',
macbuf, (int) timep, NMAP_PLATFORM);
NMAP_VERSION, ltime->tm_mon + 1, ltime->tm_mday,
otbuf, ctbuf, cubuf, isipprivate(addr) ? 'Y' : 'N', dsbuf, dcbuf, isGoodFP ? 'Y' : 'N',
macbuf, (int) timep, NMAP_PLATFORM);
}
/* Puts a textual representation of the test in s.
@ -616,13 +690,13 @@ static std::vector<struct AVal> str2AVal(char *str) {
return std::vector<struct AVal>();
/* count the AVals */
while((q = strchr(q, '%'))) {
while ((q = strchr(q, '%'))) {
count++;
q++;
}
AVs.reserve(count);
for(i=0; i < count; i++) {
for (i = 0; i < count; i++) {
struct AVal av;
q = strchr(p, '=');
@ -635,7 +709,7 @@ static std::vector<struct AVal> str2AVal(char *str) {
if (i != count - 1) {
q = strchr(p, '%');
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';
}
@ -783,7 +857,8 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
/* Lets start by writing the fake "SCAN" test for submitting fingerprints */
WriteSInfo(p, sizeof(str), isGoodFP, addr, distance, distance_calculation_method, mac, openTcpPort, closedTcpPort, closedUdpPort);
p = p + strlen(str);
if (!wrapit) *p++ = '\n';
if (!wrapit)
*p++ = '\n';
assert(p <= end);
@ -808,31 +883,32 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
*p = '\0';
if(!wrapit) {
return str;
if (!wrapit) {
return str;
} else {
/* Wrap the str. */
int len;
char *p1 = wrapstr;
end = wrapstr + sizeof(wrapstr) - 1;
/* Wrap the str. */
int len;
char *p1 = wrapstr;
end = wrapstr + sizeof(wrapstr) - 1;
p = str;
p = str;
while(*p && end-p1 >= 3) {
len = 0;
strcpy(p1, "OS:"); p1 += 3; len +=3;
while(*p && len <= FP_RESULT_WRAP_LINE_LEN && end-p1 > 0) {
*p1++=*p++; len++;
}
if(end-p1<=0) {
fatal("Wrapped result too long!\n");
break;
}
*p1++ = '\n';
}
*p1 = '\0';
while (*p && end-p1 >= 3) {
len = 0;
strcpy(p1, "OS:"); p1 += 3; len +=3;
while (*p && len <= FP_RESULT_WRAP_LINE_LEN && end-p1 > 0) {
*p1++ = *p++;
len++;
}
if (end-p1 <= 0) {
fatal("Wrapped result too long!\n");
break;
}
*p1++ = '\n';
}
*p1 = '\0';
return wrapstr;
return wrapstr;
}
}
@ -841,7 +917,8 @@ const char *fp2ascii(FingerPrint *FP) {
std::vector<FingerTest>::iterator iter;
char *p = str;
if (!FP) return "(None)";
if (!FP)
return "(None)";
for (iter = FP->tests.begin(); iter != FP->tests.end(); iter++) {
int len;
@ -907,10 +984,10 @@ static void parse_classline(FingerPrint *FP, char *thisline, int lineno) {
}
/* Parses a single fingerprint from the memory region given. If a
non-null fingerprint is returned, the user is in charge of freeing it
when done. This function does not require the fingerprint to be 100%
complete since it is used by scripts such as scripts/fingerwatch for
which some partial fingerpritns are OK. */
non-null fingerprint is returned, the user is in charge of freeing it
when done. This function does not require the fingerprint to be 100%
complete since it is used by scripts such as scripts/fingerwatch for
which some partial fingerpritns are OK. */
/* This function is not currently used by Nmap, but it is present here because
it is used by fingerprint utilities that link with Nmap object files. */
FingerPrint *parse_single_fingerprint(char *fprint_orig) {
@ -923,26 +1000,30 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
FP = new FingerPrint;
thisline = fprint;
do /* 1 line at a time */ {
nextline = strchr(thisline, '\n');
if (nextline) *nextline++ = '\0';
if (nextline)
*nextline++ = '\0';
/* printf("Preparing to handle next line: %s\n", thisline); */
while(*thisline && isspace((int) (unsigned char) *thisline)) thisline++;
while (*thisline && isspace((int) (unsigned char) *thisline))
thisline++;
if (!*thisline) {
fatal("Parse error on line %d of fingerprint: %s", lineno, nextline);
fatal("Parse error on line %d of fingerprint: %s", lineno, nextline);
}
if (strncmp(thisline, "Fingerprint ", 12) == 0) {
/* Ignore a second Fingerprint line if it appears. */
if (FP->OS_name == NULL) {
p = thisline + 12;
while(*p && isspace((int) (unsigned char) *p)) p++;
while (*p && isspace((int) (unsigned char) *p))
p++;
q = strchr(p, '\n');
if (!q) q = p + strlen(p);
while(q > p && isspace((int) (unsigned char) *(--q)))
if (!q)
q = p + strlen(p);
while (q > p && isspace((int) (unsigned char) *(--q)))
;
FP->OS_name = (char *) cp_alloc(q - p + 2);
@ -952,10 +1033,11 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
} else if (strncmp(thisline, "MatchPoints", 11) == 0) {
p = thisline + 11;
if (*p && !isspace((int) (unsigned char) *p))
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
while(*p && isspace((int) (unsigned char) *p)) p++;
fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline);
while (*p && isspace((int) (unsigned char) *p))
p++;
if (*p != '\0')
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) {
parse_classline(FP, thisline, lineno);
@ -968,7 +1050,7 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
*q = '(';
q = strchr(p, ')');
if (!q) {
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';
test.results = str2AVal(p);
@ -989,112 +1071,119 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
FingerPrintDB *parse_fingerprint_file(const char *fname) {
FingerPrintDB *DB = NULL;
FingerPrint *current;
FILE *fp;
char line[2048];
int lineno = 0;
bool parsingMatchPoints = false;
FingerPrintDB *DB = NULL;
FingerPrint *current;
FILE *fp;
char line[2048];
int lineno = 0;
bool parsingMatchPoints = false;
DB = new 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__);
fp = fopen(fname, "r");
if (!fp) fatal("Unable to open Nmap fingerprint file: %s", fname);
fp = fopen(fname, "r");
if (!fp)
fatal("Unable to open Nmap fingerprint file: %s", fname);
top:
while(fgets(line, sizeof(line), fp)) {
lineno++;
/* Read in a record */
if (*line == '\n' || *line == '#')
continue;
fparse:
if (strncasecmp(line, "FingerPrint", 11) == 0) {
parsingMatchPoints = false;
} else if (strncasecmp(line, "MatchPoints", 11) == 0) {
if (DB->MatchPoints) fatal("Found MatchPoints directive on line %d of %s even though it has previously been seen in the file", lineno, fname);
parsingMatchPoints = true;
} else {
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
continue;
}
current = new FingerPrint;
if (parsingMatchPoints) {
current->OS_name = NULL;
DB->MatchPoints = current;
} else {
DB->prints.push_back(current);
p = line + 12;
while(*p && isspace((int) (unsigned char) *p)) p++;
q = strpbrk(p, "\n#");
if (!q) fatal("Parse error on line %d of fingerprint: %s", lineno, line);
while(isspace((int) (unsigned char) *(--q)))
;
if (q < p) fatal("Parse error on line %d of fingerprint: %s", lineno, line);
current->OS_name = (char *) cp_alloc(q - p + 2);
memcpy(current->OS_name, p, q - p + 1);
current->OS_name[q - p + 1] = '\0';
}
current->line = lineno;
/* Now we read the fingerprint itself */
while(fgets(line, sizeof(line), fp)) {
top:
while (fgets(line, sizeof(line), fp)) {
lineno++;
if (*line == '#')
/* Read in a record */
if (*line == '\n' || *line == '#')
continue;
if (*line == '\n')
break;
if (!strncmp(line, "FingerPrint ",12)) {
goto fparse;
} else if (strncmp(line, "Class ", 6) == 0) {
parse_classline(current, line, lineno);
fparse:
if (strncasecmp(line, "FingerPrint", 11) == 0) {
parsingMatchPoints = false;
} else if (strncasecmp(line, "MatchPoints", 11) == 0) {
if (DB->MatchPoints)
fatal("Found MatchPoints directive on line %d of %s even though it has previously been seen in the file", lineno, fname);
parsingMatchPoints = true;
} else {
FingerTest test;
p = line;
q = strchr(line, '(');
if (!q) {
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
goto top;
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
continue;
}
current = new FingerPrint;
if (parsingMatchPoints) {
current->OS_name = NULL;
DB->MatchPoints = current;
} else {
DB->prints.push_back(current);
p = line + 12;
while (*p && isspace((int) (unsigned char) *p))
p++;
q = strpbrk(p, "\n#");
if (!q)
fatal("Parse error on line %d of fingerprint: %s", lineno, line);
while (isspace((int) (unsigned char) *(--q)))
;
if (q < p)
fatal("Parse error on line %d of fingerprint: %s", lineno, line);
current->OS_name = (char *) cp_alloc(q - p + 2);
memcpy(current->OS_name, p, q - p + 1);
current->OS_name[q - p + 1] = '\0';
}
current->line = lineno;
/* Now we read the fingerprint itself */
while (fgets(line, sizeof(line), fp)) {
lineno++;
if (*line == '#')
continue;
if (*line == '\n')
break;
if (!strncmp(line, "FingerPrint ",12)) {
goto fparse;
} else if (strncmp(line, "Class ", 6) == 0) {
parse_classline(current, line, lineno);
} else {
FingerTest test;
p = line;
q = strchr(line, '(');
if (!q) {
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
goto top;
}
*q = '\0';
test.name = string_pool_insert(p);
p = q+1;
*q = '(';
q = strchr(p, ')');
if (!q) {
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
goto top;
}
*q = '\0';
test.results = str2AVal(p);
current->tests.push_back(test);
}
*q = '\0';
test.name = string_pool_insert(p);
p = q+1;
*q = '(';
q = strchr(p, ')');
if (!q) {
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
goto top;
}
*q = '\0';
test.results = str2AVal(p);
current->tests.push_back(test);
}
}
}
fclose(fp);
return DB;
fclose(fp);
return DB;
}
FingerPrintDB *parse_fingerprint_reference_file(const char *dbname) {
char filename[256];
char filename[256];
if (nmap_fetchfile(filename, sizeof(filename), dbname) != 1){
if (nmap_fetchfile(filename, sizeof(filename), dbname) != 1) {
fatal("OS scan requested but I cannot find %s file. It should be in %s, ~/.nmap/ or .", dbname, NMAPDATADIR);
}
/* Record where this data file was found. */
o.loaded_data_files[dbname] = filename;
}
/* Record where this data file was found. */
o.loaded_data_files[dbname] = filename;
return parse_fingerprint_file(filename);
return parse_fingerprint_file(filename);
}