diff --git a/FingerPrintResults.cc b/FingerPrintResults.cc index 08d57ff09..25eed9d23 100644 --- a/FingerPrintResults.cc +++ b/FingerPrintResults.cc @@ -117,7 +117,7 @@ FingerPrintResults::~FingerPrintResults() { /* Free OS fingerprints of OS scanning was done */ for(i=0; i < numFPs; i++) { - freeFingerPrint(FPs[i]); + delete(FPs[i]); FPs[i] = NULL; } numFPs = 0; @@ -184,7 +184,8 @@ const char *FingerPrintResults::OmitSubmissionFP() { /* Goes through fingerprinting results to populate OSR */ void FingerPrintResults::populateClassification() { - int printno, classno; + std::vector::iterator osclass; + int printno; OSR.OSC_num_perfect_matches = OSR.OSC_num_matches = 0; OSR.overall_results = OSSCAN_SUCCESS; @@ -198,8 +199,10 @@ void FingerPrintResults::populateClassification() { for(printno = 0; printno < num_matches; printno++) { // a single print may have multiple classifications - for(classno = 0; classno < prints[printno]->num_OS_Classifications; classno++) { - if (!classAlreadyExistsInResults(&(prints[printno]->OS_class[classno]))) { + for (osclass = prints[printno]->OS_class.begin(); + osclass != prints[printno]->OS_class.end(); + osclass++) { + if (!classAlreadyExistsInResults(&*osclass)) { // Then we have to add it ... first ensure we have room if (OSR.OSC_num_matches == MAX_FP_RESULTS) { // 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 - 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]; if (accuracy[printno] == 1.0) OSR.OSC_num_perfect_matches++; OSR.OSC_num_matches++; diff --git a/global_structures.h b/global_structures.h index 6a2648832..ff7052a66 100644 --- a/global_structures.h +++ b/global_structures.h @@ -94,6 +94,8 @@ #ifndef GLOBAL_STRUCTURES_H #define GLOBAL_STRUCTURES_H +#include + class TargetGroup; class Target; @@ -155,35 +157,38 @@ struct ftpinfo { }; struct AVal { - char *attribute; - char value[256]; - struct AVal *next; + const char *attribute; + const char *value; }; struct OS_Classification { - char *OS_Vendor; - char *OS_Family; - char *OS_Generation; /* Can be NULL if unclassified */ - char *Device_Type; + const char *OS_Vendor; + const char *OS_Family; + const char *OS_Generation; /* Can be NULL if unclassified */ + const char *Device_Type; }; -#define MAX_OS_CLASSIFICATIONS_PER_FP 10 -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 */ +struct FingerTest { const char *name; - struct AVal *results; - struct FingerTest *next; - } FingerPrint; + std::vector results; +}; + +struct FingerPrint { + int line; /* For reference prints, the line # in nmap-os-db */ + char *OS_name; + std::vector OS_class; + std::vector tests; +}; /* This structure contains the important data from the fingerprint database (nmap-os-db) */ -typedef struct FingerPrintDB { - FingerPrint **prints; +struct FingerPrintDB { FingerPrint *MatchPoints; -} FingerPrintDB; + std::vector prints; + + FingerPrintDB(); + ~FingerPrintDB(); +}; struct timeout_info { int srtt; /* Smoothed rtt estimate (microseconds) */ diff --git a/nmap.cc b/nmap.cc index f3e0c2f1e..0217b3f22 100644 --- a/nmap.cc +++ b/nmap.cc @@ -1975,8 +1975,8 @@ void nmap_free_mem() { cp_free(); free_dns_servers(); free_etchosts(); - if(o.reference_FPs){ - free_fingerprint_file(o.reference_FPs); + if (o.reference_FPs) { + delete o.reference_FPs; o.reference_FPs = NULL; } AllProbes::service_scan_free(); diff --git a/osscan.cc b/osscan.cc index 86c14e3b5..bf70a294b 100644 --- a/osscan.cc +++ b/osscan.cc @@ -100,6 +100,7 @@ #include "nmap_error.h" #include "utils.h" +#include #if TIME_WITH_SYS_TIME # include # include @@ -112,27 +113,103 @@ #endif #include +#include extern NmapOps o; -static struct AVal *getattrbyname(struct AVal *AV, const char *name) { - if (!AV) return NULL; - do { - if (!strcmp(AV->attribute, name)) - return AV; - AV = AV->next; - } while(AV); +/* Store a string uniquely. The first time this function is called with a + certain string, it allocates memory and stores a copy of the string in a + static pool. Thereafter it will return a pointer to the saved string instead + of allocating memory for an identical one. */ +const char *string_pool_insert(const char *s) +{ + static std::set pool; + static std::pair::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::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::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; } -static struct AVal *gettestbyname(FingerPrint *FP, const char *name) { +static FingerTest *gettestbyname(FingerPrint *FP, const char *name) { + std::vector::iterator i; if (!FP) return NULL; - do { - if (!strcmp(FP->name, name)) - return FP->results; - FP = FP->next; - } while(FP); + for (i = FP->tests.begin(); i != FP->tests.end(); i++) { + if (strcmp(i->name, name) == 0) + return &*i; + }; + 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 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(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_succeeded, int shortcut, int verbose, const char *testGroupName) { - struct AVal *current_ref; - struct AVal *current_fp; - struct AVal *current_points; + std::vector::iterator current_ref; + const struct AVal *current_fp; + const struct AVal *current_points; unsigned int number, number1; unsigned int val; 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 pointsThisTest = 1; - - for(current_ref = reference; current_ref; current_ref = current_ref->next) { + for (current_ref = reference->results.begin(); + current_ref != reference->results.end(); + current_ref++) { current_fp = getattrbyname(fprint, current_ref->attribute); if (!current_fp) continue; /* 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. */ double compare_fingerprints(FingerPrint *referenceFP, FingerPrint *observedFP, FingerPrint *MatchPoints, int verbose) { - FingerPrint *currentReferenceTest; - struct AVal *currentObservedTest; - struct AVal *currentTestMatchPoints; + std::vector::iterator currentReferenceTest; + FingerTest *currentObservedTest; + FingerTest *currentTestMatchPoints; unsigned long num_subtests = 0, num_subtests_succeeded = 0; unsigned long new_subtests, new_subtests_succeeded; assert(referenceFP); assert(observedFP); - for(currentReferenceTest = referenceFP; currentReferenceTest; - currentReferenceTest = currentReferenceTest->next) { + for (currentReferenceTest = referenceFP->tests.begin(); + currentReferenceTest != referenceFP->tests.end(); + currentReferenceTest++) { currentObservedTest = gettestbyname(observedFP, currentReferenceTest->name); if (currentObservedTest) { 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); } else currentTestMatchPoints = NULL; - AVal_match(currentReferenceTest->results, currentObservedTest, currentTestMatchPoints, + AVal_match(&*currentReferenceTest, currentObservedTest, currentTestMatchPoints, &new_subtests, &new_subtests_succeeded, 0, verbose, currentReferenceTest->name); num_subtests += new_subtests; 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. */ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, FingerPrintDB *DB, double accuracy_threshold) { - - int i; double FPR_entrance_requirement = accuracy_threshold; /* accuracy must be at least this big to be added to the list */ - FingerPrint **reference_FPs = DB->prints; - FingerPrint *current_os; + std::vector::iterator current_os; double acc; int state; int skipfp; @@ -315,18 +391,17 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, FPR->overall_results = OSSCAN_SUCCESS; - for(i = 0; reference_FPs[i]; i++) { - current_os = reference_FPs[i]; + for (current_os = DB->prints.begin(); current_os != DB->prints.end(); current_os++) { 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); */ 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 (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 { @@ -370,7 +445,7 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, /* 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->prints[idx+1] = *current_os; FPR->accuracy[idx+1] = acc; state = 1; } @@ -396,21 +471,6 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR, 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) { const char *s = ""; @@ -482,50 +542,76 @@ static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP, 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 null-terminated. Returns the number of bytes written, excluding the 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::const_iterator av; char *p; char *end; size_t len; - if (AV == NULL) { - if (n > 0) - *s = '\0'; + if (n == 0) return 0; - } p = s; end = s + n - 1; - for ( ; AV != NULL; AV = AV->next) { - if (p >= end) - break; - /* Put a separator in front of every attribute-value pair but the first. */ - if (p != s) + + len = strlen(test->name); + if (p + len > end) + goto error; + + memcpy(p, test->name, len); + p += len; + if (p + 1 > end) + 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 = MIN((ptrdiff_t) strlen(AV->attribute), end - p); - memcpy(p, AV->attribute, len); + } + len = strlen(av->attribute); + if (p + len > end) + goto error; + memcpy(p, av->attribute, len); p += len; - if (p >= end) - break; + if (p + 1 > end) + goto error; *p++ = '='; - len = MIN((ptrdiff_t) strlen(AV->value), end - p); - memcpy(p, AV->value, len); + len = strlen(av->value); + if (p + len > end) + goto error; + memcpy(p, av->value, len); p += len; } + + if (p + 1 > end) + goto error; + *p++ = ')'; + *p = '\0'; return p - s; + +error: + if (n > 0) + *s = '\0'; + + return -1; } -static struct AVal *str2AVal(char *str) { +static std::vector str2AVal(char *str) { int i = 1; int count = 1; char *q = str, *p=str; - struct AVal *AVs; - if (!*str) return NULL; + std::vector AVs; + + if (!*str) + return std::vector(); /* count the AVals */ while((q = strchr(q, '%'))) { @@ -533,14 +619,16 @@ static struct AVal *str2AVal(char *str) { q++; } - AVs = (struct AVal *) safe_zalloc(count * sizeof(struct AVal)); + AVs.reserve(count); for(i=0; i < count; i++) { + struct AVal av; + q = strchr(p, '='); if (!q) { fatal("Parse error with AVal string (%s) in nmap-os-db file", str); } *q = '\0'; - AVs[i].attribute = strdup(p); + av.attribute = string_pool_insert(p); p = q+1; if (i != count - 1) { 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); } *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; + AVs.push_back(av); } + return AVs; } /* 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 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) { - struct AVal *av_a, *av_b; +static bool test_match_literal(const FingerTest *a, const FingerTest *b) { + std::vector::const_iterator i; + const struct AVal *av; /* 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) { - av_b = getattrbyname(b, av_a->attribute); - if (av_b == NULL || strcmp(av_a->value, av_b->value) != 0) + for (i = a->results.begin(); i != a->results.end(); i++) { + av = getattrbyname(b, i->attribute); + if (av == NULL || strcmp(i->value, av->value) != 0) return false; } /* 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) { - av_a = getattrbyname(a, av_b->attribute); - if (av_a == NULL || strcmp(av_a->value, av_b->value) != 0) + for (i = b->results.begin(); i != b->results.end(); i++) { + av = getattrbyname(a, i->attribute); + if (av == NULL || strcmp(i->value, av->value) != 0) 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 */ std::list tests; std::list::iterator iter; - const FingerTest *ft; + std::vector::iterator ft; if (numFPs <= 0) 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. */ for (i = 0; i < numFPs; i++) { - for (ft = FPs[i]; ft != NULL; ft = ft->next) - tests.push_back(ft); + for (ft = FPs[i]->tests.begin(); ft != FPs[i]->tests.end(); ft++) + tests.push_back(&*ft); } /* 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) { next = tmp_i; next++; - if (AVal_match_literal((*iter)->results, (*tmp_i)->results)) { + if (test_match_literal(*iter, *tmp_i)) { /* This is a duplicate test. Remove it. */ 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. */ 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++) { - if (strcmp((*iter)->name, ft->name) == 0 - && AVal_match_literal((*iter)->results, ft->results)) { + if (strcmp((*iter)->name, ft->name) == 0 && test_match_literal(*iter, &*ft)) { break; } } if (iter == tests.end()) { char buf[200]; - AVal2str(ft->results, buf, sizeof(buf)); - fatal("The test %s(%s) was somehow lost in %s.\n", ft->name, buf, __func__); + test2str(&*ft, buf, sizeof(buf)); + 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. */ for (iter = tests.begin(); iter != tests.end(); iter++) { - size_t len; + int len; - ft = *iter; - len = MIN((ptrdiff_t) strlen(ft->name), (end - p)); - memcpy(p, ft->name, len); - p += len; - if (p >= end) + len = test2str(*iter, p, end - p + 1); + if (len == -1) break; - *p++ = '('; - len = AVal2str(ft->results, p, end - p + 1); p += len; - if (p >= end) - break; - *p++ = ')'; if (!wrapit) { - if (p >= end) + if (p + 1 > end) break; *p++ = '\n'; } } /* 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__); *p = '\0'; @@ -754,87 +835,52 @@ return str; } const char *fp2ascii(FingerPrint *FP) { -static char str[2048]; -FingerPrint *current; -struct AVal *AV; -char *p = str; -memset(str, 0, sizeof(str)); + static char str[2048]; + std::vector::iterator iter; + char *p = str; -if (!FP) return "(None)"; + if (!FP) return "(None)"; -for(current = FP; current ; current = current->next) { - Strncpy(p, current->name, sizeof(str) - (p-str)); - p += strlen(p); - assert(p-str < (int) sizeof(str) - 30); - *p++='('; - for(AV = current->results; AV; AV = AV->next) { - Strncpy(p, AV->attribute, sizeof(str) - (p-str)); - p += strlen(p); - assert(p-str < (int) sizeof(str) - 30); - *p++='='; - Strncpy(p, AV->value, sizeof(str) - (p-str)); - p += strlen(p); - assert(p-str < (int) sizeof(str) - 30); - *p++ = '%'; + for (iter = FP->tests.begin(); iter != FP->tests.end(); iter++) { + int len; + + len = test2str(&*iter, p, sizeof(str) - (p - str)); + if (len == -1) + break; + p += len; + if (p + 1 > str + sizeof(str)) + break; + *p++ = '\n'; } - if(*(p-1) != '(') - p--; /* Kill the final & */ - *p++ = ')'; - *p++ = '\n'; -} -*p = '\0'; -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; + *p = '\0'; - 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; + return str; } /* 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 current fingerprint. The function quits if there is a parse error */ -static void parse_classline(FingerPrint *FP, char *thisline, int lineno, - int *classno) { +static void parse_classline(FingerPrint *FP, char *thisline, int lineno) { const char *begin, *end; - struct OS_Classification *os_class; + struct OS_Classification os_class; if (!thisline || strncmp(thisline, "Class ", 6) != 0) 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. */ begin = thisline + 6; end = strchr(begin, '|'); if (end == NULL) 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. */ begin = end + 1; end = strchr(begin, '|'); if (end == NULL) 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. */ begin = end + 1; @@ -846,17 +892,16 @@ static void parse_classline(FingerPrint *FP, char *thisline, int lineno, while (isspace((int) (unsigned char) *begin)) begin++; if (begin < end) - os_class->OS_Generation = substrstrip(begin, end); + os_class.OS_Generation = string_pool_substr_strip(begin, end); else - os_class->OS_Generation = NULL; + os_class.OS_Generation = NULL; /* And finally the device type. We look for '\0' instead of '|'. */ begin = end + 1; end = strchr(begin, '\0'); - os_class->Device_Type = substrstrip(begin, end); + os_class.Device_Type = string_pool_substr_strip(begin, end); - (*classno)++; - FP->num_OS_Classifications++; + FP->OS_class.push_back(os_class); } /* 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. */ FingerPrint *parse_single_fingerprint(char *fprint_orig) { int lineno = 0; - int classno = 0; /* Number of Class lines dealt with so far */ char *p, *q; char *thisline, *nextline; char *fprint = strdup(fprint_orig); /* Make a copy we can futz with */ 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; @@ -914,15 +956,12 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) { fatal("Parse error on line %d of fingerprint: %s\n", lineno, thisline); } else if (strncmp(thisline, "Class ", 6) == 0) { - parse_classline(FP, thisline, lineno, &classno); + parse_classline(FP, thisline, lineno); } else if ((q = strchr(thisline, '('))) { + FingerTest test; *q = '\0'; - if(current->name) { - current->next = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); - current = current->next; - } - current->name = strdup(thisline); + test.name = string_pool_insert(thisline); p = q+1; *q = '('; 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); } *q = '\0'; - current->results = str2AVal(p); + test.results = str2AVal(p); + FP->tests.push_back(test); } else { 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 *DB = NULL; FingerPrint *current; FILE *fp; -int max_records = 4096; char line[2048]; -int numrecords = 0; int lineno = 0; bool parsingMatchPoints = false; 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!!!! */ if (!DB) fatal("non-allocated DB passed to %s", __func__); - DB->prints = (FingerPrint **) safe_zalloc(sizeof(FingerPrint *) * max_records); - fp = fopen(fname, "r"); if (!fp) fatal("Unable to open Nmap fingerprint file: %s", fname); @@ -1033,13 +1024,13 @@ while(fgets(line, sizeof(line), fp)) { continue; } - current = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + current = new FingerPrint; if (parsingMatchPoints) { current->OS_name = NULL; DB->MatchPoints = current; } else { - DB->prints[numrecords] = current; + DB->prints.push_back(current); p = line + 12; while(*p && isspace((int) (unsigned char) *p)) p++; @@ -1069,8 +1060,9 @@ while(fgets(line, sizeof(line), fp)) { if (!strncmp(line, "FingerPrint ",12)) { goto fparse; } else if (strncmp(line, "Class ", 6) == 0) { - parse_classline(current, line, lineno, &classno); + parse_classline(current, line, lineno); } else { + FingerTest test; p = line; q = strchr(line, '('); if (!q) { @@ -1078,11 +1070,7 @@ while(fgets(line, sizeof(line), fp)) { goto top; } *q = '\0'; - if(current->name) { - current->next = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); - current = current->next; - } - current->name = strdup(p); + test.name = string_pool_insert(p); p = q+1; *q = '('; q = strchr(p, ')'); @@ -1091,17 +1079,12 @@ while(fgets(line, sizeof(line), fp)) { goto top; } *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); - DB->prints[numrecords] = NULL; return DB; } diff --git a/osscan.h b/osscan.h index 33999ebd1..1d0ec04a7 100644 --- a/osscan.h +++ b/osscan.h @@ -110,6 +110,13 @@ /* moved to global_structures.h */ /********************** 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); /* Parses a single fingerprint from the memory region given. If a diff --git a/osscan2.cc b/osscan2.cc index e2e225a66..521fc487b 100644 --- a/osscan2.cc +++ b/osscan2.cc @@ -271,7 +271,7 @@ public: unsigned int numProbesToSend() {return probesToSend.size();} unsigned int numProbesActive() {return probesActive.size();} - FingerPrint *getFP() {fpPassed = true; return FP;} + FingerPrint *getFP() {return FP;} Target *target; /* the Target */ struct seq_info si; @@ -327,7 +327,7 @@ private: * finally be passed to hs->target->FPR->FPs[x]. */ FingerPrint *FP; - FingerPrint *FPtests[NUM_FPTESTS]; + FingerTest *FPtests[NUM_FPTESTS]; #define FP_TSeq FPtests[0] #define FP_TOps FPtests[1] #define FP_TWin FPtests[2] @@ -345,11 +345,6 @@ private: struct AVal *TOps_AVs[6]; /* 6 AVs of TOps */ struct AVal *TWin_AVs[6]; /* 6 AVs of TWin */ - /* Whether the above FPs is passed. If not and the hss stats is to be - deleted, delete the FPs. This happens when the host is timedout - during the scan. */ - bool fpPassed; - /* The following are variables to store temporary results * during the os fingerprinting process of this host. */ @@ -609,7 +604,6 @@ HostOsScanStats::HostOsScanStats(Target * t) { TOps_AVs[i] = NULL; TWin_AVs[i] = NULL; } - fpPassed = true; icmpEchoReply = NULL; @@ -620,15 +614,9 @@ HostOsScanStats::HostOsScanStats(Target * t) { HostOsScanStats::~HostOsScanStats() { int i; - if(!fpPassed) { - for(i=0; iresults) { - free(FPtests[i]->results); - } - free(FPtests[i]); - } - } + for (i = 0; i < NUM_FPTESTS; i++) { + if (FPtests[i] != NULL) + delete FPtests[i]; } for (i = 0; i < 6; i++) { if (TOps_AVs[i]) @@ -726,8 +714,6 @@ void HostOsScanStats::initScanStats() { TWin_AVs[i] = NULL; } - fpPassed = false; - TOpsReplyNum = 0; TWinReplyNum = 0; @@ -1568,9 +1554,8 @@ void HostOsScan::makeFP(HostOsScanStats *hss) { assert(hss); int i; - int last; - FingerPrint *FP; - struct AVal *pAV; + struct AVal AV; + std::vector::iterator it; int ttl; @@ -1591,22 +1576,22 @@ void HostOsScan::makeFP(HostOsScanStats *hss) { /* We create a Resp (response) attribute with value of N (no) because it is important here to note whether responses were or were not received */ - hss->FPtests[i] = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); - pAV = (struct AVal *) safe_zalloc(sizeof(struct AVal)); - pAV->attribute = (char*)"R"; - strcpy(pAV->value, "N"); - pAV->next = NULL; - hss->FPtests[i]->results = pAV; + hss->FPtests[i] = new FingerTest; + AV.attribute = "R"; + AV.value = "N"; + hss->FPtests[i]->results.push_back(AV); hss->FPtests[i]->name = (i == 3)? "ECN" : (i == 4)? "T1" : (i == 5)? "T2" : (i == 6)? "T3" : (i == 7)? "T4" : (i == 8)? "T5" : (i == 9)? "T6" : (i == 10)? "T7" : (i == 11)? "U1" : "IE"; } else if(hss->FPtests[i]) { /* Replace TTL with initial TTL. */ - for(pAV = hss->FPtests[i]->results; pAV; pAV = pAV->next) { - if(pAV->attribute == (char*)"T") { + for (it = hss->FPtests[i]->results.begin(); + it != hss->FPtests[i]->results.end(); + it++) { + if (strcmp(it->attribute, "T") == 0) { /* Found TTL item. The value for this attribute is the received TTL encoded in decimal. We replace it with the initial TTL encoded in hex. */ - ttl = atoi(pAV->value); + ttl = atoi(it->value); if(hss->distance_guess == -1) hss->distance_guess = get_initial_ttl_guess(ttl) - ttl; @@ -1615,11 +1600,11 @@ void HostOsScan::makeFP(HostOsScanStats *hss) { /* We've gotten response for the UDP probe and thus have the "true" hop count. Add the received TTL to the hop count to get the initial TTL. */ - sprintf(pAV->value, "%hX", ttl + hss->distance); + it->value = string_pool_sprintf("%hX", ttl + hss->distance); } else { /* Guess the initial TTL value */ - pAV->attribute = (char*) "TG"; - sprintf(pAV->value, "%hX", get_initial_ttl_guess(ttl)); + it->attribute = "TG"; + it->value = string_pool_sprintf("%hX", get_initial_ttl_guess(ttl)); } break; } @@ -1628,49 +1613,38 @@ void HostOsScan::makeFP(HostOsScanStats *hss) { } /* Link them up. */ - last = -1; - FP = NULL; - for(i=0; i < NUM_FPTESTS ; i++) { - if (!hss->FPtests[i]) continue; - if (!FP) FP = hss->FPtests[i]; - if (last > -1) { - hss->FPtests[last]->next = hss->FPtests[i]; - } - last = i; + hss->FP = new FingerPrint; + for (i = 0; i < NUM_FPTESTS; i++) { + if (hss->FPtests[i] == NULL) + continue; + hss->FP->tests.push_back(*hss->FPtests[i]); } - if (last != -1) hss->FPtests[last]->next = NULL; - - /* printf("%s", fp2ascii(FP)); */ - - hss->FP = FP; } /* Fill in a struct AVal with a value based on the IP ID sequence generation class (one of the IPID_SEQ_* constants). If ipid_seqclass is such that the test result should be omitted, the function returns NULL and doesn't modify *av. Otherwise, it returns av after filling in the information. */ -static struct AVal *make_aval_ipid_seq(struct AVal *av, char *attribute, +static struct AVal *make_aval_ipid_seq(struct AVal *av, const char *attribute, int ipid_seqclass, int ipids[NUM_SEQ_SAMPLES]) { - char buf[32]; - switch(ipid_seqclass) { case IPID_SEQ_CONSTANT: - snprintf(buf, sizeof(buf), "%X", ipids[0]); + av->value = string_pool_sprintf("%X", ipids[0]); break; case IPID_SEQ_INCR: - strncpy(buf, "I", sizeof(buf)); + av->value = "I"; break; case IPID_SEQ_BROKEN_INCR: - strncpy(buf, "BI", sizeof(buf)); + av->value = "BI"; break; case IPID_SEQ_RPI: - strncpy(buf, "RI", sizeof(buf)); + av->value = "RI"; break; case IPID_SEQ_RD: - strncpy(buf, "RD", sizeof(buf)); + av->value = "RD"; break; case IPID_SEQ_ZERO: - strncpy(buf, "Z", sizeof(buf)); + av->value = "Z"; break; default: /* Signal to omit test result. */ @@ -1678,9 +1652,7 @@ static struct AVal *make_aval_ipid_seq(struct AVal *av, char *attribute, break; } - av->attribute = attribute; - assert(sizeof(av->value) >= sizeof(buf)); - strcpy(av->value, buf); + av->attribute = string_pool_insert(attribute); return av; } @@ -1691,7 +1663,6 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { u32 ts_diffs[NUM_SEQ_SAMPLES]; float seq_rates[NUM_SEQ_SAMPLES]; unsigned long time_usec_diffs[NUM_SEQ_SAMPLES]; - int avnum; double seq_stddev = 0; double seq_rate = 0; double seq_avg_rate = 0; @@ -1703,11 +1674,11 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { int good_tcp_ipid_num, good_tcp_closed_ipid_num, good_icmp_ipid_num; int tsnewval = 0; - struct AVal *seq_AVs; + std::vector seq_AVs; + struct AVal AV; /* Need 8 AVals for SP, GCD, ISR, TI, CI, II, SS, TS. */ - seq_AVs = (struct AVal *) safe_zalloc(sizeof(struct AVal) * 8); - avnum = 0; + seq_AVs.reserve(8); /* Now we make sure there are no gaps in our response array ... */ for(i=0, j=0; i < NUM_SEQ_SAMPLES; i++) { @@ -1736,7 +1707,6 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { /* Time to look at the TCP ISN predictability */ if (hss->si.responses >= 4 && o.scan_delay <= 1000) { - seq_avg_rate /= hss->si.responses - 1; seq_rate = seq_avg_rate; @@ -1790,15 +1760,15 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { } } - seq_AVs[avnum].attribute = (char*)"SP"; - sprintf(seq_AVs[avnum].value, "%X", hss->si.index); - avnum++; - seq_AVs[avnum].attribute = (char*)"GCD"; - sprintf(seq_AVs[avnum].value, "%X", seq_gcd); - avnum++; - seq_AVs[avnum].attribute = (char*)"ISR"; - sprintf(seq_AVs[avnum].value, "%X", (unsigned int) seq_rate); - avnum++; + AV.attribute = "SP"; + AV.value = string_pool_sprintf("%X", hss->si.index); + seq_AVs.push_back(AV); + AV.attribute = "GCD"; + AV.value = string_pool_sprintf("%X", seq_gcd); + seq_AVs.push_back(AV); + AV.attribute = "ISR"; + AV.value = string_pool_sprintf("%X", (unsigned int) seq_rate); + seq_AVs.push_back(AV); } else if (hss->si.responses > 0) { if (o.debugging) log_write(LOG_PLAIN, "Insufficient responses from %s for TCP sequencing (%d), OS detection may be less accurate\n", hss->target->targetipstr(), hss->si.responses); @@ -1853,12 +1823,12 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { } /* This fills in TI=Z or something like that. */ - if (make_aval_ipid_seq(&seq_AVs[avnum], (char *) "TI", tcp_ipid_seqclass, hss->ipid.tcp_ipids) != NULL) - avnum++; - if (make_aval_ipid_seq(&seq_AVs[avnum], (char *) "CI", tcp_closed_ipid_seqclass, hss->ipid.tcp_closed_ipids) != NULL) - avnum++; - if (make_aval_ipid_seq(&seq_AVs[avnum], (char *) "II", icmp_ipid_seqclass, hss->ipid.icmp_ipids) != NULL) - avnum++; + if (make_aval_ipid_seq(&AV, "TI", tcp_ipid_seqclass, hss->ipid.tcp_ipids) != NULL) + seq_AVs.push_back(AV); + if (make_aval_ipid_seq(&AV, "CI", tcp_closed_ipid_seqclass, hss->ipid.tcp_closed_ipids) != NULL) + seq_AVs.push_back(AV); + if (make_aval_ipid_seq(&AV, "II", icmp_ipid_seqclass, hss->ipid.icmp_ipids) != NULL) + seq_AVs.push_back(AV); /* SS: Shared IP ID sequence boolean */ if ( (tcp_ipid_seqclass == IPID_SEQ_INCR || @@ -1869,14 +1839,14 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { icmp_ipid_seqclass == IPID_SEQ_RPI)) { /* Both are incremental. Thus we have "SS" test. Check if they are in the same sequence. */ - seq_AVs[avnum].attribute = (char*)"SS"; + AV.attribute = "SS"; int avg = (hss->ipid.tcp_ipids[good_tcp_ipid_num-1] - hss->ipid.tcp_ipids[0]) / (good_tcp_ipid_num - 1); if ( hss->ipid.icmp_ipids[0] < hss->ipid.tcp_ipids[good_tcp_ipid_num-1] + 3 * avg) { - strcpy(seq_AVs[avnum].value, "S"); + AV.value = "S"; } else { - strcpy(seq_AVs[avnum].value, "O"); + AV.value = "O"; } - avnum++; + seq_AVs.push_back(AV); } /* Now we look at TCP Timestamp sequence prediction */ @@ -1931,15 +1901,15 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { switch(hss->si.ts_seqclass) { case TS_SEQ_ZERO: - seq_AVs[avnum].attribute = (char*)"TS"; - strcpy(seq_AVs[avnum].value, "0"); - avnum++; + AV.attribute = "TS"; + AV.value = "0"; + seq_AVs.push_back(AV); break; case TS_SEQ_2HZ: case TS_SEQ_100HZ: case TS_SEQ_1000HZ: case TS_SEQ_OTHER_NUM: - seq_AVs[avnum].attribute = (char*)"TS"; + AV.attribute = "TS"; /* Here we "cheat" a little to make the classes correspond more closely to common real-life frequencies (particularly 100) @@ -1962,27 +1932,20 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { tsnewval = (unsigned int)(0.5 + log(avg_ts_hz)/log(2.0)); } - sprintf(seq_AVs[avnum].value, "%X", tsnewval); - avnum++; + AV.value = string_pool_sprintf("%X", tsnewval); + seq_AVs.push_back(AV); break; case TS_SEQ_UNSUPPORTED: - seq_AVs[avnum].attribute = (char*)"TS"; - strcpy(seq_AVs[avnum].value, "U"); - avnum++; + AV.attribute = "TS"; + AV.value = "U"; + seq_AVs.push_back(AV); break; } - /* Link up the AVals. */ - for (i = 0; i < avnum - 1; i++) - seq_AVs[i].next = &seq_AVs[i + 1]; - seq_AVs[i].next = NULL; - /* Now generate the SEQ line of the fingerprint if there are any test results in seq_AVs. */ - if (avnum == 0) { - free(seq_AVs); - } else { - hss->FP_TSeq = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + if (!seq_AVs.empty()) { + hss->FP_TSeq = new FingerTest; hss->FP_TSeq->name = "SEQ"; hss->FP_TSeq->results = seq_AVs; } @@ -1990,7 +1953,7 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { void HostOsScan::makeTOpsFP(HostOsScanStats *hss) { assert(hss); - struct AVal *AVs; + std::vector AVs; int i, n; if (hss->TOpsReplyNum != 6) @@ -2006,26 +1969,19 @@ void HostOsScan::makeTOpsFP(HostOsScanStats *hss) { return; } - /* Create the Avals */ - AVs = (struct AVal *) safe_zalloc(n * sizeof(struct AVal)); + AVs.reserve(n); - for (i = 0; i < n - 1; i++) { - if (!hss->TOps_AVs[i]) - break; - AVs[i] = *hss->TOps_AVs[i]; - AVs[i].next = &AVs[i + 1]; - } - AVs[i] = *hss->TOps_AVs[i]; - AVs[i].next = NULL; + for (i = 0; i < n; i++) + AVs.push_back(*hss->TOps_AVs[i]); - hss->FP_TOps= (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + hss->FP_TOps = new FingerTest; hss->FP_TOps->results = AVs; hss->FP_TOps->name = "OPS"; } void HostOsScan::makeTWinFP(HostOsScanStats *hss) { assert(hss); - struct AVal *AVs; + std::vector AVs; int i, n; if (hss->TWinReplyNum != 6) @@ -2041,21 +1997,12 @@ void HostOsScan::makeTWinFP(HostOsScanStats *hss) { return; } - /* Create the Avals */ - AVs = (struct AVal *) safe_zalloc(n * sizeof(struct AVal)); + AVs.reserve(n); - for (i = 0; i < n - 1; i++) { - if (!hss->TWin_AVs[i]) - break; - AVs[i] = *hss->TWin_AVs[i]; - AVs[i].next = &AVs[i + 1]; - } - AVs[i] = *hss->TWin_AVs[i]; - AVs[i].next = NULL; - - hss->TWin_AVs[5]->next = NULL; + for (i = 0; i < n; i++) + AVs.push_back(*hss->TWin_AVs[i]); - hss->FP_TWin = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + hss->FP_TWin = new FingerTest; hss->FP_TWin->results = AVs; hss->FP_TWin->name = "WIN"; } @@ -2128,39 +2075,40 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, struct ip *ip, int replyN bool HostOsScan::processTOpsResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int replyNo) { assert(replyNo>=0 || replyNo<6); + char ops_buf[256]; bool opsParseResult; if (hss->FP_TOps || hss->TOps_AVs[replyNo]) return false; hss->TOps_AVs[replyNo] = (struct AVal *) safe_zalloc(sizeof(struct AVal)); - opsParseResult = get_tcpopt_string(tcp, this->tcpMss, - hss->TOps_AVs[replyNo]->value, - sizeof(hss->TOps_AVs[replyNo]->value)); + opsParseResult = get_tcpopt_string(tcp, this->tcpMss, ops_buf, sizeof(ops_buf)); if (!opsParseResult) { if (o.debugging) error("Option parse error for TOps response %d from %s.", replyNo, hss->target->targetipstr()); - hss->TOps_AVs[replyNo]->value[0] = '\0'; + hss->TOps_AVs[replyNo]->value = ""; } + + hss->TOps_AVs[replyNo]->value = string_pool_insert(ops_buf); switch(replyNo) { case 0: - hss->TOps_AVs[replyNo]->attribute = (char*)"O1"; + hss->TOps_AVs[replyNo]->attribute = "O1"; break; case 1: - hss->TOps_AVs[replyNo]->attribute = (char*)"O2"; + hss->TOps_AVs[replyNo]->attribute = "O2"; break; case 2: - hss->TOps_AVs[replyNo]->attribute = (char*)"O3"; + hss->TOps_AVs[replyNo]->attribute = "O3"; break; case 3: - hss->TOps_AVs[replyNo]->attribute = (char*)"O4"; + hss->TOps_AVs[replyNo]->attribute = "O4"; break; case 4: - hss->TOps_AVs[replyNo]->attribute = (char*)"O5"; + hss->TOps_AVs[replyNo]->attribute = "O5"; break; case 5: - hss->TOps_AVs[replyNo]->attribute = (char*)"O6"; + hss->TOps_AVs[replyNo]->attribute = "O6"; break; } @@ -2174,26 +2122,26 @@ bool HostOsScan::processTWinResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int if (hss->FP_TWin || hss->TWin_AVs[replyNo]) return false; hss->TWin_AVs[replyNo] = (struct AVal *) safe_zalloc(sizeof(struct AVal)); - sprintf(hss->TWin_AVs[replyNo]->value, "%hX", ntohs(tcp->th_win)); + hss->TWin_AVs[replyNo]->value = string_pool_sprintf("%hX", ntohs(tcp->th_win)); switch(replyNo) { case 0: - hss->TWin_AVs[replyNo]->attribute = (char*)"W1"; + hss->TWin_AVs[replyNo]->attribute = "W1"; break; case 1: - hss->TWin_AVs[replyNo]->attribute = (char*)"W2"; + hss->TWin_AVs[replyNo]->attribute = "W2"; break; case 2: - hss->TWin_AVs[replyNo]->attribute = (char*)"W3"; + hss->TWin_AVs[replyNo]->attribute = "W3"; break; case 3: - hss->TWin_AVs[replyNo]->attribute = (char*)"W4"; + hss->TWin_AVs[replyNo]->attribute = "W4"; break; case 4: - hss->TWin_AVs[replyNo]->attribute = (char*)"W5"; + hss->TWin_AVs[replyNo]->attribute = "W5"; break; case 5: - hss->TWin_AVs[replyNo]->attribute = (char*)"W6"; + hss->TWin_AVs[replyNo]->attribute = "W6"; break; } @@ -2202,92 +2150,88 @@ bool HostOsScan::processTWinResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int } bool HostOsScan::processTEcnResp(HostOsScanStats *hss, struct ip *ip) { - struct AVal *AVs; - int i; + std::vector AVs; + struct AVal AV; + char ops_buf[256]; + char quirks_buf[10]; char *p; int numtests = 7; - int current_testno = 0; struct tcp_hdr *tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); bool opsParseResult; if (hss->FP_TEcn) return false; /* Create the Avals */ - AVs = (struct AVal *) safe_zalloc(numtests * sizeof(struct AVal)); + AVs.reserve(numtests); - /* Link them together */ - for(i=0; i < numtests - 1; i++) - AVs[i].next = &AVs[i+1]; - AVs[numtests-1].next = NULL; - - AVs[current_testno].attribute = (char*)"R"; - strcpy(AVs[current_testno].value, "Y"); - - current_testno++; + AV.attribute = "R"; + AV.value = "Y"; + AVs.push_back(AV); /* don't frag flag */ - AVs[current_testno].attribute = (char*)"DF"; - if(ntohs(ip->ip_off) & IP_DF) { - strcpy(AVs[current_testno].value,"Y"); - } else strcpy(AVs[current_testno].value, "N"); - - current_testno++; + AV.attribute = "DF"; + if (ntohs(ip->ip_off) & IP_DF) + AV.value = "Y"; + else + AV.value = "N"; + AVs.push_back(AV); /* TTL */ - AVs[current_testno].attribute = (char*)"T"; - sprintf(AVs[current_testno].value, "%d", ip->ip_ttl); - - current_testno++; + AV.attribute = "T"; + AV.value = string_pool_sprintf("%d", ip->ip_ttl); + AVs.push_back(AV); /* TCP Window size */ - AVs[current_testno].attribute = (char*)"W"; - sprintf(AVs[current_testno].value, "%hX", ntohs(tcp->th_win)); - - current_testno++; + AV.attribute = "W"; + AV.value = string_pool_sprintf("%hX", ntohs(tcp->th_win)); + AVs.push_back(AV); /* Now for the TCP options ... */ - AVs[current_testno].attribute = (char*)"O"; - opsParseResult = get_tcpopt_string(tcp, this->tcpMss, - AVs[current_testno].value, - sizeof(AVs[current_testno].value)); + AV.attribute = "O"; + opsParseResult = get_tcpopt_string(tcp, this->tcpMss, ops_buf, sizeof(ops_buf)); + if (!opsParseResult) { if (o.debugging) error("Option parse error for ECN response from %s.", hss->target->targetipstr()); - AVs[current_testno].value[0] = '\0'; + AV.value = ""; } - current_testno++; - + AV.value = string_pool_insert(ops_buf); + AVs.push_back(AV); + /* Explicit Congestion Notification support test */ - AVs[current_testno].attribute = (char*)"CC"; + AV.attribute = "CC"; if ((tcp->th_flags & TH_ECE) && (tcp->th_flags & TH_CWR)) /* echo back */ - strcpy(AVs[current_testno].value,"S"); + AV.value = "S"; else if (tcp->th_flags & TH_ECE) /* support */ - strcpy(AVs[current_testno].value,"Y"); + AV.value = "Y"; else if (!(tcp->th_flags & TH_CWR)) /* not support */ - strcpy(AVs[current_testno].value,"N"); + AV.value = "N"; else - strcpy(AVs[current_testno].value,"O"); - - current_testno++; + AV.value = "O"; + AVs.push_back(AV); /* TCP miscellaneous quirks test */ - AVs[current_testno].attribute = (char*)"Q"; - p = AVs[current_testno].value; + AV.attribute = "Q"; + p = quirks_buf; if (tcp->th_x2) { /* Reserved field of TCP is not zero */ + assert(p + 1 < quirks_buf + sizeof(quirks_buf)); *p++ = 'R'; } if (!(tcp->th_flags & TH_URG) && tcp->th_urp) { /* URG pointer value when urg flag not set */ + assert(p + 1 < quirks_buf + sizeof(quirks_buf)); *p++ = 'U'; } - *p++ = '\0'; + *p = '\0'; + AV.value = string_pool_insert(quirks_buf); + AVs.push_back(AV); - hss->FP_TEcn = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + hss->FP_TEcn = new FingerTest; hss->FP_TEcn->name = "ECN"; hss->FP_TEcn->results = AVs; @@ -2295,17 +2239,18 @@ bool HostOsScan::processTEcnResp(HostOsScanStats *hss, struct ip *ip) { } bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyNo) { - + std::vector AVs; + struct AVal AV; assert(replyNo>=0 && replyNo<7); int numtests; struct tcp_hdr *tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); - struct AVal *AVs; - int current_testno = 0; int i; bool opsParseResult; int length; + char flags_buf[10]; + char quirks_buf[10]; char *p; if (hss->FPtests[FP_T1_7_OFF+replyNo]) return false; @@ -2314,40 +2259,32 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyN else numtests = 10; /* Create the Avals */ - AVs = (struct AVal *) safe_zalloc(numtests * sizeof(struct AVal)); + AVs.reserve(numtests); - /* Link them together */ - for(i=0; i < numtests - 1; i++) - AVs[i].next = &AVs[i+1]; - AVs[numtests-1].next = NULL; - /* First we give the "response" flag to say we did actually receive a packet -- this way we won't match a template with R=N */ - AVs[current_testno].attribute = (char*)"R"; - strcpy(AVs[current_testno].value, "Y"); - - current_testno++; + AV.attribute = "R"; + AV.value = "Y"; + AVs.push_back(AV); /* Next we check whether the Don't Fragment bit is set */ - AVs[current_testno].attribute = (char*)"DF"; - if(ntohs(ip->ip_off) & IP_DF) { - strcpy(AVs[current_testno].value,"Y"); - } else strcpy(AVs[current_testno].value, "N"); - - current_testno++; + AV.attribute = "DF"; + if (ntohs(ip->ip_off) & IP_DF) + AV.value = "Y"; + else + AV.value = "N"; + AVs.push_back(AV); /* TTL */ - AVs[current_testno].attribute = (char*)"T"; - sprintf(AVs[current_testno].value, "%d", ip->ip_ttl); - - current_testno++; + AV.attribute = "T"; + AV.value = string_pool_sprintf("%d", ip->ip_ttl); + AVs.push_back(AV); if(replyNo!=0) { /* Now we do the TCP Window size */ - AVs[current_testno].attribute = (char*)"W"; - sprintf(AVs[current_testno].value, "%hX", ntohs(tcp->th_win)); - - current_testno++; + AV.attribute = "W"; + AV.value = string_pool_sprintf("%hX", ntohs(tcp->th_win)); + AVs.push_back(AV); } /* Seq test values: @@ -2356,17 +2293,16 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyN A+ = ack + 1 O = other */ - AVs[current_testno].attribute = (char*)"S"; + AV.attribute = "S"; if (ntohl(tcp->th_seq) == 0) - strcpy(AVs[current_testno].value, "Z"); + AV.value = "Z"; else if (ntohl(tcp->th_seq) == tcpAck) - strcpy(AVs[current_testno].value, "A"); + AV.value = "A"; else if (ntohl(tcp->th_seq) == tcpAck + 1) - strcpy(AVs[current_testno].value, "A+"); + AV.value = "A+"; else - strcpy(AVs[current_testno].value, "O"); - - current_testno++; + AV.value = "O"; + AVs.push_back(AV); /* ACK test values: Z = zero @@ -2374,17 +2310,16 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyN S+ = syn + 1 O = other */ - AVs[current_testno].attribute = (char*)"A"; + AV.attribute = "A"; if (ntohl(tcp->th_ack) == 0) - strcpy(AVs[current_testno].value, "Z"); + AV.value = "Z"; else if (ntohl(tcp->th_ack) == tcpSeqBase) - strcpy(AVs[current_testno].value, "S"); + AV.value = "S"; else if (ntohl(tcp->th_ack) == tcpSeqBase + 1) - strcpy(AVs[current_testno].value, "S+"); + AV.value = "S+"; else - strcpy(AVs[current_testno].value, "O"); - - current_testno++; + AV.value = "O"; + AVs.push_back(AV); /* Flags. They must be in this order: E = ECN Echo @@ -2395,60 +2330,73 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyN S = Synchronize F = Final */ - AVs[current_testno].attribute = (char*)"F"; - p = AVs[current_testno].value; - if (tcp->th_flags & TH_ECE) *p++ = 'E'; - if (tcp->th_flags & TH_URG) *p++ = 'U'; - if (tcp->th_flags & TH_ACK) *p++ = 'A'; - if (tcp->th_flags & TH_PUSH) *p++ = 'P'; - if (tcp->th_flags & TH_RST) *p++ = 'R'; - if (tcp->th_flags & TH_SYN) *p++ = 'S'; - if (tcp->th_flags & TH_FIN) *p++ = 'F'; - *p++ = '\0'; - - current_testno++; + struct { + u8 flag; + char c; + } flag_defs[] = { + { TH_ECE, 'E' }, + { TH_URG, 'U' }, + { TH_ACK, 'A' }, + { TH_PUSH, 'P' }, + { TH_RST, 'R' }, + { TH_SYN, 'S' }, + { TH_FIN, 'F' }, + }; + assert(sizeof(flag_defs) / sizeof(flag_defs[0]) < sizeof(flags_buf)); + AV.attribute = "F"; + p = flags_buf; + for (i = 0; i < (int) (sizeof(flag_defs) / sizeof(flag_defs[0])); i++) { + if (tcp->th_flags & flag_defs[i].flag) + *p++ = flag_defs[i].c; + } + *p = '\0'; + AV.value = string_pool_insert(flags_buf); + AVs.push_back(AV); if(replyNo!=0) { + char ops_buf[256]; + /* Now for the TCP options ... */ - AVs[current_testno].attribute = (char*)"O"; - opsParseResult = get_tcpopt_string(tcp, this->tcpMss, - AVs[current_testno].value, - sizeof(AVs[current_testno].value)); + AV.attribute = "O"; + opsParseResult = get_tcpopt_string(tcp, this->tcpMss, ops_buf, sizeof(ops_buf)); if (!opsParseResult) { if (o.debugging) error("Option parse error for T%d response from %s.", replyNo, hss->target->targetipstr()); - AVs[current_testno].value[0] = '\0'; + AV.value = ""; } - current_testno++; + AV.value = string_pool_insert(ops_buf); + AVs.push_back(AV); } /* Rst Data CRC32 */ - AVs[current_testno].attribute = (char*)"RD"; + AV.attribute = "RD"; length = (int) ntohs(ip->ip_len) - 4 * ip->ip_hl -4 * tcp->th_off; if ((tcp->th_flags & TH_RST) && length>0) { - sprintf(AVs[current_testno].value, "%08lX", nbase_crc32(((u8 *)tcp) + 4 * tcp->th_off, length)); + AV.value = string_pool_sprintf("%08lX", nbase_crc32(((u8 *)tcp) + 4 * tcp->th_off, length)); + } else { + AV.value = "0"; } - else { - strcpy(AVs[current_testno].value, "0"); - } - - current_testno++; + AVs.push_back(AV); /* TCP miscellaneous quirks test */ - AVs[current_testno].attribute = (char*)"Q"; - p = AVs[current_testno].value; + AV.attribute = "Q"; + p = quirks_buf; if (tcp->th_x2) { /* Reserved field of TCP is not zero */ + assert(p + 1 < quirks_buf + sizeof(quirks_buf)); *p++ = 'R'; } if (!(tcp->th_flags & TH_URG) && tcp->th_urp) { /* URG pointer value when urg flag not set */ + assert(p + 1 < quirks_buf + sizeof(quirks_buf)); *p++ = 'U'; } *p = '\0'; + AV.value = string_pool_insert(quirks_buf); + AVs.push_back(AV); - hss->FPtests[FP_T1_7_OFF+replyNo] = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + hss->FPtests[FP_T1_7_OFF+replyNo] = new FingerTest; hss->FPtests[FP_T1_7_OFF+replyNo]->results = AVs; hss->FPtests[FP_T1_7_OFF+replyNo]->name = (replyNo == 0)? "T1" : (replyNo == 1)? "T2" : (replyNo == 2)? "T3" : (replyNo == 3)? "T4" : (replyNo == 4)? "T5" : (replyNo == 5)? "T6" : "T7"; @@ -2456,6 +2404,9 @@ bool HostOsScan::processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyN } bool HostOsScan::processTUdpResp(HostOsScanStats *hss, struct ip *ip) { + std::vector AVs; + struct AVal AV; + assert(hss); assert(ip); @@ -2465,9 +2416,6 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, struct ip *ip) { unsigned short checksum; unsigned short *checksumptr; struct udp_hdr *udp; - struct AVal *AVs; - int i; - int current_testno = 0; unsigned char *datastart, *dataend; #if !defined(SOLARIS) && !defined(SUNOS) && !defined(IRIX) && !defined(HPUX) @@ -2494,105 +2442,92 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, struct ip *ip) { } /* Create the Avals */ - AVs = (struct AVal *) safe_zalloc(numtests * sizeof(struct AVal)); + AVs.reserve(numtests); - /* Link them together */ - for(i=0; i < numtests - 1; i++) - AVs[i].next = &AVs[i+1]; - AVs[numtests-1].next = NULL; - /* First of all, if we got this far the response was yes */ - AVs[current_testno].attribute = (char*)"R"; - strcpy(AVs[current_testno].value, "Y"); - - current_testno++; + AV.attribute = "R"; + AV.value = "Y"; + AVs.push_back(AV); /* Also, we now know that the port we reached was closed */ if (hss->target->FPR->osscan_closedudpport == -1) hss->target->FPR->osscan_closedudpport = hss->upi.dport; /* Now let us do an easy one, Don't fragment */ - AVs[current_testno].attribute = (char*)"DF"; - if(ntohs(ip->ip_off) & IP_DF) { - strcpy(AVs[current_testno].value,"Y"); - } else strcpy(AVs[current_testno].value, "N"); - - current_testno++; + AV.attribute = "DF"; + if (ntohs(ip->ip_off) & IP_DF) + AV.value = "Y"; + else + AV.value = "N"; + AVs.push_back(AV); /* TTL */ - AVs[current_testno].attribute = (char*)"T"; - sprintf(AVs[current_testno].value, "%d", ip->ip_ttl); - - current_testno++; + AV.attribute = "T"; + AV.value = string_pool_sprintf("%d", ip->ip_ttl); + AVs.push_back(AV); /* Now we look at the IP datagram length that was returned, some machines send more of the original packet back than others */ - AVs[current_testno].attribute = (char*)"IPL"; - sprintf(AVs[current_testno].value, "%hX", ntohs(ip->ip_len)); - - current_testno++; + AV.attribute = "IPL"; + AV.value = string_pool_sprintf("%hX", ntohs(ip->ip_len)); + AVs.push_back(AV); /* unused filed not zero in Destination Unreachable Message */ - AVs[current_testno].attribute = (char*)"UN"; - sprintf(AVs[current_testno].value, "%hX", ntohl(icmp->icmp_void)); - - current_testno++; + AV.attribute = "UN"; + AV.value = string_pool_sprintf("%hX", ntohl(icmp->icmp_void)); + AVs.push_back(AV); /* OK, lets check the returned IP length, some systems @$@ this up */ - AVs[current_testno].attribute = (char*)"RIPL"; + AV.attribute = "RIPL"; if(ntohs(ip2->ip_len) == 328) - strcpy(AVs[current_testno].value, "G"); + AV.value = "G"; else - sprintf(AVs[current_testno].value, "%hX", ntohs(ip2->ip_len)); - - current_testno++; + AV.value = string_pool_sprintf("%hX", ntohs(ip2->ip_len)); + AVs.push_back(AV); /* This next test doesn't work on Solaris because the lamers overwrite our ip_id */ #if !defined(SOLARIS) && !defined(SUNOS) && !defined(IRIX) && !defined(HPUX) /* Now lets see how they treated the ID we sent ... */ - AVs[current_testno].attribute = (char*)"RID"; + AV.attribute = "RID"; if (ntohs(ip2->ip_id) == hss->upi.ipid) - strcpy(AVs[current_testno].value, "G"); /* The good "expected" value */ + AV.value = "G"; /* The good "expected" value */ else - sprintf(AVs[current_testno].value, "%hX", ntohs(ip2->ip_id)); - - current_testno++; + AV.value = string_pool_sprintf("%hX", ntohs(ip2->ip_id)); + AVs.push_back(AV); #endif /* Let us see if the IP checksum we got back computes */ - AVs[current_testno].attribute = (char*)"RIPCK"; + AV.attribute = "RIPCK"; /* Thanks to some machines not having struct ip member ip_sum we have to go with this BS */ checksumptr = (unsigned short *) ((char *) ip2 + 10); checksum = *checksumptr; if (checksum == 0) - strcpy(AVs[current_testno].value, "Z"); + AV.value = "Z"; else { *checksumptr = 0; if (in_cksum((unsigned short *)ip2, 20) == checksum) { - strcpy(AVs[current_testno].value, "G"); /* The "expected" good value */ + AV.value = "G"; /* The "expected" good value */ } else { - strcpy(AVs[current_testno].value, "I"); /* They fucked it up */ + AV.value = "I"; /* They fucked it up */ } *checksumptr = checksum; } - - current_testno++; + AVs.push_back(AV); /* UDP checksum */ - AVs[current_testno].attribute = (char*)"RUCK"; + AV.attribute = "RUCK"; if (udp->uh_sum == hss->upi.udpck) - strcpy(AVs[current_testno].value, "G"); /* The "expected" good value */ + AV.value = "G"; /* The "expected" good value */ else - sprintf(AVs[current_testno].value, "%hX", ntohs(udp->uh_sum)); - - current_testno++; + AV.value = string_pool_sprintf("%hX", ntohs(udp->uh_sum)); + AVs.push_back(AV); /* Finally we ensure the data is OK */ datastart = ((unsigned char *)udp) + 8; @@ -2602,13 +2537,14 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, struct ip *ip) { if (*datastart != hss->upi.patternbyte) break; datastart++; } - AVs[current_testno].attribute = (char*)"RUD"; + AV.attribute = "RUD"; if (datastart < dataend) - strcpy(AVs[current_testno].value, "I"); /* They fucked it up */ + AV.value = "I"; /* They fucked it up */ else - strcpy(AVs[current_testno].value, "G"); + AV.value = "G"; + AVs.push_back(AV); - hss->FP_TUdp = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + hss->FP_TUdp = new FingerTest; hss->FP_TUdp->name = "U1"; hss->FP_TUdp->results = AVs; @@ -2623,13 +2559,12 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, struct ip *ip) { bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, struct ip *ip, int replyNo) { assert(replyNo==0 || replyNo==1); + std::vector AVs; + struct AVal AV; int numtests = 4; - struct AVal *AVs; struct ip *ip1, *ip2; struct icmp *icmp1, *icmp2; unsigned short value1, value2; - int i; - int current_testno = 0; if (hss->FP_TIcmp) return false; @@ -2660,17 +2595,11 @@ bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, struct ip *ip, int reply assert(icmp1->icmp_type == 0 && icmp2->icmp_type == 0); /* Create the Avals */ - AVs = (struct AVal *) safe_zalloc(numtests * sizeof(struct AVal)); + AVs.reserve(numtests); - /* Link them together */ - for(i=0; i < numtests - 1; i++) - AVs[i].next = &AVs[i+1]; - AVs[numtests-1].next = NULL; - - AVs[current_testno].attribute = (char*)"R"; - strcpy(AVs[current_testno].value, "Y"); - - current_testno++; + AV.attribute = "R"; + AV.value = "Y"; + AVs.push_back(AV); /* DFI test values: * Y. Both set DF; @@ -2678,53 +2607,50 @@ bool HostOsScan::processTIcmpResp(HostOsScanStats *hss, struct ip *ip, int reply * N. Both not set; * O. Other(both different with the sender, -_-b). */ - AVs[current_testno].attribute = (char*)"DFI"; + AV.attribute = "DFI"; value1 = (ntohs(ip1->ip_off) & IP_DF); value2 = (ntohs(ip2->ip_off) & IP_DF); if (value1 && value2) /* both set */ - strcpy(AVs[current_testno].value, "Y"); + AV.value = "Y"; else if (value1 && !value2) /* echo back */ - strcpy(AVs[current_testno].value, "S"); + AV.value = "S"; else if (!value1 && !value2) /* neither set */ - strcpy(AVs[current_testno].value, "N"); + AV.value = "N"; else - strcpy(AVs[current_testno].value, "O"); - - current_testno++; + AV.value = "O"; + AVs.push_back(AV); /* TTL */ - AVs[current_testno].attribute = (char*)"T"; - sprintf(AVs[current_testno].value, "%d", ip1->ip_ttl); - - current_testno++; + AV.attribute = "T"; + AV.value = string_pool_sprintf("%d", ip1->ip_ttl); + AVs.push_back(AV); /* ICMP Code value. Test values: * [Value]. Both set Code to the same value [Value]; * S. Both use the Code that the sender uses; * O. Other. */ - AVs[current_testno].attribute = (char*)"CD"; + AV.attribute = "CD"; value1 = icmp1->icmp_code; value2 = icmp2->icmp_code; if (value1 == value2){ if (value1 == 0) - strcpy(AVs[current_testno].value, "Z"); + AV.value = "Z"; else - sprintf(AVs[current_testno].value, "%hX", value1); + AV.value = string_pool_sprintf("%hX", value1); } else if (value1 == 9 && value2 == 0) /* both the same as in the corresponding probe */ - strcpy(AVs[current_testno].value, "S"); + AV.value = "S"; else - strcpy(AVs[current_testno].value, "O"); + AV.value = "O"; + AVs.push_back(AV); - current_testno++; - - hss->FP_TIcmp= (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); + hss->FP_TIcmp= new FingerTest; hss->FP_TIcmp->name = "IE"; hss->FP_TIcmp->results = AVs; @@ -2823,7 +2749,7 @@ HostOsScanInfo::HostOsScanInfo(Target *t, OsScanInfo *OsSI) { target = t; OSI = OsSI; - FPs = (FingerPrint **) safe_zalloc(o.maxOSTries() * sizeof(FingerPrint *)); + FPs = (FingerPrint **) safe_zalloc(o.maxOSTries() * sizeof(FingerPrint)); FP_matches = (FingerPrintResults *) safe_zalloc(o.maxOSTries() * sizeof(FingerPrintResults)); timedOut = false; isCompleted = false; diff --git a/output.cc b/output.cc index aa1827349..9433986ea 100644 --- a/output.cc +++ b/output.cc @@ -1493,8 +1493,8 @@ void write_host_status(Target * currenths, int resolve_all) { that only unique entries are added. Also note that *numentries is incremented if the candidate is added. arrsize is the number of char * members that fit into arr */ -static int addtochararrayifnew(char *arr[], int *numentries, int arrsize, - char *candidate) { +static int addtochararrayifnew(const char *arr[], int *numentries, int arrsize, + const char *candidate) { int i; // First lets see if the member already exists @@ -1520,7 +1520,7 @@ static void printosclassificationoutput(const struct bool guess) { int classno, i, familyno; 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]" double familyaccuracy[MAX_OS_CLASSMEMBERS]; // highest accuracy for this fullfamily char familygenerations[MAX_OS_CLASSMEMBERS][48]; // example: "4.X|5.X|6.X"