mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 13:11:28 +00:00
Update nmap-os-db syntax to support nested ranges
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
#
|
#
|
||||||
# For a complete description of Nmap OS detection and the format of
|
# For a complete description of Nmap OS detection and the format of
|
||||||
# fingerprints in this file, see https://nmap.org/book/osdetect.html.
|
# fingerprints in this file, see https://nmap.org/book/osdetect.html.
|
||||||
|
This nmap-os-db is only valid for Nmap 7.94.2 and later
|
||||||
|
|
||||||
# This first element provides the number of points every fingerprint
|
# This first element provides the number of points every fingerprint
|
||||||
# test is worth. Tests like TTL or Don't fragment are worth less
|
# test is worth. Tests like TTL or Don't fragment are worth less
|
||||||
|
|||||||
2
nmap.h
2
nmap.h
@@ -123,7 +123,7 @@
|
|||||||
file by the makefiles. */
|
file by the makefiles. */
|
||||||
#define NMAP_MAJOR 7
|
#define NMAP_MAJOR 7
|
||||||
#define NMAP_MINOR 94
|
#define NMAP_MINOR 94
|
||||||
#define NMAP_BUILD 1
|
#define NMAP_BUILD 2
|
||||||
/* SVN, BETA, etc. */
|
/* SVN, BETA, etc. */
|
||||||
#define NMAP_SPECIAL "SVN"
|
#define NMAP_SPECIAL "SVN"
|
||||||
|
|
||||||
|
|||||||
96
osscan.cc
96
osscan.cc
@@ -292,43 +292,99 @@ void FingerPrint::erase() {
|
|||||||
| (or)
|
| (or)
|
||||||
- (range)
|
- (range)
|
||||||
No parentheses are allowed. */
|
No parentheses are allowed. */
|
||||||
bool expr_match(const char *val, size_t vlenx, const char *expr, size_t explen, bool do_nested) {
|
bool expr_match(const char *val, size_t vlen, const char *expr, size_t explen, bool do_nested) {
|
||||||
const char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */
|
const char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */
|
||||||
size_t vlen = strlen(val);
|
if (vlen == 0)
|
||||||
|
vlen = strlen(val);
|
||||||
|
if (explen == 0)
|
||||||
|
explen = strlen(expr);
|
||||||
|
|
||||||
|
// If both are empty, match; else if either is empty, no match.
|
||||||
|
if (vlen == 0) {
|
||||||
|
return explen == 0;
|
||||||
|
}
|
||||||
|
else if (explen == 0) {
|
||||||
|
return vlen == 0;
|
||||||
|
}
|
||||||
|
|
||||||
p = expr;
|
p = expr;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
const char *nest = NULL; // where the [] nested expr starts
|
||||||
|
const char *subval = val; // portion of val after previous nest and before the next one
|
||||||
|
size_t sublen; // length of subval not subject to nested matching
|
||||||
q = strchr(p, '|');
|
q = strchr(p, '|');
|
||||||
size_t explen = q ? q - p : strlen(p);
|
|
||||||
|
// if we're already in a nested expr, we skip this and just match as usual.
|
||||||
|
if (do_nested) {
|
||||||
|
nest = strchr(p, '[');
|
||||||
|
subval = val;
|
||||||
|
// As long as we keep finding nested portions, e.g. M[>500]ST11W[1-5]
|
||||||
|
while (nest) {
|
||||||
|
q1 = strchr(nest, ']');
|
||||||
|
assert(q1);
|
||||||
|
if (q && q < q1) {
|
||||||
|
// "AB[C|D]E|XYZ"
|
||||||
|
q = strchr(q1, '|');
|
||||||
|
}
|
||||||
|
// "AB[C-D]E" or or "AB[C-D]E|F"
|
||||||
|
sublen = nest - p;
|
||||||
|
if (strncmp(p, subval, sublen) != 0) {
|
||||||
|
goto next_expr;
|
||||||
|
}
|
||||||
|
nest++;
|
||||||
|
subval += sublen;
|
||||||
|
size_t nlen = 0;
|
||||||
|
while (isxdigit(subval[nlen])) {
|
||||||
|
nlen++;
|
||||||
|
}
|
||||||
|
p = q1 + 1;
|
||||||
|
// fprintf(stderr, "nest: %-.*s cmp %-.*s\n", nlen, subval, q1 - nest, nest);
|
||||||
|
if (nlen > 0 && expr_match(subval, nlen, nest, q1 - nest, false)) {
|
||||||
|
subval += nlen;
|
||||||
|
nest = strchr(p, '[');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
goto next_expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No more nested portions. string match the rest:
|
||||||
|
sublen = vlen - (subval - val);
|
||||||
|
if ((explen - (p - expr)) == sublen && !strncmp(subval, p, sublen)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sublen = q ? q - p : explen - (p - expr);
|
||||||
if (*p == '>') {
|
if (*p == '>') {
|
||||||
if ((vlen > explen - 1)
|
if ((vlen > sublen - 1)
|
||||||
|| (vlen == explen - 1 && strncmp(val, p + 1, vlen) > 0)) {
|
|| (vlen == sublen - 1 && strncmp(subval, p + 1, vlen) > 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*p == '<') {
|
else if (*p == '<') {
|
||||||
if ((vlen < explen - 1)
|
if ((vlen < sublen - 1)
|
||||||
|| (vlen == explen - 1 && strncmp(val, p + 1, vlen) < 0)) {
|
|| (vlen == sublen - 1 && strncmp(subval, p + 1, vlen) < 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
q1 = strchr(p, '-');
|
q1 = strchr(p, '-');
|
||||||
if (q1 != NULL) {
|
if (q1 != NULL) {
|
||||||
size_t explen1 = q1 - p;
|
size_t sublen1 = q1 - p;
|
||||||
if ((vlen > explen1)
|
if ((vlen > sublen1)
|
||||||
|| (vlen == explen1 && strncmp(val, p + 1, vlen) >= 0)) {
|
|| (vlen == sublen1 && strncmp(subval, p, vlen) >= 0)) {
|
||||||
explen -= (explen1 + 1);
|
p = q1 + 1;
|
||||||
if ((vlen < explen)
|
sublen -= (sublen1 + 1);
|
||||||
|| (vlen == explen && strncmp(val, p + 1, vlen) <= 0)) {
|
if ((vlen < sublen)
|
||||||
|
|| (vlen == sublen && strncmp(subval, p, vlen) <= 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (vlen == explen && !strncmp(p, val, vlen)) {
|
else if (vlen == sublen && !strncmp(p, subval, vlen)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
next_expr:
|
||||||
if (q)
|
if (q)
|
||||||
p = q + 1;
|
p = q + 1;
|
||||||
} while (q);
|
} while (q);
|
||||||
@@ -348,6 +404,7 @@ static void AVal_match(const FingerTest &reference, const FingerTest &fprint, co
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const std::vector<Attr> &pointsV = points.Attrs;
|
const std::vector<Attr> &pointsV = points.Attrs;
|
||||||
|
bool tcp_opt_match = points.name == "OPS";
|
||||||
|
|
||||||
const std::vector<const char *> &refV = *reference.results;
|
const std::vector<const char *> &refV = *reference.results;
|
||||||
assert(refV.size() == points.numAttrs);
|
assert(refV.size() == points.numAttrs);
|
||||||
@@ -366,7 +423,7 @@ static void AVal_match(const FingerTest &reference, const FingerTest &fprint, co
|
|||||||
fatal("%s: Got bogus point amount (%d) for test %s.%s", __func__, pointsThisTest, points.name.str, aDef.name.str);
|
fatal("%s: Got bogus point amount (%d) for test %s.%s", __func__, pointsThisTest, points.name.str, aDef.name.str);
|
||||||
subtests += pointsThisTest;
|
subtests += pointsThisTest;
|
||||||
|
|
||||||
if (expr_match(current_fp, 0, current_ref, 0)) {
|
if (expr_match(current_fp, 0, current_ref, 0, tcp_opt_match || aDef.name == "O")) {
|
||||||
subtests_succeeded += pointsThisTest;
|
subtests_succeeded += pointsThisTest;
|
||||||
} else {
|
} else {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@@ -1072,6 +1129,15 @@ fparse:
|
|||||||
if (DB->MatchPoints)
|
if (DB->MatchPoints)
|
||||||
fatal("Found MatchPoints directive on line %d of %s even though it has previously been seen in the file", lineno, fname);
|
fatal("Found MatchPoints directive on line %d of %s even though it has previously been seen in the file", lineno, fname);
|
||||||
parsingMatchPoints = true;
|
parsingMatchPoints = true;
|
||||||
|
} else if (strncmp(line, "This nmap-os-db", 15) == 0) {
|
||||||
|
p = strstr(line, "Nmap ");
|
||||||
|
if (!p)
|
||||||
|
fatal("Parse error on line %d of nmap-os-db file: %s", lineno, line);
|
||||||
|
q = strchr(p + 5, ' ');
|
||||||
|
if (strncmp(p + 5, NMAP_NUM_VERSION, q - p) > 0) {
|
||||||
|
error("%sOS detection results may be inaccurate.", line);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
|
error("Parse error on line %d of nmap-os-db file: %s", lineno, line);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ const struct expr_test tests[] = {
|
|||||||
{"<A", "", false},
|
{"<A", "", false},
|
||||||
{">A", "", false},
|
{">A", "", false},
|
||||||
{"1-9", "", false},
|
{"1-9", "", false},
|
||||||
#if 0
|
|
||||||
{"M[1-9]", "M2", true},
|
{"M[1-9]", "M2", true},
|
||||||
{"M[<5]S", "M2S", true},
|
{"M[<5]S", "M2S", true},
|
||||||
{"M[>A]S", "MFS", true},
|
{"M[>A]S", "MFS", true},
|
||||||
@@ -116,7 +115,6 @@ const struct expr_test tests[] = {
|
|||||||
{"[<5]S", "2B", false},
|
{"[<5]S", "2B", false},
|
||||||
{"[>A7]S", "FS", false},
|
{"[>A7]S", "FS", false},
|
||||||
{"[>A7]S", "A6S", false},
|
{"[>A7]S", "A6S", false},
|
||||||
#endif
|
|
||||||
{"", "", true}
|
{"", "", true}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user