summaryrefslogtreecommitdiffstats
path: root/osscan.h
diff options
context:
space:
mode:
Diffstat (limited to 'osscan.h')
-rw-r--r--osscan.h323
1 files changed, 323 insertions, 0 deletions
diff --git a/osscan.h b/osscan.h
new file mode 100644
index 0000000..76f0fd7
--- /dev/null
+++ b/osscan.h
@@ -0,0 +1,323 @@
+/***************************************************************************
+ * osscan.h -- Routines used for OS detection via TCP/IP fingerprinting. *
+ * For more information on how this works in Nmap, see my paper at *
+ * https://nmap.org/osdetect/ *
+ * *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef OSSCAN_H
+#define OSSCAN_H
+
+#include <nbase.h>
+#include <vector>
+#include <map>
+
+class Target;
+class FingerPrintResultsIPv4;
+
+#define OSSCAN_SUCCESS 0
+#define OSSCAN_NOMATCHES -1
+#define OSSCAN_TOOMANYMATCHES -2
+
+/* We won't even consider matches with a lower accuracy than this */
+#define OSSCAN_GUESS_THRESHOLD 0.85
+
+/* The method used to calculate the Target::distance, included in OS
+ fingerprints. */
+enum dist_calc_method {
+ DIST_METHOD_NONE,
+ DIST_METHOD_LOCALHOST,
+ DIST_METHOD_DIRECT,
+ DIST_METHOD_ICMP,
+ DIST_METHOD_TRACEROUTE
+};
+
+/********************** STRUCTURES ***********************************/
+
+#define NUM_FPTESTS 13
+ // T2-T7 and U1 have 11 attributes each
+#define FP_MAX_TEST_ATTRS 11
+ // RIPCK
+#define FP_MAX_NAME_LEN 5
+
+// Short alphanumeric strings.
+template<u8 _MaxStrLen>
+struct ShortStr {
+ char str[_MaxStrLen+1];
+ bool trunc;
+ ShortStr() : trunc(false) {memset(str, 0, sizeof(str));}
+ ShortStr(const char *s) { setStr(s); }
+ ShortStr(const char *s, const char *e) { setStr(s, e); }
+ void setStr(const char *in);
+ void setStr(const char *in, const char *end);
+ // Helpers for type conversion
+ operator const char *() const {return this->str;}
+ operator char *() {return this->str;}
+ bool operator==(const char *other) const {
+ return (!trunc && strncmp(str, other, _MaxStrLen) == 0);
+ }
+ bool operator==(const ShortStr &other) const {
+ return (!trunc && !other.trunc
+ && strncmp(str, other.str, _MaxStrLen) == 0);
+ }
+ bool operator!=(const ShortStr &other) const {
+ return (trunc || other.trunc
+ || strncmp(str, other.str, _MaxStrLen) != 0);
+ }
+ bool operator<(const ShortStr &other) const {
+ return (trunc < other.trunc || strncmp(str, other.str, _MaxStrLen) < 0);
+ }
+};
+
+typedef ShortStr<FP_MAX_NAME_LEN> FPstr;
+
+struct Attr {
+ FPstr name;
+ int points;
+ Attr() : name(), points(0) {}
+ Attr(const char *n) : name(n), points(0) {}
+};
+
+struct FingerTestDef {
+ FPstr name;
+ u8 numAttrs;
+ bool hasR;
+ std::map<FPstr, u8> AttrIdx;
+ std::vector<Attr> Attrs;
+
+ FingerTestDef() : name(), numAttrs(0), hasR(false) {}
+ FingerTestDef(const FPstr &n, const char *a[]);
+};
+
+#define ID2INT(_i) static_cast<int>(_i)
+#define INT2ID(_i) static_cast<FingerPrintDef::TestID>(_i)
+class FingerPrintDef {
+ public:
+ enum TestID { SEQ, OPS, WIN, ECN, T1, T2, T3, T4, T5, T6, T7, U1, IE, INVALID };
+ static const char *test_attrs[NUM_FPTESTS][FP_MAX_TEST_ATTRS];
+ FingerPrintDef();
+ bool parseTestStr(const char *str, const char *end);
+ FingerTestDef &getTestDef(TestID id) { return TestDefs[ID2INT(id)]; }
+ const FingerTestDef &getTestDef(TestID id) const { return TestDefs[ID2INT(id)]; }
+ int getTestIndex(const FPstr testname) const { return ID2INT(TestIdx.at(testname)); }
+ TestID str2TestID(const FPstr testname) const { return TestIdx.at(testname); }
+
+ private:
+ std::map<FPstr, TestID> TestIdx;
+ std::vector<FingerTestDef> TestDefs;
+};
+
+struct OS_Classification {
+ const char *OS_Vendor;
+ const char *OS_Family;
+ const char *OS_Generation; /* Can be NULL if unclassified */
+ const char *Device_Type;
+ std::vector<const char *> cpe;
+};
+
+/* A description of an operating system: a human-readable name and a list of
+ classifications. */
+struct FingerMatch {
+ int line; /* For reference prints, the line # in nmap-os-db */
+ /* For IPv6 matches, the number of fingerprints that contributed to this
+ * classification group */
+ /* For IPv4 fingerprints, the number of points possible */
+ unsigned short numprints;
+ const char *OS_name;
+ std::vector<OS_Classification> OS_class;
+
+ FingerMatch() : line(-1), numprints(0), OS_name(NULL) {}
+};
+
+struct FingerPrintDB;
+struct FingerTest {
+ FingerPrintDef::TestID id;
+ const FingerTestDef *def;
+ std::vector<const char *> *results;
+ FingerTest() : id(FingerPrintDef::INVALID), def(NULL), results(NULL) {}
+ FingerTest(const FPstr &testname, const FingerPrintDef &Defs) {
+ id = Defs.str2TestID(testname);
+ def = &Defs.getTestDef(id);
+ results = new std::vector<const char *>(def->numAttrs, NULL);
+ }
+ FingerTest(FingerPrintDef::TestID testid, const FingerPrintDef &Defs)
+ : id(testid), results(NULL) {
+ def = &Defs.getTestDef(id);
+ results = new std::vector<const char *>(def->numAttrs, NULL);
+ }
+ FingerTest(const FingerTest &other) : id(other.id), def(other.def), results(other.results) {}
+ ~FingerTest() {
+ // results must be freed manually
+ }
+ void erase();
+ bool str2AVal(const char *str, const char *end);
+ void setAVal(const char *attr, const char *value);
+ const char *getAVal(const char *attr) const;
+ const char *getAValName(u8 index) const;
+ const char *getTestName() const { return def->name.str; }
+ int getMaxPoints() const;
+};
+
+/* Same struct used for reference prints (DB) and observations */
+struct FingerPrint {
+ FingerMatch match;
+ FingerTest tests[NUM_FPTESTS];
+ void erase();
+ void setTest(const FingerTest &test) {
+ tests[ID2INT(test.id)] = test;
+ }
+};
+
+/* These structs are used in fingerprint-processing code outside of Nmap itself
+ * {
+ */
+/* SCAN pseudo-test */
+struct FingerPrintScan {
+ enum Attribute { V, E, D, OT, CT, CU, PV, DS, DC, G, M, TM, P, MAX_ATTR };
+ static const char *attr_names[static_cast<int>(MAX_ATTR)];
+
+ const char *values[static_cast<int>(MAX_ATTR)];
+ bool present;
+ FingerPrintScan() : present(false) {memset(values, 0, sizeof(values));}
+ bool parse(const char *str, const char *end);
+ const char *scan2str() const;
+};
+
+/* An observation parsed from string representation */
+struct ObservationPrint {
+ FingerPrint fp;
+ FingerPrintScan scan_info;
+ std::vector<FingerTest> extra_tests;
+ const char *getInfo(FingerPrintScan::Attribute attr) const {
+ if (attr >= FingerPrintScan::MAX_ATTR)
+ return NULL;
+ return scan_info.values[static_cast<int>(attr)];
+ }
+ void mergeTest(const FingerTest &test) {
+ FingerTest &ours = fp.tests[ID2INT(test.id)];
+ if (ours.id == FingerPrintDef::INVALID)
+ ours = test;
+ else {
+ extra_tests.push_back(test);
+ }
+ }
+};
+/* } */
+
+/* This structure contains the important data from the fingerprint
+ database (nmap-os-db) */
+struct FingerPrintDB {
+ FingerPrintDef *MatchPoints;
+ std::vector<FingerPrint *> prints;
+
+ FingerPrintDB();
+ ~FingerPrintDB();
+};
+
+/********************** PROTOTYPES ***********************************/
+
+const char *fp2ascii(const FingerPrint *FP);
+
+/* 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 fingerprints are OK. */
+ObservationPrint *parse_single_fingerprint(const FingerPrintDB *DB, const char *fprint);
+
+/* These functions take a file/db name and open+parse it, returning an
+ (allocated) FingerPrintDB containing the results. They exit with
+ an error message in the case of error. */
+FingerPrintDB *parse_fingerprint_file(const char *fname, bool points_only);
+FingerPrintDB *parse_fingerprint_reference_file(const char *dbname);
+
+void free_fingerprint_file(FingerPrintDB *DB);
+
+/* 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). MatchPoints is
+ a special "fingerprints" which tells how many points each test is worth. */
+double compare_fingerprints(const FingerPrint *referenceFP, const FingerPrint *observedFP,
+ const FingerPrintDef *MatchPoints, int verbose, double threshold);
+
+/* Takes a fingerprint and looks for matches inside the passed in
+ reference fingerprint DB. The results are stored in in FPR (which
+ must point to an instantiated FingerPrintResultsIPv4 class) -- results
+ will be reverse-sorted by accuracy. No results below
+ accuracy_threshold will be included. The max matches returned is
+ the maximum that fits in a FingerPrintResultsIPv4 class. */
+void match_fingerprint(const FingerPrint *FP, FingerPrintResultsIPv4 *FPR,
+ const FingerPrintDB *DB, double accuracy_threshold);
+
+/* Returns true if perfect match -- if num_subtests & num_subtests_succeeded are non_null it updates them. if shortcircuit is zero, it does all the tests, otherwise it returns when the first one fails */
+
+void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP,
+ const char *engine_id,
+ const struct sockaddr_storage *addr, int distance,
+ enum dist_calc_method distance_calculation_method,
+ const u8 *mac, int openTcpPort,
+ int closedTcpPort, int closedUdpPort);
+const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
+ const struct sockaddr_storage *addr, int distance,
+ enum dist_calc_method distance_calculation_method,
+ const u8 *mac, int openTcpPort, int closedTcpPort,
+ int closedUdpPort, bool wrapit);
+
+#endif /*OSSCAN_H*/
+