diff --git a/README.md b/README.md index 44a4a9a0..a0c44622 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -[![Masscan unittests](https://github.com/robertdavidgraham/masscan/actions/workflows/unittests.yml/badge.svg?branch=master)](https://github.com/robertdavidgraham/masscan/actions/workflows/unittests.yml/?branch=master) -[![Follow on Twitter](https://img.shields.io/twitter/follow/erratarob.svg?logo=twitter)](https://twitter.com/erratarob) -[![Follow on Mastodon](https://img.shields.io/mastodon/follow/109293216115833216?domain=https%3A%2F%2Finfosec.exchange&style=social)](https://infosec.exchange/@erratarob) +[![unittests](https://github.com/robertdavidgraham/masscan/actions/workflows/unittests.yml/badge.svg?branch=master)](https://github.com/robertdavidgraham/masscan/actions/workflows/unittests.yml/?branch=master) # MASSCAN: Mass IP port scanner diff --git a/src/event-timeout.c b/src/event-timeout.c index 8afbcdfc..d465edb1 100644 --- a/src/event-timeout.c +++ b/src/event-timeout.c @@ -24,7 +24,7 @@ code and causing the bug to come back again. */ #include "event-timeout.h" -#include "logger.h" +#include "util-logger.h" #include "util-malloc.h" #include #include @@ -48,6 +48,13 @@ struct Timeouts { */ uint64_t current_index; + /** + * Counts the number of outstanding timeouts. Adding a timeout increments + * this number, and removing a timeout decrements this number. The + * program shouldn't exit until this number is zero. + */ + uint64_t outstanding_count; + /** * The number of slots is a power-of-2, so the mask is just this * number minus 1 @@ -104,6 +111,8 @@ timeouts_add(struct Timeouts *timeouts, struct TimeoutEntry *entry, unsigned index; /* Unlink from wherever the entry came from */ + if (entry->timestamp) + timeouts->outstanding_count--; timeout_unlink(entry); if (entry->prev) { @@ -122,6 +131,8 @@ timeouts_add(struct Timeouts *timeouts, struct TimeoutEntry *entry, entry->prev = &timeouts->slots[index]; if (entry->next) entry->next->prev = &entry->next; + + timeouts->outstanding_count++; } /*************************************************************************** @@ -155,6 +166,7 @@ timeouts_remove(struct Timeouts *timeouts, uint64_t timestamp) } /* unlink this entry from the timeout system */ + timeouts--; timeout_unlink(entry); /* return a pointer to the structure holding this entry */ diff --git a/src/event-timeout.h b/src/event-timeout.h index f6eb351f..a5d9a186 100644 --- a/src/event-timeout.h +++ b/src/event-timeout.h @@ -3,6 +3,7 @@ #include #include #include /* offsetof*/ +#include "util-bool.h" /* */ #if defined(_MSC_VER) #undef inline #define inline _inline @@ -34,6 +35,16 @@ struct TimeoutEntry { unsigned offset; }; +/*************************************************************************** + ***************************************************************************/ +static inline bool +timeout_is_unlinked(const struct TimeoutEntry *entry) { + if (entry->prev == 0 || entry->next == 0) + return true; + else + return false; +} + /*************************************************************************** ***************************************************************************/ static inline void diff --git a/src/in-binary.c b/src/in-binary.c index b79a7f92..adfab175 100644 --- a/src/in-binary.c +++ b/src/in-binary.c @@ -13,6 +13,7 @@ #include "in-filter.h" #include "in-report.h" #include "util-malloc.h" +#include "util-logger.h" #include #include @@ -485,17 +486,24 @@ _binaryfile_parse(struct Output *out, const char *filename, goto end; } + LOG(0, "[+] --readscan %s\n", filename); + + if (feof(fp)) { + LOG(0, "[-] %s: file is empty\n", filename); + goto end; + } + /* first record is pseudo-record */ bytes_read = fread(buf, 1, 'a'+2, fp); if (bytes_read < 'a'+2) { - perror(filename); + LOG(0, "[-] %s: %s\n", filename, strerror(errno)); goto end; } /* Make sure it's got the format string */ if (memcmp(buf, "masscan/1.1", 11) != 0) { - fprintf(stderr, - "%s: unknown file format (expeced \"masscan/1.1\")\n", + LOG(0, + "[-] %s: unknown file format (expeced \"masscan/1.1\")\n", filename); goto end; } @@ -557,7 +565,7 @@ _binaryfile_parse(struct Output *out, const char *filename, length = (length << 7) | (buf[0] & 0x7F); } if (length > BUF_MAX) { - fprintf(stderr, "file corrupt\n"); + LOG(0, "[-] file corrupt\n"); goto end; } @@ -582,7 +590,7 @@ _binaryfile_parse(struct Output *out, const char *filename, break; case 4: if (fread(buf+bytes_read,1,1,fp) != 1) { - fprintf(stderr, "read() error\n"); + LOG(0, "[-] read() error\n"); exit(1); } bytes_read++; @@ -617,12 +625,12 @@ _binaryfile_parse(struct Output *out, const char *filename, //goto end; break; default: - fprintf(stderr, "file corrupt: unknown type %u\n", type); + LOG(0, "[-] file corrupt: unknown type %u\n", type); goto end; } total_records++; if ((total_records & 0xFFFF) == 0) - fprintf(stderr, "%s: %8" PRIu64 "\r", filename, total_records); + LOG(0, "[+] %s: %8" PRIu64 "\r", filename, total_records); } end: @@ -641,15 +649,15 @@ _binaryfile_parse(struct Output *out, const char *filename, * other formats. This preserves the original timestamps. *****************************************************************************/ void -read_binary_scanfile(struct Masscan *masscan, +readscan_binary_scanfile(struct Masscan *masscan, int arg_first, int arg_max, char *argv[]) { struct Output *out; int i; - //readscan_report_init(); - - + /* + * Create the output system, such as XML or JSON output + */ out = output_create(masscan, 0); /* @@ -672,10 +680,8 @@ read_binary_scanfile(struct Masscan *masscan, _binaryfile_parse(out, argv[i], &masscan->targets, &masscan->banner_types); } + /* Done! */ output_destroy(out); - - //readscan_report_print(); - } diff --git a/src/in-binary.h b/src/in-binary.h index b8630eb1..f3930af7 100644 --- a/src/in-binary.h +++ b/src/in-binary.h @@ -9,7 +9,7 @@ struct Masscan; * JSON or XML. */ void -read_binary_scanfile(struct Masscan *masscan, +readscan_binary_scanfile(struct Masscan *masscan, int arg_first, int arg_max, char *argv[]); #endif diff --git a/src/main-conf.c b/src/main-conf.c index cea527fb..0414c2ec 100644 --- a/src/main-conf.c +++ b/src/main-conf.c @@ -15,7 +15,7 @@ #include "massip-addr.h" #include "masscan-version.h" #include "string_s.h" -#include "logger.h" +#include "util-logger.h" #include "proto-banner1.h" #include "templ-payloads.h" #include "crypto-base64.h" @@ -128,9 +128,13 @@ print_version() compiler_version = "post-2013"; } - + #elif defined(__GNUC__) +# if defined(__clang__) + compiler = "clang"; +# else compiler = "gcc"; +# endif compiler_version = __VERSION__; #if defined(i386) || defined(__i386) || defined(__i386__) @@ -919,30 +923,59 @@ config_top_ports(struct Masscan *masscan, unsigned maxports) 1812, /* RADIUS */ 1646, /* RADIUS */ 1813, /* RADIUS */ + 3343, /* Microsoft Cluster Services */ + 2535, /* MADCAP rfc2730 TODO FIXME */ + }; static const unsigned short top_tcp_ports[] = { - 1,3,4,6,7,9,13,17,19,20,21,22,23,24,25,26,30,32,33,37,42,43,49,53,70, - 79,80,81,82,83,84,85,88,89,90,99,100,106,109,110,111,113,119,125,135, - 139,143,144,146,161,163,179,199,211,212,222,254,255,256,259,264,280, - 301,306,311,340,366,389,406,407,416,417,425,427,443,444,445,458,464, - 465,481,497,500,512,513,514,515,524,541,543,544,545,548,554,555,563, - 587,593,616,617,625,631,636,646,648,666,667,668,683,687,691,700,705, + 80, 443, 8080, /* also web */ + 21, 990, /* FTP, oldie but goodie */ + 22, /* SSH, so much infrastructure */ + 23, 992, /* Telnet, oldie but still around*/ + 24, /* people put things here instead of TelnetSSH*/ + 25, 465, 587, 2525, /* SMTP email*/ + 5800, 5900, 5901, /* VNC */ + 111, /* SunRPC */ + 139, 445, /* Microsoft Windows networking */ + 135, /* DCEPRC, more Microsoft Windows */ + 3389, /* Microsoft Windows RDP */ + 88, /* Kerberos, also Microsoft windows */ + 389, 636, /* LDAP and MS Win */ + 1433, /* MS SQL */ + 53, /* DNS */ + 2083, 2096, /* cPanel */ + 9050, /* ToR */ + 8140, /* Puppet */ + 11211, /* memcached */ + 1098, 1099, /* Java RMI */ + 6000, 6001, /* XWindows */ + 5060, 5061, /* SIP - session initiation protocool */ + 554, /* RTSP */ + 548, /* AFP */ + + + 1,3,4,6,7,9,13,17,19,20,26,30,32,33,37,42,43,49,70, + 79,81,82,83,84,85,89,90,99,100,106,109,110,113,119,125, + 143,144,146,161,163,179,199,211,212,222,254,255,256,259,264,280, + 301,306,311,340,366,406,407,416,417,425,427,444,458,464, + 465,481,497,500,512,513,514,515,524,541,543,544,545,554,555,563, + 593,616,617,625,631,646,648,666,667,668,683,687,691,700,705, 711,714,720,722,726,749,765,777,783,787,800,801,808,843,873,880,888, - 898,900,901,902,903,911,912,981,987,990,992,993,995,999,1000,1001, + 898,900,901,902,903,911,912,981,987,993,995,999,1000,1001, 1002,1007,1009,1010,1011,1021,1022,1023,1024,1025,1026,1027,1028, 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041, 1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054, 1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067, 1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080, 1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093, - 1094,1095,1096,1097,1098,1099,1100,1102,1104,1105,1106,1107,1108, + 1094,1095,1096,1097,1100,1102,1104,1105,1106,1107,1108, 1110,1111,1112,1113,1114,1117,1119,1121,1122,1123,1124,1126,1130, 1131,1132,1137,1138,1141,1145,1147,1148,1149,1151,1152,1154,1163, 1164,1165,1166,1169,1174,1175,1183,1185,1186,1187,1192,1198,1199, 1201,1213,1216,1217,1218,1233,1234,1236,1244,1247,1248,1259,1271, 1272,1277,1287,1296,1300,1301,1309,1310,1311,1322,1328,1334,1352, - 1417,1433,1434,1443,1455,1461,1494,1500,1501,1503,1521,1524,1533, + 1417,1434,1443,1455,1461,1494,1500,1501,1503,1521,1524,1533, 1556,1580,1583,1594,1600,1641,1658,1666,1687,1688,1700,1717,1718, 1719,1720,1721,1723,1755,1761,1782,1783,1801,1805,1812,1839,1840, 1862,1863,1864,1875,1900,1914,1935,1947,1971,1972,1974,1984,1998, @@ -951,7 +984,7 @@ config_top_ports(struct Masscan *masscan, unsigned maxports) 2046,2047,2048,2049,2065,2068,2099,2100,2103,2105,2106,2107,2111, 2119,2121,2126,2135,2144,2160,2161,2170,2179,2190,2191,2196,2200, 2222,2251,2260,2288,2301,2323,2366,2381,2382,2383,2393,2394,2399, - 2401,2492,2500,2522,2525,2557,2601,2602,2604,2605,2607,2608,2638, + 2401,2492,2500,2522,2557,2601,2602,2604,2605,2607,2608,2638, 2701,2702,2710,2717,2718,2725,2800,2809,2811,2869,2875,2909,2910, 2920,2967,2968,2998,3000,3001,3003,3005,3006,3007,3011,3013,3017, 3030,3031,3052,3071,3077,3128,3168,3211,3221,3260,3261,3268,3269, @@ -962,13 +995,13 @@ config_top_ports(struct Masscan *masscan, unsigned maxports) 3995,3998,4000,4001,4002,4003,4004,4005,4006,4045,4111,4125,4126, 4129,4224,4242,4279,4321,4343,4443,4444,4445,4446,4449,4550,4567, 4662,4848,4899,4900,4998,5000,5001,5002,5003,5004,5009,5030,5033, - 5050,5051,5054,5060,5061,5080,5087,5100,5101,5102,5120,5190,5200, + 5050,5051,5054,5080,5087,5100,5101,5102,5120,5190,5200, 5214,5221,5222,5225,5226,5269,5280,5298,5357,5405,5414,5431,5432, 5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678,5679, - 5718,5730,5800,5801,5802,5810,5811,5815,5822,5825,5850,5859,5862, - 5877,5900,5901,5902,5903,5904,5906,5907,5910,5911,5915,5922,5925, - 5950,5952,5959,5960,5961,5962,5963,5987,5988,5989,5998,5999,6000, - 6001,6002,6003,6004,6005,6006,6007,6009,6025,6059,6100,6101,6106, + 5718,5730,5801,5802,5810,5811,5815,5822,5825,5850,5859,5862, + 5877,5902,5903,5904,5906,5907,5910,5911,5915,5922,5925, + 5950,5952,5959,5960,5961,5962,5963,5987,5988,5989,5998,5999, + 6002,6003,6004,6005,6006,6007,6009,6025,6059,6100,6101,6106, 6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565,6566,6567, 6580,6646,6666,6667,6668,6669,6689,6692,6699,6779,6788,6789,6792, 6839,6881,6901,6969,7000,7001,7002,7004,7007,7019,7025,7070,7100, @@ -978,7 +1011,7 @@ config_top_ports(struct Masscan *masscan, unsigned maxports) 8084,8085,8086,8087,8088,8089,8090,8093,8099,8100,8180,8181,8192, 8193,8194,8200,8222,8254,8290,8291,8292,8300,8333,8383,8400,8402, 8443,8500,8600,8649,8651,8652,8654,8701,8800,8873,8888,8899,8994, - 9000,9001,9002,9003,9009,9010,9011,9040,9050,9071,9080,9081,9090, + 9000,9001,9002,9003,9009,9010,9011,9040,9071,9080,9081,9090, 9091,9099,9100,9101,9102,9103,9110,9111,9200,9207,9220,9290,9415, 9418,9485,9500,9502,9503,9535,9575,9593,9594,9595,9618,9666,9876, 9877,9878,9898,9900,9917,9929,9943,9944,9968,9998,9999,10000,10001, @@ -1504,213 +1537,6 @@ static int SET_nobanners(struct Masscan *masscan, const char *name, const char * return CONF_OK; } -static int SET_tcpmss(struct Masscan *masscan, const char *name, const char *value) -{ - /* h/t @IvreRocks */ - static const unsigned default_mss = 1460; - - if (masscan->echo) { - if (masscan->templ_opts) { - switch (masscan->templ_opts->tcp.is_mss) { - case Default: - break; - case Add: - if (masscan->templ_opts->tcp.mss == default_mss) - fprintf(masscan->echo, "tcp-mss = %s\n", "enable"); - else - fprintf(masscan->echo, "tcp-mss = %u\n", - masscan->templ_opts->tcp.mss); - break; - case Remove: - fprintf(masscan->echo, "tcp-mss = %s\n", "disable"); - break; - default: - break; - } - } - return 0; - } - - if (masscan->templ_opts == NULL) - masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); - - if (value == 0 || value[0] == '\0') { - /* no following parameter, so interpret this to mean "enable" */ - masscan->templ_opts->tcp.is_mss = Add; - masscan->templ_opts->tcp.mss = default_mss; /* 1460 */ - } else if (isBoolean(value)) { - /* looking for "enable" or "disable", but any boolean works, - * like "true/false" or "off/on" */ - if (parseBoolean(value)) { - masscan->templ_opts->tcp.is_mss = Add; - masscan->templ_opts->tcp.mss = default_mss; /* 1460 */ - } else - masscan->templ_opts->tcp.is_mss = Remove; - } else if (isInteger(value)) { - /* A specific number was specified */ - uint64_t num = parseInt(value); - if (num >= 0x10000) - goto fail; - masscan->templ_opts->tcp.is_mss = Add; - masscan->templ_opts->tcp.mss = (unsigned)num; - } else - goto fail; - - return CONF_OK; -fail: - fprintf(stderr, "[-] %s: bad value: %s\n", name, value); - return CONF_ERR; -} - -static int SET_tcp_wscale(struct Masscan *masscan, const char *name, const char *value) -{ - static const unsigned default_value = 3; - - if (masscan->echo) { - if (masscan->templ_opts) { - switch (masscan->templ_opts->tcp.is_wscale) { - case Default: - break; - case Add: - if (masscan->templ_opts->tcp.wscale == default_value) - fprintf(masscan->echo, "tcp-wscale = %s\n", "enable"); - else - fprintf(masscan->echo, "tcp-wscale = %u\n", - masscan->templ_opts->tcp.wscale); - break; - case Remove: - fprintf(masscan->echo, "tcp-wscale = %s\n", "disable"); - break; - default: - break; - } - } - return 0; - } - - if (masscan->templ_opts == NULL) - masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); - - if (value == 0 || value[0] == '\0') { - masscan->templ_opts->tcp.is_wscale = Add; - masscan->templ_opts->tcp.wscale = default_value; - } else if (isBoolean(value)) { - if (parseBoolean(value)) { - masscan->templ_opts->tcp.is_wscale = Add; - masscan->templ_opts->tcp.wscale = default_value; - } else - masscan->templ_opts->tcp.is_wscale = Remove; - } else if (isInteger(value)) { - uint64_t num = parseInt(value); - if (num >= 255) - goto fail; - masscan->templ_opts->tcp.is_wscale = Add; - masscan->templ_opts->tcp.wscale = (unsigned)num; - } else - goto fail; - - return CONF_OK; -fail: - fprintf(stderr, "[-] %s: bad value: %s\n", name, value); - return CONF_ERR; -} - -static int SET_tcp_tsecho(struct Masscan *masscan, const char *name, const char *value) -{ - static const unsigned default_value = 0x12345678; - - if (masscan->echo) { - if (masscan->templ_opts) { - switch (masscan->templ_opts->tcp.is_tsecho) { - case Default: - break; - case Add: - if (masscan->templ_opts->tcp.tsecho == default_value) - fprintf(masscan->echo, "tcp-tsecho = %s\n", "enable"); - else - fprintf(masscan->echo, "tcp-tsecho = %u\n", - masscan->templ_opts->tcp.tsecho); - break; - case Remove: - fprintf(masscan->echo, "tcp-tsecho = %s\n", "disable"); - break; - default: - break; - } - } - return 0; - } - - if (masscan->templ_opts == NULL) - masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); - - if (value == 0 || value[0] == '\0') { - masscan->templ_opts->tcp.is_tsecho = Add; - masscan->templ_opts->tcp.tsecho = default_value; - } else if (isBoolean(value)) { - if (parseBoolean(value)) { - masscan->templ_opts->tcp.is_tsecho = Add; - masscan->templ_opts->tcp.tsecho = default_value; - } else - masscan->templ_opts->tcp.is_tsecho = Remove; - } else if (isInteger(value)) { - uint64_t num = parseInt(value); - if (num >= 255) - goto fail; - masscan->templ_opts->tcp.is_tsecho = Add; - masscan->templ_opts->tcp.tsecho = (unsigned)num; - } else - goto fail; - - return CONF_OK; -fail: - fprintf(stderr, "[-] %s: bad value: %s\n", name, value); - return CONF_ERR; -} - -static int SET_tcp_sackok(struct Masscan *masscan, const char *name, const char *value) -{ - if (masscan->echo) { - if (masscan->templ_opts) { - switch (masscan->templ_opts->tcp.is_sackok) { - case Default: - break; - case Add: - fprintf(masscan->echo, "tcp-sackok = %s\n", "enable"); - break; - case Remove: - fprintf(masscan->echo, "tcp-sackok = %s\n", "disable"); - break; - default: - break; - } - } - return 0; - } - - if (masscan->templ_opts == NULL) - masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); - - if (value == 0 || value[0] == '\0') { - masscan->templ_opts->tcp.is_sackok = Add; - } else if (isBoolean(value)) { - if (parseBoolean(value)) { - masscan->templ_opts->tcp.is_sackok = Add; - } else - masscan->templ_opts->tcp.is_sackok = Remove; - } else if (isInteger(value)) { - if (parseInt(value) != 0) - masscan->templ_opts->tcp.is_sackok = Add; - } else - goto fail; - - return CONF_OK; -fail: - fprintf(stderr, "[-] %s: bad value: %s\n", name, value); - return CONF_ERR; -} - - static int SET_noreset(struct Masscan *masscan, const char *name, const char *value) { UNUSEDPARM(name); @@ -2284,6 +2110,222 @@ static int SET_topports(struct Masscan *masscan, const char *name, const char *v return CONF_OK; } +static int SET_tcp_mss(struct Masscan *masscan, const char *name, const char *value) +{ + /* h/t @IvreRocks */ + static const unsigned default_mss = 1460; + + if (masscan->echo) { + if (masscan->templ_opts) { + switch (masscan->templ_opts->tcp.is_mss) { + case Default: + break; + case Add: + if (masscan->templ_opts->tcp.mss == default_mss) + fprintf(masscan->echo, "tcp-mss = %s\n", "enable"); + else + fprintf(masscan->echo, "tcp-mss = %u\n", + masscan->templ_opts->tcp.mss); + break; + case Remove: + fprintf(masscan->echo, "tcp-mss = %s\n", "disable"); + break; + default: + break; + } + } + return 0; + } + + if (masscan->templ_opts == NULL) + masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); + + if (value == 0 || value[0] == '\0') { + /* no following parameter, so interpret this to mean "enable" */ + masscan->templ_opts->tcp.is_mss = Add; + masscan->templ_opts->tcp.mss = default_mss; /* 1460 */ + } else if (isBoolean(value)) { + /* looking for "enable" or "disable", but any boolean works, + * like "true/false" or "off/on" */ + if (parseBoolean(value)) { + masscan->templ_opts->tcp.is_mss = Add; + masscan->templ_opts->tcp.mss = default_mss; /* 1460 */ + } else + masscan->templ_opts->tcp.is_mss = Remove; + } else if (isInteger(value)) { + /* A specific number was specified */ + uint64_t num = parseInt(value); + if (num >= 0x10000) + goto fail; + masscan->templ_opts->tcp.is_mss = Add; + masscan->templ_opts->tcp.mss = (unsigned)num; + } else + goto fail; + + return CONF_OK; +fail: + fprintf(stderr, "[-] %s: bad value: %s\n", name, value); + return CONF_ERR; +} + +static int SET_tcp_wscale(struct Masscan *masscan, const char *name, const char *value) +{ + static const unsigned default_value = 3; + + if (masscan->echo) { + if (masscan->templ_opts) { + switch (masscan->templ_opts->tcp.is_wscale) { + case Default: + break; + case Add: + if (masscan->templ_opts->tcp.wscale == default_value) + fprintf(masscan->echo, "tcp-wscale = %s\n", "enable"); + else + fprintf(masscan->echo, "tcp-wscale = %u\n", + masscan->templ_opts->tcp.wscale); + break; + case Remove: + fprintf(masscan->echo, "tcp-wscale = %s\n", "disable"); + break; + default: + break; + } + } + return 0; + } + + if (masscan->templ_opts == NULL) + masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); + + if (value == 0 || value[0] == '\0') { + masscan->templ_opts->tcp.is_wscale = Add; + masscan->templ_opts->tcp.wscale = default_value; + } else if (isBoolean(value)) { + if (parseBoolean(value)) { + masscan->templ_opts->tcp.is_wscale = Add; + masscan->templ_opts->tcp.wscale = default_value; + } else + masscan->templ_opts->tcp.is_wscale = Remove; + } else if (isInteger(value)) { + uint64_t num = parseInt(value); + if (num >= 255) + goto fail; + masscan->templ_opts->tcp.is_wscale = Add; + masscan->templ_opts->tcp.wscale = (unsigned)num; + } else + goto fail; + + return CONF_OK; +fail: + fprintf(stderr, "[-] %s: bad value: %s\n", name, value); + return CONF_ERR; +} + +static int SET_tcp_tsecho(struct Masscan *masscan, const char *name, const char *value) +{ + static const unsigned default_value = 0x12345678; + + if (masscan->echo) { + if (masscan->templ_opts) { + switch (masscan->templ_opts->tcp.is_tsecho) { + case Default: + break; + case Add: + if (masscan->templ_opts->tcp.tsecho == default_value) + fprintf(masscan->echo, "tcp-tsecho = %s\n", "enable"); + else + fprintf(masscan->echo, "tcp-tsecho = %u\n", + masscan->templ_opts->tcp.tsecho); + break; + case Remove: + fprintf(masscan->echo, "tcp-tsecho = %s\n", "disable"); + break; + default: + break; + } + } + return 0; + } + + if (masscan->templ_opts == NULL) + masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); + + if (value == 0 || value[0] == '\0') { + masscan->templ_opts->tcp.is_tsecho = Add; + masscan->templ_opts->tcp.tsecho = default_value; + } else if (isBoolean(value)) { + if (parseBoolean(value)) { + masscan->templ_opts->tcp.is_tsecho = Add; + masscan->templ_opts->tcp.tsecho = default_value; + } else + masscan->templ_opts->tcp.is_tsecho = Remove; + } else if (isInteger(value)) { + uint64_t num = parseInt(value); + if (num >= 255) + goto fail; + masscan->templ_opts->tcp.is_tsecho = Add; + masscan->templ_opts->tcp.tsecho = (unsigned)num; + } else + goto fail; + + return CONF_OK; +fail: + fprintf(stderr, "[-] %s: bad value: %s\n", name, value); + return CONF_ERR; +} + +static int SET_tcp_sackok(struct Masscan *masscan, const char *name, const char *value) +{ + if (masscan->echo) { + if (masscan->templ_opts) { + switch (masscan->templ_opts->tcp.is_sackok) { + case Default: + break; + case Add: + fprintf(masscan->echo, "tcp-sackok = %s\n", "enable"); + break; + case Remove: + fprintf(masscan->echo, "tcp-sackok = %s\n", "disable"); + break; + default: + break; + } + } + return 0; + } + + if (masscan->templ_opts == NULL) + masscan->templ_opts = calloc(1, sizeof(*masscan->templ_opts)); + + if (value == 0 || value[0] == '\0') { + masscan->templ_opts->tcp.is_sackok = Add; + } else if (isBoolean(value)) { + if (parseBoolean(value)) { + masscan->templ_opts->tcp.is_sackok = Add; + } else + masscan->templ_opts->tcp.is_sackok = Remove; + } else if (isInteger(value)) { + if (parseInt(value) != 0) + masscan->templ_opts->tcp.is_sackok = Add; + } else + goto fail; + + return CONF_OK; +fail: + fprintf(stderr, "[-] %s: bad value: %s\n", name, value); + return CONF_ERR; +} + + +static int SET_debug_tcp(struct Masscan *masscan, const char *name, const char *value) { + extern int is_tcp_debug; + if (value == 0 || value[0] == '\0') + is_tcp_debug = 1; + else + is_tcp_debug = parseBoolean(value); + return CONF_OK; +} + struct ConfigParameter { @@ -2303,10 +2345,6 @@ struct ConfigParameter config_parameters[] = { {"shard", SET_shard, 0, {"shards",0}}, {"banners", SET_banners, F_BOOL, {"banner",0}}, {"nobanners", SET_nobanners, F_BOOL, {"nobanner",0}}, - {"tcpmss", SET_tcpmss, F_NUMABLE, {0}}, - {"tcp-wscale", SET_tcp_wscale, F_NUMABLE, {0}}, - {"tcp-tsecho", SET_tcp_tsecho, F_NUMABLE, {0}}, - {"tcp-sackok", SET_tcp_sackok, F_BOOL, {0}}, {"retries", SET_retries, 0, {"retry", "max-retries", "max-retry", 0}}, {"noreset", SET_noreset, F_BOOL, {0}}, {"nmap-payloads", SET_nmap_payloads, 0, {"nmap-payload",0}}, @@ -2345,7 +2383,13 @@ struct ConfigParameter config_parameters[] = { {"stylesheet", SET_output_stylesheet, 0, {0}}, {"script", SET_script, 0, {0}}, {"SPACE", SET_space, 0, {0}}, + {"tcp-mss", SET_tcp_mss, F_NUMABLE, {"tcpmss",0}}, + {"tcp-wscale", SET_tcp_wscale, F_NUMABLE, {0}}, + {"tcp-tsecho", SET_tcp_tsecho, F_NUMABLE, {0}}, + {"tcp-sackok", SET_tcp_sackok, F_BOOL, {0}}, {"top-ports", SET_topports, F_NUMABLE, {"top-port",0}}, + + {"debug-tcp", SET_debug_tcp, F_BOOL, {"tcp-debug", 0}}, {0} }; @@ -3699,7 +3743,7 @@ masscan_echo(struct Masscan *masscan, FILE *fp, unsigned is_echo_all) } } fprintf(fp, "\n"); - } + } } diff --git a/src/main-initadapter.c b/src/main-initadapter.c index 47dec398..330ddeee 100755 --- a/src/main-initadapter.c +++ b/src/main-initadapter.c @@ -1,5 +1,5 @@ #include "masscan.h" -#include "logger.h" +#include "util-logger.h" #include "rawsock.h" #include "rawsock-adapter.h" #include "stack-arpv4.h" diff --git a/src/main-listscan.c b/src/main-listscan.c index d4a4d744..c4d0470d 100644 --- a/src/main-listscan.c +++ b/src/main-listscan.c @@ -1,5 +1,5 @@ #include "masscan.h" -#include "logger.h" +#include "util-logger.h" #include "crypto-blackrock.h" diff --git a/src/main-throttle.c b/src/main-throttle.c index e84b8e02..cce132c0 100644 --- a/src/main-throttle.c +++ b/src/main-throttle.c @@ -18,7 +18,7 @@ */ #include "main-throttle.h" #include "pixie-timer.h" -#include "logger.h" +#include "util-logger.h" #include #include diff --git a/src/main.c b/src/main.c index 8e65d467..06cc6fb1 100644 --- a/src/main.c +++ b/src/main.c @@ -31,7 +31,7 @@ #include "crypto-lcg.h" /* the LCG randomization func */ #include "crypto-base64.h" /* base64 encode/decode */ #include "templ-pkt.h" /* packet template, that we use to send */ -#include "logger.h" /* adjust with -v command-line opt */ +#include "util-logger.h" /* adjust with -v command-line opt */ #include "stack-ndpv6.h" /* IPv6 Neighbor Discovery Protocol */ #include "stack-arpv4.h" /* Handle ARP resolution and requests */ #include "rawsock.h" /* API on top of Linux, Windows, Mac OS X*/ @@ -54,7 +54,7 @@ #include "proto-x509.h" #include "proto-arp.h" /* for responding to ARP requests */ #include "proto-banner1.h" /* for snatching banners from systems */ -#include "proto-tcp.h" /* for TCP/IP connection table */ +#include "stack-tcp-core.h" /* for TCP/IP connection table */ #include "proto-preprocess.h" /* quick parse of packets */ #include "proto-icmp.h" /* handle ICMP responses */ #include "proto-udp.h" /* handle UDP responses */ @@ -158,7 +158,14 @@ struct ThreadPair { size_t thread_handle_recv; }; - +struct source_t { + unsigned ipv4; + unsigned ipv4_mask; + unsigned port; + unsigned port_mask; + ipv6address ipv6; + ipv6address ipv6_mask; +}; /*************************************************************************** * We support a range of source IP/port. This function converts that @@ -167,29 +174,25 @@ struct ThreadPair { static void adapter_get_source_addresses(const struct Masscan *masscan, unsigned nic_index, - unsigned *src_ipv4, - unsigned *src_ipv4_mask, - unsigned *src_port, - unsigned *src_port_mask, - ipv6address *src_ipv6, - ipv6address *src_ipv6_mask) + struct source_t *src) { - const struct stack_src_t *src = &masscan->nic[nic_index].src; + const struct stack_src_t *ifsrc = &masscan->nic[nic_index].src; static ipv6address mask = {~0ULL, ~0ULL}; - *src_ipv4 = src->ipv4.first; - *src_ipv4_mask = src->ipv4.last - src->ipv4.first; + src->ipv4 = ifsrc->ipv4.first; + src->ipv4_mask = ifsrc->ipv4.last - ifsrc->ipv4.first; - *src_port = src->port.first; - *src_port_mask = src->port.last - src->port.first; + src->port = ifsrc->port.first; + src->port_mask = ifsrc->port.last - ifsrc->port.first; - *src_ipv6 = src->ipv6.first; + src->ipv6 = ifsrc->ipv6.first; /* TODO: currently supports only a single address. This needs to * be fixed to support a list of addresses */ - *src_ipv6_mask = mask; + src->ipv6_mask = mask; } + /*************************************************************************** * This thread spews packets as fast as it can * @@ -218,17 +221,14 @@ transmit_thread(void *v) /*aka. scanning_thread() */ struct Adapter *adapter = parms->adapter; uint64_t packets_sent = 0; unsigned increment = masscan->shard.of * masscan->nic_count; - unsigned src_ipv4; - unsigned src_ipv4_mask; - unsigned src_port; - unsigned src_port_mask; - ipv6address src_ipv6; - ipv6address src_ipv6_mask; + struct source_t src; uint64_t seed = masscan->seed; uint64_t repeats = 0; /* --infinite repeats */ uint64_t *status_syn_count; uint64_t entropy = masscan->seed; + /* Wait to make sure receive_thread is ready */ + pixie_usleep(1000000); LOG(1, "[+] starting transmit thread #%u\n", parms->nic_index); /* export a pointer to this variable outside this threads so @@ -241,10 +241,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */ /* Normally, we have just one source address. In special cases, though * we can have multiple. */ - adapter_get_source_addresses(masscan, parms->nic_index, - &src_ipv4, &src_ipv4_mask, - &src_port, &src_port_mask, - &src_ipv6, &src_ipv6_mask); + adapter_get_source_addresses(masscan, parms->nic_index, &src); /* "THROTTLER" rate-limits how fast we transmit, set with the @@ -345,8 +342,8 @@ transmit_thread(void *v) /*aka. scanning_thread() */ ip_them = range6list_pick(&masscan->targets.ipv6, xXx % count_ipv6); port_them = rangelist_pick(&masscan->targets.ports, xXx / count_ipv6); - ip_me = src_ipv6; - port_me = src_port; + ip_me = src.ipv6; + port_me = src.port; cookie = syn_cookie_ipv6(ip_them, port_them, ip_me, port_me, entropy); @@ -378,16 +375,16 @@ transmit_thread(void *v) /*aka. scanning_thread() */ * SYN-COOKIE LOGIC * Figure out the source IP/port, and the SYN cookie */ - if (src_ipv4_mask > 1 || src_port_mask > 1) { + if (src.ipv4_mask > 1 || src.port_mask > 1) { uint64_t ck = syn_cookie_ipv4((unsigned)(i+repeats), (unsigned)((i+repeats)>>32), (unsigned)xXx, (unsigned)(xXx>>32), entropy); - port_me = src_port + (ck & src_port_mask); - ip_me = src_ipv4 + ((ck>>16) & src_ipv4_mask); + port_me = src.port + (ck & src.port_mask); + ip_me = src.ipv4 + ((ck>>16) & src.ipv4_mask); } else { - ip_me = src_ipv4; - port_me = src_port; + ip_me = src.ipv4; + port_me = src.port; } cookie = syn_cookie_ipv4(ip_them, port_them, ip_me, port_me, entropy); @@ -548,6 +545,7 @@ receive_thread(void *v) uint64_t entropy = masscan->seed; struct ResetFilter *rf; struct stack_t *stack = parms->stack; + struct source_t src = {0}; @@ -625,8 +623,14 @@ receive_thread(void *v) * Initialize TCP scripting */ scripting_init_tcp(tcpcon, masscan->scripting.L); - - + + /* + * Get the possible source IP addresses and ports that masscan + * might be using to transmit from. + */ + adapter_get_source_addresses(masscan, parms->nic_index, &src); + + /* * Set some flags [kludge] */ @@ -959,43 +963,41 @@ receive_thread(void *v) struct TCP_Control_Block *tcb; /* does a TCB already exist for this connection? */ - tcb = tcb_lookup(tcpcon, + tcb = tcpcon_lookup_tcb(tcpcon, ip_me, ip_them, port_me, port_them); if (TCP_IS_SYNACK(px, parsed.transport_offset)) { if (cookie != seqno_me - 1) { ipaddress_formatted_t fmt = ipaddress_fmt(ip_them); - LOG(2, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n", + LOG(0, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n", fmt.string, seqno_me-1, cookie); continue; } - if (tcb == NULL) { tcb = tcpcon_create_tcb(tcpcon, ip_me, ip_them, port_me, port_them, seqno_me, seqno_them+1, - parsed.ip_ttl); + parsed.ip_ttl, NULL, + secs, usecs); (*status_tcb_count)++; - } - Q += stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_SYNACK, - 0, 0, secs, usecs, seqno_them+1); + 0, 0, secs, usecs, seqno_them+1, seqno_me); } else if (tcb) { /* If this is an ACK, then handle that first */ if (TCP_IS_ACK(px, parsed.transport_offset)) { Q += stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_ACK, - 0, seqno_me, secs, usecs, seqno_them); + 0, 0, secs, usecs, seqno_them, seqno_me); } /* If this contains payload, handle that second */ if (parsed.app_length) { Q += stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_DATA, px + parsed.app_offset, parsed.app_length, - secs, usecs, seqno_them); + secs, usecs, seqno_them, seqno_me); } /* If this is a FIN, handle that. Note that ACK + @@ -1003,13 +1005,16 @@ receive_thread(void *v) if (TCP_IS_FIN(px, parsed.transport_offset) && !TCP_IS_RST(px, parsed.transport_offset)) { Q += stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_FIN, - 0, parsed.app_length, secs, usecs, seqno_them); + 0, 0, + secs, usecs, + seqno_them + parsed.app_length, /* the FIN comes after any data in the packet */ + seqno_me); } /* If this is a RST, then we'll be closing the connection */ if (TCP_IS_RST(px, parsed.transport_offset)) { Q += stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_RST, - 0, 0, secs, usecs, seqno_them); + 0, 0, secs, usecs, seqno_them, seqno_me); } } else if (TCP_IS_FIN(px, parsed.transport_offset)) { ipaddress_formatted_t fmt; @@ -1042,7 +1047,6 @@ receive_thread(void *v) if (TCP_IS_SYNACK(px, parsed.transport_offset) || TCP_IS_RST(px, parsed.transport_offset)) { - /* figure out the status */ status = PortStatus_Unknown; if (TCP_IS_SYNACK(px, parsed.transport_offset)) @@ -1054,7 +1058,7 @@ receive_thread(void *v) /* verify: syn-cookies */ if (cookie != seqno_me - 1) { ipaddress_formatted_t fmt = ipaddress_fmt(ip_them); - LOG(5, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n", + LOG(2, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n", fmt.string, seqno_me-1, cookie); continue; } @@ -1311,8 +1315,8 @@ main_scan(struct Masscan *masscan) if (masscan->nic[index].src.port.range == 0) { unsigned port = 40000 + now % 20000; masscan->nic[index].src.port.first = port; - masscan->nic[index].src.port.last = port; - masscan->nic[index].src.port.range = 1; + masscan->nic[index].src.port.last = port + 16; + masscan->nic[index].src.port.range = 16; } stack = stack_create(parms->source_mac, &masscan->nic[index].src); @@ -1778,7 +1782,7 @@ int main(int argc, char *argv[]) * read the binary files, and output them again depending upon * the output parameters */ - read_binary_scanfile(masscan, start, stop, argv); + readscan_binary_scanfile(masscan, start, stop, argv); } break; diff --git a/src/masscan-app.c b/src/masscan-app.c index 720ecbc8..a7ca37e4 100644 --- a/src/masscan-app.c +++ b/src/masscan-app.c @@ -27,6 +27,7 @@ masscan_app_to_string(enum ApplicationProtocol proto) case PROTO_IMAP4: return "imap"; case PROTO_UDP_ZEROACCESS: return "zeroaccess"; case PROTO_X509_CERT: return "X509"; + case PROTO_X509_CACERT: return "X509CA"; case PROTO_HTML_TITLE: return "title"; case PROTO_HTML_FULL: return "html"; case PROTO_NTP: return "ntp"; @@ -34,6 +35,7 @@ masscan_app_to_string(enum ApplicationProtocol proto) case PROTO_HEARTBLEED: return "heartbleed"; case PROTO_TICKETBLEED: return "ticketbleed"; case PROTO_VNC_RFB: return "vnc"; + case PROTO_VNC_INFO: return "vnc-info"; case PROTO_SAFE: return "safe"; case PROTO_MEMCACHED: return "memcached"; case PROTO_SCRIPTING: return "scripting"; @@ -44,6 +46,8 @@ masscan_app_to_string(enum ApplicationProtocol proto) case PROTO_HTTP_SERVER: return "http.server"; case PROTO_MC: return "minecraft"; + case PROTO_ERROR: return "error"; + default: sprintf_s(tmp, sizeof(tmp), "(%u)", proto); return tmp; @@ -73,6 +77,7 @@ masscan_string_to_app(const char *str) {"pop", PROTO_POP3}, {"imap", PROTO_IMAP4}, {"x509", PROTO_X509_CERT}, + {"x509ca", PROTO_X509_CACERT}, {"zeroaccess", PROTO_UDP_ZEROACCESS}, {"title", PROTO_HTML_TITLE}, {"html", PROTO_HTML_FULL}, @@ -81,6 +86,7 @@ masscan_string_to_app(const char *str) {"heartbleed", PROTO_HEARTBLEED}, {"ticketbleed", PROTO_TICKETBLEED}, {"vnc", PROTO_VNC_RFB}, + {"vnc", PROTO_VNC_INFO}, {"safe", PROTO_SAFE}, {"memcached", PROTO_MEMCACHED}, {"scripting", PROTO_SCRIPTING}, diff --git a/src/masscan-app.h b/src/masscan-app.h index 1aa95354..bead1eea 100644 --- a/src/masscan-app.h +++ b/src/masscan-app.h @@ -22,6 +22,7 @@ enum ApplicationProtocol { PROTO_IMAP4, PROTO_UDP_ZEROACCESS, PROTO_X509_CERT, + PROTO_X509_CACERT, PROTO_HTML_TITLE, PROTO_HTML_FULL, PROTO_NTP, /* network time protocol, udp/123 */ @@ -29,6 +30,7 @@ enum ApplicationProtocol { PROTO_HEARTBLEED, PROTO_TICKETBLEED, PROTO_VNC_RFB, + PROTO_VNC_INFO, PROTO_SAFE, PROTO_MEMCACHED, PROTO_SCRIPTING, @@ -39,6 +41,8 @@ enum ApplicationProtocol { PROTO_HTTP_SERVER, /* HTTP "Server:" field */ PROTO_MC, /* Minecraft server */ + PROTO_ERROR, + PROTO_end_of_list /* must be last one */ }; diff --git a/src/masscan-version.h b/src/masscan-version.h index 74d3d0f3..24f902ac 100644 --- a/src/masscan-version.h +++ b/src/masscan-version.h @@ -1,6 +1,6 @@ #ifndef MASSCAN_VERSION -#define MASSCAN_VERSION "1.3.2" +#define MASSCAN_VERSION "1.3.9-integration" #endif diff --git a/src/masscan.h b/src/masscan.h index 5eb51709..fa988850 100644 --- a/src/masscan.h +++ b/src/masscan.h @@ -208,7 +208,7 @@ struct Masscan /** Packet template options, such as whether we should add a TCP MSS * value, or remove it from the packet */ - struct TemplateOptions *templ_opts; + struct TemplateOptions *templ_opts; /* e.g. --tcpmss */ /** * Wait forever for responses, instead of the default 10 seconds diff --git a/src/massip-addr.c b/src/massip-addr.c index ef70952b..a46859cd 100644 --- a/src/massip-addr.c +++ b/src/massip-addr.c @@ -242,6 +242,36 @@ unsigned massint128_bitcount(massint128_t number) return _count_long(number.lo); } +ipv6address_t ipv6address_add_uint64(ipv6address_t lhs, uint64_t rhs) { + lhs.lo += rhs; + if (lhs.lo < rhs) { + lhs.hi += 1; + } + return lhs; +} + +ipv6address_t ipv6address_subtract(ipv6address_t lhs, ipv6address_t rhs) { + ipv6address_t difference; + difference.hi = lhs.hi - rhs.hi; + difference.lo = lhs.lo - rhs.lo; + + /* check for underflow */ + if (difference.lo > lhs.lo) + difference.hi -= 1; + return difference; +} + +ipv6address_t ipv6address_add(ipv6address_t lhs, ipv6address_t rhs) { + ipv6address_t sum; + sum.hi = lhs.hi + rhs.hi; + sum.lo = lhs.lo - rhs.lo; + + /* check for underflow */ + if (sum.lo > lhs.lo) + sum.hi += 1; + return sum; +} + int ipv6address_selftest(void) { diff --git a/src/massip-addr.h b/src/massip-addr.h index 7f4c1789..bba32b85 100644 --- a/src/massip-addr.h +++ b/src/massip-addr.h @@ -79,11 +79,23 @@ static inline int ipv6address_is_invalid(ipv6address_t a) { return a.hi == ~0ULL && a.lo == ~0ULL; } + /** Compare two IPv6 addresses */ static inline int ipv6address_is_equal(ipv6address_t a, ipv6address_t b) { return a.hi == b.hi && a.lo == b.lo; } +static inline int ipaddress_is_equal(ipaddress a, ipaddress b) { + if (a.version != b.version) + return 0; + if (a.version == 4) { + return a.ipv4 == b.ipv4; + } else if (a.version == 6) { + return ipv6address_is_equal(a.ipv6, b.ipv6); + } else + return 0; +} + /** Compare two IPv6 addresses, to see which one comes frist. This is used * in sorting the addresses * @return true if a < b, false otherwise */ @@ -96,6 +108,10 @@ static inline int ipv6address_is_lessthan(ipv6address_t a, ipv6address_t b) { */ int ipv6address_is_equal_prefixed(ipv6address_t lhs, ipv6address_t rhs, unsigned prefix); +ipv6address_t ipv6address_add_uint64(ipv6address_t lhs, uint64_t rhs); +ipv6address_t ipv6address_subtract(ipv6address_t lhs, ipv6address_t rhs); +ipv6address_t ipv6address_add(ipv6address_t lhs, ipv6address_t rhs); + /** * Given a typical EXTERNAL representation of an IPv6 address, which is * an array of 16 bytes, convert to the canonical INTERNAL address. diff --git a/src/massip-parse.c b/src/massip-parse.c index 1151c4dd..25a3148c 100644 --- a/src/massip-parse.c +++ b/src/massip-parse.c @@ -11,7 +11,7 @@ #include "massip-parse.h" #include "massip-rangesv4.h" #include "massip-rangesv6.h" -#include "logger.h" +#include "util-logger.h" #include "util-bool.h" #include "util-malloc.h" #include "string_s.h" diff --git a/src/massip-rangesv4.c b/src/massip-rangesv4.c index c2d0852a..c66cc4d3 100644 --- a/src/massip-rangesv4.c +++ b/src/massip-rangesv4.c @@ -28,7 +28,7 @@ */ #include "massip-rangesv4.h" #include "massip-port.h" -#include "logger.h" +#include "util-logger.h" #include "util-bool.h" #include "util-malloc.h" diff --git a/src/massip-rangesv6.c b/src/massip-rangesv6.c index ad1dfcfb..6d50c59c 100644 --- a/src/massip-rangesv6.c +++ b/src/massip-rangesv6.c @@ -4,7 +4,7 @@ #include "massip-rangesv6.h" #include "massip-rangesv4.h" #include "util-malloc.h" -#include "logger.h" +#include "util-logger.h" #include "massip.h" #include "massip-parse.h" diff --git a/src/out-grepable.c b/src/out-grepable.c index 931349d4..69cdfe8b 100644 --- a/src/out-grepable.c +++ b/src/out-grepable.c @@ -181,9 +181,9 @@ grepable_out_banner(struct Output *out, FILE *fp, time_t timestamp, enum ApplicationProtocol proto, unsigned ttl, const unsigned char *px, unsigned length) { - char banner_buffer[4096]; + char banner_buffer[MAX_BANNER_LENGTH]; ipaddress_formatted_t fmt; - + UNUSEDPARM(ttl); UNUSEDPARM(timestamp); UNUSEDPARM(out); diff --git a/src/out-redis.c b/src/out-redis.c index e259c366..9aad9ace 100644 --- a/src/out-redis.c +++ b/src/out-redis.c @@ -1,7 +1,7 @@ #include "output.h" #include "masscan.h" #include "pixie-sockets.h" -#include "logger.h" +#include "util-logger.h" #include /**************************************************************************** @@ -163,14 +163,14 @@ redis_out_open(struct Output *out, FILE *fp) "$%u\r\n%s\r\n", (unsigned)strlen(out->redis.password), out->redis.password); - count = send(fd, line, (int)strlen(line), 0); + count = send((SOCKET)fd, line, (int)strlen(line), 0); if (count != strlen(line)) { LOG(0, "redis: error auth\n"); exit(1); } - count = recv_line(fd, line, sizeof(line)); + count = recv_line((SOCKET)fd, line, sizeof(line)); if (count != 5 && memcmp(line, "+OK\r\n", 5) != 0) { LOG(0, "redis: unexpected response from redis server: %s\n", line); diff --git a/src/out-text.c b/src/out-text.c index ba3346e9..1a2856b4 100644 --- a/src/out-text.c +++ b/src/out-text.c @@ -54,7 +54,7 @@ text_out_banner(struct Output *out, FILE *fp, time_t timestamp, enum ApplicationProtocol proto, unsigned ttl, const unsigned char *px, unsigned length) { - char banner_buffer[4096]; + char banner_buffer[MAX_BANNER_LENGTH]; ipaddress_formatted_t fmt = ipaddress_fmt(ip); diff --git a/src/out-xml.c b/src/out-xml.c index ce23f6a7..fd73305a 100644 --- a/src/out-xml.c +++ b/src/out-xml.c @@ -98,7 +98,7 @@ xml_out_banner(struct Output *out, FILE *fp, time_t timestamp, unsigned ttl, const unsigned char *px, unsigned length) { - char banner_buffer[4096]; + char banner_buffer[MAX_BANNER_LENGTH]; const char *reason; ipaddress_formatted_t fmt = ipaddress_fmt(ip); diff --git a/src/output.c b/src/output.c index d62ef4a4..0f543189 100644 --- a/src/output.c +++ b/src/output.c @@ -35,13 +35,14 @@ #include "masscan.h" #include "masscan-status.h" #include "string_s.h" -#include "logger.h" #include "proto-banner1.h" #include "masscan-app.h" #include "main-globals.h" #include "pixie-file.h" #include "pixie-sockets.h" #include "util-malloc.h" +#include "util-errormsg.h" +#include "util-logger.h" #include #include @@ -781,8 +782,11 @@ output_report_status(struct Output *out, time_t timestamp, int status, } - if (fp == NULL) + if (fp == NULL) { + ERRMSG("no output file, use `--output-filename ` to set one\n"); + ERRMSG("for `stdout`, use `--output-filename -`\n"); return; + } /* Rotate, if we've pass the time limit. Rotating the log files happens * inline while writing output, whenever there's output to write to the @@ -881,7 +885,7 @@ output_report_banner(struct Output *out, time_t now, * line screen */ if (out->is_interactive || out->format == 0 || out->format == Output_Interactive) { unsigned count; - char banner_buffer[4096]; + char banner_buffer[MAX_BANNER_LENGTH]; count = fprintf(stdout, "Banner on port %u/%s on %s: [%s] %s", port, diff --git a/src/output.h b/src/output.h index c2fec62b..462c68e4 100644 --- a/src/output.h +++ b/src/output.h @@ -9,6 +9,8 @@ #include "unusedparm.h" #include "masscan-app.h" +#define MAX_BANNER_LENGTH 8192 + struct Masscan; struct Output; enum ApplicationProtocol; diff --git a/src/proto-arp.c b/src/proto-arp.c index 0f67c408..5abbbae0 100644 --- a/src/proto-arp.c +++ b/src/proto-arp.c @@ -1,6 +1,6 @@ #include "proto-arp.h" #include "proto-preprocess.h" -#include "logger.h" +#include "util-logger.h" #include "output.h" #include "masscan-status.h" #include "unusedparm.h" diff --git a/src/proto-banner1.c b/src/proto-banner1.c index 9070e98f..ddcd5ae4 100644 --- a/src/proto-banner1.c +++ b/src/proto-banner1.c @@ -4,7 +4,7 @@ #include "smack.h" #include "rawsock-pcapfile.h" #include "proto-preprocess.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-banner1.h" #include "proto-http.h" #include "proto-ssl.h" @@ -19,10 +19,11 @@ #include "proto-vnc.h" #include "proto-memcached.h" #include "proto-mc.h" +#include "proto-versioning.h" #include "masscan-app.h" #include "scripting.h" -#include "versioning.h" #include "util-malloc.h" +#include "util-logger.h" #include #include #include @@ -112,10 +113,10 @@ struct Patterns patterns[] = { unsigned banner1_parse( const struct Banner1 *banner1, - struct ProtocolState *tcb_state, + struct StreamState *tcb_state, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { size_t x; unsigned offset = 0; @@ -171,14 +172,14 @@ banner1_parse( tcb_state, s, s_len, banout, - more); + socket); } banner1_parse( banner1, tcb_state, px, length, banout, - more); + socket); } else { banout_append(banout, PROTO_HEUR, px, length); } @@ -189,7 +190,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_SMTP: banner_smtp.parse( banner1, @@ -197,7 +198,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_TELNET: @@ -206,7 +207,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_RDP: banner_rdp.parse( banner1, @@ -214,7 +215,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_POP3: banner_pop3.parse( banner1, @@ -222,7 +223,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_IMAP4: banner_imap4.parse(banner1, @@ -230,7 +231,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_SSH1: @@ -243,7 +244,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_HTTP: banner_http.parse( @@ -252,7 +253,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_SSL3: banner_ssl.parse( @@ -261,7 +262,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_SMB: banner_smb1.parse( @@ -270,7 +271,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_VNC_RFB: banner_vnc.parse( banner1, @@ -278,7 +279,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_MEMCACHED: banner_memcached.parse( banner1, @@ -286,7 +287,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_SCRIPTING: banner_scripting.parse( banner1, @@ -294,7 +295,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_VERSIONING: banner_versioning.parse( banner1, @@ -302,7 +303,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; case PROTO_MC: banner_mc.parse( @@ -311,7 +312,7 @@ banner1_parse( tcb_state, px, length, banout, - more); + socket); break; default: @@ -323,6 +324,170 @@ banner1_parse( return tcb_state->app_proto; } +/* + * Simple banners with hello probes from nmap-service-probes + */ + +static const char +genericlines_hello[] = "\r\n\r\n"; + +struct ProtocolParserStream banner_genericlines = { + "banner-GenericLines", 1098, genericlines_hello, sizeof(genericlines_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +x11_hello[] = "\x6C\0\x0B\0\0\0\0\0\0\0\0\0"; + +struct ProtocolParserStream banner_x11 = { + "banner-X11Probe", 6000, x11_hello, sizeof(x11_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +javarmi_hello[] = "\x4a\x52\x4d\x49\0\x02\x4b"; + +struct ProtocolParserStream banner_javarmi = { + "banner-JavaRMI", 1098, javarmi_hello, sizeof(javarmi_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +mongodb_hello[] = "\x41\0\0\0\x3a\x30\0\0\xff\xff\xff\xff\xd4\x07\0\0\0\0\0\0test.$cmd\0\0\0\0\0\xff\xff\xff\xff\x1b\0\0\0\x01serverStatus\0\0\0\0\0\0\0\xf0\x3f\0"; + +struct ProtocolParserStream banner_mongodb = { + "banner-mongodb", 27017, mongodb_hello, sizeof(mongodb_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +kerberos_hello[] = "\0\0\0\x71\x6a\x81\x6e\x30\x81\x6b\xa1\x03\x02\x01\x05\xa2\x03\x02\x01\x0a\xa4\x81\x5e\x30\x5c\xa0\x07\x03\x05\0\x50\x80\0\x10\xa2\x04\x1b\x02NM\xa3\x17\x30\x15\xa0\x03\x02\x01\0\xa1\x0e\x30\x0c\x1b\x06krbtgt\x1b\x02NM\xa5\x11\x18\x0f""19700101000000Z\xa7\x06\x02\x04\x1f\x1e\xb9\xd9\xa8\x17\x30\x15\x02\x01\x12\x02\x01\x11\x02\x01\x10\x02\x01\x17\x02\x01\x01\x02\x01\x03\x02\x01\x02"; + +struct ProtocolParserStream banner_kerberos = { + "banner-Kerberos", 88, kerberos_hello, sizeof(kerberos_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +dicom_hello[] = "\x01\x00\x00\x00\x00\xcd\x00\x01\x00\x00""ANY-SCP ECHOSCU 0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x15""1.2.840.10008.3.1.1.1 \x00\x00.\x01\x00\x00\x00""0\x00\x00\x11""1.2.840.10008.1.1@\x00\x00\x11""1.2.840.10008.1.2P\x00\x00:Q\x00\x00\x04\x00\x00@\x00R\x00\x00\x1b""1.2.276.0.7230010.3.0.3.6.2U\x00\x00\x0fOFFIS_DCMTK_362"; + +struct ProtocolParserStream banner_dicom = { + "banner-dicom", 104, dicom_hello, sizeof(dicom_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +ldap_hello[] = "\x30\x84\x00\x00\x00\x2d\x02\x01\x07\x63\x84\x00\x00\x00\x24\x04\x00\x0a\x01\x00\x0a\x01\x00\x02\x01\x00\x02\x01\x64\x01\x01\x00\x87\x0b\x6f\x62\x6a\x65\x63\x74\x43\x6c\x61\x73\x73\x30\x84\x00\x00\x00\x00"; + +struct ProtocolParserStream banner_ldap = { + "banner-LDAPSearchReq", 389, ldap_hello, sizeof(ldap_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +sip_hello[] = "OPTIONS sip:nm SIP/2.0\r\nVia: SIP/2.0/TCP nm;branch=foo\r\nFrom: ;tag=root\r\nTo: \r\nCall-ID: 50000\r\nCSeq: 42 OPTIONS\r\nMax-Forwards: 70\r\nContent-Length: 0\r\nContact: \r\nAccept: application/sdp\r\n\r\n"; + +struct ProtocolParserStream banner_sip = { + "banner-SIPOptions", 5060, sip_hello, sizeof(sip_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +rtsp_hello[] = "OPTIONS / RTSP/1.0\r\n\r\n"; + +struct ProtocolParserStream banner_rtsp = { + "banner-RTSPRequest", 554, rtsp_hello, sizeof(rtsp_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +rpc_hello[] = "\x80\0\0\x28\x72\xFE\x1D\x13\0\0\0\0\0\0\0\x02\0\x01\x86\xA0\0\x01\x97\x7C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + +struct ProtocolParserStream banner_rpc = { + "banner-RPCCheck", 111, rpc_hello, sizeof(rpc_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +dns_hello[] = "\0\x1E\0\x06\x01\0\0\x01\0\0\0\0\0\0\x07version\x04""bind\0\0\x10\0\x03"; + +struct ProtocolParserStream banner_dns = { + "banner-DNSVersionBindReqTCP", 53, dns_hello, sizeof(dns_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +docker_hello[] = "GET /version HTTP/1.1\r\n\r\n"; + +struct ProtocolParserStream banner_docker = { + "banner-docker", 2375, docker_hello, sizeof(docker_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +redis_hello[] = "*1\r\n$4\r\ninfo\r\n"; + +struct ProtocolParserStream banner_redis = { + "banner-redis-server", 6379, redis_hello, sizeof(redis_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +notes_rpc_hello[] = "\x3A\x00\x00\x00\x2F\x00\x00\x00\x02\x00\x00\x40\x02\x0F\x00\x01\x00\x3D\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x1F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; + +struct ProtocolParserStream banner_notes_rpc = { + "banner-NotesRPC", 6379, notes_rpc_hello, sizeof(notes_rpc_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +ms_sql_s_hello[] = "\x12\x01\x00\x34\x00\x00\x00\x00\x00\x00\x15\x00\x06\x01\x00\x1b\x00\x01\x02\x00\x1c\x00\x0c\x03\x00\x28\x00\x04\xff\x08\x00\x01\x55\x00\x00\x00\x4d\x53\x53\x51\x4c\x53\x65\x72\x76\x65\x72\x00\x48\x0f\x00\x00"; + +struct ProtocolParserStream banner_ms_sql_s = { + "banner-ms-sql-s", 6379, ms_sql_s_hello, sizeof(ms_sql_s_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + +static const char +afp_hello[] = "\x00\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x0f\x00"; + +struct ProtocolParserStream banner_afp = { + "banner-afp", 548, afp_hello, sizeof(afp_hello) - 1, 0, + NULL, + NULL, + NULL, +}; + /*************************************************************************** * Create the --banners systems @@ -358,6 +523,10 @@ banner1_create(void) b->payloads.tcp[8080] = &banner_http; b->payloads.tcp[139] = (void*)&banner_smb0; b->payloads.tcp[445] = (void*)&banner_smb1; + b->payloads.tcp[8530] = (void*)&banner_http; /* WSUS */ + b->payloads.tcp[8531] = (void*)&banner_ssl; /* WSUS/s */ + /* https://www.nomotion.net/blog/sharknatto/ */ + b->payloads.tcp[49955] = (void*)&banner_ssl; /* AT&T box */ b->payloads.tcp[443] = (void*)&banner_ssl; /* HTTP/s */ b->payloads.tcp[465] = (void*)&banner_ssl; /* SMTP/s */ b->payloads.tcp[990] = (void*)&banner_ssl; /* FTP/s */ @@ -375,7 +544,69 @@ banner1_create(void) b->payloads.tcp[11211] = (void*)&banner_memcached; b->payloads.tcp[23] = (void*)&banner_telnet; b->payloads.tcp[3389] = (void*)&banner_rdp; - + + b->payloads.tcp[1098] = (void*)&banner_javarmi; + b->payloads.tcp[1099] = (void*)&banner_javarmi; + for (i=0; i < 20; i++) { + b->payloads.tcp[6000 + i] = (void*)&banner_x11; + } + b->payloads.tcp[88] = (void*)&banner_kerberos; + b->payloads.tcp[9001] = (void*)&banner_mongodb; + b->payloads.tcp[27017] = (void*)&banner_mongodb; + b->payloads.tcp[49153] = (void*)&banner_mongodb; + b->payloads.tcp[104] = (void*)&banner_dicom; + b->payloads.tcp[2345] = (void*)&banner_dicom; + b->payloads.tcp[2761] = (void*)&banner_dicom; + b->payloads.tcp[2762] = (void*)&banner_dicom; + b->payloads.tcp[4242] = (void*)&banner_dicom; + b->payloads.tcp[11112] = (void*)&banner_dicom; + b->payloads.tcp[256] = (void*)&banner_ldap; + b->payloads.tcp[257] = (void*)&banner_ldap; + b->payloads.tcp[389] = (void*)&banner_ldap; + b->payloads.tcp[390] = (void*)&banner_ldap; + b->payloads.tcp[1702] = (void*)&banner_ldap; + b->payloads.tcp[3268] = (void*)&banner_ldap; + b->payloads.tcp[3892] = (void*)&banner_ldap; + b->payloads.tcp[11711] = (void*)&banner_ldap; + /* LDAP/s */ + b->payloads.tcp[636] = (void*)&banner_ssl; + b->payloads.tcp[637] = (void*)&banner_ssl; + b->payloads.tcp[3269] = (void*)&banner_ssl; + b->payloads.tcp[11712] = (void*)&banner_ssl; + b->payloads.tcp[406] = (void*)&banner_sip; + b->payloads.tcp[5060] = (void*)&banner_sip; + b->payloads.tcp[8081] = (void*)&banner_sip; + b->payloads.tcp[31337] = (void*)&banner_sip; + /* SIP/s */ + b->payloads.tcp[5061] = (void*)&banner_ssl; + b->payloads.tcp[554] = (void*)&banner_rtsp; + b->payloads.tcp[8554] = (void*)&banner_rtsp; + /* RTSP/s */ + b->payloads.tcp[322] = (void*)&banner_ssl; + b->payloads.tcp[111] = (void*)&banner_rpc; + b->payloads.tcp[2049] = (void*)&banner_rpc; + b->payloads.tcp[53] = (void*)&banner_dns; + b->payloads.tcp[135] = (void*)&banner_dns; + b->payloads.tcp[50000] = (void*)&banner_dns; + b->payloads.tcp[50001] = (void*)&banner_dns; + b->payloads.tcp[50002] = (void*)&banner_dns; + b->payloads.tcp[2375] = (void*)&banner_docker; + /* Docker/s */ + b->payloads.tcp[2376] = (void*)&banner_ssl; + b->payloads.tcp[2379] = (void*)&banner_docker; + b->payloads.tcp[2380] = (void*)&banner_docker; + b->payloads.tcp[6379] = (void*)&banner_redis; + b->payloads.tcp[130] = (void*)&banner_notes_rpc; + b->payloads.tcp[427] = (void*)&banner_notes_rpc; + b->payloads.tcp[1352] = (void*)&banner_notes_rpc; + b->payloads.tcp[1972] = (void*)&banner_notes_rpc; + b->payloads.tcp[7171] = (void*)&banner_notes_rpc; + b->payloads.tcp[8728] = (void*)&banner_notes_rpc; + b->payloads.tcp[22001] = (void*)&banner_notes_rpc; + b->payloads.tcp[1433] = (void*)&banner_ms_sql_s; + /* AFP */ + b->payloads.tcp[548] = (void*)&banner_afp; + /* * This goes down the list of all the TCP protocol handlers and initializes * them. @@ -388,6 +619,7 @@ banner1_create(void) banner_smtp.init(b); banner_ssh.init(b); banner_ssl.init(b); + banner_ssl_12.init(b); banner_smb0.init(b); banner_smb1.init(b); banner_telnet.init(b); @@ -396,8 +628,8 @@ banner1_create(void) banner_mc.init(b); /* scripting/versioning come after the rest */ - banner_scripting.init(b); - banner_versioning.init(b); + //banner_scripting.init(b); + //banner_versioning.init(b); return b; @@ -475,7 +707,7 @@ banner1_selftest() { unsigned i; struct Banner1 *b; - struct ProtocolState tcb_state[1]; + struct StreamState tcb_state[1]; const unsigned char *px; unsigned length; struct BannerOutput banout[1]; @@ -495,6 +727,8 @@ banner1_selftest() length = (unsigned)strlen(http_header); + LOG(1, "[ ] banners: selftesting\n"); + /* * First, test the "banout" subsystem */ @@ -513,7 +747,7 @@ banner1_selftest() memset(tcb_state, 0, sizeof(tcb_state[0])); for (i=0; i #include @@ -13,10 +13,10 @@ static void ftp_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -42,7 +42,7 @@ ftp_parse( const struct Banner1 *banner1, case 103: if (!isdigit(px[i]&0xFF)) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } else { ftp->code *= 10; ftp->code += (px[i] - '0'); @@ -62,7 +62,7 @@ ftp_parse( const struct Banner1 *banner1, banout_append_char(banout, PROTO_FTP, px[i]); } else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 5: @@ -70,7 +70,7 @@ ftp_parse( const struct Banner1 *banner1, continue; else if (px[i] == '\n') { if (ftp->is_last) { - tcp_transmit(more, "AUTH TLS\r\n", 10, 0); + tcpapi_send(socket, "AUTH TLS\r\n", 10, 0); state = 100; banout_append_char(banout, PROTO_FTP, px[i]); } else { @@ -79,7 +79,7 @@ ftp_parse( const struct Banner1 *banner1, } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_FTP, px[i]); @@ -100,15 +100,15 @@ ftp_parse( const struct Banner1 *banner1, pstate->port = (unsigned short)port; state = 0; - tcp_transmit(more, banner_ssl.hello, banner_ssl.hello_length, 0); + tcpapi_send(socket, banner_ssl.hello, banner_ssl.hello_length, 0); } else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_FTP, px[i]); @@ -127,7 +127,7 @@ ftp_parse( const struct Banner1 *banner1, static void * ftp_init(struct Banner1 *banner1) { - UNUSEDPARM(banner1); + //banner1->payloads.tcp[21] = &banner_ftp; return 0; } diff --git a/src/proto-http.c b/src/proto-http.c index 0cae3fad..b25188a2 100644 --- a/src/proto-http.c +++ b/src/proto-http.c @@ -1,13 +1,13 @@ #include "proto-http.h" #include "proto-banner1.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "smack.h" #include "unusedparm.h" #include "string_s.h" #include "masscan-app.h" #include "util-malloc.h" #include "util-bool.h" -#include "proto-tcp.h" +#include "stack-tcp-core.h" #include #include #include @@ -385,7 +385,11 @@ http_change_field(unsigned char **inout_header, size_t header_length, ***************************************************************************/ static const char http_hello[] = "GET / HTTP/1.0\r\n" - "User-Agent: masscan/1.3 (https://github.com/robertdavidgraham/masscan)\r\n" +#ifdef IVRE_BUILD + "User-Agent: ivre-masscan/1.3 https://ivre.rocks/\r\n" +#else + "User-Agent: ivre-masscan/1.3 https://github.com/robertdavidgraham/\r\n" +#endif "Accept: */*\r\n" //"Connection: Keep-Alive\r\n" //"Content-Length: 0\r\n" @@ -484,10 +488,10 @@ static void http_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -508,7 +512,7 @@ http_parse( }; UNUSEDPARM(banner1_private); - UNUSEDPARM(more); + UNUSEDPARM(socket); state2 = (state>>16) & 0xFFFF; id = (state>>8) & 0xFF; @@ -519,7 +523,7 @@ http_parse( case 0: case 1: case 2: case 3: case 4: if (toupper(px[i]) != "HTTP/"[state]) { state = DONE_PARSING; - tcp_close(more); + tcpapi_close(socket); } else state++; break; @@ -528,7 +532,7 @@ http_parse( state++; else if (!isdigit(px[i])) { state = DONE_PARSING; - tcp_close(more); + tcpapi_close(socket); } break; case 6: @@ -536,7 +540,7 @@ http_parse( state++; else if (!isdigit(px[i])) { state = DONE_PARSING; - tcp_close(more); + tcpapi_close(socket); } break; case 7: @@ -709,13 +713,12 @@ static int http_selftest_parser(void) { struct Banner1 *banner1 = NULL; - struct ProtocolState pstate[1]; + struct StreamState pstate[1]; struct BannerOutput banout[1]; - struct InteractiveData more[1]; + memset(pstate, 0, sizeof(pstate[0])); memset(banout, 0, sizeof(banout[0])); - memset(more, 0, sizeof(more[0])); /* * Test start @@ -728,7 +731,7 @@ http_selftest_parser(void) /* * Run Test */ - http_parse(banner1, 0, pstate, (const unsigned char *)test_response, strlen(test_response), banout, more); + http_parse(banner1, 0, pstate, (const unsigned char *)test_response, strlen(test_response), banout, 0); /* diff --git a/src/proto-icmp.c b/src/proto-icmp.c index 9c1bff7d..de7c2217 100644 --- a/src/proto-icmp.c +++ b/src/proto-icmp.c @@ -1,7 +1,7 @@ #include "proto-icmp.h" #include "proto-preprocess.h" #include "syn-cookie.h" -#include "logger.h" +#include "util-logger.h" #include "output.h" #include "masscan-status.h" #include "massip-port.h" diff --git a/src/proto-imap4.c b/src/proto-imap4.c index fc0c2e3d..58c83883 100644 --- a/src/proto-imap4.c +++ b/src/proto-imap4.c @@ -9,7 +9,7 @@ #include "proto-banner1.h" #include "unusedparm.h" #include "masscan-app.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-ssl.h" #include #include @@ -20,10 +20,10 @@ static void imap4_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -43,7 +43,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 1: @@ -52,7 +52,7 @@ imap4_parse( const struct Banner1 *banner1, continue; } else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } /* fall through */ case 2: @@ -61,7 +61,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 3: @@ -70,7 +70,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 4: @@ -89,7 +89,7 @@ imap4_parse( const struct Banner1 *banner1, case 5: banout_append_char(banout, PROTO_IMAP4, px[i]); if (px[i] == '\n') { - tcp_transmit(more, "a001 CAPABILITY\r\n", 17, 0); + tcpapi_send(socket, "a001 CAPABILITY\r\n", 17, 0); state = 100; } break; @@ -102,7 +102,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 101: @@ -112,7 +112,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 102: @@ -122,7 +122,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 103: @@ -131,7 +131,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 303: @@ -140,7 +140,7 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 104: @@ -150,13 +150,13 @@ imap4_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 105: banout_append_char(banout, PROTO_IMAP4, px[i]); if (px[i] == '\n') { - tcp_transmit(more, "a002 STARTTLS\r\n", 15, 0); + tcpapi_send(socket, "a002 STARTTLS\r\n", 15, 0); state = 300; } break; @@ -178,7 +178,7 @@ imap4_parse( const struct Banner1 *banner1, pstate->port = (unsigned short)port; state = 0; - tcp_transmit(more, banner_ssl.hello, banner_ssl.hello_length, 0); + tcpapi_send(socket, banner_ssl.hello, banner_ssl.hello_length, 0); break; } break; diff --git a/src/proto-interactive.c b/src/proto-interactive.c deleted file mode 100644 index 9a3d4ac8..00000000 --- a/src/proto-interactive.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "proto-interactive.h" -#include "unusedparm.h" -#include "util-malloc.h" -#include - -/* - * TODO: we need to track the memory used for this better than with malloc(), such - * as using a preallocated array of packet buffers. But for now, I'm just using - * malloc() 'cause I'm a lazy programmer. - */ -unsigned char * -tcp_transmit_alloc(struct InteractiveData *more, size_t length) -{ - /* Note using this parameter yet, but in the future, we are going to have - * memory pools instead of heap malloc(), which will use this parameter */ - UNUSEDPARM(more); - - return MALLOC(length); -} - -void -tcp_close(struct InteractiveData *more) -{ - if (more == NULL) - return; - more->is_closing = 1; -} - -/* - * This doesn't actually transmit right now. Instead, marks the payload as ready - * to transmit, which will be transmitted later - */ -void -tcp_transmit(struct InteractiveData *more, const void *payload, size_t length, unsigned flags) -{ - more->m_payload = payload; - more->m_length = (unsigned)length; - - if (flags & TCPTRAN_DYNAMIC) - more->is_payload_dynamic = 1; -} diff --git a/src/proto-interactive.h b/src/proto-interactive.h deleted file mode 100644 index 4813f3ea..00000000 --- a/src/proto-interactive.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PROTO_INTERACTIVE_H -#define PROTO_INTERACTIVE_H -#include - -struct InteractiveData { - const void *m_payload; - unsigned m_length; - unsigned is_payload_dynamic:1; - unsigned is_closing:1; -}; -enum { - TCPTRAN_DYNAMIC = 0x0001, -}; - -/** - * Called to 'transmit' TCP packet payload. - */ -void -tcp_transmit(struct InteractiveData *more, const void *data, size_t length, unsigned flags); - -/** - * Called to close the connection - */ -void -tcp_close(struct InteractiveData *more); - -/** - * Called to allocate a TCP buffer. - */ -unsigned char * -tcp_transmit_alloc(struct InteractiveData *more, size_t length); - -#endif diff --git a/src/proto-isakmp.c b/src/proto-isakmp.c new file mode 100644 index 00000000..6080b6c5 --- /dev/null +++ b/src/proto-isakmp.c @@ -0,0 +1,67 @@ +/* ISAKMP protocol support */ + +#include "proto-isakmp.h" +#include "proto-banout.h" +#include "proto-preprocess.h" +#include "syn-cookie.h" +#include "massip-port.h" +#include "output.h" + +static unsigned +isakmp_parse(struct Output *out, time_t timestamp, + const unsigned char *px, unsigned length, + struct PreprocessedInfo *parsed, + uint64_t entropy + ) +{ + ipaddress ip_them; + ipaddress ip_me; + unsigned port_them = parsed->port_src; + unsigned port_me = parsed->port_dst; + unsigned cookie; + unsigned resp_cookie; + unsigned char i; + + /* All memcached responses will be at least 8 bytes */ + if (length < 16) + return 0; + + /* Grab IP addresses */ + ip_them = parsed->src_ip; + ip_me = parsed->dst_ip; + + cookie = (unsigned)syn_cookie(ip_them, port_them | Templ_UDP, ip_me, port_me, entropy); + + resp_cookie = 0; + for(i = 0; i < 8; i++) + resp_cookie |= px[8 + i] << (56 - 8 * i); + + if (resp_cookie != cookie) + output_report_banner(out, timestamp, ip_them, 17, port_them, + PROTO_ERROR, parsed->ip_ttl, + (unsigned char *) "IP-MISSMATCH", 12); + + output_report_banner(out, timestamp, ip_them, 17, port_them, PROTO_NONE, + parsed->ip_ttl, px, length); + + return 0; +} + +unsigned +isakmp_set_cookie(unsigned char *px, size_t length, uint64_t seqno) +{ + /* + The frame header starts with an 8 bytes init cookie, which is just + fine for us + */ + + unsigned char i; + + if (length < 8) + return 0; + + for(i = 0; i < 8; i++) + px[i] = (unsigned char)(seqno >> (56 - 8 * i)); + + return 0; +} diff --git a/src/proto-isakmp.h b/src/proto-isakmp.h new file mode 100644 index 00000000..53012f13 --- /dev/null +++ b/src/proto-isakmp.h @@ -0,0 +1,9 @@ +#ifndef PROTO_ISAKMP_H +#define PROTO_ISAKMP_H + +#include +#include + +unsigned isakmp_set_cookie(unsigned char *px, size_t length, uint64_t seqno); + +#endif diff --git a/src/proto-mc.c b/src/proto-mc.c index 2a0ba702..ac0a3a88 100644 --- a/src/proto-mc.c +++ b/src/proto-mc.c @@ -2,7 +2,7 @@ #include "proto-banner1.h" #include "unusedparm.h" #include "masscan-app.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "output.h" #include #include @@ -47,10 +47,10 @@ memstr(void * mem, size_t len, char * str) static void mc_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { size_t i; struct MCSTUFF *mc = &pstate->sub.mc; @@ -62,7 +62,7 @@ mc_parse( const struct Banner1 *banner1, mc->brackcount--; } if(mc->brackcount <= 0) - more->is_closing = 1; + tcpapi_close(socket); if((mc->imgstart&&mc->imgend) || mc->brackcount <= 0) { // we already found and removed image data banout_append(banout, PROTO_MC,px,length); diff --git a/src/proto-memcached.c b/src/proto-memcached.c index 8e72fce2..68cec957 100644 --- a/src/proto-memcached.c +++ b/src/proto-memcached.c @@ -8,7 +8,7 @@ #include "unusedparm.h" #include "masscan-app.h" #include "output.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-preprocess.h" #include "proto-ssl.h" #include "proto-udp.h" @@ -107,10 +107,10 @@ static void memcached_tcp_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -119,7 +119,7 @@ memcached_tcp_parse( UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); + UNUSEDPARM(socket); if (sm_memcached_responses == 0) return; @@ -360,7 +360,7 @@ memcached_udp_parse(struct Output *out, time_t timestamp, /* Parse the remainder of the packet as if this were TCP */ { - struct ProtocolState stuff[1]; + struct StreamState stuff[1]; memset(stuff, 0, sizeof(stuff[0])); diff --git a/src/proto-netbios.c b/src/proto-netbios.c index 8bb6bed2..19174a16 100644 --- a/src/proto-netbios.c +++ b/src/proto-netbios.c @@ -3,7 +3,7 @@ #include "proto-dns-parse.h" #include "proto-preprocess.h" #include "syn-cookie.h" -#include "logger.h" +#include "util-logger.h" #include "output.h" #include "masscan-app.h" #include "proto-banner1.h" diff --git a/src/proto-pop3.c b/src/proto-pop3.c index 45519aa6..96841bd6 100644 --- a/src/proto-pop3.c +++ b/src/proto-pop3.c @@ -9,7 +9,7 @@ #include "proto-banner1.h" #include "unusedparm.h" #include "masscan-app.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-ssl.h" #include #include @@ -20,10 +20,10 @@ static void pop3_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -42,14 +42,14 @@ pop3_parse( const struct Banner1 *banner1, banout_append_char(banout, PROTO_POP3, px[i]); if ("+OK"[state] != px[i]) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } else state++; break; case 3: banout_append_char(banout, PROTO_POP3, px[i]); if (px[i] == '\n') { - tcp_transmit(more, "CAPA\r\n", 6, 0); + tcpapi_send(socket, "CAPA\r\n", 6, 0); state++; } break; @@ -62,7 +62,7 @@ pop3_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 5: @@ -72,7 +72,7 @@ pop3_parse( const struct Banner1 *banner1, state++; else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 6: @@ -82,7 +82,7 @@ pop3_parse( const struct Banner1 *banner1, state += 2; /* oops, I had too many states here */ else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 8: @@ -108,7 +108,7 @@ pop3_parse( const struct Banner1 *banner1, continue; banout_append_char(banout, PROTO_POP3, px[i]); if (px[i] == '\n') { - tcp_transmit(more, "STLS\r\n", 6, 0); + tcpapi_send(socket, "STLS\r\n", 6, 0); state = 204; } else { state = 8; @@ -128,7 +128,7 @@ pop3_parse( const struct Banner1 *banner1, pstate->port = (unsigned short)port; state = 0; - tcp_transmit(more, banner_ssl.hello, banner_ssl.hello_length, 0); + tcpapi_send(socket, banner_ssl.hello, banner_ssl.hello_length, 0); break; } @@ -140,7 +140,7 @@ pop3_parse( const struct Banner1 *banner1, banout_append_char(banout, PROTO_POP3, px[i]); if (px[i] == '\n') { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; default: diff --git a/src/proto-smb.c b/src/proto-smb.c index dc0aff42..73ef9632 100644 --- a/src/proto-smb.c +++ b/src/proto-smb.c @@ -3,7 +3,7 @@ */ #include "proto-smb.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "unusedparm.h" #include "masscan-app.h" #include "crypto-siphash24.h" @@ -1015,7 +1015,18 @@ smb2_parse_negotiate(struct SMBSTUFF *smb, const unsigned char *px, size_t offse break; case N_BOOT1: case N_BOOT2: case N_BOOT3: case N_BOOT4: case N_BOOT5: case N_BOOT6: case N_BOOT7: case N_BOOT8: - smb->parms.negotiate2.boot_time |= (px[offset]<<((state-N_BOOT1)*8)); + smb->parms.negotiate2.boot_time |= ((uint64_t)px[offset]<<(uint64_t)((state-N_BOOT1)*8)); + if (state == N_BOOT8 && !smb->is_printed_boottime) { + char str[64] = "(err)"; + time_t timestamp = convert_windows_time(smb->parms.negotiate2.boot_time); + struct tm tm = {0}; + size_t len; + + gmtime_s(&tm, ×tamp); + len = strftime(str, sizeof(str), " boottime=%Y-%m-%d %H:%M:%S ", &tm); + banout_append(banout, PROTO_SMB, str, len); + smb->is_printed_boottime = 1; + } state++; break; case N_BLOB_OFFSET1: @@ -1229,7 +1240,7 @@ smb2_parse_header(struct SMBSTUFF *smb, const unsigned char *px, size_t offset, *****************************************************************************/ static size_t smb_parse_smb(struct SMBSTUFF *smb, const unsigned char *px, size_t max, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { size_t len; /*scratch variables used in a couple places */ unsigned state = smb->nbt_state; @@ -1399,7 +1410,7 @@ smb_parse_smb(struct SMBSTUFF *smb, const unsigned char *px, size_t max, struct break; case SMB1_PARAMETERS: /* Transfer control to a sub-parser, which may consume zero - * or more bytes, up to the end of the parameters field + * or greater bytes, up to the end of the parameters field * (meaning, up to word_count*2 bytes) */ len = smb_params_parse(smb, px, i, max); i += len; @@ -1440,26 +1451,23 @@ smb_parse_smb(struct SMBSTUFF *smb, const unsigned char *px, size_t max, struct smb->hdr.smb1.byte_state = 0; if (smb->hdr.smb1.flags2 & 0x0800) { - tcp_transmit(more, smb1_null_session_setup_ex, sizeof(smb1_null_session_setup_ex), 0); + tcpapi_send(socket, smb1_null_session_setup_ex, sizeof(smb1_null_session_setup_ex), 0); } else { if (smb->parms.negotiate.SessionKey) { unsigned char *buf; - buf = tcp_transmit_alloc(more, sizeof(smb1_null_session_setup)); + buf = malloc(sizeof(smb1_null_session_setup)); memcpy(buf, smb1_null_session_setup, sizeof(smb1_null_session_setup)); buf[0x2f] = (unsigned char)(smb->parms.negotiate.SessionKey>> 0) & 0xFF; buf[0x30] = (unsigned char)(smb->parms.negotiate.SessionKey>> 8) & 0xFF; buf[0x31] = (unsigned char)(smb->parms.negotiate.SessionKey>>16) & 0xFF; buf[0x32] = (unsigned char)(smb->parms.negotiate.SessionKey>>24) & 0xFF; - tcp_transmit(more, buf, sizeof(smb1_null_session_setup), TCPTRAN_DYNAMIC); - - /* NOTE: the following line is here to silence LLVM warnings about a potential - * memory leak. The 'tcp_transmit' function 'adopts' the pointer and will be - * responsible for freeing it after the packet gets successfully transmitted */ - buf = 0; + tcpapi_send(socket, buf, sizeof(smb1_null_session_setup), TCP__copy); + free(buf); } else { - tcp_transmit(more, smb1_null_session_setup, sizeof(smb1_null_session_setup), 0); + tcpapi_send(socket, + smb1_null_session_setup, sizeof(smb1_null_session_setup), TCP__static); } } @@ -1504,7 +1512,7 @@ smb_parse_smb(struct SMBSTUFF *smb, const unsigned char *px, size_t max, struct /* close the connection, we've found all we can */ if (smb->hdr.smb1.command == 0x73) - tcp_close(more); + tcpapi_close(socket); } break; @@ -1582,9 +1590,9 @@ smb_parse_smb(struct SMBSTUFF *smb, const unsigned char *px, size_t max, struct switch (smb->hdr.smb2.opcode) { case 0x00: /* negotiate response */ if (smb->hdr.smb2.seqno == 0) { - tcp_transmit(more, smb2_negotiate_request, sizeof(smb2_negotiate_request), 0); + tcpapi_send(socket, smb2_negotiate_request, sizeof(smb2_negotiate_request), 0); } else if (smb->hdr.smb2.seqno == 1) { - tcp_transmit(more, smb2_null_session_setup, sizeof(smb2_null_session_setup), 0); + tcpapi_send(socket, smb2_null_session_setup, sizeof(smb2_null_session_setup), 0); } break; default: @@ -1631,7 +1639,7 @@ smb_parse_smb(struct SMBSTUFF *smb, const unsigned char *px, size_t max, struct /* Close the connection when we get a SessionSetup response */ if (smb->hdr.smb2.opcode == 1) - tcp_close(more); + tcpapi_close(socket); } } break; @@ -1663,10 +1671,10 @@ static void smb_parse_record( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t max, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { size_t i; unsigned state = pstate->state; @@ -1729,7 +1737,7 @@ smb_parse_record( state = NBT_UNKNOWN; break; case 0x82: - tcp_transmit(more, smb1_hello_template, sizeof(smb1_hello_template), 0); + tcpapi_send(socket, smb1_hello_template, sizeof(smb1_hello_template), 0); state = NBT_DRAIN; break; case 0x85: @@ -1781,7 +1789,7 @@ smb_parse_record( break; case NBT_SMB: - i += smb_parse_smb(smb, px+i, max-i, banout, more); + i += smb_parse_smb(smb, px+i, max-i, banout, socket); if (smb->nbt_length == 0) { state = 0; i--; @@ -1884,9 +1892,9 @@ static int smb_do_test(const char *substring, const unsigned char *packet_bytes, size_t length) { struct Banner1 *banner1; - struct ProtocolState state[1]; + struct StreamState state[1]; struct BannerOutput banout1[1]; - struct InteractiveData more; + struct stack_handle_t socket = {0}; int x; banner1 = banner1_create(); @@ -1899,7 +1907,7 @@ smb_do_test(const char *substring, const unsigned char *packet_bytes, size_t len packet_bytes, length, banout1, - &more); + &socket); x = banout_is_contains(banout1, PROTO_SMB, substring); if (x == 0) printf("smb parser failure: %s\n", substring); @@ -2017,7 +2025,7 @@ smb_selftest(void) struct Banner1 *banner1; struct ProtocolState state[1]; struct BannerOutput banout1[1]; - struct InteractiveData more; + struct InteractiveData socket; size_t i; /* @@ -2045,7 +2053,7 @@ smb_selftest(void) packet_bytes, sizeof(packet_bytes), banout1, - &more); + &socket); banner1_destroy(banner1); banout_release(banout1); @@ -2061,7 +2069,7 @@ smb_selftest(void) /***************************************************************************** *****************************************************************************/ static void -smb_cleanup(struct ProtocolState *pstate) +smb_cleanup(struct StreamState *pstate) { struct SMBSTUFF *smb = &pstate->sub.smb; if (smb->spnego.ntlmssp.buf) diff --git a/src/proto-smtp.c b/src/proto-smtp.c index 9c3cb720..710050a9 100644 --- a/src/proto-smtp.c +++ b/src/proto-smtp.c @@ -23,7 +23,7 @@ #include "proto-banner1.h" #include "unusedparm.h" #include "masscan-app.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-ssl.h" #include #include @@ -34,10 +34,10 @@ static void smtp_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -67,7 +67,7 @@ smtp_parse( const struct Banner1 *banner1, case 203: if (!isdigit(px[i]&0xFF)) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } else { smtp->code *= 10; smtp->code += (px[i] - '0'); @@ -88,7 +88,7 @@ smtp_parse( const struct Banner1 *banner1, banout_append_char(banout, PROTO_SMTP, px[i]); } else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } break; case 5: @@ -96,7 +96,7 @@ smtp_parse( const struct Banner1 *banner1, continue; else if (px[i] == '\n') { if (smtp->is_last) { - tcp_transmit(more, "EHLO masscan\r\n", 14, 0); + tcpapi_send(socket, "EHLO masscan\r\n", 14, 0); state = 100; banout_append_char(banout, PROTO_SMTP, px[i]); } else { @@ -105,7 +105,7 @@ smtp_parse( const struct Banner1 *banner1, } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_SMTP, px[i]); @@ -116,7 +116,7 @@ smtp_parse( const struct Banner1 *banner1, continue; else if (px[i] == '\n') { if (smtp->is_last) { - tcp_transmit(more, "STARTTLS\r\n", 10, 0); + tcpapi_send(socket, "STARTTLS\r\n", 10, 0); state = 200; banout_append_char(banout, PROTO_SMTP, px[i]); } else { @@ -125,7 +125,7 @@ smtp_parse( const struct Banner1 *banner1, } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_SMTP, px[i]); @@ -146,15 +146,15 @@ smtp_parse( const struct Banner1 *banner1, pstate->port = (unsigned short)port; state = 0; - tcp_transmit(more, banner_ssl.hello, banner_ssl.hello_length, 0); + tcpapi_send(socket, banner_ssl.hello, banner_ssl.hello_length, 0); } else { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; - tcp_close(more); + tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_SMTP, px[i]); diff --git a/src/proto-ssh.c b/src/proto-ssh.c index 058367f5..aac8df48 100644 --- a/src/proto-ssh.c +++ b/src/proto-ssh.c @@ -2,44 +2,179 @@ #include "proto-banner1.h" #include "unusedparm.h" #include "masscan-app.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include +#define PAYLOAD_BANNER "SSH-2.0-OPENSSH_7.9\r\n" +#define SIZE_BANNER 21 +#define PAYLOAD_KEY_EXHANGE_INIT "\x00\x00\x04\x4c" /* packet length: 1100 */ \ + "\x04" /* padding_length (this value is include in the packet length) */ \ + "\x14" /* message_code = 20 */ \ + "\xf3\xca\xd2\x90\xec\xf4\x7c\x47\x55\x4c\x88\xcf\x3a\x72\x2b\xb2" /*cookie */ \ + "\x00\x00\x00\xd8" /* kex_algorithms_length */ \ + "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256" /* kex_algorithms_string */ \ + "\x00\x00\x00\x21" /* server_host_key_algorithms_length */ \ + "ssh-rsa,rsa-sha2-512,rsa-sha2-256" /* server_host_key_algorithms_string */ \ + "\x00\x00\x00\xaf" /* encryption_algorithms_client_to_server_length */ \ + "chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,aes192-cbc,aes256-cbc,blowfish-cbc,cast128-cbc,3des-cbc" /* encryption_algorithms_client_to_server_string */ \ + "\x00\x00\x00\xaf" /* encryption_algorithms_server_to_client_length */ \ + "chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,aes192-cbc,aes256-cbc,blowfish-cbc,cast128-cbc,3des-cbc" /* encryption_algorithms_server_to_client_string */ \ + "\x00\x00\x00\xd5" /* mac_algorithms_client_to_server_length */ \ + "umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1" /* mac_algorithms_client_to_server_string */ \ + "\x00\x00\x00\xd5" /* mac_algorithms_server_to_client_length */ \ + "umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1" /* mac_algorithms_server_to_client_string */ \ + "\x00\x00\x00\x04" /* compression_algorithms_client_to_server_length */ \ + "none" /* compression_algorithms_client_to_server_string */ \ + "\x00\x00\x00\x04" /* compression_algorithms_server_to_client_length */ \ + "none" /* compression_algorithms_server_to_client_string */ \ + "\x00\x00\x00\x00" /* languages_client_to_server_length */ \ + "\x00\x00\x00\x00" /* languages_server_to_client_length */ \ + "\x00" /* first_KEX_Packet_Follows */ \ + "\x00\x00\x00\x00" /* reserved */ \ + "\x00\x00\x00\x00" /* Padding_String */ \ + "\x00\x00\x00\x8c" /* DH_packet_length */ \ + "\x05" /* DH_padding_length */ \ + "\x1e" /* DH_message_code */ \ + "\x00\x00\x00\x81" /* DH_multiprecision_integer_length */ \ + "\x00\xd4\x6e\xe0\x12\xa6\x56\x95\x37\xa0\x14\x2e\x4e\x4d\x57\x48\x1d\x4b\x80\x90\x1e\x61\x6f\x5c\xc4\xd7\xbc\x17\x25\xb7\x41\x8c\x6c\x8b\xed\x74\x2d\xc0\x54\xeb\x08\x3a\x79\x5e\x0c\xad\x04\xe8\xb7\xfb\xa1\x68\x62\x66\xd3\x9a\x26\x39\xaa\x6c\x89\x2f\x5c\x99\xab\xd2\x43\xda\xa7\xef\x1c\x19\xdc\xa6\x03\xc9\x8a\x56\x19\x74\xd1\xb8\x08\xdc\x76\x14\xe7\x86\x50\x74\x01\xed\xd4\xfb\x1a\x1a\x25\x5d\x1a\xc7\x5f\x0c\xb3\xcc\x58\x5a\x40\xd5\x04\xa5\xc1\x30\x14\x86\xf0\xb8\x33\x17\xb4\x23\x9d\x43\x6d\x38\x87\xec\xa9\xbc\x3b" /* DH_padding_string */ \ + "\x00\x00\x00\x00\x00" /* DH_padding_string */ +#define SIZE_KEY_EXCHANGE_INIT (1100+4+140+4) //length_of_the_first_packet(packet_length + length of the packet_length_field(4)) + DH_packet_length (including the DH_padding_length) + the length of the DH_length_field (4). +#define PAYLOAD_NEWKEYS "\x00\x00\x00\x0c" /* packet length */ \ + "\x0a" /* padding length */ \ + "\x15" /* message code */ \ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" /* padding string */ +#define SIZE_NEWKEYS (12+4) + +#define DEADSTORE(x) x=x /*************************************************************************** ***************************************************************************/ static void ssh_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; + size_t packet_length = pstate -> sub.ssh.packet_length; unsigned i; + enum{ + BANNER = 0, + MSG_KEY_EXCHANGE_INIT = 1, + MSG_NEW_KEYS = 2, + MSG_UNKNOWN = 9, + PADDING_LENGTH = 10, + MESSAGE_CODE = 11, + CHECK_LENGTH = 20, + LENGTH_1 = 21, + LENGTH_2 = 22, + LENGTH_3 = 23, + LENGTH_4 = 24, + BEFORE_END = 29, + END = 30, + ERROR = 31, + }; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); - - for (i=0; istate = state; + pstate->sub.ssh.packet_length = packet_length; } /*************************************************************************** diff --git a/src/proto-ssl.c b/src/proto-ssl.c index 06104e2d..7d27f341 100644 --- a/src/proto-ssl.c +++ b/src/proto-ssl.c @@ -46,7 +46,7 @@ open TCP connections with minimal memory usage. */ #include "proto-ssl.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "unusedparm.h" #include "masscan-app.h" #include "crypto-siphash24.h" @@ -128,10 +128,10 @@ static void parse_server_hello( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { struct SSL_SERVER_HELLO *hello = &pstate->sub.ssl.x.server_hello; unsigned state = hello->state; @@ -155,7 +155,7 @@ parse_server_hello( UNUSEDPARM(banout); UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); + UNUSEDPARM(socket); /* What this structure looks like in ASN.1 format struct { @@ -371,10 +371,10 @@ static void parse_server_cert( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { struct SSL_SERVER_CERT *data = &pstate->sub.ssl.x.server_cert; unsigned state = data->state; @@ -385,6 +385,8 @@ parse_server_cert( LEN0, LEN1, LEN2, CLEN0, CLEN1, CLEN2, CERT, + CALEN0, CALEN1, CALEN2, + CACERT, UNKNOWN, }; @@ -404,6 +406,7 @@ parse_server_cert( DROPDOWN(i,length,state); case CLEN0: + case CALEN0: if (remaining < 3) { state = UNKNOWN; continue; @@ -412,10 +415,12 @@ parse_server_cert( remaining--; DROPDOWN(i,length,state); case CLEN1: + case CALEN1: cert_remaining = cert_remaining * 256 + px[i]; remaining--; DROPDOWN(i,length,state); case CLEN2: + case CALEN2: cert_remaining = cert_remaining * 256 + px[i]; remaining--; if (banner1->is_capture_cert) { @@ -432,8 +437,10 @@ parse_server_cert( DROPDOWN(i,length,state); case CERT: + case CACERT: { unsigned len = (unsigned)length-i; + unsigned proto = (state == CERT ? PROTO_X509_CERT : PROTO_X509_CACERT); if (len > remaining) len = remaining; if (len > cert_remaining) @@ -442,7 +449,7 @@ parse_server_cert( /* parse the certificate */ if (banner1->is_capture_cert) { banout_append_base64(banout, - PROTO_X509_CERT, + proto, px+i, len, &pstate->base64); } @@ -459,14 +466,17 @@ parse_server_cert( * a record of it */ if (banner1->is_capture_cert) { banout_finalize_base64(banout, - PROTO_X509_CERT, + proto, &pstate->base64); - banout_end(banout, PROTO_X509_CERT); + banout_end(banout, proto); } - state = CLEN0; + state = CALEN0; if (remaining == 0) { - if (!banner1->is_heartbleed) - tcp_close(more); + /* FIXME: reduce this logic, it should only flush the + * FIXME: ertificate, not close the connection*/ + if (!banner1->is_heartbleed) { + ; //tcpapi_close(socket); + } } } } @@ -512,10 +522,10 @@ static void parse_handshake( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { struct SSLRECORD *ssl = &pstate->sub.ssl; unsigned state = ssl->handshake.state; @@ -573,7 +583,7 @@ parse_handshake( static const char heartbleed_request[] = "\x15\x03\x02\x00\x02\x01\x80" "\x18\x03\x02\x00\x03\x01" "\x40\x00"; - tcp_transmit(more, heartbleed_request, sizeof(heartbleed_request)-1, 0); + tcpapi_send(socket, heartbleed_request, sizeof(heartbleed_request)-1, 0); } DROPDOWN(i,length,state); @@ -611,7 +621,7 @@ parse_handshake( pstate, px+i, len, banout, - more); + socket); break; case 11: /* server certificate */ parse_server_cert( banner1, @@ -619,7 +629,7 @@ parse_handshake( pstate, px+i, len, banout, - more); + socket); break; } @@ -658,10 +668,10 @@ static void parse_heartbeat( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { struct SSLRECORD *ssl = &pstate->sub.ssl; unsigned state = ssl->handshake.state; @@ -674,7 +684,7 @@ parse_heartbeat( UNKNOWN, }; - UNUSEDPARM(more); + UNUSEDPARM(socket); UNUSEDPARM(banner1_private); /* @@ -778,10 +788,10 @@ static void parse_alert( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { struct SSLRECORD *ssl = &pstate->sub.ssl; unsigned state = ssl->handshake.state; @@ -793,7 +803,7 @@ parse_alert( UNKNOWN, }; - UNUSEDPARM(more); + UNUSEDPARM(socket); UNUSEDPARM(banner1_private); /* @@ -882,10 +892,10 @@ static void ssl_parse_record( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned remaining = pstate->remaining; @@ -909,7 +919,7 @@ ssl_parse_record( /* * The initial state parses the "type" byte. There are only a few types - * defined so far, the values 20-25, but more can be defined in the + * defined so far, the values 20-25, but socket can be defined in the * future. The standard explicitly says that they must be lower than 128, * so if the high-order bit is set, we know that the byte is invalid, * and that something is wrong. @@ -992,7 +1002,7 @@ ssl_parse_record( pstate, px+i, len, banout, - more); + socket); break; case 22: /* handshake */ parse_handshake(banner1, @@ -1000,7 +1010,7 @@ ssl_parse_record( pstate, px+i, len, banout, - more); + socket); break; case 23: /* application data */ /* encrypted, always*/ @@ -1012,7 +1022,7 @@ ssl_parse_record( pstate, px+i, len, banout, - more); + socket); break; } @@ -1093,7 +1103,20 @@ ssl_hello_template[] = "\x02\x02\x04\x02\x05\x02\x06\x02" ; - +/***************************************************************************** + * This is the template "Client Hello" packet that is sent to the server + * to initiate the SSL connection. Right now, it's statically just transmitted + * on to the wire. + * TODO: we need to make this dynamically generated, so that users can + * select various options. + *****************************************************************************/ +static const char +ssl_12_hello_template[] = +"\x16\x03\x01\x01\x1a" +"\x01" +"\x00\x01\x16" +"\x03\x03\x02\x58\x33\x79\x5f\x71\x03\xef\x07\xfe\x36\x61\xb0\x32\x81\xaa\x99\x10\x87\x6a\x8e\x5b\xf9\x03\x93\x44\x58\x4b\x19\xff\x42\x6a\x20\x64\x84\xcd\x28\x9c\xe9\xb1\x9d\xcd\x8a\x11\x4c\x3b\x40\x1c\x90\x02\xf2\xb5\x1a\xf1\x7e\x5d\xb8\x42\xc2\x1e\x17\x1e\x59\xa4\xac\x00\x3e\x13\x02\x13\x03\x13\x01\xc0\x2c\xc0\x30\x00\x9f\xcc\xa9\xcc\xa8\xcc\xaa\xc0\x2b\xc0\x2f\x00\x9e\xc0\x24\xc0\x28\x00\x6b\xc0\x23\xc0\x27\x00\x67\xc0\x0a\xc0\x14\x00\x39\xc0\x09\xc0\x13\x00\x33\x00\x9d\x00\x9c\x00\x3d\x00\x3c\x00\x35\x00\x2f\x00\xff\x01\x00\x00\x8f\x00\x0b\x00\x04\x03\x00\x01\x02\x00\x0a\x00\x0c\x00\x0a\x00\x1d\x00\x17\x00\x1e\x00\x19\x00\x18\x00\x23\x00\x00\x00\x16\x00\x00\x00\x17\x00\x00\x00\x0d\x00\x2a\x00\x28\x04\x03\x05\x03\x06\x03\x08\x07\x08\x08\x08\x09\x08\x0a\x08\x0b\x08\x04\x08\x05\x08\x06\x04\x01\x05\x01\x06\x01\x03\x03\x03\x01\x03\x02\x04\x02\x05\x02\x06\x02\x00\x2b\x00\x09\x08\x03\x04\x03\x03\x03\x02\x03\x01\x00\x2d\x00\x02\x01\x01\x00\x33\x00\x26\x00\x24\x00\x1d\x00\x20\xb6\x87\xb7\x72\xb9\xcb\x07\xe0\x14\x0a\x14\x81\x3f\x3f\x0a\xcc\xc4\x7d\x80\xf7\xe8\xaa\x1e\x73\xb0\xa9\xad\xb8\x3a\xa7\x3c\x64"; +; /***************************************************************************** *****************************************************************************/ static char * @@ -1246,11 +1269,11 @@ static int ssl_selftest(void) { struct Banner1 *banner1; - struct ProtocolState state[1]; + struct StreamState state[1]; unsigned ii; struct BannerOutput banout1[1]; struct BannerOutput banout2[1]; - struct InteractiveData more; + unsigned x; /* @@ -1325,7 +1348,7 @@ ssl_selftest(void) ssl_test_case_3+i, 1, banout1, - &more + 0 ); } /*if (0) { @@ -1360,7 +1383,7 @@ ssl_selftest(void) (const unsigned char *)ssl_test_case_3+ii, 1, banout2, - &more + 0 ); banner1_destroy(banner1); banout_release(banout2); @@ -1408,10 +1431,20 @@ ssl_selftest(void) * This is the 'plugin' structure that registers callbacks for this parser in * the main system. *****************************************************************************/ -struct ProtocolParserStream banner_ssl = { - "ssl", 443, ssl_hello_template, sizeof(ssl_hello_template)-1, 0, +struct ProtocolParserStream banner_ssl_12 = { + "ssl", 443, ssl_12_hello_template, sizeof(ssl_12_hello_template)-1, 0, ssl_selftest, ssl_init, ssl_parse_record, }; +struct ProtocolParserStream banner_ssl = { + "ssl", 443, ssl_hello_template, sizeof(ssl_hello_template)-1, + SF__close, /* send FIN after the hello */ + ssl_selftest, + ssl_init, + ssl_parse_record, + 0, + 0, + &banner_ssl_12, +}; diff --git a/src/proto-ssl.h b/src/proto-ssl.h index 72b9b4b8..9d726a54 100644 --- a/src/proto-ssl.h +++ b/src/proto-ssl.h @@ -3,6 +3,7 @@ #include "proto-banner1.h" extern struct ProtocolParserStream banner_ssl; +extern struct ProtocolParserStream banner_ssl_12; extern const char *ssl_hello_heartbeat_template; extern const char *ssl_hello_ticketbleed_template; diff --git a/src/proto-tcp-rdp.c b/src/proto-tcp-rdp.c index d5085a07..5ad7b895 100644 --- a/src/proto-tcp-rdp.c +++ b/src/proto-tcp-rdp.c @@ -1,7 +1,7 @@ #include "proto-tcp-rdp.h" #include "proto-banner1.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "unusedparm.h" #include "masscan-app.h" #include "util-malloc.h" @@ -201,10 +201,10 @@ cotp_parse(struct BannerOutput *banout, struct RDPSTUFF *rdp, const unsigned cha static void rdp_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state & 0xFFFFFF; struct RDPSTUFF *rdp = &pstate->sub.rdp; @@ -218,7 +218,7 @@ rdp_parse( const struct Banner1 *banner1, }; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); + UNUSEDPARM(socket); for (offset=0; offsetstate; size_t offset; @@ -109,29 +111,21 @@ telnet_parse( const struct Banner1 *banner1, TELNET_SB_DATA, TELNET_INVALID, }; - static const char *foobar[4] = {"DO", "DONT", "WILL", "WONT"}; + //static const char *foobar[4] = {"DO", "DONT", "WILL", "WONT"}; unsigned char nego[256] = {0}; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); + UNUSEDPARM(socket); for (offset=0; offsetstate = state; @@ -314,9 +267,9 @@ static int telnet_selftest_item(const char *input, const char *output) { struct Banner1 *banner1; - struct ProtocolState pstate[1]; + struct StreamState pstate[1]; struct BannerOutput banout1[1]; - struct InteractiveData more; + int x; /* @@ -335,7 +288,7 @@ telnet_selftest_item(const char *input, const char *output) (const unsigned char *)input, strlen(input), banout1, - &more + 0 ); //fprintf(stderr, "%.*s\n", (int)banout_string_length(banout1, PROTO_TELNET), banout_string(banout1, PROTO_TELNET)); /* @@ -360,7 +313,7 @@ telnet_selftest(void) const char *input; const char *output; } tests[] = { - {"\xff\xfd\x1flogin:", "login"}, + {"\xff\xfd\x1flogin:", "login:"}, {"\xff\xfd\x27\xff\xfd\x18 ", " "}, { "\xff\xfb\x25\xff\xfd\x03\xff\xfb\x18\xff\xfb\x1f\xff\xfb\x20\xff" \ @@ -375,7 +328,7 @@ telnet_selftest(void) }, { "\xff\xfd\x01\xff\xfd\x1f\xff\xfd\x21\xff\xfb\x01\xff\xfb\x03\x46" "\x36\x37\x30\x0d\x0a\x0d\x4c\x6f\x67\x69\x6e\x3a\x20", - "F670\\n Login:" + "F670\r\n\rLogin:" }, {0,0} }; diff --git a/src/proto-tcp.c b/src/proto-tcp.c deleted file mode 100644 index a17030df..00000000 --- a/src/proto-tcp.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* - TCP connection table -*/ -#include "proto-tcp.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "syn-cookie.h" -#include "event-timeout.h" /* for tracking future events */ -#include "rawsock.h" -#include "logger.h" -#include "templ-pkt.h" -#include "pixie-timer.h" -#include "stack-queue.h" -#include "proto-banner1.h" -#include "proto-ssl.h" -#include "proto-http.h" -#include "proto-smb.h" -#include "output.h" -#include "string_s.h" -#include "main-globals.h" -#include "crypto-base64.h" -#include "proto-interactive.h" -#include "util-malloc.h" -#include "scripting.h" -#include "versioning.h" - - - -/*************************************************************************** - * A "TCP control block" is what most operating-systems/network-stack - * calls the structure that corresponds to a TCP connection. It contains - * things like the IP addresses, port numbers, sequence numbers, timers, - * and other things. - ***************************************************************************/ -struct TCP_Control_Block -{ - ipaddress ip_me; - ipaddress ip_them; - - unsigned short port_me; - unsigned short port_them; - - uint32_t seqno_me; /* next seqno I will use for transmit */ - uint32_t seqno_them; /* the next seqno I expect to receive */ - uint32_t ackno_me; - uint32_t ackno_them; - uint32_t seqno_them_first; /* ipv6-todo */ - - struct TCP_Control_Block *next; - struct TimeoutEntry timeout[1]; - - unsigned char ttl; - unsigned tcpstate:4; - unsigned is_ipv6:1; - - /** Set to true when the TCB is in-use/allocated, set to zero - * when it's about to be deleted soon */ - unsigned is_active:1; - - /* If the payload we've sent was dynamically allocated with - * malloc() from the heap, in which case we'll have to free() - * it. (Most payloads are static memory) */ - unsigned is_payload_dynamic:1; - - unsigned established; - - unsigned short payload_length; - time_t when_created; - const unsigned char *payload; - - /* - * If Running a script, the thread object - */ - struct ScriptingThread *scripting_thread; - - struct BannerOutput banout; - - struct ProtocolState banner1_state; - - unsigned packet_number; -}; - -struct TCP_ConnectionTable { - struct TCP_Control_Block **entries; - struct TCP_Control_Block *freed_list; - unsigned count; - unsigned mask; - unsigned timeout_connection; - unsigned timeout_hello; - - uint64_t active_count; - uint64_t entropy; - - struct Timeouts *timeouts; - struct TemplatePacket *pkt_template; - struct stack_t *stack; - - struct Banner1 *banner1; - OUTPUT_REPORT_BANNER report_banner; - struct Output *out; - - struct ScriptingVM *scripting_vm; -}; - -enum { - STATE_SYN_SENT, - //STATE_SYN_RECEIVED, - STATE_ESTABLISHED_SEND, /* our own special state, can only send */ - STATE_ESTABLISHED_RECV, /* our own special state, can only receive */ - //STATE_CLOSE_WATI, - STATE_LAST_ACK, - STATE_FIN_WAIT1, - STATE_FIN_WAIT2, - STATE_CLOSING, - STATE_TIME_WAIT, -}; - - - -/*************************************************************************** - * Process all events, up to the current time, that need timing out. - ***************************************************************************/ -void -tcpcon_timeouts(struct TCP_ConnectionTable *tcpcon, unsigned secs, unsigned usecs) -{ - uint64_t timestamp = TICKS_FROM_TV(secs, usecs); - - for (;;) { - struct TCP_Control_Block *tcb; - - /* - * Get the next event that is older than the current time - */ - tcb = (struct TCP_Control_Block *)timeouts_remove(tcpcon->timeouts, - timestamp); - - /* - * If everything up to the current time has already been processed, - * then exit this loop - */ - if (tcb == NULL) - break; - - /* - * Process this timeout - */ - stack_incoming_tcp( - tcpcon, - tcb, - TCP_WHAT_TIMEOUT, - 0, 0, - secs, usecs, - tcb->seqno_them); - - /* If the TCB hasn't been destroyed, then we need to make sure - * there is a timeout associated with it. KLUDGE: here is the problem: - * there must ALWAYS be a 'timeout' associated with a TCB, otherwise, - * we'll lose track of it and leak memory. In theory, this should be - * automatically handled elsewhere, but I have bugs, and it's not, - * so I put some code here as a catch-all: if the TCB hasn't been - * deleted, but hasn't been inserted back into the timeout system, - * then insert it here. */ - if (tcb->timeout->prev == 0 && tcb->is_active) { - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+2, usecs)); - } - } -} - -/*************************************************************************** - ***************************************************************************/ -static int -name_equals(const char *lhs, const char *rhs) -{ - for (;;) { - while (*lhs == '-' || *lhs == '.' || *lhs == '_') - lhs++; - while (*rhs == '-' || *rhs == '.' || *rhs == '_') - rhs++; - if (*lhs == '\0' && *rhs == '[') - return 1; /*arrays*/ - if (*rhs == '\0' && *lhs == '[') - return 1; /*arrays*/ - if (tolower(*lhs & 0xFF) != tolower(*rhs & 0xFF)) - return 0; - if (*lhs == '\0') - return 1; - lhs++; - rhs++; - } -} - -/*************************************************************************** - * When setting parameters, this will parse integers from the config - * parameter strings. - ***************************************************************************/ -static uint64_t -parseInt(const void *vstr, size_t length) -{ - const char *str = (const char *)vstr; - uint64_t result = 0; - size_t i; - - for (i=0; ibanner1; - - if (name_equals(name, "http-payload")) { - char lenstr[64]; - sprintf_s(lenstr, sizeof(lenstr), "%u", (unsigned)value_length); - - banner_http.hello_length = http_change_requestline( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - (const unsigned char *)value, - value_length, - 3); /* payload*/ - - banner_http.hello_length = http_change_field( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - "Content-Length:", - (const unsigned char *)lenstr, - strlen(lenstr), - http_field_replace); - return; - } - - /* - * You can reset your user-agent here. Whenever I do a scan, I always - * reset my user-agent. That's now you know it's not me scanning - * you on the open Internet -- I would never use the default user-agent - * string built into masscan - */ - if (name_equals(name, "http-user-agent")) { - banner_http.hello_length = http_change_field( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - "User-Agent:", - (const unsigned char *)value, - value_length, - http_field_replace); - return; - } - if (name_equals(name, "http-host")) { - banner_http.hello_length = http_change_field( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - "Host:", - (const unsigned char *)value, - value_length, - http_field_replace); - return; - } - - /** - * Changes the URL - */ - if (name_equals(name, "http-method")) { - banner_http.hello_length = http_change_requestline( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - (const unsigned char *)value, - value_length, - 0); /* method*/ - return; - } - if (name_equals(name, "http-url")) { - banner_http.hello_length = http_change_requestline( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - (const unsigned char *)value, - value_length, - 1); /* url */ - return; - } - if (name_equals(name, "http-version")) { - banner_http.hello_length = http_change_requestline( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - (const unsigned char *)value, - value_length, - 2); /* version */ - return; - } - - if (name_equals(name, "timeout") || name_equals(name, "connection-timeout")) { - uint64_t n = parseInt(value, value_length); - tcpcon->timeout_connection = (unsigned)n; - LOG(1, "TCP connection-timeout = %u\n", tcpcon->timeout_connection); - return; - } - if (name_equals(name, "hello-timeout")) { - uint64_t n = parseInt(value, value_length); - tcpcon->timeout_hello = (unsigned)n; - LOG(1, "TCP hello-timeout = \"%.*s\"\n", (int)value_length, (const char *)value); - LOG(1, "TCP hello-timeout = %u\n", (unsigned)tcpcon->timeout_hello); - return; - } - - /* - * Force SSL processing on all ports - */ - if (name_equals(name, "hello") && name_equals(value, "ssl")) { - unsigned i; - - LOG(2, "HELLO: setting SSL hello message\n"); - for (i=0; i<65535; i++) { - banner1->payloads.tcp[i] = &banner_ssl; - } - - return; - } - - /* - * Force HTTP processing on all ports - */ - if (name_equals(name, "hello") && name_equals(value, "http")) { - unsigned i; - - LOG(2, "HELLO: setting HTTP hello message\n"); - for (i=0; i<65535; i++) { - banner1->payloads.tcp[i] = &banner_http; - } - - return; - } - - /* - * Downgrade SMB hello from v1/v2 to use only v1 - */ - if (name_equals(name, "hello") && name_equals(value, "smbv1")) { - smb_set_hello_v1(&banner_smb1); - return; - } - - /* - * 2014-04-08: scan for Neel Mehta's "heartbleed" bug - */ - if (name_equals(name, "heartbleed")) { - unsigned i; - - /* Change the hello message to including negotiating the use of - * the "heartbeat" extension */ - banner_ssl.hello = ssl_hello(ssl_hello_heartbeat_template); - banner_ssl.hello_length = ssl_hello_size(banner_ssl.hello); - tcpcon->banner1->is_heartbleed = 1; - - for (i=0; i<65535; i++) { - banner1->payloads.tcp[i] = &banner_ssl; - } - - return; - } - - if (name_equals(name, "ticketbleed")) { - unsigned i; - - /* Change the hello message to including negotiating the use of - * the "heartbeat" extension */ - banner_ssl.hello = ssl_hello(ssl_hello_ticketbleed_template); - banner_ssl.hello_length = ssl_hello_size(banner_ssl.hello); - tcpcon->banner1->is_ticketbleed = 1; - - for (i=0; i<65535; i++) { - banner1->payloads.tcp[i] = &banner_ssl; - } - - return; - } - - /* - * 2014-10-16: scan for SSLv3 servers (POODLE) - */ - if (name_equals(name, "poodle") || name_equals(name, "sslv3")) { - unsigned i; - void *px; - - /* Change the hello message to including negotiating the use of - * the "heartbeat" extension */ - px = ssl_hello(ssl_hello_sslv3_template); - banner_ssl.hello = ssl_add_cipherspec(px, 0x5600, 1); - banner_ssl.hello_length = ssl_hello_size(banner_ssl.hello); - tcpcon->banner1->is_poodle_sslv3 = 1; - - for (i=0; i<65535; i++) { - banner1->payloads.tcp[i] = &banner_ssl; - } - - return; - } - - - /* - * You can reconfigure the "hello" message to be anything - * you want. - */ - if (name_equals(name, "hello-string")) { - struct ProtocolParserStream *x; - const char *p = strchr(name, '['); - unsigned port; - - - if (p == NULL) { - LOG(0, "tcpcon: parameter: expected array []: %s\n", name); - exit(1); - } - port = (unsigned)strtoul(p+1, 0, 0); - - x = banner1->payloads.tcp[port]; - if (x == NULL) { - x = CALLOC(1, sizeof(*x)); - x->name = "(allocated)"; - } - - x->hello = MALLOC(value_length); - x->hello_length = base64_decode((char*)x->hello, value_length, value, value_length); - - banner1->payloads.tcp[port] = x; - } - -} - - -/*************************************************************************** - ***************************************************************************/ -void -tcpcon_set_banner_flags(struct TCP_ConnectionTable *tcpcon, - unsigned is_capture_cert, - unsigned is_capture_servername, - unsigned is_capture_html, - unsigned is_capture_heartbleed, - unsigned is_capture_ticketbleed) -{ - tcpcon->banner1->is_capture_cert = is_capture_cert; - tcpcon->banner1->is_capture_servername = is_capture_servername; - tcpcon->banner1->is_capture_html = is_capture_html; - tcpcon->banner1->is_capture_heartbleed = is_capture_heartbleed; - tcpcon->banner1->is_capture_ticketbleed = is_capture_ticketbleed; -} - -/*************************************************************************** - ***************************************************************************/ -void scripting_init_tcp(struct TCP_ConnectionTable *tcpcon, struct lua_State *L) -{ - tcpcon->banner1->L = L; - - banner_scripting.init(tcpcon->banner1); -} - -/*************************************************************************** - * Called at startup, by a receive thread, to create a TCP connection - * table. - ***************************************************************************/ -struct TCP_ConnectionTable * -tcpcon_create_table( size_t entry_count, - struct stack_t *stack, - struct TemplatePacket *pkt_template, - OUTPUT_REPORT_BANNER report_banner, - struct Output *out, - unsigned connection_timeout, - uint64_t entropy - ) -{ - struct TCP_ConnectionTable *tcpcon; - - - tcpcon = CALLOC(1, sizeof(*tcpcon)); - tcpcon->timeout_connection = connection_timeout; - if (tcpcon->timeout_connection == 0) - tcpcon->timeout_connection = 30; /* half a minute before destroying tcb */ - tcpcon->timeout_hello = 2; - tcpcon->entropy = entropy; - - /* Find nearest power of 2 to the tcb count, but don't go - * over the number 16-million */ - { - size_t new_entry_count; - new_entry_count = 1; - while (new_entry_count < entry_count) { - new_entry_count *= 2; - if (new_entry_count == 0) { - new_entry_count = (1<<24); - break; - } - } - if (new_entry_count > (1<<24)) - new_entry_count = (1<<24); - if (new_entry_count < (1<<10)) - new_entry_count = (1<<10); - entry_count = new_entry_count; - } - - /* Create the table. If we can't allocate enough memory, then shrink - * the desired size of the table */ - while (tcpcon->entries == 0) { - tcpcon->entries = malloc(entry_count * sizeof(*tcpcon->entries)); - if (tcpcon->entries == NULL) { - entry_count >>= 1; - } - } - memset(tcpcon->entries, 0, entry_count * sizeof(*tcpcon->entries)); - - - /* fill in the table structure */ - tcpcon->count = (unsigned)entry_count; - tcpcon->mask = (unsigned)(entry_count-1); - - /* create an event/timeouts structure */ - tcpcon->timeouts = timeouts_create(TICKS_FROM_SECS(time(0))); - - - tcpcon->pkt_template = pkt_template; - - tcpcon->stack = stack; - - - tcpcon->banner1 = banner1_create(); - - tcpcon->report_banner = report_banner; - tcpcon->out = out; - return tcpcon; -} - -static int EQUALS(const struct TCP_Control_Block *lhs, const struct TCP_Control_Block *rhs) -{ - if (lhs->port_me != rhs->port_me || lhs->port_them != rhs->port_them) - return 0; - if (lhs->ip_me.version != rhs->ip_me.version) - return 0; - if (lhs->ip_me.version == 6) { - if (memcmp(&lhs->ip_me.ipv6, &rhs->ip_me.ipv6, sizeof(rhs->ip_me.ipv6)) != 0) - return 0; - if (memcmp(&lhs->ip_them.ipv6, &rhs->ip_them.ipv6, sizeof(rhs->ip_them.ipv6)) != 0) - return 0; - } else { - if (lhs->ip_me.ipv4 != rhs->ip_me.ipv4) - return 0; - if (lhs->ip_them.ipv4 != rhs->ip_them.ipv4) - return 0; - } - - return 1; -} - -/*************************************************************************** - ***************************************************************************/ -static unsigned -tcb_hash( ipaddress ip_me, unsigned port_me, - ipaddress ip_them, unsigned port_them, - uint64_t entropy) -{ - unsigned index; - - /* TCB hash table uses symmetric hash, so incoming/outgoing packets - * get the same hash. */ - if (ip_me.version == 6) { - ipv6address ipv6 = ip_me.ipv6; - ipv6.hi ^= ip_them.ipv6.hi; - ipv6.lo ^= ip_them.ipv6.lo; - index = (unsigned)syn_cookie_ipv6( - ipv6, - port_me ^ port_them, - ipv6, - port_me ^ port_them, - entropy); - - } else { - index = (unsigned)syn_cookie_ipv4( ip_me.ipv4 ^ ip_them.ipv4, - port_me ^ port_them, - ip_me.ipv4 ^ ip_them.ipv4, - port_me ^ port_them, - entropy - ); - } - return index; -} - -enum DestroyReason { - Reason_Timeout = 1, - Reason_FIN = 2, - Reason_RST = 3, - Reason_Foo = 4, - Reason_Shutdown = 5, - Reason_StateDone = 6, - -}; - -/*************************************************************************** - * Flush all the banners associated with this TCP connection. This always - * called when TCB is destroyed. This may also be called earlier, such - * as when a FIN is received. - ***************************************************************************/ -static void -tcpcon_flush_banners(struct TCP_ConnectionTable *tcpcon, struct TCP_Control_Block *tcb) -{ - struct BannerOutput *banout; - - /* Go through and print all the banners. Some protocols have - * multiple banners. For example, web servers have both - * HTTP and HTML banners, and SSL also has several - * X.509 certificate banners */ - for (banout = &tcb->banout; banout != NULL; banout = banout->next) { - if (banout->length && banout->protocol) { - tcpcon->report_banner( - tcpcon->out, - global_now, - tcb->ip_them, - 6, /*TCP protocol*/ - tcb->port_them, - banout->protocol & 0x0FFFFFFF, - tcb->ttl, - banout->banner, - banout->length); - } - } - - /* - * Free up all the banners. - */ - banout_release(&tcb->banout); - -} - -/*************************************************************************** - * Destroy a TCP connection entry. We have to unlink both from the - * TCB-table as well as the timeout-table. - * Called from - ***************************************************************************/ -static void -tcpcon_destroy_tcb( - struct TCP_ConnectionTable *tcpcon, - struct TCP_Control_Block *tcb, - enum DestroyReason reason) -{ - unsigned index; - struct TCP_Control_Block **r_entry; - ipaddress_formatted_t fmt; - - UNUSEDPARM(reason); - - fmt = ipaddress_fmt(tcb->ip_them); - LOG(1, "%s %u - closing\n", fmt.string, tcb->port_them); - - /* - * The TCB doesn't point to it's location in the table. Therefore, we - * have to do a lookup to find the head pointer in the table. - */ - index = tcb_hash( tcb->ip_me, tcb->port_me, - tcb->ip_them, tcb->port_them, - tcpcon->entropy); - - /* - * At this point, we have the head of a linked list of TCBs. Now, - * traverse that linked list until we find our TCB - */ - r_entry = &tcpcon->entries[index & tcpcon->mask]; - while (*r_entry && *r_entry != tcb) - r_entry = &(*r_entry)->next; - - if (*r_entry == NULL) { - LOG(1, "tcb: double free\n"); - return; - } - - /* - * Print out any banners associated with this TCP session. Most of the - * time, there'll only be one. After printing them out, delete the - * banners. - */ - tcpcon_flush_banners(tcpcon, tcb); - if (tcb->is_payload_dynamic && tcb->payload_length && tcb->payload) - free((void*)tcb->payload); - - if (tcb->scripting_thread) - ; //scripting_thread_close(tcb->scripting_thread); - tcb->scripting_thread = 0; - - /* KLUDGE: this needs to be made more elegant */ - switch (tcb->banner1_state.app_proto) { - case PROTO_SMB: - banner_smb1.cleanup(&tcb->banner1_state); - break; - } - - /* - * Unlink this from the timeout system. - */ - timeout_unlink(tcb->timeout); - - tcb->ip_them.ipv4 = (unsigned)~0; - tcb->port_them = (unsigned short)~0; - tcb->ip_me.ipv4 = (unsigned)~0; - tcb->port_me = (unsigned short)~0; - - tcb->is_active = 0; - - - - - (*r_entry) = tcb->next; - tcb->next = tcpcon->freed_list; - tcpcon->freed_list = tcb; - tcpcon->active_count--; -} - - -/*************************************************************************** - * Called at shutdown to free up all the memory used by the TCP - * connection table. - ***************************************************************************/ -void -tcpcon_destroy_table(struct TCP_ConnectionTable *tcpcon) -{ - unsigned i; - - if (tcpcon == NULL) - return; - - /* - * Do a graceful destruction of all the entires. If they have banners, - * they will be sent to the output - */ - for (i=0; i<=tcpcon->mask; i++) { - while (tcpcon->entries[i]) - tcpcon_destroy_tcb(tcpcon, tcpcon->entries[i], Reason_Shutdown); - } - - /* - * Now free the memory - */ - while (tcpcon->freed_list) { - struct TCP_Control_Block *tcb = tcpcon->freed_list; - tcpcon->freed_list = tcb->next; - free(tcb); - } - - banner1_destroy(tcpcon->banner1); - free(tcpcon->entries); - free(tcpcon); -} - - -/*************************************************************************** - * - * Called when we receive a "SYN-ACK" packet with the correct SYN-cookie. - * - ***************************************************************************/ -struct TCP_Control_Block * -tcpcon_create_tcb( - struct TCP_ConnectionTable *tcpcon, - ipaddress ip_me, ipaddress ip_them, - unsigned port_me, unsigned port_them, - unsigned seqno_me, unsigned seqno_them, - unsigned ttl) -{ - unsigned index; - struct TCP_Control_Block tmp; - struct TCP_Control_Block *tcb; - - assert(ip_me.version != 0 && ip_them.version != 0); - - tmp.ip_me = ip_me; - tmp.ip_them = ip_them; - tmp.port_me = (unsigned short)port_me; - tmp.port_them = (unsigned short)port_them; - - index = tcb_hash(ip_me, port_me, ip_them, port_them, tcpcon->entropy); - - - tcb = tcpcon->entries[index & tcpcon->mask]; - while (tcb && !EQUALS(tcb, &tmp)) { - tcb = tcb->next; - } - if (tcb == NULL) { - if (tcpcon->freed_list) { - tcb = tcpcon->freed_list; - tcpcon->freed_list = tcb->next; - } else { - tcb = MALLOC(sizeof(*tcb)); - } - memset(tcb, 0, sizeof(*tcb)); - tcb->next = tcpcon->entries[index & tcpcon->mask]; - tcpcon->entries[index & tcpcon->mask] = tcb; - - tcb->ip_me = ip_me; - tcb->ip_them = ip_them; - tcb->port_me = (unsigned short)port_me; - tcb->port_them = (unsigned short)port_them; - - tcb->seqno_them_first = seqno_them; /* ipv6-todo */ - tcb->seqno_me = seqno_me; - tcb->seqno_them = seqno_them; - tcb->ackno_me = seqno_them; - tcb->ackno_them = seqno_me; - tcb->when_created = global_now; - tcb->banner1_state.port = tmp.port_them; - tcb->ttl = (unsigned char)ttl; - - timeout_init(tcb->timeout); - banout_init(&tcb->banout); - - /* The TCB is now allocated/in-use */ - assert(tcb->ip_me.version != 0 && tcb->ip_them.version != 0); - tcb->is_active = 1; - - - tcpcon->active_count++; - } - - tcb_lookup(tcpcon, ip_me, ip_them, port_me, port_them); - - return tcb; -} - - - -/*************************************************************************** - ***************************************************************************/ -struct TCP_Control_Block * -tcb_lookup( - struct TCP_ConnectionTable *tcpcon, - ipaddress ip_me, ipaddress ip_them, - unsigned port_me, unsigned port_them) -{ - unsigned index; - struct TCP_Control_Block tmp; - struct TCP_Control_Block *tcb; - ipaddress_formatted_t fmt1; - ipaddress_formatted_t fmt2; - - tmp.ip_me = ip_me; - tmp.ip_them = ip_them; - tmp.port_me = (unsigned short)port_me; - tmp.port_them = (unsigned short)port_them; - - index = tcb_hash(ip_me, port_me, ip_them, port_them, tcpcon->entropy); - - fmt1 = ipaddress_fmt(ip_me); - fmt2 = ipaddress_fmt(ip_them); - LOG(1, "tcb_hash(0x%08x) = %s %u %s %u\n", - (unsigned)index, - fmt1.string, port_me, - fmt2.string, port_them); - - /* Hash to an entry in the table, then follow a linked list from - * that point forward. */ - tcb = tcpcon->entries[index & tcpcon->mask]; - while (tcb && !EQUALS(tcb, &tmp)) { - tcb = tcb->next; - } - - - return tcb; -} - - -/*************************************************************************** - ***************************************************************************/ -static void -tcpcon_send_packet( - struct TCP_ConnectionTable *tcpcon, - struct TCP_Control_Block *tcb, - unsigned tcp_flags, - const unsigned char *payload, size_t payload_length, - unsigned ctrl) -{ - struct PacketBuffer *response = 0; - - assert(tcb->ip_me.version != 0 && tcb->ip_them.version != 0); - - - /* Get a buffer for sending the response packet. This thread doesn't - * send the packet itself. Instead, it formats a packet, then hands - * that packet off to a transmit thread for later transmission. */ - response = stack_get_packetbuffer(tcpcon->stack); - if (response == NULL) { - static int is_warning_printed = 0; - if (!is_warning_printed) { - LOG(0, "packet buffers empty (should be impossible)\n"); - is_warning_printed = 1; - } - fflush(stdout); - - /* FIXME: I'm no sure the best way to handle this. - * This would result from a bug in the code, - * but I'm not sure what should be done in response */ - pixie_usleep(100); /* no packet available */ - } - if (response == NULL) - return; - - /* Format the packet as requested. Note that there are really only - * four types of packets: - * 1. a SYN-ACK packet with no payload - * 2. an ACK packet with no payload - * 3. a RST packet with no payload - * 4. a PSH-ACK packet WITH PAYLOAD - */ - response->length = tcp_create_packet( - tcpcon->pkt_template, - tcb->ip_them, tcb->port_them, - tcb->ip_me, tcb->port_me, - tcb->seqno_me, tcb->seqno_them, - tcp_flags, - payload, payload_length, - response->px, sizeof(response->px) - ); - - /* - * KLUDGE: - */ - if (ctrl & CTRL_SMALL_WINDOW) { - tcp_set_window(response->px, response->length, 600); - } - //tcp_set_window(response->px, response->length, 600); - - /* If we have payload, then: - * 1. remember the payload so we can resend it - */ - tcb->payload = payload; - tcb->payload_length = (unsigned short)payload_length; - - /* Put this buffer on the transmit queue. Remember: transmits happen - * from a transmit-thread only, and this function is being called - * from a receive-thread. Therefore, instead of transmiting ourselves, - * we hae to queue it up for later transmission. */ - stack_transmit_packetbuffer(tcpcon->stack, response); -} - -/*************************************************************************** - ***************************************************************************/ -void -tcp_send_RST( - struct TemplatePacket *templ, - struct stack_t *stack, - ipaddress ip_them, ipaddress ip_me, - unsigned port_them, unsigned port_me, - unsigned seqno_them, unsigned seqno_me -) -{ - struct PacketBuffer *response = 0; - - - /* Get a buffer for sending the response packet. This thread doesn't - * send the packet itself. Instead, it formats a packet, then hands - * that packet off to a transmit thread for later transmission. */ - response = stack_get_packetbuffer(stack); - if (response == NULL) { - static int is_warning_printed = 0; - if (!is_warning_printed) { - LOG(0, "packet buffers empty (should be impossible)\n"); - is_warning_printed = 1; - } - fflush(stdout); - pixie_usleep(100); /* no packet available */ - } - if (response == NULL) - return; - - response->length = tcp_create_packet( - templ, - ip_them, port_them, - ip_me, port_me, - seqno_me, seqno_them, - 0x04, /*RST*/ - 0, 0, - response->px, sizeof(response->px) - ); - - - /* Put this buffer on the transmit queue. Remember: transmits happen - * from a transmit-thread only, and this function is being called - * from a receive-thread. Therefore, instead of transmitting ourselves, - * we have to queue it up for later transmission. */ - stack_transmit_packetbuffer(stack, response); -} - -/*************************************************************************** - * DEBUG: when printing debug messages (-d option), this prints a string - * for the given state. - ***************************************************************************/ -static const char * -state_to_string(int state) -{ - static char buf[64]; - switch (state) { - //STATE_SYN_RECEIVED, - //STATE_CLOSE_WATI, - case STATE_LAST_ACK: return "LAST-ACK"; - case STATE_FIN_WAIT1: return "FIN-WAIT-1"; - case STATE_FIN_WAIT2: return "FIN-WAIT-2"; - case STATE_CLOSING: return "CLOSING"; - case STATE_TIME_WAIT: return "TIME-WAIT"; - case STATE_SYN_SENT: return "SYN_SENT"; - case STATE_ESTABLISHED_SEND:return "ESTABLISHED_SEND"; - case STATE_ESTABLISHED_RECV:return "ESTABLISHED_RECV"; - - default: - sprintf_s(buf, sizeof(buf), "%d", state); - return buf; - } -} - -/*************************************************************************** - * DEBUG: when printing debug messages (-d option), this prints a string - * for the given state. - ***************************************************************************/ -static const char * -what_to_string(enum TCP_What state) -{ - static char buf[64]; - switch (state) { - case TCP_WHAT_TIMEOUT: return "TIMEOUT"; - case TCP_WHAT_SYNACK: return "SYNACK"; - case TCP_WHAT_RST: return "RST"; - case TCP_WHAT_FIN: return "FIN"; - case TCP_WHAT_ACK: return "ACK"; - case TCP_WHAT_DATA: return "DATA"; - default: - sprintf_s(buf, sizeof(buf), "%d", state); - return buf; - } -} - - -/*************************************************************************** - ***************************************************************************/ - -static void -LOGSEND(struct TCP_Control_Block *tcb, const char *what) -{ - if (tcb == NULL) - return; - LOGip(5, tcb->ip_them, tcb->port_them, "=%s : --->> %s \n", - state_to_string(tcb->tcpstate), - what); -} - - -/*************************************************************************** - * Sends a fake FIN when we've already closed our connection, on the - * assumption this will help the other side close their side more - * gracefully. Maybe we should do a RST instead. - ***************************************************************************/ -void -tcpcon_send_FIN( - struct TCP_ConnectionTable *tcpcon, - ipaddress ip_me, ipaddress ip_them, - unsigned port_me, unsigned port_them, - uint32_t seqno_them, uint32_t ackno_them) -{ - struct TCP_Control_Block tcb; - - memset(&tcb, 0, sizeof(tcb)); - - tcb.ip_me = ip_me; - tcb.ip_them = ip_them; - tcb.port_me = (unsigned short)port_me; - tcb.port_them = (unsigned short)port_them; - tcb.seqno_me = ackno_them; - tcb.ackno_me = seqno_them + 1; - tcb.seqno_them = seqno_them + 1; - tcb.ackno_them = ackno_them; - - LOGSEND(&tcb, "peer(FIN) fake"); - tcpcon_send_packet(tcpcon, &tcb, 0x11, 0, 0, 0); -} - -void -tcpcon_send_RST( - struct TCP_ConnectionTable *tcpcon, - ipaddress ip_me, ipaddress ip_them, - unsigned port_me, unsigned port_them, - uint32_t seqno_them, uint32_t ackno_them) -{ - struct TCP_Control_Block tcb; - - memset(&tcb, 0, sizeof(tcb)); - - tcb.ip_me = ip_me; - tcb.ip_them = ip_them; - tcb.port_me = (unsigned short)port_me; - tcb.port_them = (unsigned short)port_them; - tcb.seqno_me = ackno_them; - tcb.ackno_me = seqno_them + 1; - tcb.seqno_them = seqno_them + 1; - tcb.ackno_them = ackno_them; - - LOGSEND(&tcb, "send RST"); - tcpcon_send_packet(tcpcon, &tcb, 0x04, 0, 0, 0); -} - - -/*************************************************************************** - * Parse the information we get from the server we are scanning. Typical - * examples are SSH banners, FTP banners, or the response from HTTP - * requests - ***************************************************************************/ -static size_t -parse_banner( - struct TCP_ConnectionTable *tcpcon, - struct TCP_Control_Block *tcb, - const unsigned char *payload, - size_t payload_length, - struct InteractiveData *more) -{ - assert(tcb->banout.max_length); - - banner1_parse( - tcpcon->banner1, - &tcb->banner1_state, - payload, - payload_length, - &tcb->banout, - more); - return payload_length; -} - - -/*************************************************************************** - ***************************************************************************/ -static int -handle_ack( - struct TCP_Control_Block *tcb, - uint32_t ackno) -{ - - /*LOG(4, "%s - %u-sending, %u-reciving\n", - fmt.string, - tcb->seqno_me - ackno, - ackno - tcb->ackno_them - );*/ - - /* Normal: just discard repeats */ - if (ackno == tcb->ackno_them) { - return 0; - } - - /* Make sure this isn't a duplicate ACK from past - * WRAPPING of 32-bit arithmetic happens here */ - if (ackno - tcb->ackno_them > 10000) { - ipaddress_formatted_t fmt = ipaddress_fmt(tcb->ip_them); - LOG(4, "%s - " - "tcb: ackno from past: " - "old ackno = 0x%08x, this ackno = 0x%08x\n", - fmt.string, - tcb->ackno_me, ackno); - return 0; - } - - /* Make sure this isn't invalid ACK from the future - * WRAPPING of 32-bit arithmetic happens here */ - if (tcb->seqno_me - ackno > 10000) { - ipaddress_formatted_t fmt = ipaddress_fmt(tcb->ip_them); - LOG(4, "%s - " - "tcb: ackno from future: " - "my seqno = 0x%08x, their ackno = 0x%08x\n", - fmt.string, - tcb->seqno_me, ackno); - return 0; - } - - /* now that we've verified this is a good ACK, record this number */ - tcb->ackno_them = ackno; - - /* Mark that this was a good ack */ - return 1; -} - -enum AppAction { - APP_CONNECTED, - APP_RECV_TIMEOUT, - APP_RECV_PAYLOAD, - APP_SEND_SENT, -}; - - -/*************************************************************************** - ***************************************************************************/ -static void -application(struct TCP_ConnectionTable *tcpcon, - struct TCP_Control_Block *tcb, - enum AppAction action, const void *payload, size_t payload_length, - unsigned secs, unsigned usecs) -{ - struct Banner1 *banner1 = tcpcon->banner1; - - enum { - App_Connect, - App_ReceiveHello, - App_ReceiveNext, - App_SendNext, - }; - - switch (tcb->established) { - case App_Connect: - if (banner1->payloads.tcp[tcb->port_them] == &banner_scripting) { - //int x; - ; //tcb->scripting_thread = scripting_thread_new(tcpcon->scripting_vm); - ; //x = scripting_thread_run(tcb->scripting_thread); - } else { - /* - * Wait 1 second for "server hello" (like SSH), and if that's - * not found, then transmit a "client hello" - */ - assert(action == APP_CONNECTED); - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+tcpcon->timeout_hello,usecs) - ); - /* Start of connection */ - tcb->tcpstate = STATE_ESTABLISHED_RECV; - tcb->established = App_ReceiveHello; - } - break; - case App_ReceiveHello: - if (action == APP_RECV_TIMEOUT) { - struct ProtocolParserStream *stream = banner1->payloads.tcp[tcb->port_them]; - - if (stream) { - struct InteractiveData more = {0}; - unsigned ctrl = 0; - - if (stream->transmit_hello) - stream->transmit_hello(banner1, &more); - else { - more.m_length = (unsigned)banner1->payloads.tcp[tcb->port_them]->hello_length; - more.m_payload = banner1->payloads.tcp[tcb->port_them]->hello; - more.is_payload_dynamic = 0; - } - - /* - * Kludge - */ - if (banner1->payloads.tcp[tcb->port_them] == &banner_ssl) { - tcb->banner1_state.is_sent_sslhello = 1; - } - - /* - * KLUDGE - */ - if (tcpcon->banner1->is_heartbleed) { - ctrl = CTRL_SMALL_WINDOW; - } - - /* - * Queue up the packet to be sent - */ - LOGip(4, tcb->ip_them, tcb->port_them, "sending payload %u bytes\n", more.m_length); - LOGSEND(tcb, "peer(payload)"); - tcpcon_send_packet(tcpcon, tcb, 0x18, more.m_payload, more.m_length, ctrl); - tcb->seqno_me += (uint32_t)more.m_length; - tcb->is_payload_dynamic = more.is_payload_dynamic; - tcb->tcpstate = STATE_ESTABLISHED_SEND; - - //tcb->established = App_SendNext; - } - - /* Add a timeout so that we can resend the data in case it - * goes missing. Note that we put this back in the timeout - * system regardless if we've sent data. */ - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+1,usecs) - ); - break; - } else if (action == APP_RECV_PAYLOAD) { - tcb->established = App_ReceiveNext; - /* fall through */ - } - /* fall through */ - case App_ReceiveNext: - if (action == APP_RECV_PAYLOAD) { - struct InteractiveData more = {0}; - - /* [--banners] - * This is an important part of the system, where the TCP - * stack passes incoming packet payloads off to the application - * layer protocol parsers. This is where, in Sockets API, you - * might call the 'recv()' function. - */ - parse_banner( - tcpcon, - tcb, - payload, - payload_length, - &more); - - /* move their sequence number forward */ - tcb->seqno_them += (unsigned)payload_length; - - /* acknowledge the bytes received */ - if (more.m_length) { - LOGSEND(tcb, "peer(ACK)"); - LOGSEND(tcb, "peer(payload)"); - tcpcon_send_packet(tcpcon, tcb, 0x18, more.m_payload, more.m_length, 0); - tcb->seqno_me += (uint32_t)more.m_length; - tcb->is_payload_dynamic = more.is_payload_dynamic; - tcb->tcpstate = STATE_ESTABLISHED_SEND; - tcb->established = App_SendNext; - LOGip(4, tcb->ip_them, tcb->port_them, "sending payload %u bytes\n", more.m_length); - - } else { - LOGSEND(tcb, "peer(ACK)"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, - 0, 0, 0); - } - - if (more.is_closing) { - /* Send FIN packet */ - LOGSEND(tcb, "peer(FIN)"); - tcpcon_send_packet(tcpcon, tcb, - 0x11, - 0, 0, 0); - tcb->seqno_me++; - - tcb->tcpstate = STATE_FIN_WAIT1; - LOGSEND(tcb, "+timeout"); - - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+1,usecs) - ); - //tcpcon_destroy_tcb(tcpcon, tcb, Reason_StateDone); - } - } - break; - case App_SendNext: - if (action == APP_SEND_SENT) { - tcb->tcpstate = STATE_ESTABLISHED_RECV; - tcb->established = App_ReceiveNext; - } - break; - default: - LOG(0, "TCP state error\n"); - exit(1); - break; - } -} - - -/***************************************************************************** - * Handles incoming events, like timeouts and packets, that cause a change - * in the TCP control block "state". - * - * This is the part of the code that implements the famous TCP state-machine - * you see drawn everywhere, where they have states like "TIME_WAIT". Only - * we don't really have those states. - *****************************************************************************/ -int -stack_incoming_tcp(struct TCP_ConnectionTable *tcpcon, - struct TCP_Control_Block *tcb, - int in_what, const void *vpayload, size_t payload_length, - unsigned secs, unsigned usecs, - unsigned seqno_them) -{ - enum TCP_What what = in_what; - const unsigned char *payload = (const unsigned char *)vpayload; - - if (tcb == NULL) - return 0; - - LOGip(5, tcb->ip_them, tcb->port_them, "=%s : %s \n", - state_to_string(tcb->tcpstate), - what_to_string(what)); - - /* Make sure no connection lasts more than ~30 seconds */ - if (what == TCP_WHAT_TIMEOUT) { - if (tcb->when_created + tcpcon->timeout_connection < secs) { - LOGip(8, tcb->ip_them, tcb->port_them, - "%s \n", - "CONNECTION TIMEOUT---"); - LOGSEND(tcb, "peer(RST)"); - tcpcon_send_packet(tcpcon, tcb, - 0x04, - 0, 0, 0); - tcpcon_destroy_tcb(tcpcon, tcb, Reason_Timeout); - return 1; - } - } - - if (what == TCP_WHAT_RST) { - LOGSEND(tcb, "tcb(destroy)"); - tcpcon_destroy_tcb(tcpcon, tcb, Reason_RST); - return 1; - } - - - /* - * - * - * - * - * - * - */ - switch (tcb->tcpstate) { - /* TODO: validate any SYNACK is real before sending it here - * to the state-machine, by validating that it's acking - * something */ - case STATE_SYN_SENT: - switch (what) { - case TCP_WHAT_RST: - case TCP_WHAT_TIMEOUT: - //case TCP_WHAT_SYNACK: - case TCP_WHAT_FIN: - case TCP_WHAT_ACK: - case TCP_WHAT_DATA: - break; - case TCP_WHAT_SYNACK: - /* Send "ACK" to acknowlege their "SYN-ACK" */ - LOGSEND(tcb, "peer(ACK) [acknowledge SYN-ACK 1]"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, - 0, 0, 0); - LOGSEND(tcb, "app(connected)"); - application(tcpcon, tcb, APP_CONNECTED, 0, 0, secs, usecs); - break; - } - break; - case STATE_ESTABLISHED_SEND: - case STATE_ESTABLISHED_RECV: - switch (what) { - case TCP_WHAT_RST: - break; - case TCP_WHAT_SYNACK: - /* Send "ACK" to acknowlege their "SYN-ACK" */ - LOGSEND(tcb, "peer(ACK) [acknowledge SYN-ACK 2]"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, /* ACK */ - 0, 0, 0); - break; - case TCP_WHAT_FIN: - if (tcb->tcpstate == STATE_ESTABLISHED_RECV) { - tcb->seqno_them = seqno_them + 1; - - LOGSEND(tcb, "peer(FIN)"); - tcpcon_send_packet(tcpcon, tcb, - 0x11, /* FIN-ACK */ - 0, 0, 0); - tcb->seqno_me++; - tcb->tcpstate = STATE_LAST_ACK; - } else if (tcb->tcpstate == STATE_ESTABLISHED_RECV) { - /* Do nothing, the same thing as if we received data - * during the SEND state. The other side will send it - * again after it has acknowledged our data */ - ; - } - break; - case TCP_WHAT_ACK: - /* There's actually nothing that goes on in this state. We are - * just waiting for the timer to expire. In the meanwhile, - * though, the other side is might acknowledge that we sent - * a SYN-ACK */ - - /* NOTE: the arg 'payload_length' was overloaded here to be the - * 'ackno' instead */ - handle_ack( tcb, (uint32_t)payload_length); - if (tcb->tcpstate == STATE_ESTABLISHED_SEND) { - if (tcb->ackno_them - tcb->seqno_me == 0) { - /* All the payload has been sent */ - if (tcb->is_payload_dynamic) - free((void*)tcb->payload); - tcb->payload = 0; - tcb->payload_length = 0; - tcb->is_payload_dynamic = 0; - - LOGSEND(tcb, "app(sent)"); - application(tcpcon, tcb, APP_SEND_SENT, 0, 0, secs, usecs); - tcb->tcpstate = STATE_ESTABLISHED_RECV; - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+10,usecs) - ); - } else { - /* Reset the timeout, waiting for more data to arrive */ - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+1,usecs) - ); - - } - } - break; - case TCP_WHAT_TIMEOUT: - if (tcb->tcpstate == STATE_ESTABLISHED_RECV) { - /* Didn't receive data in the expected timeframe. This is - * often a normal condition, such as during the start - * of a scanned connection, when we don't understand the - * protocol and are simply waiting for anything the - * server might send us. - */ - LOGSEND(tcb, "app(timeout)"); - application(tcpcon, tcb, APP_RECV_TIMEOUT, 0, 0, secs, usecs); - } else if (tcb->tcpstate == STATE_ESTABLISHED_SEND) { - /* - * We did not get a complete ACK of our sent data, so retransmit - * it to the server - */ - uint32_t len; - - - len = tcb->seqno_me - tcb->ackno_them; - - /* Resend the payload */ - tcb->seqno_me -= len; - LOGSEND(tcb, "peer(payload) retransmit"); - - /* kludge: should never be NULL< but somehow is */ - if (tcb->payload) - tcpcon_send_packet(tcpcon, tcb, - 0x18, - tcb->payload + tcb->payload_length - len, - len, 0); - tcb->seqno_me += len; - - - /* Now that we've resent the packet, register another - * timeout in order to resend it yet again if not - * acknowledged. */ - LOGSEND(tcb, "+timeout"); - timeouts_add(tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+2,usecs) - ); - } - - break; - case TCP_WHAT_DATA: - - if ((unsigned)(tcb->seqno_them - seqno_them) > payload_length) { - LOGSEND(tcb, "peer(ACK) [acknowledge payload 1]"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, - 0, 0, 0); - return 1; - } - - while (seqno_them != tcb->seqno_them && payload_length) { - seqno_them++; - payload_length--; - payload++; - } - - if (payload_length == 0) { - LOGSEND(tcb, "peer(ACK) [acknowledge empty data]"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, - 0, 0, 0); - return 1; - } - - LOGSEND(tcb, "app(payload)"); - application(tcpcon, tcb, APP_RECV_PAYLOAD, payload, payload_length, secs, usecs); - - /* Send ack for the data */ - LOGSEND(tcb, "peer(ACK) [acknowledge payload 2]"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, - 0, 0, 0); - break; - - } - break; - case STATE_FIN_WAIT1: - switch (what) { - case TCP_WHAT_TIMEOUT: - /* resend FIN packet */ - LOGSEND(tcb, "peer(FIN)"); - tcpcon_send_packet(tcpcon, tcb, - 0x11, - 0, 0, 0); - - /* reset timeout */ - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+1,usecs) - ); - break; - case TCP_WHAT_ACK: - if (handle_ack( tcb, (uint32_t)payload_length)) { - tcb->tcpstate = STATE_FIN_WAIT2; - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+5,usecs) - ); - } - break; - case TCP_WHAT_FIN: - break; - case TCP_WHAT_SYNACK: - case TCP_WHAT_RST: - case TCP_WHAT_DATA: - break; - } - break; - - case STATE_FIN_WAIT2: - case STATE_TIME_WAIT: - switch (what) { - case TCP_WHAT_TIMEOUT: - if (tcb->tcpstate == STATE_TIME_WAIT) { - tcpcon_destroy_tcb(tcpcon, tcb, Reason_Timeout); - return 1; - } - break; - case TCP_WHAT_ACK: - break; - case TCP_WHAT_FIN: - tcb->seqno_them = seqno_them + 1; - LOGSEND(tcb, "peer(ACK) [acknowledge FIN]"); - tcpcon_send_packet(tcpcon, tcb, - 0x10, - 0, 0, 0); - tcb->tcpstate = STATE_TIME_WAIT; - LOGSEND(tcb, "+timeout"); - timeouts_add( tcpcon->timeouts, - tcb->timeout, - offsetof(struct TCP_Control_Block, timeout), - TICKS_FROM_TV(secs+5,usecs) - ); - break; - case TCP_WHAT_SYNACK: - case TCP_WHAT_RST: - case TCP_WHAT_DATA: - break; - } - break; - - case STATE_LAST_ACK: - LOGip(1, tcb->ip_them, tcb->port_them, "=%s : %s \n", state_to_string(tcb->tcpstate), what_to_string(what)); - //LOG(1, "TCP-state: unknown state\n"); - break; - default: - LOG(1, "TCP-state: unknown state\n"); - } - return 1; -} - diff --git a/src/proto-udp.c b/src/proto-udp.c index dc5d42c2..5ab29a38 100644 --- a/src/proto-udp.c +++ b/src/proto-udp.c @@ -8,7 +8,7 @@ #include "proto-zeroaccess.h" #include "proto-preprocess.h" #include "syn-cookie.h" -#include "logger.h" +#include "util-logger.h" #include "output.h" #include "masscan-status.h" #include "unusedparm.h" @@ -94,16 +94,29 @@ handle_udp(struct Output *out, time_t timestamp, break; } - if (status == 0) - output_report_status( - out, - timestamp, - PortStatus_Open, - ip_them, - 17, /* ip proto = udp */ - port_them, - 0, - 0, - parsed->mac_src); - + if (status == 0) { + if (px != 0 && parsed->app_length == 0) { + output_report_status( + out, + timestamp, + PortStatus_Open, + ip_them, + 17, /* ip proto = udp */ + port_them, + 0, + parsed->ip_ttl, + parsed->mac_src); + } else { + output_report_banner( + out, + timestamp, + ip_them, + 17, /* ip proto = udp */ + port_them, + PROTO_NONE, + parsed->ip_ttl, + px + parsed->app_offset, + parsed->app_length); + } + } } diff --git a/src/versioning.c b/src/proto-versioning.c similarity index 93% rename from src/versioning.c rename to src/proto-versioning.c index 02b6a802..663b528f 100644 --- a/src/versioning.c +++ b/src/proto-versioning.c @@ -2,13 +2,13 @@ SERVICE VERSIONING */ -#include "versioning.h" +#include "proto-versioning.h" #include "proto-banner1.h" #include "smack.h" #include "unusedparm.h" #include "masscan-app.h" #include "output.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-preprocess.h" #include "proto-ssl.h" #include "proto-udp.h" @@ -26,17 +26,17 @@ static void versioning_tcp_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); + UNUSEDPARM(socket); UNUSEDPARM(px); UNUSEDPARM(length); UNUSEDPARM(banout); diff --git a/src/versioning.h b/src/proto-versioning.h similarity index 100% rename from src/versioning.h rename to src/proto-versioning.h diff --git a/src/proto-vnc.c b/src/proto-vnc.c index 19e51aab..c261056e 100644 --- a/src/proto-vnc.c +++ b/src/proto-vnc.c @@ -1,6 +1,6 @@ #include "proto-vnc.h" #include "proto-banner1.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "unusedparm.h" #include "masscan-app.h" #include "string_s.h" @@ -34,56 +34,56 @@ vnc_append_sectype(struct BannerOutput *banout, unsigned sectype) */ switch (sectype) { case 0: - banout_append(banout, PROTO_VNC_RFB, "invalid", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " invalid", AUTO_LEN); break; case 1: - banout_append(banout, PROTO_VNC_RFB, "none", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " none", AUTO_LEN); break; case 2: - banout_append(banout, PROTO_VNC_RFB, "VNC-chap", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " VNC-chap", AUTO_LEN); break; case 5: - banout_append(banout, PROTO_VNC_RFB, "RA2", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " RA2", AUTO_LEN); break; case 6: - banout_append(banout, PROTO_VNC_RFB, "RA2ne", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " RA2ne", AUTO_LEN); break; case 7: - banout_append(banout, PROTO_VNC_RFB, "SSPI", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " SSPI", AUTO_LEN); break; case 8: - banout_append(banout, PROTO_VNC_RFB, "SSPIne", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " SSPIne", AUTO_LEN); break; case 16: - banout_append(banout, PROTO_VNC_RFB, "Tight", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " Tight", AUTO_LEN); break; case 17: - banout_append(banout, PROTO_VNC_RFB, "Ultra", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " Ultra", AUTO_LEN); break; case 18: - banout_append(banout, PROTO_VNC_RFB, "TLS", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " TLS", AUTO_LEN); break; case 19: - banout_append(banout, PROTO_VNC_RFB, "VeNCrypt", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " VeNCrypt", AUTO_LEN); break; case 20: - banout_append(banout, PROTO_VNC_RFB, "GTK-VNC-SASL", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " GTK-VNC-SASL", AUTO_LEN); break; case 21: - banout_append(banout, PROTO_VNC_RFB, "MD5", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " MD5", AUTO_LEN); break; case 22: - banout_append(banout, PROTO_VNC_RFB, "Colin-Dean-xvp", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " Colin-Dean-xvp", AUTO_LEN); break; case 30: - banout_append(banout, PROTO_VNC_RFB, "Apple30", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " Apple30", AUTO_LEN); break; case 35: - banout_append(banout, PROTO_VNC_RFB, "Apple35", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, " Apple35", AUTO_LEN); break; default: - sprintf_s(foo, sizeof(foo), "%u", sectype); - banout_append(banout, PROTO_VNC_RFB, foo, AUTO_LEN); + sprintf_s(foo, sizeof(foo), " %u", sectype); + banout_append(banout, PROTO_VNC_INFO, foo, AUTO_LEN); break; } } @@ -93,10 +93,10 @@ vnc_append_sectype(struct BannerOutput *banout, unsigned sectype) static void vnc_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; unsigned i; @@ -129,6 +129,7 @@ vnc_parse( const struct Banner1 *banner1, banout_append_char(banout, PROTO_VNC_RFB, px[i]); break; case 11: + banout_append_char(banout, PROTO_VNC_RFB, px[i]); if ('\n' == px[i]) { static const char *response[] = { "RFB 003.003\n", @@ -144,7 +145,7 @@ vnc_parse( const struct Banner1 *banner1, }; unsigned version = pstate->sub.vnc.version % 10; - tcp_transmit(more, response[version], 12, 0); + tcpapi_send(socket, response[version], 12, 0); if (version < 7) /* Version 3.3: the server selects either "none" or @@ -159,7 +160,7 @@ vnc_parse( const struct Banner1 *banner1, } } else { state = 0xFFFFFFFF; - tcp_close(more); + tcpapi_close(socket); } break; case RFB3_3_SECURITYTYPES: @@ -184,19 +185,18 @@ vnc_parse( const struct Banner1 *banner1, case RFB3_3_SECURITYTYPES+3: pstate->sub.vnc.sectype <<= 8; pstate->sub.vnc.sectype |= px[i]; - banout_append(banout, PROTO_VNC_RFB, " auth=[", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "Security types:\n", AUTO_LEN); vnc_append_sectype(banout, pstate->sub.vnc.sectype); - banout_append(banout, PROTO_VNC_RFB, "]", AUTO_LEN); if (pstate->sub.vnc.sectype == 0) state = RFB_SECURITYERROR; else if (pstate->sub.vnc.sectype == 1) { /* v3.3 sectype=none * We move immediately to ClientInit stage */ - tcp_transmit(more, "\x01", 1, 0); + tcpapi_send(socket, "\x01", 1, 0); state = RFB_SERVERINIT; } else { state = RFB_DONE; - tcp_close(more); + tcpapi_close(socket); } break; case RFB_SECURITYRESULT+3: @@ -204,7 +204,7 @@ vnc_parse( const struct Banner1 *banner1, pstate->sub.vnc.sectype |= px[i]; if (pstate->sub.vnc.sectype == 0) { /* security OK, move to client init */ - tcp_transmit(more, "\x01", 1, 0); + tcpapi_send(socket, "\x01", 1, 0); state = RFB_SERVERINIT; } else { /* error occurred, so grab error message */ @@ -214,16 +214,16 @@ vnc_parse( const struct Banner1 *banner1, case RFB_SECURITYERROR+3: pstate->sub.vnc.sectype <<= 8; pstate->sub.vnc.sectype = px[i]; - banout_append(banout, PROTO_VNC_RFB, " ERROR=", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "ERROR: ", AUTO_LEN); state++; break; case RFB_SECURITYERROR+4: if (pstate->sub.vnc.sectype == 0) { state = RFB_DONE; - tcp_close(more); + tcpapi_close(socket); } else { pstate->sub.vnc.sectype--; - banout_append_char(banout, PROTO_VNC_RFB, px[i]); + banout_append_char(banout, PROTO_VNC_INFO, px[i]); } break; case RFB3_7_SECURITYTYPES: @@ -232,7 +232,7 @@ vnc_parse( const struct Banner1 *banner1, state = RFB_SECURITYERROR; else { state++; - banout_append(banout, PROTO_VNC_RFB, " auth=[", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "Security types:\n", AUTO_LEN); } break; case RFB3_7_SECURITYTYPES+1: @@ -241,19 +241,19 @@ vnc_parse( const struct Banner1 *banner1, vnc_append_sectype(banout, px[i]); } if (pstate->sub.vnc.len == 0) { - banout_append(banout, PROTO_VNC_RFB, "]", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "\n", AUTO_LEN); if (pstate->sub.vnc.version < 7) { state = RFB_SERVERINIT; - tcp_transmit(more, "\x01", 1, 0); + tcpapi_send(socket, "\x01", 1, 0); } else if (pstate->sub.vnc.version == 7) { state = RFB_SERVERINIT; - tcp_transmit(more, "\x01\x01", 2, 0); + tcpapi_send(socket, "\x01\x01", 2, 0); } else { state = RFB_SECURITYRESULT; - tcp_transmit(more, "\x01", 1, 0); + tcpapi_send(socket, "\x01", 1, 0); } } else { - banout_append(banout, PROTO_VNC_RFB, "/", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "\n", AUTO_LEN); } break; @@ -306,27 +306,27 @@ vnc_parse( const struct Banner1 *banner1, pstate->sub.vnc.sectype |= px[i]; state++; if (pstate->sub.vnc.sectype) { - banout_append(banout, PROTO_VNC_RFB, " name=[", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "Name: ", AUTO_LEN); } else { state = RFB_DONE; - tcp_close(more); + tcpapi_close(socket); } break; case RFB_SERVERINIT+24: pstate->sub.vnc.sectype--; - banout_append_char(banout, PROTO_VNC_RFB, px[i]); + banout_append_char(banout, PROTO_VNC_INFO, px[i]); if (pstate->sub.vnc.sectype == 0) { - banout_append(banout, PROTO_VNC_RFB, "]", AUTO_LEN); + banout_append(banout, PROTO_VNC_INFO, "\n", AUTO_LEN); state = RFB_DONE; - tcp_close(more); + tcpapi_close(socket); } break; case RFB_DONE: - tcp_close(more); + tcpapi_close(socket); i = (unsigned)length; break; default: diff --git a/src/proto-x509.c b/src/proto-x509.c index dee8c576..8c4f0705 100644 --- a/src/proto-x509.c +++ b/src/proto-x509.c @@ -90,7 +90,7 @@ TBSCertificate ::= SEQUENCE { #include "proto-banout.h" #include "masscan-app.h" #include "smack.h" -#include "logger.h" +#include "util-logger.h" #include #include #include diff --git a/src/rawsock-getif.c b/src/rawsock-getif.c index 42abf50c..01ff6c03 100755 --- a/src/rawsock-getif.c +++ b/src/rawsock-getif.c @@ -7,7 +7,7 @@ #include "rawsock.h" #include "string_s.h" #include "util-malloc.h" -#include "logger.h" +#include "util-logger.h" #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun__) #include diff --git a/src/rawsock-getmac.c b/src/rawsock-getmac.c index 8725c050..a816de3d 100644 --- a/src/rawsock-getmac.c +++ b/src/rawsock-getmac.c @@ -11,7 +11,7 @@ */ #include "rawsock.h" #include "string_s.h" -#include "logger.h" +#include "util-logger.h" /***************************************************************************** *****************************************************************************/ diff --git a/src/rawsock-getroute.c b/src/rawsock-getroute.c index a33c37c3..67afbcb1 100644 --- a/src/rawsock-getroute.c +++ b/src/rawsock-getroute.c @@ -8,7 +8,7 @@ #include "string_s.h" #include "util-malloc.h" #include "massip-parse.h" -#include "logger.h" +#include "util-logger.h" #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun__) #include diff --git a/src/rawsock.c b/src/rawsock.c index 158271a7..75b6be7a 100755 --- a/src/rawsock.c +++ b/src/rawsock.c @@ -6,7 +6,7 @@ */ #include "rawsock.h" #include "templ-pkt.h" -#include "logger.h" +#include "util-logger.h" #include "main-ptrace.h" #include "string_s.h" #include "stub-pcap.h" diff --git a/src/read-service-probes.c b/src/read-service-probes.c index 9ed2d455..1a18b896 100644 --- a/src/read-service-probes.c +++ b/src/read-service-probes.c @@ -1079,7 +1079,7 @@ nmapserviceprobes_print(const struct NmapServiceProbeList *list, FILE *fp) fprintf(fp, " "); for (vi=match->versioninfo; vi; vi=vi->next) { - const char *tag = ""; + const char *tag; switch (vi->type) { case SvcV_Unknown: tag = "u"; break; case SvcV_ProductName: tag = "p"; break; @@ -1089,6 +1089,7 @@ nmapserviceprobes_print(const struct NmapServiceProbeList *list, FILE *fp) case SvcV_OperatingSystem: tag = "o"; break; case SvcV_DeviceType: tag = "e"; break; case SvcV_CpeName: tag = "cpe:"; break; + default: tag = ""; } fprintf(fp, "%s", tag); nmapserviceprobes_print_dstring(fp, vi->value, strlen(vi->value), '/'); diff --git a/src/scripting-banner.c b/src/scripting-banner.c index 6195d2ff..20fe65d2 100644 --- a/src/scripting-banner.c +++ b/src/scripting-banner.c @@ -6,10 +6,10 @@ #include "proto-banner1.h" #include "smack.h" #include "unusedparm.h" -#include "logger.h" +#include "util-logger.h" #include "masscan-app.h" #include "output.h" -#include "proto-interactive.h" +#include "stack-tcp-api.h" #include "proto-preprocess.h" #include "proto-ssl.h" #include "proto-udp.h" @@ -24,9 +24,9 @@ /*************************************************************************** ***************************************************************************/ static void -scripting_transmit_hello(const struct Banner1 *banner1, struct InteractiveData *more) +scripting_transmit_hello(const struct Banner1 *banner1, struct stack_handle_t *socket) { - UNUSEDPARM(banner1); UNUSEDPARM(more); + UNUSEDPARM(banner1); UNUSEDPARM(socket); LOG(0, "SCRIPTING: HELLO\n"); } @@ -36,17 +36,17 @@ static void scripting_tcp_parse( const struct Banner1 *banner1, void *banner1_private, - struct ProtocolState *pstate, + struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, - struct InteractiveData *more) + struct stack_handle_t *socket) { unsigned state = pstate->state; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); - UNUSEDPARM(more); + UNUSEDPARM(socket); UNUSEDPARM(banout); UNUSEDPARM(px); UNUSEDPARM(length); @@ -60,7 +60,7 @@ static void register_script_for_port(struct Banner1 *b, int port) { LOG(0, "SCRIPTING: using port %d\n", port); - b->payloads.tcp[port] = (struct ProtocolParserStream *)&banner_scripting; + b->payloads.tcp[port] = (const struct ProtocolParserStream *)&banner_scripting; } /*************************************************************************** diff --git a/src/scripting.c b/src/scripting.c index 7aaf1215..3b542df8 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -1,7 +1,7 @@ #include "masscan.h" #include "scripting.h" #include "stub-lua.h" -#include "logger.h" +#include "util-logger.h" #include diff --git a/src/smack1.c b/src/smack1.c index 6c4dbe2f..fb53b228 100644 --- a/src/smack1.c +++ b/src/smack1.c @@ -103,6 +103,7 @@ ****************************************************************************/ #include "smack.h" #include "smackqueue.h" +#include "util-logger.h" #include #include @@ -1706,6 +1707,8 @@ smack_selftest(void) static const size_t END_TEST_THINGY1 = 9001; static const size_t END_TEST_THINGY2 = 9002; + LOG(1, "[ ] smack: selftest started\n"); + /* * using SMACK is 5 steps: * #1 create an instance at program startup @@ -1795,7 +1798,6 @@ smack_selftest(void) smack_destroy(s); - - + LOG(1, "[+] smack: success!\n"); return 0; } diff --git a/src/stack-arpv4.c b/src/stack-arpv4.c index ce49cab5..99cd8471 100755 --- a/src/stack-arpv4.c +++ b/src/stack-arpv4.c @@ -18,7 +18,7 @@ #include "stack-arpv4.h" #include "stack-queue.h" #include "string_s.h" -#include "logger.h" +#include "util-logger.h" #include "pixie-timer.h" #include "proto-preprocess.h" #include "util-checksum.h" diff --git a/src/stack-ndpv6.c b/src/stack-ndpv6.c index f0eafbd5..04b5627a 100644 --- a/src/stack-ndpv6.c +++ b/src/stack-ndpv6.c @@ -4,7 +4,7 @@ #include "util-checksum.h" #include "rawsock-adapter.h" #include "rawsock.h" -#include "logger.h" +#include "util-logger.h" #include diff --git a/src/stack-tcp-api.h b/src/stack-tcp-api.h new file mode 100644 index 00000000..a2b8e1b6 --- /dev/null +++ b/src/stack-tcp-api.h @@ -0,0 +1,80 @@ +#ifndef STACK_HANDLE_H +#define STACK_HANDLE_H +#include +#include "util-bool.h" /* */ + +struct ProtocolParserStream; + +enum TCP__flags { + TCP__static,/* it's static data, so the send function can point to it */ + TCP__copy, /* the send function must copy the data */ + TCP__adopt, /* the buffer was just allocated, so the send function can adopt the pointer */ + TCP__close_fin /* close connection */ +}; + +enum { + SOCKERR_NONE=0, /* no error */ + SOCKERR_EBADF=10, /* bad socket descriptor */ +}; + +typedef struct stack_handle_t { + void *tcpcon; + void *tcb; + unsigned secs; + unsigned usecs; +} stack_handle_t; + + + +/** + * Set a new default timeout. + */ +int +tcpapi_set_timeout(struct stack_handle_t *socket, + unsigned secs, + unsigned usecs + ); + +/** + * Change from the "send" state to the "receive" state. + * Has no effect if in any state other than "send". + * This is none-blocking, an event will be triggered + * later that has the data. + */ +int +tcpapi_recv(struct stack_handle_t *socket); + +int +tcpapi_send(struct stack_handle_t *socket, + const void *buf, size_t length, + enum TCP__flags flags); + +/** + * Re-connect to the target, same IP and port, creating a new connection + * from a different port on this side. + */ +int +tcpapi_reconnect(struct stack_handle_t *old_socket, + struct ProtocolParserStream *new_stream, + unsigned new_app_state); + +/** + * The "app state" variable is stored opaquely in the `tcb` structure, so + * to reset it, we need an access function. + */ +unsigned +tcpapi_change_app_state(struct stack_handle_t *socket, unsigned new_app_state); + + +/** Perform the sockets half-close function (calling `close()`). This + * doesn't actually get rid of the socket, but only stops sending. + * It sends a FIN packet to the other side, and transitions to the + * TCP CLOSE-WAIT state. + * The socket will continue to receive from the opposing side until they + * give us a FIN packet. */ +int +tcpapi_close(struct stack_handle_t *socket); + + + +#endif diff --git a/src/stack-tcp-app.c b/src/stack-tcp-app.c new file mode 100644 index 00000000..4694619a --- /dev/null +++ b/src/stack-tcp-app.c @@ -0,0 +1,219 @@ +#include "stack-tcp-app.h" +#include "stack-tcp-api.h" +#include "proto-banner1.h" +#include "proto-ssl.h" +#include "unusedparm.h" +#include "util-malloc.h" +#include "util-logger.h" +#include "util-errormsg.h" +#include + +enum { + App_Connect, + App_ReceiveHello, + App_ReceiveNext, + App_SendFirst, + App_SendNext, + App_Close, +}; +static const char *state_to_string(unsigned state) { + switch (state) { + case App_Connect: return "connect"; + case App_ReceiveHello: return "wait-for-hello"; + case App_ReceiveNext: return "receive"; + case App_SendFirst: return "send-first"; + case App_SendNext: return "send"; + case App_Close: return "close"; + default: return "unknown"; + } +} +static const char *event_to_string(enum App_Event ev) { + switch (ev) { + case APP_CONNECTED: return "connected"; + case APP_RECV_TIMEOUT: return "timeout"; + case APP_RECV_PAYLOAD: return "payload"; + case APP_SEND_SENT: return "sent"; + case APP_CLOSE: return "close"; + case APP_SENDING: return "sending"; + default: return "unknown"; + } +} + +unsigned +application_event(struct stack_handle_t *socket, + unsigned state, enum App_Event event, + const struct ProtocolParserStream *stream, + struct Banner1 *banner1, + const void *payload, size_t payload_length + ) { + + + +again: + switch (state) { + case App_Connect: + switch (event) { + case APP_CONNECTED: + /* We have a receive a SYNACK here. If there are multiple handlers + * for this port, then attempt another connection using the + * other protocol handlers. For example, for SSL, we might want + * to try both TLSv1.0 and TLSv1.3 */ + if (stream && stream->next) { + tcpapi_reconnect(socket, stream->next, App_Connect); + } + + /* + * By default, wait for the "hello timeout" period + * receiving any packets they send us. If nothing is + * received in this period, then timeout will cause us + * to switch to sending + */ + if (stream != NULL && (stream->flags & SF__nowait_hello) != 0) { + tcpapi_change_app_state(socket, App_SendFirst); + state = App_SendFirst; + goto again; + } else { + tcpapi_set_timeout(socket, 2 /*tcpcon->timeout_hello*/, 0); + tcpapi_recv(socket); + tcpapi_change_app_state(socket, App_ReceiveHello); + } + break; + default: + ERRMSG("TCP.app: unhandled event: state=%s event=%s\n", + state_to_string(state), event_to_string(event)); + break; + } + + break; + case App_ReceiveHello: + switch (event) { + case APP_RECV_TIMEOUT: + /* We've got no response from the initial connection, + * so switch from them being responsible for communications + * to us being responsible, and start sending */ + if (stream) { + tcpapi_change_app_state(socket, App_SendFirst); + state = App_SendFirst; + goto again; + } + break; + case APP_RECV_PAYLOAD: + /* We've receive some data from them, so wait for some more. + * This means we won't be transmitting anything to them. */ + tcpapi_change_app_state(socket, App_ReceiveNext); + state = App_ReceiveNext; + goto again; + case APP_CLOSE: + banner_flush(socket); + tcpapi_close(socket); + break; + default: + ERRMSG("TCP.app: unhandled event: state=%s event=%s\n", + state_to_string(state), event_to_string(event)); + break; + } + break; + + case App_ReceiveNext: + switch (event) { + case APP_RECV_PAYLOAD: + /* [--banners] + * This is an important part of the system, where the TCP + * stack passes incoming packet payloads off to the application + * layer protocol parsers. This is where, in Sockets API, you + * might call the 'recv()' function. + */ + banner_parse(socket, + payload, + payload_length + ); + break; + case APP_CLOSE: + /* The other side has sent us a FIN, therefore, we need + * to likewise close our end. */ + banner_flush(socket); + tcpapi_close(socket); + break; + case APP_RECV_TIMEOUT: + break; + case APP_SENDING: + /* A higher level protocol has started sending packets while processing + * a receive, therefore, change to the SEND state */ + tcpapi_change_app_state(socket, App_SendNext); + break; + case APP_SEND_SENT: + /* FIXME */ + break; + default: + ERRMSG("TCP.app: unhandled event: state=%s event=%s\n", + state_to_string(state), event_to_string(event)); + break; + } + break; + + case App_SendFirst: + /* This isn't called from the outside, but from one of the + * states internally whhen we transmit for the first time */ + if (stream == &banner_ssl || stream == &banner_ssl_12) { + /* + * Kludge, extreme kludge + * I don't even know what this does any longer + */ + banner_set_sslhello(socket, true); + } + + if (banner_is_heartbleed(socket)) { + /* + * Kludge, extreme kludge + * I don't even know what this does any longer + */ + banner_set_small_window(socket, true); + } + + /* + * We either have a CALLBACK that will handle the + * sending/receiving of packets, or we will send a fixed + * "probe" string that will hopefull trigger a response. + */ + if (stream && stream->transmit_hello) { + /* We have a callback function for the protocol stream that will + * craft a packet, such as maybe generate an HTTP request containing + * valid "Host:" field. */ + stream->transmit_hello(banner1, socket); + } else if (stream && stream->hello_length) { + + /* We just have a template to blindly copy some bytes onto the wire + * in order to trigger/probe for a response */ + tcpapi_send(socket, stream->hello, stream->hello_length, TCP__static); + + /* If specified, then send a FIN right after the hello data. + * This will complete a reponse faster from the server. */ + if ((stream->flags & SF__close) != 0) + tcpapi_close(socket); + } + tcpapi_change_app_state(socket, App_SendNext); + break; + case App_SendNext: + switch (event) { + case APP_SEND_SENT: + /* We've got an acknowledgement that all our data + * was sent. Therefore, change the receive state */ + tcpapi_recv(socket); + tcpapi_change_app_state(socket, App_ReceiveNext); + break; + case APP_SENDING: + break; + default: + ERRMSG("TCP.app: unhandled event: state=%s event=%s\n", + state_to_string(state), event_to_string(event)); + break; + } + break; + default: + ERRMSG("TCP.app: unhandled event: state=%s event=%s\n", + state_to_string(state), event_to_string(event)); + break; + } + return 0; +} + diff --git a/src/stack-tcp-app.h b/src/stack-tcp-app.h new file mode 100644 index 00000000..e33ddef6 --- /dev/null +++ b/src/stack-tcp-app.h @@ -0,0 +1,51 @@ +#ifndef STACK_TCP_APP_H +#define STACK_TCP_APP_H +#include +#include "util-bool.h" /* */ +struct stack_handle_t; +struct ProtocolParserStream; +struct Banner1; + + +enum App_Event { + APP_CONNECTED, + APP_RECV_TIMEOUT, + APP_RECV_PAYLOAD, + APP_SENDING, + APP_SEND_SENT, + APP_CLOSE /*FIN received */ +}; + +/** + * This is the interface between the underlying custom TCP/IP stack and + * the rest of masscan. SCRIPTING will eventually go in here. + */ +unsigned +application_event( struct stack_handle_t *socket, + unsigned state, enum App_Event event, + const struct ProtocolParserStream *stream, + struct Banner1 *banner1, + const void *payload, size_t payload_length + ); + +void +banner_set_sslhello(struct stack_handle_t *socket, bool is_true); + +void +banner_set_small_window(struct stack_handle_t *socket, bool is_true); + +bool +banner_is_heartbleed(const struct stack_handle_t *socket); + +void +banner_flush(struct stack_handle_t *socket); + +size_t +banner_parse( + struct stack_handle_t *socket, + const unsigned char *payload, + size_t payload_length + ); + +#endif + diff --git a/src/stack-tcp-core.c b/src/stack-tcp-core.c new file mode 100644 index 00000000..e1d8b6f2 --- /dev/null +++ b/src/stack-tcp-core.c @@ -0,0 +1,2319 @@ +/* + * This is the core TCP layer in the stack. It's notified of incoming + * IP datagrams containing TCP protocols. This is where the TCP state + * diagram is handled. + * + * + * +---------+ ---------\ active OPEN + * | CLOSED | \ ----------- + * +---------+<---------\ \ create TCB + * | ^ \ \ snd SYN + * passive OPEN | | CLOSE \ \ + * ------------ | | ---------- \ \ + * create TCB | | delete TCB \ \ + * V | \ \ + * +---------+ CLOSE | \ + * | LISTEN | ---------- | | + * +---------+ delete TCB | | + * rcv SYN | | SEND | | + * ----------- | | ------- | V + * +---------+ snd SYN,ACK / \ snd SYN +---------+ + * | |<----------------- ------------------>| | + * | SYN | rcv SYN | SYN | + * | RCVD |<-----------------------------------------------| SENT | + * | | snd ACK | | + * | |------------------ -------------------| | + * +---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+ + * | -------------- | | ----------- + * | x | | snd ACK + * | V V + * | CLOSE +---------+ + * | ------- | ESTAB | + * | snd FIN +---------+ + * | CLOSE | | rcv FIN + * V ------- | | ------- + * +---------+ snd FIN / \ snd ACK +---------+ + * | FIN |<----------------- ------------------>| CLOSE | + * | WAIT-1 |------------------ | WAIT | + * +---------+ rcv FIN \ +---------+ + * | rcv ACK of FIN ------- | CLOSE | + * | -------------- snd ACK | ------- | + * V x V snd FIN V + * +---------+ +---------+ +---------+ + * |FINWAIT-2| | CLOSING | | LAST-ACK| + * +---------+ +---------+ +---------+ + * | rcv ACK of FIN | rcv ACK of FIN | + * | rcv FIN -------------- | Timeout=2MSL -------------- | + * | ------- x V ------------ x V + * \ snd ACK +---------+delete TCB +---------+ + * ------------------------>|TIME WAIT|------------------>| CLOSED | + * +---------+ +---------+ + * + */ +#include "stack-tcp-core.h" +#include "stack-tcp-api.h" +#include "stack-tcp-app.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "syn-cookie.h" +#include "event-timeout.h" /* for tracking future events */ +#include "rawsock.h" +#include "util-logger.h" +#include "templ-pkt.h" +#include "pixie-timer.h" +#include "stack-queue.h" +#include "proto-banner1.h" +#include "proto-ssl.h" +#include "proto-http.h" +#include "proto-smb.h" +#include "proto-versioning.h" +#include "output.h" +#include "string_s.h" +#include "main-globals.h" +#include "crypto-base64.h" +#include "util-malloc.h" +#include "util-errormsg.h" +#include "scripting.h" + + +#ifdef _MSC_VER +#pragma warning(disable:4204) +#define snprintf _snprintf +#pragma warning(disable:4996) +#endif + +struct TCP_Segment { + unsigned seqno; + unsigned char *buf; + size_t length; + enum TCP__flags flags; + bool is_fin; /* was fin sent */ + struct TCP_Segment *next; +}; + + + +/*************************************************************************** + * A "TCP control block" is what most operating-systems/network-stack + * calls the structure that corresponds to a TCP connection. It contains + * things like the IP addresses, port numbers, sequence numbers, timers, + * and other things. + ***************************************************************************/ +struct TCP_Control_Block +{ + ipaddress ip_me; + ipaddress ip_them; + + unsigned short port_me; + unsigned short port_them; + + uint32_t seqno_me; /* next seqno I will use for transmit */ + uint32_t seqno_them; /* the next seqno I expect to receive */ + uint32_t ackno_me; + uint32_t ackno_them; + + uint32_t seqno_me_first; + uint32_t seqno_them_first; + + struct TCP_Control_Block *next; + struct TimeoutEntry timeout[1]; + + unsigned char ttl; + unsigned char syns_sent; /* reconnect */ + unsigned short mss; /* maximum segment size 1460 */ + unsigned tcpstate:4; + unsigned is_ipv6:1; + unsigned is_small_window:1; /* send with smaller window */ + unsigned is_their_fin:1; + + /** Set to true when the TCB is in-use/allocated, set to zero + * when it's about to be deleted soon */ + unsigned is_active:1; + + /* If the payload we've sent was dynamically allocated with + * malloc() from the heap, in which case we'll have to free() + * it. (Most payloads are static memory) */ + unsigned is_payload_dynamic:1; + + unsigned app_state; + + struct TCP_Segment *segments; + + /* + unsigned short payload_length; + const unsigned char *payload; + */ + time_t when_created; + + /* + * If Running a script, the thread object + */ + struct ScriptingThread *scripting_thread; + const struct ProtocolParserStream *stream; + + struct BannerOutput banout; + + struct StreamState banner1_state; + + unsigned packet_number; +}; + +struct TCP_ConnectionTable { + struct TCP_Control_Block **entries; + struct TCP_Control_Block *freed_list; + unsigned count; + unsigned mask; + unsigned timeout_connection; + unsigned timeout_hello; + + uint64_t active_count; + uint64_t entropy; + + struct Timeouts *timeouts; + struct TemplatePacket *pkt_template; + struct stack_t *stack; + + struct Banner1 *banner1; + OUTPUT_REPORT_BANNER report_banner; + struct Output *out; + + struct ScriptingVM *scripting_vm; + + /** This is for creating follow-up connections based on the first + * connection. Given an existing IP/port, it returns a different + * one for the new conenction. */ + struct { + const void *data; + void *(*cb)(const void *in_src, const ipaddress ip, unsigned port, + ipaddress *next_ip, unsigned *next_port); + } next_ip_port; +}; + +enum { + STATE_SYN_SENT=0, /* must be zero */ + //STATE_SYN_RECEIVED, + STATE_ESTABLISHED_SEND, /* our own special state, can only send */ + STATE_ESTABLISHED_RECV, /* our own special state, can only receive */ + STATE_CLOSE_WAIT, + STATE_LAST_ACK, + STATE_FIN_WAIT1_SEND, + STATE_FIN_WAIT1_RECV, + STATE_FIN_WAIT2, + STATE_CLOSING, + STATE_TIME_WAIT, +}; + +/*************************************************************************** + * DEBUG: when printing debug messages (-d option), this prints a string + * for the given state. + ***************************************************************************/ +static const char * +state_to_string(int state) +{ + static char buf[64]; + switch (state) { + //STATE_SYN_RECEIVED, + case STATE_CLOSE_WAIT: return "CLOSE-WAIT"; + case STATE_LAST_ACK: return "LAST-ACK"; + case STATE_FIN_WAIT1_SEND: return "FIN-WAIT-1-SEND"; + case STATE_FIN_WAIT1_RECV: return "FIN-WAIT-1-RECV"; + case STATE_FIN_WAIT2: return "FIN-WAIT-2"; + case STATE_CLOSING: return "CLOSING"; + case STATE_TIME_WAIT: return "TIME-WAIT"; + case STATE_SYN_SENT: return "SYN_SENT"; + case STATE_ESTABLISHED_SEND:return "ESTABLISHED_SEND"; + case STATE_ESTABLISHED_RECV:return "ESTABLISHED_RECV"; + + default: + sprintf_s(buf, sizeof(buf), "%d", state); + return buf; + } +} + +static void +vLOGtcb(const struct TCP_Control_Block *tcb, int dir, const char *fmt, va_list marker) +{ + char sz[80]; + ipaddress_formatted_t fmt1 = ipaddress_fmt(tcb->ip_them); + + snprintf(sz, sizeof(sz), "[%s:%u %4u,%4u] %s:%5u [%4u,%4u] {%s} ", + fmt1.string, tcb->port_them, + tcb->seqno_them - tcb->seqno_them_first, + tcb->ackno_me - tcb->seqno_them_first, + (dir > 0) ? "-->" : "<--", + tcb->port_me, + tcb->seqno_me - tcb->seqno_me_first, + tcb->ackno_them - tcb->seqno_me_first, + state_to_string(tcb->tcpstate) + ); + if (dir == 2) { + char *brace = strchr(sz, '{'); + memset(sz, ' ', brace-sz); + } + fprintf(stderr, "%s", sz); + vfprintf(stderr, fmt, marker); + fflush(stderr); +} +int is_tcp_debug = 0; + +static void +LOGtcb(const struct TCP_Control_Block *tcb, int dir, const char *fmt, ...) +{ + va_list marker; + + if (!is_tcp_debug) + return; + va_start(marker, fmt); + vLOGtcb(tcb, dir, fmt, marker); + va_end(marker); +} + + + +/*************************************************************************** + * Process all events, up to the current time, that need timing out. + ***************************************************************************/ +void +tcpcon_timeouts(struct TCP_ConnectionTable *tcpcon, unsigned secs, unsigned usecs) +{ + uint64_t timestamp = TICKS_FROM_TV(secs, usecs); + + for (;;) { + struct TCP_Control_Block *tcb; + enum TCB_result x; + + /* + * Get the next event that is older than the current time + */ + tcb = (struct TCP_Control_Block *)timeouts_remove(tcpcon->timeouts, + timestamp); + + /* + * If everything up to the current time has already been processed, + * then exit this loop + */ + if (tcb == NULL) + break; + + /* + * Process this timeout + */ + x = stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_TIMEOUT, + 0, 0, + secs, usecs, + tcb->seqno_them, + tcb->ackno_them); + + /* If the TCB hasn't been destroyed, then we need to make sure + * there is a timeout associated with it. KLUDGE: here is the problem: + * there must ALWAYS be a 'timeout' associated with a TCB, otherwise, + * we'll lose track of it and leak memory. In theory, this should be + * automatically handled elsewhere, but I have bugs, and it's not, + * so I put some code here as a catch-all: if the TCB hasn't been + * deleted, but hasn't been inserted back into the timeout system, + * then insert it here. */ + if (x != TCB__destroyed && timeout_is_unlinked(tcb->timeout)) { + timeouts_add( tcpcon->timeouts, + tcb->timeout, + offsetof(struct TCP_Control_Block, timeout), + TICKS_FROM_TV(secs+2, usecs)); + } + } +} + +/*************************************************************************** + ***************************************************************************/ +static int +name_equals(const char *lhs, const char *rhs) +{ + for (;;) { + while (*lhs == '-' || *lhs == '.' || *lhs == '_') + lhs++; + while (*rhs == '-' || *rhs == '.' || *rhs == '_') + rhs++; + if (*lhs == '\0' && *rhs == '[') + return 1; /*arrays*/ + if (*rhs == '\0' && *lhs == '[') + return 1; /*arrays*/ + if (tolower(*lhs & 0xFF) != tolower(*rhs & 0xFF)) + return 0; + if (*lhs == '\0') + return 1; + lhs++; + rhs++; + } +} + +/*************************************************************************** + * When setting parameters, this will parse integers from the config + * parameter strings. + ***************************************************************************/ +static uint64_t +parseInt(const void *vstr, size_t length) +{ + const char *str = (const char *)vstr; + uint64_t result = 0; + size_t i; + + for (i=0; ibanner1; + + if (name_equals(name, "http-payload")) { + char lenstr[64]; + sprintf_s(lenstr, sizeof(lenstr), "%u", (unsigned)value_length); + + banner_http.hello_length = http_change_requestline( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + (const unsigned char *)value, + value_length, + 3); /* payload*/ + + banner_http.hello_length = http_change_field( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + "Content-Length:", + (const unsigned char *)lenstr, + strlen(lenstr), + http_field_replace); + return; + } + + /* + * You can reset your user-agent here. Whenever I do a scan, I always + * reset my user-agent. That's now you know it's not me scanning + * you on the open Internet -- I would never use the default user-agent + * string built into masscan + */ + if (name_equals(name, "http-user-agent")) { + banner_http.hello_length = http_change_field( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + "User-Agent:", + (const unsigned char *)value, + value_length, + http_field_replace); + return; + } + if (name_equals(name, "http-host")) { + banner_http.hello_length = http_change_field( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + "Host:", + (const unsigned char *)value, + value_length, + http_field_replace); + return; + } + + /** + * Changes the URL + */ + if (name_equals(name, "http-method")) { + banner_http.hello_length = http_change_requestline( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + (const unsigned char *)value, + value_length, + 0); /* method*/ + return; + } + if (name_equals(name, "http-url")) { + banner_http.hello_length = http_change_requestline( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + (const unsigned char *)value, + value_length, + 1); /* url */ + return; + } + if (name_equals(name, "http-version")) { + banner_http.hello_length = http_change_requestline( + (unsigned char**)&banner_http.hello, + banner_http.hello_length, + (const unsigned char *)value, + value_length, + 2); /* version */ + return; + } + + if (name_equals(name, "timeout") || name_equals(name, "connection-timeout")) { + uint64_t n = parseInt(value, value_length); + tcpcon->timeout_connection = (unsigned)n; + LOG(1, "TCP connection-timeout = %u\n", tcpcon->timeout_connection); + return; + } + if (name_equals(name, "hello-timeout")) { + uint64_t n = parseInt(value, value_length); + tcpcon->timeout_hello = (unsigned)n; + LOG(1, "TCP hello-timeout = \"%.*s\"\n", (int)value_length, (const char *)value); + LOG(1, "TCP hello-timeout = %u\n", (unsigned)tcpcon->timeout_hello); + return; + } + + /* + * Force SSL processing on all ports + */ + if (name_equals(name, "hello") && name_equals(value, "ssl")) { + unsigned i; + + LOG(2, "HELLO: setting SSL hello message\n"); + for (i=0; i<65535; i++) { + banner1->payloads.tcp[i] = &banner_ssl; + } + + return; + } + + /* + * Force HTTP processing on all ports + */ + if (name_equals(name, "hello") && name_equals(value, "http")) { + unsigned i; + + LOG(2, "HELLO: setting HTTP hello message\n"); + for (i=0; i<65535; i++) { + banner1->payloads.tcp[i] = &banner_http; + } + + return; + } + + /* + * Downgrade SMB hello from v1/v2 to use only v1 + */ + if (name_equals(name, "hello") && name_equals(value, "smbv1")) { + smb_set_hello_v1(&banner_smb1); + return; + } + + /* + * 2014-04-08: scan for Neel Mehta's "heartbleed" bug + */ + if (name_equals(name, "heartbleed")) { + unsigned i; + + /* Change the hello message to including negotiating the use of + * the "heartbeat" extension */ + banner_ssl.hello = ssl_hello(ssl_hello_heartbeat_template); + banner_ssl.hello_length = ssl_hello_size(banner_ssl.hello); + tcpcon->banner1->is_heartbleed = 1; + + for (i=0; i<65535; i++) { + banner1->payloads.tcp[i] = &banner_ssl; + } + + return; + } + + if (name_equals(name, "ticketbleed")) { + unsigned i; + + /* Change the hello message to including negotiating the use of + * the "heartbeat" extension */ + banner_ssl.hello = ssl_hello(ssl_hello_ticketbleed_template); + banner_ssl.hello_length = ssl_hello_size(banner_ssl.hello); + tcpcon->banner1->is_ticketbleed = 1; + + for (i=0; i<65535; i++) { + banner1->payloads.tcp[i] = &banner_ssl; + } + + return; + } + + /* + * 2014-10-16: scan for SSLv3 servers (POODLE) + */ + if (name_equals(name, "poodle") || name_equals(name, "sslv3")) { + unsigned i; + void *px; + + /* Change the hello message to including negotiating the use of + * the "heartbeat" extension */ + px = ssl_hello(ssl_hello_sslv3_template); + banner_ssl.hello = ssl_add_cipherspec(px, 0x5600, 1); + banner_ssl.hello_length = ssl_hello_size(banner_ssl.hello); + tcpcon->banner1->is_poodle_sslv3 = 1; + + for (i=0; i<65535; i++) { + banner1->payloads.tcp[i] = &banner_ssl; + } + + return; + } + + + /* + * You can reconfigure the "hello" message to be anything + * you want. + */ + if (name_equals(name, "hello-string")) { + struct ProtocolParserStream *x; + const char *p = strchr(name, '['); + unsigned port; + + + if (p == NULL) { + ERRMSG("tcpcon: parameter: expected array []: %s\n", name); + return; + } + port = (unsigned)strtoul(p+1, 0, 0); + + x = CALLOC(1, sizeof(*x)); + if (banner1->payloads.tcp[port]) + memcpy(x, banner1->payloads.tcp[port], sizeof (*x)); + x->name = "(allocated)"; + + x->hello = MALLOC(value_length); + x->hello_length = base64_decode((char*)x->hello, value_length, value, value_length); + + banner1->payloads.tcp[port] = x; + } + +} + + +/*************************************************************************** + ***************************************************************************/ +void +tcpcon_set_banner_flags(struct TCP_ConnectionTable *tcpcon, + unsigned is_capture_cert, + unsigned is_capture_servername, + unsigned is_capture_html, + unsigned is_capture_heartbleed, + unsigned is_capture_ticketbleed) +{ + tcpcon->banner1->is_capture_cert = is_capture_cert; + tcpcon->banner1->is_capture_servername = is_capture_servername; + tcpcon->banner1->is_capture_html = is_capture_html; + tcpcon->banner1->is_capture_heartbleed = is_capture_heartbleed; + tcpcon->banner1->is_capture_ticketbleed = is_capture_ticketbleed; +} + +/*************************************************************************** + ***************************************************************************/ +void scripting_init_tcp(struct TCP_ConnectionTable *tcpcon, struct lua_State *L) +{ + tcpcon->banner1->L = L; + + banner_scripting.init(tcpcon->banner1); +} + +/*************************************************************************** + * Called at startup, by a receive thread, to create a TCP connection + * table. + ***************************************************************************/ +struct TCP_ConnectionTable * +tcpcon_create_table( size_t entry_count, + struct stack_t *stack, + struct TemplatePacket *pkt_template, + OUTPUT_REPORT_BANNER report_banner, + struct Output *out, + unsigned connection_timeout, + uint64_t entropy + ) +{ + struct TCP_ConnectionTable *tcpcon; + + + tcpcon = CALLOC(1, sizeof(*tcpcon)); + tcpcon->timeout_connection = connection_timeout; + if (tcpcon->timeout_connection == 0) + tcpcon->timeout_connection = 30; /* half a minute before destroying tcb */ + tcpcon->timeout_hello = 2; + tcpcon->entropy = entropy; + + /* Find nearest power of 2 to the tcb count, but don't go + * over the number 16-million */ + { + size_t new_entry_count; + new_entry_count = 1; + while (new_entry_count < entry_count) { + new_entry_count *= 2; + if (new_entry_count == 0) { + new_entry_count = (1<<24); + break; + } + } + if (new_entry_count > (1<<24)) + new_entry_count = (1<<24); + if (new_entry_count < (1<<10)) + new_entry_count = (1<<10); + entry_count = new_entry_count; + } + + /* Create the table. If we can't allocate enough memory, then shrink + * the desired size of the table */ + while (tcpcon->entries == 0) { + tcpcon->entries = malloc(entry_count * sizeof(*tcpcon->entries)); + if (tcpcon->entries == NULL) { + entry_count >>= 1; + } + } + memset(tcpcon->entries, 0, entry_count * sizeof(*tcpcon->entries)); + + + /* fill in the table structure */ + tcpcon->count = (unsigned)entry_count; + tcpcon->mask = (unsigned)(entry_count-1); + + /* create an event/timeouts structure */ + tcpcon->timeouts = timeouts_create(TICKS_FROM_SECS(time(0))); + + + tcpcon->pkt_template = pkt_template; + + tcpcon->stack = stack; + + + tcpcon->banner1 = banner1_create(); + + tcpcon->report_banner = report_banner; + tcpcon->out = out; + return tcpcon; +} + +static int TCB_EQUALS(const struct TCP_Control_Block *lhs, const struct TCP_Control_Block *rhs) +{ + if (lhs->port_me != rhs->port_me || lhs->port_them != rhs->port_them) + return 0; + if (lhs->ip_me.version != rhs->ip_me.version) + return 0; + if (lhs->ip_me.version == 6) { + if (memcmp(&lhs->ip_me.ipv6, &rhs->ip_me.ipv6, sizeof(rhs->ip_me.ipv6)) != 0) + return 0; + if (memcmp(&lhs->ip_them.ipv6, &rhs->ip_them.ipv6, sizeof(rhs->ip_them.ipv6)) != 0) + return 0; + } else { + if (lhs->ip_me.ipv4 != rhs->ip_me.ipv4) + return 0; + if (lhs->ip_them.ipv4 != rhs->ip_them.ipv4) + return 0; + } + + return 1; +} + +/*************************************************************************** + ***************************************************************************/ +static void +_tcb_change_state_to(struct TCP_Control_Block *tcb, unsigned new_state) { + + LOGtcb(tcb, 2, "to {%s}\n", state_to_string(new_state)); + tcb->tcpstate = new_state; +} + +/*************************************************************************** + ***************************************************************************/ +static unsigned +tcb_hash( ipaddress ip_me, unsigned port_me, + ipaddress ip_them, unsigned port_them, + uint64_t entropy) +{ + unsigned index; + + /* TCB hash table uses symmetric hash, so incoming/outgoing packets + * get the same hash. */ + if (ip_me.version == 6) { + ipv6address ipv6 = ip_me.ipv6; + ipv6.hi ^= ip_them.ipv6.hi; + ipv6.lo ^= ip_them.ipv6.lo; + index = (unsigned)syn_cookie_ipv6( + ipv6, + port_me ^ port_them, + ipv6, + port_me ^ port_them, + entropy); + + } else { + index = (unsigned)syn_cookie_ipv4( ip_me.ipv4 ^ ip_them.ipv4, + port_me ^ port_them, + ip_me.ipv4 ^ ip_them.ipv4, + port_me ^ port_them, + entropy + ); + } + return index; +} + +enum DestroyReason { + Reason_Timeout = 1, + Reason_FIN = 2, + Reason_RST = 3, + Reason_Foo = 4, + Reason_Shutdown = 5, + Reason_StateDone = 6, + +}; + +/*************************************************************************** + * Flush all the banners associated with this TCP connection. This always + * called when TCB is destroyed. This may also be called earlier, such + * as when a FIN is received. + ***************************************************************************/ +void +banner_flush(struct stack_handle_t *socket) +{ + struct TCP_ConnectionTable *tcpcon = socket->tcpcon; + struct TCP_Control_Block *tcb = socket->tcb; + struct BannerOutput *banout; + + /* Go through and print all the banners. Some protocols have + * multiple banners. For example, web servers have both + * HTTP and HTML banners, and SSL also has several + * X.509 certificate banners */ + for (banout = &tcb->banout; banout != NULL; banout = banout->next) { + if (banout->length && banout->protocol) { + tcpcon->report_banner( + tcpcon->out, + global_now, + tcb->ip_them, + 6, /*TCP protocol*/ + tcb->port_them, + banout->protocol & 0x0FFFFFFF, + tcb->ttl, + banout->banner, + banout->length); + } + } + + /* + * Free up all the banners. + */ + banout_release(&tcb->banout); + +} + +/*************************************************************************** + * Destroy a TCP connection entry. We have to unlink both from the + * TCB-table as well as the timeout-table. + * Called from + ***************************************************************************/ +static void +tcpcon_destroy_tcb( + struct TCP_ConnectionTable *tcpcon, + struct TCP_Control_Block *tcb, + enum DestroyReason reason) +{ + unsigned index; + struct TCP_Control_Block **r_entry; + + UNUSEDPARM(reason); + + /* + * The TCB doesn't point to it's location in the table. Therefore, we + * have to do a lookup to find the head pointer in the table. + */ + index = tcb_hash( tcb->ip_me, tcb->port_me, + tcb->ip_them, tcb->port_them, + tcpcon->entropy); + + /* + * At this point, we have the head of a linked list of TCBs. Now, + * traverse that linked list until we find our TCB + */ + r_entry = &tcpcon->entries[index & tcpcon->mask]; + while (*r_entry && *r_entry != tcb) + r_entry = &(*r_entry)->next; + + if (*r_entry == NULL) { + LOG(1, "tcb: double free\n"); + return; + } + + /* + * Print out any banners associated with this TCP session. Most of the + * time, there'll only be one. After printing them out, delete the + * banners. + */ + { + struct stack_handle_t socket[1] = {tcpcon, tcb, 0, 0}; + banner_flush(socket); + } + + LOGtcb(tcb, 2, "--DESTROYED--\n"); + + /* + * If there are any queued segments to transmit, then free them + */ + while (tcb->segments) { + struct TCP_Segment *seg; + seg = tcb->segments; + tcb->segments = seg->next; + if (seg->flags == TCP__copy || seg->flags == TCP__adopt) { + free(seg->buf); + seg->buf = 0; + } + free(seg); + } + + if (tcb->scripting_thread) + ; //scripting_thread_close(tcb->scripting_thread); + tcb->scripting_thread = 0; + + /* KLUDGE: this needs to be made elegant */ + switch (tcb->banner1_state.app_proto) { + case PROTO_SMB: + banner_smb1.cleanup(&tcb->banner1_state); + break; + } + + /* + * Unlink this from the timeout system. + */ + timeout_unlink(tcb->timeout); + + tcb->ip_them.ipv4 = (unsigned)~0; + tcb->port_them = (unsigned short)~0; + tcb->ip_me.ipv4 = (unsigned)~0; + tcb->port_me = (unsigned short)~0; + + tcb->is_active = 0; + + + + + (*r_entry) = tcb->next; + tcb->next = tcpcon->freed_list; + tcpcon->freed_list = tcb; + tcpcon->active_count--; +} + + +/*************************************************************************** + * Called at shutdown to free up all the memory used by the TCP + * connection table. + ***************************************************************************/ +void +tcpcon_destroy_table(struct TCP_ConnectionTable *tcpcon) +{ + unsigned i; + + if (tcpcon == NULL) + return; + + /* + * Do a graceful destruction of all the entires. If they have banners, + * they will be sent to the output + */ + for (i=0; i<=tcpcon->mask; i++) { + while (tcpcon->entries[i]) + tcpcon_destroy_tcb(tcpcon, tcpcon->entries[i], Reason_Shutdown); + } + + /* + * Now free the memory + */ + while (tcpcon->freed_list) { + struct TCP_Control_Block *tcb = tcpcon->freed_list; + tcpcon->freed_list = tcb->next; + free(tcb); + } + + banner1_destroy(tcpcon->banner1); + free(tcpcon->entries); + free(tcpcon); +} + + +/*************************************************************************** + * + * Called when we receive a "SYN-ACK" packet with the correct SYN-cookie. + * + ***************************************************************************/ +struct TCP_Control_Block * +tcpcon_create_tcb( + struct TCP_ConnectionTable *tcpcon, + ipaddress ip_me, ipaddress ip_them, + unsigned port_me, unsigned port_them, + unsigned seqno_me, unsigned seqno_them, + unsigned ttl, + const struct ProtocolParserStream *stream, + unsigned secs, unsigned usecs) +{ + unsigned index; + struct TCP_Control_Block tmp; + struct TCP_Control_Block *tcb; + + + assert(ip_me.version != 0 && ip_them.version != 0); + + tmp.ip_me = ip_me; + tmp.ip_them = ip_them; + tmp.port_me = (unsigned short)port_me; + tmp.port_them = (unsigned short)port_them; + + /* Lookup the location in the hash table where this tcb should be + * placed */ + index = tcb_hash(ip_me, port_me, ip_them, port_them, tcpcon->entropy); + tcb = tcpcon->entries[index & tcpcon->mask]; + while (tcb && !TCB_EQUALS(tcb, &tmp)) { + tcb = tcb->next; + } + if (tcb != NULL) { + /* If it already exists, just return the existing one */ + return tcb; + } + + /* Allocate a new TCB, using a pool */ + if (tcpcon->freed_list) { + tcb = tcpcon->freed_list; + tcpcon->freed_list = tcb->next; + } else { + tcb = MALLOC(sizeof(*tcb)); + } + memset(tcb, 0, sizeof(*tcb)); + + /* Add it to this spot in the hash table */ + tcb->next = tcpcon->entries[index & tcpcon->mask]; + tcpcon->entries[index & tcpcon->mask] = tcb; + + /* + * Initialize the entry + */ + tcb->ip_me = ip_me; + tcb->ip_them = ip_them; + tcb->port_me = (unsigned short)port_me; + tcb->port_them = (unsigned short)port_them; + tcb->seqno_them_first = seqno_them; + tcb->seqno_me_first = seqno_me; + tcb->seqno_me = seqno_me; + tcb->seqno_them = seqno_them; + tcb->ackno_me = seqno_them; + tcb->ackno_them = seqno_me; + tcb->when_created = global_now; + tcb->ttl = (unsigned char)ttl; + tcb->mss = 1400; + + /* Insert the TCB into the timeout. A TCB must always have a timeout + * active. */ + timeout_init(tcb->timeout); + timeouts_add(tcpcon->timeouts, + tcb->timeout, + offsetof(struct TCP_Control_Block, timeout), + TICKS_FROM_TV(secs+1,usecs) + ); + + /* Get the protocol handler assigned to this port */ + tcb->banner1_state.port = (unsigned short)port_them; + if (stream == NULL) { + struct Banner1 *banner1 = tcpcon->banner1; + stream = banner1->payloads.tcp[port_them]; + } + tcb->stream = stream; + banout_init(&tcb->banout); + + /* The TCB is now allocated/in-use */ + assert(tcb->ip_me.version != 0 && tcb->ip_them.version != 0); + tcb->is_active = 1; + + tcpcon->active_count++; + + tcpcon_lookup_tcb(tcpcon, ip_me, ip_them, port_me, port_them); + + return tcb; +} + + + +/*************************************************************************** + ***************************************************************************/ +struct TCP_Control_Block * +tcpcon_lookup_tcb( + struct TCP_ConnectionTable *tcpcon, + ipaddress ip_me, ipaddress ip_them, + unsigned port_me, unsigned port_them) +{ + unsigned index; + struct TCP_Control_Block tmp; + struct TCP_Control_Block *tcb; + ipaddress_formatted_t fmt1; + ipaddress_formatted_t fmt2; + + tmp.ip_me = ip_me; + tmp.ip_them = ip_them; + tmp.port_me = (unsigned short)port_me; + tmp.port_them = (unsigned short)port_them; + + index = tcb_hash(ip_me, port_me, ip_them, port_them, tcpcon->entropy); + + fmt1 = ipaddress_fmt(ip_me); + fmt2 = ipaddress_fmt(ip_them); + LOG(1, "tcb_hash(0x%08x) = %s %u %s %u\n", + (unsigned)index, + fmt1.string, port_me, + fmt2.string, port_them); + + /* Hash to an entry in the table, then follow a linked list from + * that point forward. */ + tcb = tcpcon->entries[index & tcpcon->mask]; + while (tcb && !TCB_EQUALS(tcb, &tmp)) { + tcb = tcb->next; + } + + + return tcb; +} + + +/*************************************************************************** + ***************************************************************************/ +static void +tcpcon_send_packet( + struct TCP_ConnectionTable *tcpcon, + struct TCP_Control_Block *tcb, + unsigned tcp_flags, + const unsigned char *payload, size_t payload_length) +{ + struct PacketBuffer *response = 0; + unsigned is_syn = (tcp_flags == 0x02); + + assert(tcb->ip_me.version != 0 && tcb->ip_them.version != 0); + + /* If sending an ACK, print a message */ + if ((tcp_flags & 0x10) == 0x10) { + LOGtcb(tcb, 0, "xmit ACK ackingthem=%u\n", tcb->seqno_them-tcb->seqno_them_first); + } + + /* Get a buffer for sending the response packet. This thread doesn't + * send the packet itself. Instead, it formats a packet, then hands + * that packet off to a transmit thread for later transmission. */ + response = stack_get_packetbuffer(tcpcon->stack); + if (response == NULL) { + static int is_warning_printed = 0; + if (!is_warning_printed) { + LOG(0, "packet buffers empty (should be impossible)\n"); + is_warning_printed = 1; + } + fflush(stdout); + + /* FIXME: I'm no sure the best way to handle this. + * This would result from a bug in the code, + * but I'm not sure what should be done in response */ + pixie_usleep(100); /* no packet available */ + } + if (response == NULL) + return; + + /* Format the packet as requested. Note that there are really only + * four types of packets: + * 1. a SYN-ACK packet with no payload + * 2. an ACK packet with no payload + * 3. a RST packet with no payload + * 4. a PSH-ACK packet WITH PAYLOAD + */ + response->length = tcp_create_packet( + tcpcon->pkt_template, + tcb->ip_them, tcb->port_them, + tcb->ip_me, tcb->port_me, + tcb->seqno_me - is_syn, tcb->seqno_them, + tcp_flags, + payload, payload_length, + response->px, sizeof(response->px) + ); + + /* + * KLUDGE: + */ + if (tcb->is_small_window) + tcp_set_window(response->px, response->length, 600); + + /* Put this buffer on the transmit queue. Remember: transmits happen + * from a transmit-thread only, and this function is being called + * from a receive-thread. Therefore, instead of transmiting ourselves, + * we hae to queue it up for later transmission. */ + stack_transmit_packetbuffer(tcpcon->stack, response); + + if ((tcp_flags & 0x01) == 0x10) { + LOGtcb(tcb, 0, "xmit FIN myseqno=%u\n", tcb->seqno_me-tcb->seqno_me_first + payload_length); + } + +} + +/*************************************************************************** + ***************************************************************************/ +void +tcp_send_RST( + struct TemplatePacket *templ, + struct stack_t *stack, + ipaddress ip_them, ipaddress ip_me, + unsigned port_them, unsigned port_me, + unsigned seqno_them, unsigned seqno_me +) +{ + struct PacketBuffer *response = 0; + + + /* Get a buffer for sending the response packet. This thread doesn't + * send the packet itself. Instead, it formats a packet, then hands + * that packet off to a transmit thread for later transmission. */ + response = stack_get_packetbuffer(stack); + if (response == NULL) { + static int is_warning_printed = 0; + if (!is_warning_printed) { + LOG(0, "packet buffers empty (should be impossible)\n"); + is_warning_printed = 1; + } + fflush(stdout); + pixie_usleep(100); /* no packet available */ + } + if (response == NULL) + return; + + response->length = tcp_create_packet( + templ, + ip_them, port_them, + ip_me, port_me, + seqno_me, seqno_them, + 0x04, /*RST*/ + 0, 0, + response->px, sizeof(response->px) + ); + + + /* Put this buffer on the transmit queue. Remember: transmits happen + * from a transmit-thread only, and this function is being called + * from a receive-thread. Therefore, instead of transmitting ourselves, + * we have to queue it up for later transmission. */ + stack_transmit_packetbuffer(stack, response); +} + + +/*************************************************************************** + * DEBUG: when printing debug messages (-d option), this prints a string + * for the given state. + ***************************************************************************/ +static const char * +what_to_string(enum TCP_What state) +{ + static char buf[64]; + switch (state) { + case TCP_WHAT_TIMEOUT: return "TIMEOUT"; + case TCP_WHAT_SYNACK: return "SYNACK"; + case TCP_WHAT_RST: return "RST"; + case TCP_WHAT_FIN: return "FIN"; + case TCP_WHAT_ACK: return "ACK"; + case TCP_WHAT_DATA: return "DATA"; + case TCP_WHAT_CLOSE: return "CLOSE"; + default: + sprintf_s(buf, sizeof(buf), "%d", state); + return buf; + } +} + + +/*************************************************************************** + ***************************************************************************/ + +static void +LOGSEND(struct TCP_Control_Block *tcb, const char *what) +{ + if (tcb == NULL) + return; + LOGip(5, tcb->ip_them, tcb->port_them, "=%s : --->> %s \n", + state_to_string(tcb->tcpstate), + what); +} + + + +void +tcpcon_send_RST( + struct TCP_ConnectionTable *tcpcon, + ipaddress ip_me, ipaddress ip_them, + unsigned port_me, unsigned port_them, + uint32_t seqno_them, uint32_t ackno_them) +{ + struct TCP_Control_Block tcb; + + memset(&tcb, 0, sizeof(tcb)); + + tcb.ip_me = ip_me; + tcb.ip_them = ip_them; + tcb.port_me = (unsigned short)port_me; + tcb.port_them = (unsigned short)port_them; + tcb.seqno_me = ackno_them; + tcb.ackno_me = seqno_them + 1; + tcb.seqno_them = seqno_them + 1; + tcb.ackno_them = ackno_them; + + LOGSEND(&tcb, "send RST"); + tcpcon_send_packet(tcpcon, &tcb, 0x04 /*RST*/, 0, 0); +} + + +/*************************************************************************** + * Called upon timeouts when an acknowledgement hasn't been received in + * time. Will resend the segments. + ***************************************************************************/ +static void +_tcb_seg_resend(struct TCP_ConnectionTable *tcpcon, struct TCP_Control_Block *tcb) { + struct TCP_Segment *seg = tcb->segments; + + if (seg) { + if (tcb->seqno_me != seg->seqno) { + ERRMSG("SEQNO FAILURE diff=%d %s\n", tcb->seqno_me - seg->seqno, seg->is_fin?"FIN":""); + return; + } + + if (seg->is_fin && seg->length == 0) { + tcpcon_send_packet(tcpcon, tcb, + 0x11, /*FIN-ACK*/ + 0, /*FIN has no data */ + 0 /*logically is 1 byte, but not payload byte */); + } else { + tcpcon_send_packet(tcpcon, tcb, + 0x18 | (seg->is_fin?0x01:0x00), + seg->buf, + seg->length); + } + } + +} + +/*************************************************************************** + ***************************************************************************/ +static unsigned +application_notify(struct TCP_ConnectionTable *tcpcon, + struct TCP_Control_Block *tcb, + enum App_Event event, const void *payload, size_t payload_length, + unsigned secs, unsigned usecs) +{ + struct Banner1 *banner1 = tcpcon->banner1; + const struct ProtocolParserStream *stream = tcb->stream; + struct stack_handle_t socket[1] = { + tcpcon, tcb, secs, usecs}; + + return application_event(socket, + tcb->app_state, event, + stream, banner1, + payload, payload_length + ); +} + + +/*************************************************************************** + ***************************************************************************/ +static void +_tcb_seg_send(void *in_tcpcon, void *in_tcb, + const void *buf, size_t length, + enum TCP__flags flags) { + + struct TCP_ConnectionTable *tcpcon = (struct TCP_ConnectionTable *)in_tcpcon; + struct TCP_Control_Block *tcb = (struct TCP_Control_Block *)in_tcb; + struct TCP_Segment *seg; + struct TCP_Segment **next; + unsigned seqno = tcb->seqno_me; + size_t length_more = 0; + bool is_fin = (flags == TCP__close_fin); + + if (length > tcb->mss) { + length_more = length - tcb->mss; + length = tcb->mss; + } + + + if (length == 0 && !is_fin) + return; + + /* Go to the end of the segment list */ + for (next = &tcb->segments; *next; next = &(*next)->next) { + seqno = (unsigned)((*next)->seqno + (*next)->length); + if ((*next)->is_fin) { + /* can't send past a FIN */ + LOGip(0, tcb->ip_them, tcb->port_them, "can't send past a FIN\n"); + if (flags == TCP__adopt) { + free((void*)buf); /* discard const */ + buf = NULL; + } + return; + } + } + + /* Append this segment to the list */ + seg = calloc(1, sizeof(*seg)); + *next = seg; + + /* Fill in this segment's members */ + seg->seqno = seqno; + seg->length = length; + seg->flags = flags; + switch (flags) { + case TCP__static: + case TCP__adopt: + seg->buf = (void *)buf; + break; + case TCP__copy: + seg->buf = malloc(length); + memcpy(seg->buf, buf, length); + break; + case TCP__close_fin: + seg->buf = 0; + break; + } + if (length_more == 0) + seg->is_fin = is_fin; + + if (!seg->is_fin && seg->length && tcb->tcpstate != STATE_ESTABLISHED_SEND) + application_notify(tcpcon, tcb, APP_SENDING, seg->buf, seg->length, 0, 0); + + LOGtcb(tcb, 0, "send = %u-bytes %s @ %u\n", length, is_fin?"FIN":"", + seg->seqno-tcb->seqno_me_first); + + + + /* If this is the head of the segment list, then transmit right away */ + if (tcb->segments == seg) { + LOGtcb(tcb, 0, "xmit = %u-bytes %s @ %u\n", length, is_fin?"FIN":"", + seg->seqno-tcb->seqno_me_first); + tcpcon_send_packet(tcpcon, tcb, 0x18 | (is_fin?1:0), seg->buf, seg->length); + if (!is_fin) + _tcb_change_state_to(tcb, STATE_ESTABLISHED_SEND); + } + + /* If the input buffer was too large to fit a single segment, then + * split it up into multiple segments */ + if (length_more) { + if (flags == TCP__adopt) + flags = TCP__copy; + + _tcb_seg_send(tcpcon, tcb, + (unsigned char*)buf + length, length_more, + flags); + } + + //tcb->established = App_SendNext; + +} + +/*************************************************************************** + ***************************************************************************/ +static int +_tcp_seg_acknowledge( + struct TCP_Control_Block *tcb, + uint32_t ackno) +{ + + /*LOG(4, "%s - %u-sending, %u-reciving\n", + fmt.string, + tcb->seqno_me - ackno, + ackno - tcb->ackno_them + );*/ + /* Normal: just discard repeats */ + if (ackno == tcb->seqno_me) { + return 0; + } + + /* Make sure this isn't a duplicate ACK from past + * WRAPPING of 32-bit arithmetic happens here */ + if (ackno - tcb->seqno_me > 100000) { + ipaddress_formatted_t fmt = ipaddress_fmt(tcb->ip_them); + LOG(4, "%s - " + "tcb: ackno from past: " + "old ackno = 0x%08x, this ackno = 0x%08x\n", + fmt.string, + tcb->ackno_me, ackno); + return 0; + } + + /* Make sure this isn't invalid ACK from the future + * WRAPPING of 32-bit arithmetic happens here */ + if (tcb->seqno_me - ackno < 100000) { + ipaddress_formatted_t fmt = ipaddress_fmt(tcb->ip_them); + LOG(0, "%s - " + "tcb: ackno from future: " + "my seqno = 0x%08x, their ackno = 0x%08x\n", + fmt.string, + tcb->seqno_me, ackno); + return 0; + } + + /* Handle FIN specially */ +handle_fin: + if (tcb->segments && tcb->segments->is_fin) { + struct TCP_Segment *seg = tcb->segments; + + if (seg->seqno+1 == ackno) { + LOGtcb(tcb, 1, "ACKed FIN\n"); + tcb->seqno_me += 1; + tcb->ackno_them += 1; + return 1; + } else if (seg->seqno == ackno) { + return 0; + } else { + LOGtcb(tcb, 1, "@@@@@BAD ACK of FIN@@@@\n", seg->length); + return 0; + } + } + + /* Retire outstanding segments */ + { + unsigned length = ackno - tcb->seqno_me; + while (tcb->segments && length >= tcb->segments->length) { + struct TCP_Segment *seg = tcb->segments; + + if (seg->is_fin) + goto handle_fin; + + tcb->segments = seg->next; + + length -= seg->length; + tcb->seqno_me += seg->length; + tcb->ackno_them += seg->length; + + LOGtcb(tcb, 1, "ACKed %u-bytes\n", seg->length); + + /* free the old segment */ + switch (seg->flags) { + case TCP__static: + break; + case TCP__adopt: + case TCP__copy: + if (seg->buf) { + free(seg->buf); + seg->buf = NULL; + } + break; + default: + ; + } + free(seg); + if (ackno == tcb->ackno_them) + return 1; /* good ACK */ + } + + if (tcb->segments && length < tcb->segments->length) { + struct TCP_Segment *seg = tcb->segments; + + tcb->seqno_me += length + seg->is_fin; + tcb->ackno_them += length + seg->is_fin; + LOGtcb(tcb, 1, "ACKed %u-bytes %s\n", length, seg->is_fin?"FIN":""); + + /* This segment needs to be reduced */ + if (seg->flags == TCP__adopt || seg->flags == TCP__copy) { + size_t new_length = seg->length - length; + unsigned char *buf = malloc(new_length); + memcpy(buf, seg->buf + length, new_length); + free(seg->buf); + seg->buf = buf; + seg->length -= length; + seg->flags = TCP__copy; + } else { + seg->buf += length; + } + + } + } + + /* Mark that this was a good ack */ + return 1; +} + + +void +banner_set_sslhello(struct stack_handle_t *socket, bool is_true) { + struct TCP_Control_Block *tcb = socket->tcb; + tcb->banner1_state.is_sent_sslhello = is_true; +} + +void +banner_set_small_window(struct stack_handle_t *socket, bool is_true) { + struct TCP_Control_Block *tcb = socket->tcb; + tcb->is_small_window = is_true; +} + +bool +banner_is_heartbleed(const struct stack_handle_t *socket) { + struct TCP_ConnectionTable *tcpcon = socket->tcpcon; + return tcpcon->banner1->is_heartbleed != 0; +} + +/*************************************************************************** + * Parse the information we get from the server we are scanning. Typical + * examples are SSH banners, FTP banners, or the response from HTTP + * requests + ***************************************************************************/ +size_t +banner_parse( + struct stack_handle_t *socket, + const unsigned char *payload, + size_t payload_length + ) +{ + struct TCP_ConnectionTable *tcpcon = socket->tcpcon; + struct TCP_Control_Block *tcb = socket->tcb; + assert(tcb->banout.max_length); + + banner1_parse( + tcpcon->banner1, + &tcb->banner1_state, + payload, + payload_length, + &tcb->banout, + socket); + return payload_length; +} + + + + +/*************************************************************************** + ***************************************************************************/ +static void +_next_IP_port(struct TCP_ConnectionTable *tcpcon, + ipaddress *ip_me, + unsigned *port_me) { + const struct stack_src_t *src = tcpcon->stack->src; + unsigned index; + + /* Get another source port, because we can't use the existing + * one for new connection */ + index = *port_me - src->port.first + 1; + *port_me = src->port.first + index; + if (*port_me >= src->port.last) { + *port_me = src->port.first; + + /* We've wrapped the ports, so therefore choose another source + * IP address as well. */ + switch (ip_me->version) { + case 4: + index = ip_me->ipv4 - src->ipv4.first + 1; + ip_me->ipv4 = src->ipv4.first + index; + if (ip_me->ipv4 >= src->ipv4.last) + ip_me->ipv4 = src->ipv4.first; + break; + case 6: { + /* TODO: this code is untested, yolo */ + ipv6address_t diff; + + diff = ipv6address_subtract(ip_me->ipv6, src->ipv6.first); + diff = ipv6address_add_uint64(diff, 1); + ip_me->ipv6 = ipv6address_add(src->ipv6.first, diff); + if (ipv6address_is_lessthan(src->ipv6.last, ip_me->ipv6)) + ip_me->ipv6 = src->ipv6.first; + break; + } + default: + break; + } + } + +} + +/*************************************************************************** + ***************************************************************************/ +static void +_do_reconnect(struct TCP_ConnectionTable *tcpcon, + const struct TCP_Control_Block *old_tcb, + const struct ProtocolParserStream *stream, + unsigned secs, unsigned usecs, + unsigned established) { + struct TCP_Control_Block *new_tcb; + + ipaddress ip_them = old_tcb->ip_them; + unsigned port_them = old_tcb->port_them; + ipaddress ip_me = old_tcb->ip_me; + unsigned port_me = old_tcb->port_me; + unsigned seqno; + + + /* + * First, get another port number and potentially ip address + */ + { + ipaddress prev_ip = ip_me; + unsigned prev_port = port_me; + _next_IP_port(tcpcon, &ip_me, &port_me); + + if (ipaddress_is_equal(ip_me, prev_ip) && port_me == prev_port) + ERRMSG("There must be multiple source ports/addresses for reconnection\n"); + + } + + /* + * Calculate the SYN cookie, the same algorithm as for when spewing + * SYN packets. However, since we'll probably be using a different + * port or IP address, it'll be different in practice. + */ + seqno = (unsigned)syn_cookie(ip_them, port_them, + ip_me, port_me, + tcpcon->entropy); + + /* + * Now create a new TCB for this new connection + */ + new_tcb = tcpcon_create_tcb( + tcpcon, + ip_me, ip_them, + port_me, port_them, + seqno+1, 0, + 255, + stream, + secs, usecs); + new_tcb->app_state = established; +} + +static void +_tcb_seg_close(void *in_tcpcon, + void *in_tcb, + unsigned secs, unsigned usecs) { + struct TCP_ConnectionTable *tcpcon = (struct TCP_ConnectionTable *)in_tcpcon; + struct TCP_Control_Block *tcb = (struct TCP_Control_Block *)in_tcb; + + stack_incoming_tcp(tcpcon, tcb, + TCP_WHAT_CLOSE, + 0, 0, + secs, usecs, + tcb->seqno_them, tcb->ackno_them); +} + +/*************************************************************************** + ***************************************************************************/ +int +tcpapi_set_timeout(struct stack_handle_t *socket, + unsigned secs, + unsigned usecs + ) { + struct TCP_ConnectionTable *tcpcon = socket->tcpcon; + struct TCP_Control_Block *tcb = socket->tcb; + + if (socket == NULL) + return SOCKERR_EBADF; + + timeouts_add(tcpcon->timeouts, + tcb->timeout, + offsetof(struct TCP_Control_Block, timeout), + TICKS_FROM_TV(socket->secs+secs, socket->usecs + usecs) + ); + return 0; +} + + +/*************************************************************************** + ***************************************************************************/ +int +tcpapi_recv(struct stack_handle_t *socket) { + struct TCP_Control_Block *tcb; + + if (socket == 0 || socket->tcb == 0) + return SOCKERR_EBADF; + tcb = socket->tcb; + + switch (tcb->tcpstate) { + default: + case STATE_ESTABLISHED_SEND: + _tcb_change_state_to(socket->tcb, STATE_ESTABLISHED_RECV); + break; + case STATE_FIN_WAIT1_RECV: + _tcb_change_state_to(socket->tcb, STATE_FIN_WAIT1_RECV); + break; + case STATE_FIN_WAIT1_SEND: + _tcb_change_state_to(socket->tcb, STATE_FIN_WAIT1_RECV); + break; + } + return 0; +} + +int +tcpapi_send(struct stack_handle_t *socket, + const void *buf, size_t length, + enum TCP__flags flags) { + struct TCP_Control_Block *tcb; + + if (socket == 0 || socket->tcb == 0) + return SOCKERR_EBADF; + + tcb = socket->tcb; + switch (tcb->tcpstate) { + case STATE_ESTABLISHED_RECV: + _tcb_change_state_to(tcb, STATE_ESTABLISHED_SEND); + /*follow through*/ + case STATE_ESTABLISHED_SEND: + _tcb_seg_send(socket->tcpcon, tcb, buf, length, flags); + return 0; + default: + LOG(1, "TCP app attempted SEND in wrong state\n"); + return 1; + } +} + +int +tcpapi_reconnect(struct stack_handle_t *old_socket, + struct ProtocolParserStream *new_stream, + unsigned new_app_state) { + if (old_socket == 0 || old_socket->tcb == 0) + return SOCKERR_EBADF; + + _do_reconnect(old_socket->tcpcon, + old_socket->tcb, + new_stream, + old_socket->secs, old_socket->usecs, + new_app_state); + return 0; +} + +unsigned +tcpapi_change_app_state(struct stack_handle_t *socket, unsigned new_app_state) { + struct TCP_Control_Block *tcb; + + if (socket == 0 || socket->tcb == 0) + return SOCKERR_EBADF; + + tcb = socket->tcb; + + //printf("%u --> %u\n", tcb->app_state, new_app_state); + + tcb->app_state = new_app_state; + return new_app_state; +} + + +int +tcpapi_close(struct stack_handle_t *socket) { + if (socket == NULL || socket->tcb == NULL) + return SOCKERR_EBADF; + _tcb_seg_close(socket->tcpcon, + socket->tcb, + socket->secs, + socket->usecs); + return 0; +} + + + +static bool +_tcb_they_have_acked_my_fin(struct TCP_Control_Block *tcb) { + if (tcb->segments && tcb->segments->is_fin && tcb->segments->length == 0) { + if (tcb->ackno_them >= tcb->segments->seqno + 1) + return true; + return false; + } else + return false; +} + + +static void +_tcb_send_ack(struct TCP_ConnectionTable *tcpcon, struct TCP_Control_Block *tcb) { + tcpcon_send_packet(tcpcon, tcb, 0x10, 0, 0); +} + + + +static int +_tcb_seg_recv(struct TCP_ConnectionTable *tcpcon, + struct TCP_Control_Block *tcb, + const unsigned char *payload, size_t payload_length, + unsigned seqno_them, + unsigned secs, unsigned usecs, + bool is_fin) +{ + /* Special case when packet contains only a FIN */ + if (payload_length == 0 && is_fin && (tcb->seqno_them - seqno_them) == 0) { + tcb->is_their_fin = 1; + tcb->seqno_them += 1; + tcb->ackno_me += 1; + tcpcon_send_packet(tcpcon, tcb, 0x10/*ACK*/, 0, 0); + return 1; + } + + + if ((tcb->seqno_them - seqno_them) > payload_length) { + LOGSEND(tcb, "peer(ACK) [acknowledge payload 1]"); + tcpcon_send_packet(tcpcon, tcb, 0x10 /*ACK*/, 0, 0); + return 1; + } + + while (seqno_them != tcb->seqno_them && payload_length) { + seqno_them++; + payload_length--; + payload++; + } + + if (tcb->is_their_fin) { + /* payload cannot be received after a FIN */ + return 1; + } + + if (payload_length == 0) { + tcpcon_send_packet(tcpcon, tcb, 0x10/*ACK*/, 0, 0); + return 1; + } + + LOGtcb(tcb, 2, "received %u bytes\n", payload_length); + + tcb->seqno_them += payload_length + is_fin; + tcb->ackno_me += payload_length + is_fin; + + application_notify(tcpcon, tcb, APP_RECV_PAYLOAD, + payload, payload_length, secs, usecs); + + + + if (is_fin) + tcb->is_their_fin = true; + + /* Send ack for the data */ + _tcb_send_ack(tcpcon, tcb); + + return 0; +} + +/***************************************************************************** + * Handles incoming events, like timeouts and packets, that cause a change + * in the TCP control block "state". + * + * This is the part of the code that implements the famous TCP state-machine + * you see drawn everywhere, where they have states like "TIME_WAIT". Only + * we don't really have those states. + *****************************************************************************/ +enum TCB_result +stack_incoming_tcp(struct TCP_ConnectionTable *tcpcon, + struct TCP_Control_Block *tcb, + enum TCP_What what, const unsigned char *payload, size_t payload_length, + unsigned secs, unsigned usecs, + unsigned seqno_them, unsigned ackno_them) +{ + + /* FILTER + * Reject out-of-order payloads + */ + if (payload_length) { + /* Wrapping technique: If there is a gap between this + * packet and the last one, then it means there is a missing + * packet somewhere. In that case, this calculation will + * wrap and `payload_offset` will be some huge number in the future. + * If there is no gap, then this will be zero. + * If there's overlap between this packet and the previous, `payload_offset` + * will be a small number less than the `length` of this packet. + * If it's a retransmission, the numbers will be the same + */ + int payload_offset = seqno_them - tcb->seqno_them; + if (payload_offset < 0) { + /* This is a retrnasmission that we've already acknowledged */ + if (payload_offset <= 0 - payload_length) { + /* Both begin and end are old, so simply discard it */ + return TCB__okay; + } else { + /* Otherwise shorten the payload */ + payload_length += payload_offset; + payload -= payload_offset; + seqno_them -= payload_offset; + assert(payload_length < 2000); + } + } else if (payload_offset > 0) { + /* This is an out-of-order fragment in the future. an important design + * of this light-weight stack is that we don't support this, and + * force the other side to retransmit such packets */ + return TCB__okay; + } + } + + /* FILTER: + * Reject out-of-order FINs. + * Handle duplicate FINs here + */ + if (what == TCP_WHAT_FIN) { + if (seqno_them == tcb->seqno_them - 1) { + /* Duplicate FIN, respond with ACK */ + LOGtcb(tcb, 1, "duplicate FIN\n"); + _tcb_send_ack(tcpcon, tcb); + return TCB__okay; + } else if (seqno_them != tcb->seqno_them) { + /* out of order FIN, so drop it */ + LOGtcb(tcb, 1, "out-of-order FIN\n"); + return TCB__okay; + } + } + + LOGtcb(tcb, 1, "##%s##\n", what_to_string(what)); + + /* Make sure no connection lasts longer than ~30 seconds */ + if (what == TCP_WHAT_TIMEOUT) { + if (tcb->when_created + tcpcon->timeout_connection < secs) { + LOGip(8, tcb->ip_them, tcb->port_them, + "%s \n", + "CONNECTION TIMEOUT---"); + LOGSEND(tcb, "peer(RST)"); + tcpcon_send_packet(tcpcon, tcb, 0x04 /*RST*/, 0, 0); + tcpcon_destroy_tcb(tcpcon, tcb, Reason_Timeout); + return TCB__destroyed; + } + } + + if (what == TCP_WHAT_RST) { + LOGSEND(tcb, "tcb(destroy)"); + tcpcon_destroy_tcb(tcpcon, tcb, Reason_RST); + return TCB__destroyed; + } + + + + /* + * + * + * + * + * + * + */ + switch (tcb->tcpstate) { + /* TODO: validate any SYNACK is real before sending it here + * to the state-machine, by validating that it's acking + * something */ + case STATE_SYN_SENT: + switch (what) { + case TCP_WHAT_TIMEOUT: + /* We've sent a SYN, but didn't get SYN-ACK, so + * send another */ + tcb->syns_sent++; + + /* Send a SYN */ + tcpcon_send_packet(tcpcon, tcb, 0x02 /*SYN*/, 0, 0); + break; + case TCP_WHAT_SYNACK: + tcb->seqno_them = seqno_them; + tcb->seqno_them_first = seqno_them - 1; + tcb->seqno_me = ackno_them; + tcb->seqno_me_first = ackno_them - 1; + + LOGtcb(tcb, 1, "%s connection established\n", + what_to_string(what)); + + /* Send "ACK" to acknowlege their "SYN-ACK" */ + _tcb_send_ack(tcpcon, tcb); + _tcb_change_state_to(tcb, STATE_ESTABLISHED_RECV); + application_notify(tcpcon, tcb, APP_CONNECTED, 0, 0, secs, usecs); + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + + break; + } + break; + + + case STATE_ESTABLISHED_SEND: + switch (what) { + case TCP_WHAT_CLOSE: + _tcb_seg_send(tcpcon, tcb, 0, 0, TCP__close_fin); + _tcb_change_state_to(tcb, STATE_FIN_WAIT1_SEND); + break; + case TCP_WHAT_FIN: + if (seqno_them == tcb->seqno_them) { + /* I have ACKed all their data, so therefore process this */ + _tcb_seg_recv(tcpcon, tcb, 0, 0, seqno_them, secs, usecs, true); + _tcb_change_state_to(tcb, STATE_FIN_WAIT1_SEND); + _tcb_send_ack(tcpcon, tcb); + } else { + /* I haven't received all their data, so ignore it until I do */ + _tcb_send_ack(tcpcon, tcb); + } + break; + case TCP_WHAT_ACK: + _tcp_seg_acknowledge(tcb, ackno_them); + + if (tcb->segments == NULL || tcb->segments->length == 0) { + /* We've finished sending everything, so switch our application state + * back to sending */ + _tcb_change_state_to(tcb, STATE_ESTABLISHED_RECV); + + /* All the payload has been sent. Notify the application of this, so that they + * can send more if the want, or switch to listening. */ + application_notify(tcpcon, tcb, APP_SEND_SENT, 0, 0, secs, usecs); + + } + break; + case TCP_WHAT_TIMEOUT: + /* They haven't acknowledged everything yet, so resend the last segment */ + _tcb_seg_resend(tcpcon, tcb); + break; + case TCP_WHAT_DATA: + /* We don't receive data while in the sending state. We force them + * to keep re-sending it until we are prepared to receive it. This + * saves us from having to buffer it in this stack. + */ + break; + case TCP_WHAT_SYNACK: + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + + case STATE_ESTABLISHED_RECV: + switch (what) { + case TCP_WHAT_CLOSE: + _tcb_seg_send(tcpcon, tcb, 0, 0, TCP__close_fin); + _tcb_change_state_to(tcb, STATE_FIN_WAIT1_RECV); + break; + case TCP_WHAT_FIN: + if (seqno_them == tcb->seqno_them) { + /* I have ACKed all their data, so therefore process this */ + _tcb_seg_recv(tcpcon, tcb, 0, 0, seqno_them, secs, usecs, true); + _tcb_change_state_to(tcb, STATE_CLOSE_WAIT); + //_tcb_send_ack(tcpcon, tcb); + application_notify(tcpcon, tcb, APP_CLOSE, + 0, payload_length, secs, usecs); + + } else { + /* I haven't received all their data, so ignore it until I do */ + _tcb_send_ack(tcpcon, tcb); + } + break; + case TCP_WHAT_ACK: + _tcp_seg_acknowledge(tcb, ackno_them); + break; + case TCP_WHAT_TIMEOUT: + application_notify(tcpcon, tcb, APP_RECV_TIMEOUT, 0, 0, secs, usecs); + break; + case TCP_WHAT_DATA: + _tcb_seg_recv(tcpcon, tcb, payload, payload_length, seqno_them, secs, usecs, false); + break; + case TCP_WHAT_SYNACK: + /* This happens when a delayed SYN-ACK arrives from the target. + * I see these fairly often from host 178.159.37.125. + * We are going to make them silent for now, but eventually, keep + * statistics about this sort of thing. */ + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + + /* + SYN-RCVD + FIN = FIN-WAIT-1 + ESTAB + FIN = FIN-WAIT-1 + +---------+ + | FIN | + | WAIT-1 | + +---------+ + FIN-WAIT-1 + FIN --> CLOSING + FIN-WAIT-1 + ACK-of-FIN --> FIN-WAIT-2 + */ + case STATE_FIN_WAIT1_SEND: + switch (what) { + case TCP_WHAT_FIN: + /* Ignore their FIN while in the SENDing state. */ + break; + case TCP_WHAT_ACK: + /* Apply the ack */ + if (_tcp_seg_acknowledge(tcb, ackno_them)) { + + /* Same a in ESTABLISHED_SEND, once they've acknowledged + * all reception BEFORE THE FIN, then change the state */ + if (tcb->segments == NULL || tcb->segments->length == 0) { + /* All the payload has been sent. Notify the application of this, so that they + * can send more if the want, or switch to listening. */ + _tcb_change_state_to(tcb, STATE_FIN_WAIT1_RECV); + application_notify(tcpcon, tcb, APP_SEND_SENT, 0, 0, secs, usecs); + } + } + break; + case TCP_WHAT_TIMEOUT: + _tcb_seg_resend(tcpcon, tcb); /* also resends FINs */ + break; + case TCP_WHAT_DATA: + /* Ignore any data received while in the SEND state */ + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + case STATE_FIN_WAIT1_RECV: + switch (what) { + case TCP_WHAT_FIN: + _tcb_seg_recv(tcpcon, tcb, 0, 0, seqno_them, secs, usecs, true); + _tcb_change_state_to(tcb, STATE_CLOSING); + _tcb_send_ack(tcpcon, tcb); + application_notify(tcpcon, tcb, APP_CLOSE, 0, 0, secs, usecs); + break; + case TCP_WHAT_ACK: + /* Apply the ack */ + if (_tcp_seg_acknowledge(tcb, ackno_them)) { + if (_tcb_they_have_acked_my_fin(tcb)) { + _tcb_change_state_to(tcb, STATE_FIN_WAIT2); + application_notify(tcpcon, tcb, APP_CLOSE, 0, 0, secs, usecs); + } + } + break; + case TCP_WHAT_TIMEOUT: + _tcb_seg_resend(tcpcon, tcb); /* also recv FIN */ + break; + case TCP_WHAT_DATA: + _tcb_seg_recv(tcpcon, tcb, payload, payload_length, seqno_them, secs, usecs, false); + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + + + case STATE_CLOSING: + switch (what) { + case TCP_WHAT_TIMEOUT: + tcpcon_destroy_tcb(tcpcon, tcb, Reason_Timeout); + return TCB__destroyed; + case TCP_WHAT_ACK: + _tcp_seg_acknowledge(tcb, ackno_them); + if (_tcb_they_have_acked_my_fin(tcb)) { + tcpcon_destroy_tcb(tcpcon, tcb, Reason_FIN); + return TCB__destroyed; + } + break; + case TCP_WHAT_FIN: + /* I've already acknowledged their FIN, but hey, do it again */ + _tcb_send_ack(tcpcon, tcb); + break; + case TCP_WHAT_CLOSE: + /* The application this machine has issued a second `tcpapi_close()` request. + * This represents a bug in the application process. One place where I see this + * when scanning 193.109.9.122:992. + * FIXME TODO */ + ; /* make this silent for now */ + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + + + case STATE_FIN_WAIT2: + case STATE_TIME_WAIT: + switch (what) { + case TCP_WHAT_TIMEOUT: + /* giving up */ + if (tcb->tcpstate == STATE_TIME_WAIT) { + tcpcon_destroy_tcb(tcpcon, tcb, Reason_Timeout); + return TCB__destroyed; + } + break; + case TCP_WHAT_ACK: + break; + case TCP_WHAT_FIN: + /* Processing incoming FIN as an empty paylaod */ + _tcb_seg_recv(tcpcon, tcb, 0, 0, seqno_them, secs, usecs, true); + + _tcb_change_state_to(tcb, STATE_TIME_WAIT); + + timeouts_add( tcpcon->timeouts, + tcb->timeout, + offsetof(struct TCP_Control_Block, timeout), + TICKS_FROM_TV(secs+5,usecs) + ); + break; + case TCP_WHAT_SYNACK: + case TCP_WHAT_RST: + case TCP_WHAT_DATA: + break; + case TCP_WHAT_CLOSE: + /* FIXME: to reach this state, we've already done a close. + * FIXME: but this happens twice, because only have + * FIXME: a single close function. */ + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + case STATE_CLOSE_WAIT: + /* Waiting for app to call `close()` */ + switch (what) { + case TCP_WHAT_CLOSE: + _tcb_seg_send(tcpcon, tcb, 0, 0, TCP__close_fin); + _tcb_change_state_to(tcb, STATE_LAST_ACK); + break; + case TCP_WHAT_TIMEOUT: + /* Remind the app that it's waiting for it to be closed */ + application_notify(tcpcon, tcb, APP_CLOSE, + 0, payload_length, secs, usecs); + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + case STATE_LAST_ACK: + switch (what) { + case TCP_WHAT_TIMEOUT: + /* They haven't acknowledged everything yet, so resend the last segment */ + _tcb_seg_resend(tcpcon, tcb); + break; + case TCP_WHAT_ACK: + if (_tcp_seg_acknowledge(tcb, ackno_them)) { + tcpcon_destroy_tcb(tcpcon, tcb, Reason_Shutdown); + return TCB__destroyed; + } + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + break; + break; + default: + ERRMSGip(tcb->ip_them, tcb->port_them, "%s:%s **** UNHANDLED EVENT ****\n", + state_to_string(tcb->tcpstate), what_to_string(what)); + break; + } + return TCB__okay; +} + diff --git a/src/proto-tcp.h b/src/stack-tcp-core.h similarity index 89% rename from src/proto-tcp.h rename to src/stack-tcp-core.h index c473a858..4fe2fa07 100644 --- a/src/proto-tcp.h +++ b/src/stack-tcp-core.h @@ -10,6 +10,7 @@ struct TCP_Control_Block; struct TemplatePacket; struct TCP_ConnectionTable; struct lua_State; +struct ProtocolParserStream; #define TCP_SEQNO(px,i) (px[i+4]<<24|px[i+5]<<16|px[i+6]<<8|px[i+7]) #define TCP_ACKNO(px,i) (px[i+8]<<24|px[i+9]<<16|px[i+10]<<8|px[i+11]) @@ -19,6 +20,7 @@ struct lua_State; #define TCP_IS_RST(px,i) ((TCP_FLAGS(px,i) & 0x4) == 0x4) #define TCP_IS_FIN(px,i) ((TCP_FLAGS(px,i) & 0x1) == 0x1) + /** * [KLUDGE] The 'tcpcon' module doesn't have access to the main configuration, * so specific configuration options have to be sent to it using this @@ -101,26 +103,35 @@ enum TCP_What { TCP_WHAT_FIN, TCP_WHAT_ACK, TCP_WHAT_DATA, + TCP_WHAT_CLOSE +}; + +enum TCB_result { + TCB__okay, + TCB__destroyed }; -int +enum TCB_result stack_incoming_tcp(struct TCP_ConnectionTable *tcpcon, struct TCP_Control_Block *entry, - int what, const void *p, size_t length, + enum TCP_What what, + const unsigned char *payload, size_t payload_length, unsigned secs, unsigned usecs, - unsigned seqno_them); + unsigned seqno_them, unsigned ackno_them); /** * Lookup a connection record based on IP/ports. */ struct TCP_Control_Block * -tcb_lookup( +tcpcon_lookup_tcb( struct TCP_ConnectionTable *tcpcon, ipaddress ip_src, ipaddress ip_dst, unsigned port_src, unsigned port_dst); /** - * Create a new TCB (TCP control block) + * Create a new TCB (TCP control block. It's created only in two places, + * either because we've initiated an outbound TCP connection, or we've + * received incoming SYN-ACK from a probe. */ struct TCP_Control_Block * tcpcon_create_tcb( @@ -128,18 +139,11 @@ tcpcon_create_tcb( ipaddress ip_src, ipaddress ip_dst, unsigned port_src, unsigned port_dst, unsigned my_seqno, unsigned their_seqno, - unsigned ttl); + unsigned ttl, + const struct ProtocolParserStream *stream, + unsigned secs, unsigned usecs); -/** - * Acknowledge a FIN even if we've forgotten about the connection - */ -void -tcpcon_send_FIN( - struct TCP_ConnectionTable *tcpcon, - ipaddress ip_me, ipaddress ip_them, - unsigned port_me, unsigned port_them, - uint32_t seqno_them, uint32_t ackno_them); void tcpcon_send_RST( struct TCP_ConnectionTable *tcpcon, diff --git a/src/stub-pcap.c b/src/stub-pcap.c index f8f6cac1..3a4c02e9 100644 --- a/src/stub-pcap.c +++ b/src/stub-pcap.c @@ -25,7 +25,7 @@ static libpcap.a library. */ -#include "logger.h" +#include "util-logger.h" #if defined(_MSC_VER) #pragma warning(disable:4115 4201) diff --git a/src/stub-pfring.c b/src/stub-pfring.c index 03eff3ff..2a4663ae 100644 --- a/src/stub-pfring.c +++ b/src/stub-pfring.c @@ -8,7 +8,7 @@ */ #include "stub-pfring.h" #include "string_s.h" -#include "logger.h" +#include "util-logger.h" struct PFRING PFRING; diff --git a/src/templ-payloads.c b/src/templ-payloads.c index d82050ea..a35d2d42 100644 --- a/src/templ-payloads.c +++ b/src/templ-payloads.c @@ -13,13 +13,14 @@ #include "massip-port.h" #include "rawsock-pcapfile.h" /* for reading payloads from pcap files */ #include "proto-preprocess.h" /* parse packets */ -#include "logger.h" +#include "util-logger.h" #include "proto-zeroaccess.h" /* botnet p2p protocol */ #include "proto-snmp.h" #include "proto-memcached.h" #include "proto-coap.h" /* constrained app proto for IoT udp/5683*/ #include "proto-ntp.h" #include "proto-dns.h" +#include "proto-isakmp.h" #include "util-malloc.h" #include "massip.h" #include "templ-nmap-payloads.h" @@ -310,6 +311,162 @@ struct PayloadUDP_Default hard_coded_udp_payloads[] = { {27960, 65536, 0xFFFFFFFF, 0, 0, "\xFF\xFF\xFF\xFF\x67\x65\x74\x73\x74\x61\x74\x75\x73\x10"}, + /* ISAKMP */ + {500, 500, 352, 0, isakmp_set_cookie, + /* ISAKMP */ + "\x00\x11\x22\x33\x44\x55\x66\x77"/* init_cookie */ + "\x00\x00\x00\x00\x00\x00\x00\x00" /* resp_cookie*/ + "\x01" /* next_payload: SA */ + "\x10" /* version */ + "\x02" /* exch_type: identity prot. */ + "\x00" /* flags */ + "\x00\x00\x00\x00" /* id */ + "\x00\x00\x01\x60" /* length: 352 */ + /* ISAKMP_SA */ + "\x00" /* next_payload: None */ + "\x00" /* reserved */ + "\x01\x44" /* length: 324 */ + "\x00\x00\x00\x01" /* DOI: IPSEC */ + "\x00\x00\x00\x01" /* situation: identity */ + /* Proposal */ + "\x00" /* next_payload: None */ + "\x00" /* reserved */ + "\x01\x38" /* length: 312 */ + "\x01" /* proposal: 1 */ + "\x01" /* protocol: ISAKMP */ + "\x00" /* SPIsize: 0 */ + "\x0d" /* trans_count: 13 */ + "" /* SPI */ + /* Tranforms */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x20" /* length: 32 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x01\x80\x04\x00\x02" + "\x80\x0b\x00\x01\x80\x0c\x00\x01" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), ('Authentication', 'PSK'), + ('GroupDesc', '1024MODPgr'), ('LifeType', 'Seconds'), + ('LifeDuration', 1) */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x20" /* length: 32 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x01\x80\x02\x00\x01\x80\x03\x00\x01\x80\x04\x00\x02" + "\x80\x0b\x00\x01\x80\x0c\x00\x01" + /* ('Encryption', 'DES-CBC'), ('Hash', 'MD5'), ('Authentication', 'PSK'), + ('GroupDesc', '1024MODPgr'), ('LifeType', 'Seconds'), + ('LifeDuration', 1) */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x20" /* length: 32 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x07\x80\x02\x00\x04\x80\x03\x00\x01\x80\x04\x00\x0e" + "\x80\x0b\x00\x01\x80\x0c\x00\x01" + /* ('Encryption', 'AES-CBC'), ('Hash', 'SHA2-256'), + ('Authentication', 'PSK'), ('GroupDesc', '2048MODPgr'), + ('LifeType', 'Seconds'), ('LifeDuration', 1) */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x02" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'DSS') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x03" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'RSA Sig') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x04" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'RSA Encryption') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x08" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'ECDSA Sig') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfa\xdd" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'HybridInitRSA') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfa\xdf" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'HybridInitDSS') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfd\xe9" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'XAUTHInitPreShared') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfd\xeb" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'XAUTHInitDSS') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfd\xed" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'XAUTHInitRSA') */ + "\x03" /* next_payload: Transform */ + "\x00" /* reserved */ + "\x00\x14" /* length: 20 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */ + "\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfd\xef" + /* ('Encryption', '3DES-CBC'), ('Hash', 'SHA'), + ('Authentication', 'XAUTHInitRSAEncryption') */ + "\x00" /* next_payload: None */ + "\x00" /* reserved */ + "\x00\x08" /* length: 8 */ + "\x00" /* num */ + "\x01" /* id: KEY_IKE */ + "\x00\x00" /* reserved */}, {0,0,0,0,0} }; diff --git a/src/templ-pkt.c b/src/templ-pkt.c index 24e375a4..fcb93ed3 100644 --- a/src/templ-pkt.c +++ b/src/templ-pkt.c @@ -15,7 +15,7 @@ #include "proto-sctp.h" #include "string_s.h" #include "pixie-timer.h" -#include "logger.h" +#include "util-logger.h" #include "templ-payloads.h" #include "syn-cookie.h" #include "unusedparm.h" @@ -1389,18 +1389,6 @@ template_packet_init( templset->entropy = entropy; - /* [TCP] */ - length = sizeof(default_tcp_template)-1; - buf = malloc(length); - memcpy(buf, default_tcp_template, length); - templ_tcp_apply_options(&buf, &length, templ_opts); /* mss, sack, wscale */ - _template_init(&templset->pkts[Proto_TCP], - source_mac, router_mac_ipv4, router_mac_ipv6, - buf, length, - data_link); - templset->count++; - free(buf); - /* [SCTP] */ _template_init(&templset->pkts[Proto_SCTP], source_mac, router_mac_ipv4, router_mac_ipv6, @@ -1409,6 +1397,19 @@ template_packet_init( data_link); templset->count++; + /* [TCP] */ + length = sizeof(default_tcp_template) - 1; + buf = MALLOC(length); + memcpy(buf, default_tcp_template, length); + templ_tcp_apply_options(&buf, &length, templ_opts); + _template_init(&templset->pkts[Proto_TCP], + source_mac, router_mac_ipv4, router_mac_ipv6, + buf, + length, + data_link); + templset->count++; + free(buf); + /* [UDP] */ _template_init(&templset->pkts[Proto_UDP], source_mac, router_mac_ipv4, router_mac_ipv6, @@ -1543,7 +1544,7 @@ template_selftest(void) 0, /* UDP payloads = empty */ 0, /* Oproto payloads = empty */ 1, /* Ethernet */ - 0, /* no entropy */ + 0, /* no entropy */ &templ_opts ); failures += tmplset->pkts[Proto_TCP].proto != Proto_TCP; diff --git a/src/templ-tcp-hdr.c b/src/templ-tcp-hdr.c index 37ff6ea0..e1744bd1 100644 --- a/src/templ-tcp-hdr.c +++ b/src/templ-tcp-hdr.c @@ -68,7 +68,7 @@ */ #include "templ-tcp-hdr.h" #include "templ-opts.h" -#include "logger.h" +#include "util-logger.h" #include "proto-preprocess.h" #include #include diff --git a/src/unusedparm.h b/src/unusedparm.h index 08b0d8b8..02495840 100644 --- a/src/unusedparm.h +++ b/src/unusedparm.h @@ -5,3 +5,4 @@ #define UNUSEDPARM(x) (void) x #endif #endif + diff --git a/src/util-errormsg.c b/src/util-errormsg.c new file mode 100644 index 00000000..3552f817 --- /dev/null +++ b/src/util-errormsg.c @@ -0,0 +1,86 @@ +#include "util-errormsg.h" +#include "crypto-siphash24.h" +#include "massip-addr.h" +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable: 4204) +#endif + + +static unsigned long long _entropy = (unsigned long long)&_entropy; + +void errmsg_init(unsigned long long in_entropy) { + _entropy = in_entropy; +} + +static void +_errmsg(const char *fmt, va_list marker) +{ + fprintf(stderr, "[-] ERR: "); + vfprintf(stderr, fmt, marker); + fflush(stderr); +} + +static void +_errmsgip(ipaddress ip, unsigned port, const char *fmt, va_list marker) +{ + ipaddress_formatted_t fmted = ipaddress_fmt(ip); + + fprintf(stderr, "[-] %s:%u: ", fmted.string, port); + vfprintf(stderr, fmt, marker); + fflush(stderr); +} + +/*************************************************************************** + * Prints the message if the global "verbosity" flag exceeds this level. + ***************************************************************************/ +void +ERRMSG(const char *fmt, ...) +{ + va_list marker; + size_t index; + uint64_t key[2] = {_entropy, _entropy}; + static size_t _table[1024] = {0}; + + /* Hash the address of the format string */ + index = (size_t)siphash24(fmt, sizeof(fmt), key); + index %= 1024; + + /* Filter out this error if we've seen it before */ + if (_table[index] == (size_t)fmt) + return; + else + _table[index] = (size_t)fmt; + + + va_start(marker, fmt); + _errmsg(fmt, marker); + va_end(marker); +} + +void +ERRMSGip(ipaddress ip, unsigned port, const char *fmt, ...) +{ + va_list marker; + size_t index; + uint64_t key[2] = {_entropy, _entropy}; + static size_t _table[1024] = {0}; + + /* Hash the address of the format string */ + index = (size_t)siphash24(fmt, sizeof(fmt), key); + index %= 1024; + + /* Filter out this error if we've seen it before */ + if (_table[index] == (size_t)fmt) + return; + else + _table[index] = (size_t)fmt; + + + va_start(marker, fmt); + _errmsgip(ip, port, fmt, marker); + va_end(marker); +} + diff --git a/src/util-errormsg.h b/src/util-errormsg.h new file mode 100644 index 00000000..dc124819 --- /dev/null +++ b/src/util-errormsg.h @@ -0,0 +1,17 @@ +#ifndef UTIL_ERRORMSG_H +#define UTIL_ERRORMSG_H +#include "massip-addr.h" + +void errmsg_init(unsigned long long entropy); + +/** + * Prints an error message only once + */ +void +ERRMSG(const char *fmt, ...); + +void +ERRMSGip(ipaddress ip, unsigned port, const char *fmt, ...); + + +#endif diff --git a/src/logger.c b/src/util-logger.c similarity index 75% rename from src/logger.c rename to src/util-logger.c index 2ec01434..03c1c1f8 100644 --- a/src/logger.c +++ b/src/util-logger.c @@ -8,7 +8,7 @@ Details about scan results go to , so that they can easily be redirected to a file. */ -#include "logger.h" +#include "util-logger.h" #include "string_s.h" #include #include @@ -44,6 +44,31 @@ LOG(int level, const char *fmt, ...) va_end(marker); } +/*************************************************************************** + ***************************************************************************/ +static void +vLOGnet(unsigned port_me, ipaddress ip_them, const char *fmt, va_list marker) +{ + char sz_ip[64]; + ipaddress_formatted_t fmt1 = ipaddress_fmt(ip_them); + + sprintf_s(sz_ip, sizeof(sz_ip), "%s", fmt1.string); + fprintf(stderr, "%u:%s: ", port_me, sz_ip); + vfprintf(stderr, fmt, marker); + fflush(stderr); +} +void +LOGnet(unsigned port_me, ipaddress ip_them, const char *fmt, ...) +{ + va_list marker; + + va_start(marker, fmt); + vLOGnet(port_me, ip_them, fmt, marker); + va_end(marker); +} + + + /*************************************************************************** ***************************************************************************/ static void @@ -53,16 +78,12 @@ vLOGip(int level, ipaddress ip, unsigned port, const char *fmt, va_list marker) char sz_ip[64]; ipaddress_formatted_t fmt1 = ipaddress_fmt(ip); - sprintf_s(sz_ip, sizeof(sz_ip), "%s", fmt1.string); - fprintf(stderr, "%-15s:%5u: ", sz_ip, port); + sprintf_s(sz_ip, sizeof(sz_ip), "%s:%u: ", fmt1.string, port); + fprintf(stderr, "%s ", sz_ip); vfprintf(stderr, fmt, marker); fflush(stderr); } } - - -/*************************************************************************** - ***************************************************************************/ void LOGip(int level, ipaddress ip, unsigned port, const char *fmt, ...) { diff --git a/src/logger.h b/src/util-logger.h similarity index 61% rename from src/logger.h rename to src/util-logger.h index 4436a0fd..62f88d47 100644 --- a/src/logger.h +++ b/src/util-logger.h @@ -1,9 +1,11 @@ -#ifndef LOGGER_H -#define LOGGER_H +#ifndef UTIL_LOGGER_H +#define UTIL_LOGGER_H #include "massip-addr.h" void LOG(int level, const char *fmt, ...); void LOGip(int level, ipaddress ip, unsigned port, const char *fmt, ...); +void LOGnet(unsigned port_me, ipaddress ip_them, const char *fmt, ...); + void LOG_add_level(int level); diff --git a/vs10/masscan.vcxproj b/vs10/masscan.vcxproj index 982d1ff4..ced92e99 100644 --- a/vs10/masscan.vcxproj +++ b/vs10/masscan.vcxproj @@ -62,7 +62,7 @@ - + @@ -78,8 +78,6 @@ - - @@ -92,6 +90,7 @@ + @@ -114,6 +113,8 @@ + + @@ -124,8 +125,9 @@ + + - @@ -143,7 +145,6 @@ - @@ -177,7 +178,7 @@ - + @@ -193,9 +194,9 @@ - + @@ -211,6 +212,9 @@ + + + @@ -223,8 +227,9 @@ + + - diff --git a/vs10/masscan.vcxproj.filters b/vs10/masscan.vcxproj.filters index 02b508dd..9919a7f1 100644 --- a/vs10/masscan.vcxproj.filters +++ b/vs10/masscan.vcxproj.filters @@ -75,9 +75,6 @@ Source Files\proto - - Source Files\proto - Source Files\proto @@ -129,9 +126,6 @@ Source Files\misc - - Source Files\misc - Source Files\misc @@ -255,9 +249,6 @@ Source Files\proto - - Source Files\proto - Source Files\output @@ -297,9 +288,6 @@ Source Files\stubs - - Source Files\versioning - Source Files\vulncheck @@ -390,6 +378,24 @@ Source Files\proto + + Source Files\proto + + + Source Files\stack + + + Source Files\versioning + + + Source Files\stack + + + Source Files\util + + + Source Files\util + @@ -419,9 +425,6 @@ Source Files\proto - - Source Files\proto - Source Files\proto @@ -452,9 +455,6 @@ Source Files\misc - - Source Files\misc - Source Files\misc @@ -542,9 +542,6 @@ Source Files - - Source Files\proto - Source Files\proto @@ -590,9 +587,6 @@ Source Files\stubs - - Source Files\versioning - Source Files\vulncheck @@ -674,6 +668,27 @@ Source Files\proto + + Source Files\proto + + + Source Files\stack + + + Source Files\versioning + + + Source Files\stack + + + Source Files\stack + + + Source Files\util + + + Source Files\util + diff --git a/xcode4/masscan.xcodeproj/project.pbxproj b/xcode4/masscan.xcodeproj/project.pbxproj index c89ff26c..8e5f1692 100644 --- a/xcode4/masscan.xcodeproj/project.pbxproj +++ b/xcode4/masscan.xcodeproj/project.pbxproj @@ -19,7 +19,7 @@ 11420DD819A8160500DB5BFE /* proto-ftp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DD719A8160500DB5BFE /* proto-ftp.c */; }; 11420DDB19A84A9F00DB5BFE /* proto-smtp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDA19A84A9E00DB5BFE /* proto-smtp.c */; }; 11420DDE19A8FDE300DB5BFE /* proto-pop3.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDD19A8FDE300DB5BFE /* proto-pop3.c */; }; - 11420DE019A90CB300DB5BFE /* proto-interactive.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDF19A90CB300DB5BFE /* proto-interactive.c */; }; + 11420DE019A90CB300DB5BFE /* stack-tcp-app.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDF19A90CB300DB5BFE /* stack-tcp-app.c */; }; 11420DE319A9363B00DB5BFE /* proto-imap4.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DE219A9363A00DB5BFE /* proto-imap4.c */; }; 11469CA22295D80A00FA76BE /* misc-rstfilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 11469CA12295D80A00FA76BE /* misc-rstfilter.c */; }; 1155CF102AF2FE12001B235A /* proto-mc.c in Sources */ = {isa = PBXBuildFile; fileRef = 1155CF0F2AF2FE12001B235A /* proto-mc.c */; }; @@ -32,6 +32,121 @@ 118B9B3325A00FA900F5FB0B /* massip-rangesv6.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B2C25A00FA800F5FB0B /* massip-rangesv6.c */; }; 118B9B3425A00FA900F5FB0B /* massip-parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B2F25A00FA900F5FB0B /* massip-parse.c */; }; 118B9B3525A00FA900F5FB0B /* massip.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B3125A00FA900F5FB0B /* massip.c */; }; + 118D67C42B02D58F00271F7F /* util-errormsg.c in Sources */ = {isa = PBXBuildFile; fileRef = 118D67C22B02CBA000271F7F /* util-errormsg.c */; }; + 118D67C72B02DD6F00271F7F /* stack-queue.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B6297525995AA100D4786F /* stack-queue.c */; }; + 118D67C82B02DD6F00271F7F /* event-timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219317DBCC7E00DDFD32 /* event-timeout.c */; }; + 118D67C92B02DD6F00271F7F /* vulncheck-heartbleed.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD363C2107E7ED00CBE1DE /* vulncheck-heartbleed.c */; }; + 118D67CA2B02DD6F00271F7F /* massip-rangesv6.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B2C25A00FA800F5FB0B /* massip-rangesv6.c */; }; + 118D67CB2B02DD6F00271F7F /* util-logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219517DBCC7E00DDFD32 /* util-logger.c */; }; + 118D67CC2B02DD6F00271F7F /* stub-pfring.c in Sources */ = {isa = PBXBuildFile; fileRef = 119968FE2141AB3600E82767 /* stub-pfring.c */; }; + 118D67CD2B02DD6F00271F7F /* main-conf.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219717DBCC7E00DDFD32 /* main-conf.c */; }; + 118D67CE2B02DD6F00271F7F /* main-dedup.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219817DBCC7E00DDFD32 /* main-dedup.c */; }; + 118D67CF2B02DD6F00271F7F /* main-initadapter.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219A17DBCC7E00DDFD32 /* main-initadapter.c */; }; + 118D67D02B02DD6F00271F7F /* main-status.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219B17DBCC7E00DDFD32 /* main-status.c */; }; + 118D67D12B02DD6F00271F7F /* rawsock-getip6.c in Sources */ = {isa = PBXBuildFile; fileRef = 118E115825859E6F00618314 /* rawsock-getip6.c */; }; + 118D67D22B02DD6F00271F7F /* main-throttle.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219D17DBCC7E00DDFD32 /* main-throttle.c */; }; + 118D67D32B02DD6F00271F7F /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219F17DBCC7E00DDFD32 /* main.c */; }; + 118D67D42B02DD6F00271F7F /* vulncheck-sslv3.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD363D2107E7ED00CBE1DE /* vulncheck-sslv3.c */; }; + 118D67D52B02DD6F00271F7F /* out-binary.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921A117DBCC7E00DDFD32 /* out-binary.c */; }; + 118D67D62B02DD6F00271F7F /* out-null.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921A217DBCC7E00DDFD32 /* out-null.c */; }; + 118D67D72B02DD6F00271F7F /* proto-ntlmssp.c in Sources */ = {isa = PBXBuildFile; fileRef = 110ED16720CB0BC200690C91 /* proto-ntlmssp.c */; }; + 118D67D82B02DD6F00271F7F /* out-text.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921A317DBCC7E00DDFD32 /* out-text.c */; }; + 118D67D92B02DD6F00271F7F /* out-xml.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921A417DBCC7E00DDFD32 /* out-xml.c */; }; + 118D67DA2B02DD6F00271F7F /* output.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921A517DBCC7E00DDFD32 /* output.c */; }; + 118D67DB2B02DD6F00271F7F /* pixie-threads.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921A817DBCC7E00DDFD32 /* pixie-threads.c */; }; + 118D67DC2B02DD6F00271F7F /* pixie-timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921AA17DBCC7E00DDFD32 /* pixie-timer.c */; }; + 118D67DD2B02DD6F00271F7F /* read-service-probes.c in Sources */ = {isa = PBXBuildFile; fileRef = 119968FB21388A3B00E82767 /* read-service-probes.c */; }; + 118D67DE2B02DD6F00271F7F /* proto-arp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921AC17DBCC7E00DDFD32 /* proto-arp.c */; }; + 118D67DF2B02DD6F00271F7F /* proto-banner1.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921AE17DBCC7E00DDFD32 /* proto-banner1.c */; }; + 118D67E02B02DD6F00271F7F /* stub-pcap.c in Sources */ = {isa = PBXBuildFile; fileRef = 119968FF2141AB3600E82767 /* stub-pcap.c */; }; + 118D67E12B02DD6F00271F7F /* proto-tcp-rdp.c in Sources */ = {isa = PBXBuildFile; fileRef = 1107E9B1228DF7BB003384B3 /* proto-tcp-rdp.c */; }; + 118D67E22B02DD6F00271F7F /* proto-preprocess.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B017DBCC7E00DDFD32 /* proto-preprocess.c */; }; + 118D67E32B02DD6F00271F7F /* stack-tcp-core.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B217DBCC7E00DDFD32 /* stack-tcp-core.c */; }; + 118D67E42B02DD6F00271F7F /* crypto-blackrock.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B417DBCC7E00DDFD32 /* crypto-blackrock.c */; }; + 118D67E52B02DD6F00271F7F /* crypto-lcg.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B617DBCC7E00DDFD32 /* crypto-lcg.c */; }; + 118D67E62B02DD6F00271F7F /* crypto-primegen.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B817DBCC7E00DDFD32 /* crypto-primegen.c */; }; + 118D67E72B02DD6F00271F7F /* rawsock-getif.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921BD17DBCC7E00DDFD32 /* rawsock-getif.c */; }; + 118D67E82B02DD6F00271F7F /* rawsock-getip.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921BE17DBCC7E00DDFD32 /* rawsock-getip.c */; }; + 118D67E92B02DD6F00271F7F /* proto-isakmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11C000632AFDA178001EB0EB /* proto-isakmp.c */; }; + 118D67EA2B02DD6F00271F7F /* templ-tcp-hdr.c in Sources */ = {isa = PBXBuildFile; fileRef = 1155CF152AF8311C001B235A /* templ-tcp-hdr.c */; }; + 118D67EB2B02DD6F00271F7F /* rawsock-getmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921BF17DBCC7E00DDFD32 /* rawsock-getmac.c */; }; + 118D67EC2B02DD6F00271F7F /* util-malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B5897D21C0785B00DD6248 /* util-malloc.c */; }; + 118D67ED2B02DD6F00271F7F /* rawsock-getroute.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921C017DBCC7E00DDFD32 /* rawsock-getroute.c */; }; + 118D67EE2B02DD6F00271F7F /* proto-versioning.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36472108DCBB00CBE1DE /* proto-versioning.c */; }; + 118D67EF2B02DD6F00271F7F /* proto-coap.c in Sources */ = {isa = PBXBuildFile; fileRef = 11D0FAFA22763F4900332FA7 /* proto-coap.c */; }; + 118D67F02B02DD6F00271F7F /* in-report.c in Sources */ = {isa = PBXBuildFile; fileRef = 11C936C11EDCE77F0023D32E /* in-report.c */; }; + 118D67F12B02DD6F00271F7F /* rawsock-pcapfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921C117DBCC7E00DDFD32 /* rawsock-pcapfile.c */; }; + 118D67F22B02DD6F00271F7F /* rawsock.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921C517DBCC7E00DDFD32 /* rawsock.c */; }; + 118D67F32B02DD6F00271F7F /* scripting-banner.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD364A2108E0CB00CBE1DE /* scripting-banner.c */; }; + 118D67F42B02DD6F00271F7F /* rte-ring.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921C717DBCC7E00DDFD32 /* rte-ring.c */; }; + 118D67F52B02DD6F00271F7F /* smack1.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921CA17DBCC7E00DDFD32 /* smack1.c */; }; + 118D67F62B02DD6F00271F7F /* massip-rangesv4.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B2B25A00FA800F5FB0B /* massip-rangesv4.c */; }; + 118D67F72B02DD6F00271F7F /* smackqueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921CB17DBCC7E00DDFD32 /* smackqueue.c */; }; + 118D67F82B02DD6F00271F7F /* string_s.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921CD17DBCC7E00DDFD32 /* string_s.c */; }; + 118D67F92B02DD6F00271F7F /* stack-ndpv6.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B6297625995AA100D4786F /* stack-ndpv6.c */; }; + 118D67FA2B02DD6F00271F7F /* syn-cookie.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921CF17DBCC7E00DDFD32 /* syn-cookie.c */; }; + 118D67FB2B02DD6F00271F7F /* stack-arpv4.c in Sources */ = {isa = PBXBuildFile; fileRef = 1124DD6D25B4FF3C00EEFC2C /* stack-arpv4.c */; }; + 118D67FC2B02DD6F00271F7F /* templ-nmap-payloads.c in Sources */ = {isa = PBXBuildFile; fileRef = 1155CF112AF6EF72001B235A /* templ-nmap-payloads.c */; }; + 118D67FD2B02DD6F00271F7F /* util-errormsg.c in Sources */ = {isa = PBXBuildFile; fileRef = 118D67C22B02CBA000271F7F /* util-errormsg.c */; }; + 118D67FE2B02DD6F00271F7F /* templ-pkt.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921D117DBCC7E00DDFD32 /* templ-pkt.c */; }; + 118D67FF2B02DD6F00271F7F /* xring.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921D317DBCC7E00DDFD32 /* xring.c */; }; + 118D68002B02DD6F00271F7F /* proto-smb.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DE129520ABC2650041135D /* proto-smb.c */; }; + 118D68012B02DD6F00271F7F /* templ-payloads.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B2DD9C17DE4DD8007FC363 /* templ-payloads.c */; }; + 118D68022B02DD6F00271F7F /* proto-http.c in Sources */ = {isa = PBXBuildFile; fileRef = 11AC80E717E0DAD4001BCE3A /* proto-http.c */; }; + 118D68032B02DD6F00271F7F /* proto-icmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11AC80E917E0DAD4001BCE3A /* proto-icmp.c */; }; + 118D68042B02DD6F00271F7F /* proto-ssh.c in Sources */ = {isa = PBXBuildFile; fileRef = 11AC80EB17E0DAD4001BCE3A /* proto-ssh.c */; }; + 118D68052B02DD6F00271F7F /* main-ptrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 11AC80F517E0ED47001BCE3A /* main-ptrace.c */; }; + 118D68062B02DD6F00271F7F /* proto-memcached.c in Sources */ = {isa = PBXBuildFile; fileRef = 119AB2042051FFED008E4DDD /* proto-memcached.c */; }; + 118D68072B02DD6F00271F7F /* scripting-masscan.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36452107EB8700CBE1DE /* scripting-masscan.c */; }; + 118D68082B02DD6F00271F7F /* massip.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B3125A00FA900F5FB0B /* massip.c */; }; + 118D68092B02DD6F00271F7F /* proto-mc.c in Sources */ = {isa = PBXBuildFile; fileRef = 1155CF0F2AF2FE12001B235A /* proto-mc.c */; }; + 118D680A2B02DD6F00271F7F /* massip-addr.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BE533525A6441100451F95 /* massip-addr.c */; }; + 118D680B2B02DD6F00271F7F /* main-listscan.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B039C017E506B400925E7E /* main-listscan.c */; }; + 118D680C2B02DD6F00271F7F /* proto-dns.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B039C317E7834000925E7E /* proto-dns.c */; }; + 118D680D2B02DD6F00271F7F /* proto-udp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B039C517E7834000925E7E /* proto-udp.c */; }; + 118D680E2B02DD6F00271F7F /* proto-snmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B039C917EA092B00925E7E /* proto-snmp.c */; }; + 118D680F2B02DD6F00271F7F /* proto-netbios.c in Sources */ = {isa = PBXBuildFile; fileRef = 115C0CA518035BC5004E6CD7 /* proto-netbios.c */; }; + 118D68102B02DD6F00271F7F /* vulncheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD363F2107E7ED00CBE1DE /* vulncheck.c */; }; + 118D68112B02DD6F00271F7F /* proto-ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = 115C0CA718035BC5004E6CD7 /* proto-ssl.c */; }; + 118D68122B02DD6F00271F7F /* in-binary.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A868081816F3A7008E00B8 /* in-binary.c */; }; + 118D68132B02DD6F00271F7F /* stack-src.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A8680B1816F3A7008E00B8 /* stack-src.c */; }; + 118D68142B02DD6F00271F7F /* vulncheck-ntp-monlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36402107E7ED00CBE1DE /* vulncheck-ntp-monlist.c */; }; + 118D68152B02DD6F00271F7F /* misc-rstfilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 11469CA12295D80A00FA76BE /* misc-rstfilter.c */; }; + 118D68162B02DD6F00271F7F /* masscan-app.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A8680D1816F3A7008E00B8 /* masscan-app.c */; }; + 118D68172B02DD6F00271F7F /* out-redis.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A8680F1816F3A7008E00B8 /* out-redis.c */; }; + 118D68182B02DD6F00271F7F /* pixie-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A868101816F3A7008E00B8 /* pixie-file.c */; }; + 118D68192B02DD6F00271F7F /* crypto-siphash24.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A868131816F3A7008E00B8 /* crypto-siphash24.c */; }; + 118D681A2B02DD6F00271F7F /* stack-if.c in Sources */ = {isa = PBXBuildFile; fileRef = 1124DD6C25B4FF3C00EEFC2C /* stack-if.c */; }; + 118D681B2B02DD6F00271F7F /* proto-zeroaccess.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A8681C1819A6F7008E00B8 /* proto-zeroaccess.c */; }; + 118D681C2B02DD6F00271F7F /* proto-banout.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B22ED018641DCC00DA5438 /* proto-banout.c */; }; + 118D681D2B02DD6F00271F7F /* proto-ssl-test.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B22ED218641DCC00DA5438 /* proto-ssl-test.c */; }; + 118D681E2B02DD6F00271F7F /* util-checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 118E115525859D5300618314 /* util-checksum.c */; }; + 118D681F2B02DD6F00271F7F /* proto-x509.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B22ED318641DCC00DA5438 /* proto-x509.c */; }; + 118D68202B02DD6F00271F7F /* crypto-base64.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A773E91881BFC700B135DE /* crypto-base64.c */; }; + 118D68212B02DD6F00271F7F /* pixie-backtrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 11E76DB21889BC5200061F45 /* pixie-backtrace.c */; }; + 118D68222B02DD6F00271F7F /* proto-sctp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11AC2F99188CE34A008CB623 /* proto-sctp.c */; }; + 118D68232B02DD6F00271F7F /* out-grepable.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BA295F18902CEE0064A759 /* out-grepable.c */; }; + 118D68242B02DD6F00271F7F /* proto-tcp-telnet.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BA296018902CEE0064A759 /* proto-tcp-telnet.c */; }; + 118D68252B02DD6F00271F7F /* proto-ntp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BA296A189060220064A759 /* proto-ntp.c */; }; + 118D68262B02DD6F00271F7F /* scripting.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD363A2107DFEB00CBE1DE /* scripting.c */; }; + 118D68272B02DD6F00271F7F /* crypto-blackrock2.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B05EA418B9649F009C935E /* crypto-blackrock2.c */; }; + 118D68282B02DD6F00271F7F /* out-ndjson.c in Sources */ = {isa = PBXBuildFile; fileRef = 112A87191F9D8DF200D4D240 /* out-ndjson.c */; }; + 118D68292B02DD6F00271F7F /* main-readrange.c in Sources */ = {isa = PBXBuildFile; fileRef = 11B05EA518B9649F009C935E /* main-readrange.c */; }; + 118D682A2B02DD6F00271F7F /* out-json.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A50CAD191C128F006D5802 /* out-json.c */; }; + 118D682B2B02DD6F00271F7F /* out-certs.c in Sources */ = {isa = PBXBuildFile; fileRef = 11623F69191E0DB00075EEE6 /* out-certs.c */; }; + 118D682C2B02DD6F00271F7F /* out-unicornscan.c in Sources */ = {isa = PBXBuildFile; fileRef = 11126596197A086B00DC5987 /* out-unicornscan.c */; }; + 118D682D2B02DD6F00271F7F /* proto-vnc.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DD219A2D47A00DB5BFE /* proto-vnc.c */; }; + 118D682E2B02DD6F00271F7F /* in-filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 11C936BF1EDCE77F0023D32E /* in-filter.c */; }; + 118D682F2B02DD6F00271F7F /* proto-ftp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DD719A8160500DB5BFE /* proto-ftp.c */; }; + 118D68302B02DD6F00271F7F /* proto-oproto.c in Sources */ = {isa = PBXBuildFile; fileRef = 110C79AF22833AF9003FAC94 /* proto-oproto.c */; }; + 118D68312B02DD6F00271F7F /* proto-smtp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDA19A84A9E00DB5BFE /* proto-smtp.c */; }; + 118D68322B02DD6F00271F7F /* out-tcp-services.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD363321067BD300CBE1DE /* out-tcp-services.c */; }; + 118D68332B02DD6F00271F7F /* proto-pop3.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDD19A8FDE300DB5BFE /* proto-pop3.c */; }; + 118D68342B02DD6F00271F7F /* stack-tcp-app.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DDF19A90CB300DB5BFE /* stack-tcp-app.c */; }; + 118D68352B02DD6F00271F7F /* proto-imap4.c in Sources */ = {isa = PBXBuildFile; fileRef = 11420DE219A9363A00DB5BFE /* proto-imap4.c */; }; + 118D68362B02DD6F00271F7F /* massip-parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 118B9B2F25A00FA900F5FB0B /* massip-parse.c */; }; + 118D68372B02DD6F00271F7F /* out-hostonly.c in Sources */ = {isa = PBXBuildFile; fileRef = 1124DD6A25B4FF1600EEFC2C /* out-hostonly.c */; }; + 118D68382B02DD6F00271F7F /* stub-lua.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36362107DE9700CBE1DE /* stub-lua.c */; }; 118E115725859D5300618314 /* util-checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 118E115525859D5300618314 /* util-checksum.c */; }; 118E115925859E6F00618314 /* rawsock-getip6.c in Sources */ = {isa = PBXBuildFile; fileRef = 118E115825859E6F00618314 /* rawsock-getip6.c */; }; 119968FC21388A3C00E82767 /* read-service-probes.c in Sources */ = {isa = PBXBuildFile; fileRef = 119968FB21388A3B00E82767 /* read-service-probes.c */; }; @@ -48,7 +163,7 @@ 11A8681A1816F3A7008E00B8 /* crypto-siphash24.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A868131816F3A7008E00B8 /* crypto-siphash24.c */; }; 11A8681E1819A6F7008E00B8 /* proto-zeroaccess.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A8681C1819A6F7008E00B8 /* proto-zeroaccess.c */; }; 11A921D517DBCC7E00DDFD32 /* event-timeout.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219317DBCC7E00DDFD32 /* event-timeout.c */; }; - 11A921D617DBCC7E00DDFD32 /* logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219517DBCC7E00DDFD32 /* logger.c */; }; + 11A921D617DBCC7E00DDFD32 /* util-logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219517DBCC7E00DDFD32 /* util-logger.c */; }; 11A921D717DBCC7E00DDFD32 /* main-conf.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219717DBCC7E00DDFD32 /* main-conf.c */; }; 11A921D817DBCC7E00DDFD32 /* main-dedup.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219817DBCC7E00DDFD32 /* main-dedup.c */; }; 11A921D917DBCC7E00DDFD32 /* main-initadapter.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A9219A17DBCC7E00DDFD32 /* main-initadapter.c */; }; @@ -65,7 +180,7 @@ 11A921E417DBCC7E00DDFD32 /* proto-arp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921AC17DBCC7E00DDFD32 /* proto-arp.c */; }; 11A921E517DBCC7E00DDFD32 /* proto-banner1.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921AE17DBCC7E00DDFD32 /* proto-banner1.c */; }; 11A921E617DBCC7E00DDFD32 /* proto-preprocess.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B017DBCC7E00DDFD32 /* proto-preprocess.c */; }; - 11A921E717DBCC7E00DDFD32 /* proto-tcp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B217DBCC7E00DDFD32 /* proto-tcp.c */; }; + 11A921E717DBCC7E00DDFD32 /* stack-tcp-core.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B217DBCC7E00DDFD32 /* stack-tcp-core.c */; }; 11A921E817DBCC7E00DDFD32 /* crypto-blackrock.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B417DBCC7E00DDFD32 /* crypto-blackrock.c */; }; 11A921E917DBCC7E00DDFD32 /* crypto-lcg.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B617DBCC7E00DDFD32 /* crypto-lcg.c */; }; 11A921EA17DBCC7E00DDFD32 /* crypto-primegen.c in Sources */ = {isa = PBXBuildFile; fileRef = 11A921B817DBCC7E00DDFD32 /* crypto-primegen.c */; }; @@ -104,6 +219,7 @@ 11BA296318902CEE0064A759 /* proto-tcp-telnet.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BA296018902CEE0064A759 /* proto-tcp-telnet.c */; }; 11BA296B189060220064A759 /* proto-ntp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BA296A189060220064A759 /* proto-ntp.c */; }; 11BE533625A6441100451F95 /* massip-addr.c in Sources */ = {isa = PBXBuildFile; fileRef = 11BE533525A6441100451F95 /* massip-addr.c */; }; + 11C000652AFDA179001EB0EB /* proto-isakmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 11C000632AFDA178001EB0EB /* proto-isakmp.c */; }; 11C936C31EDCE77F0023D32E /* in-filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 11C936BF1EDCE77F0023D32E /* in-filter.c */; }; 11C936C41EDCE77F0023D32E /* in-report.c in Sources */ = {isa = PBXBuildFile; fileRef = 11C936C11EDCE77F0023D32E /* in-report.c */; }; 11D0FAFB22763F4900332FA7 /* proto-coap.c in Sources */ = {isa = PBXBuildFile; fileRef = 11D0FAFA22763F4900332FA7 /* proto-coap.c */; }; @@ -115,13 +231,22 @@ 11DD36432107E7ED00CBE1DE /* vulncheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD363F2107E7ED00CBE1DE /* vulncheck.c */; }; 11DD36442107E7ED00CBE1DE /* vulncheck-ntp-monlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36402107E7ED00CBE1DE /* vulncheck-ntp-monlist.c */; }; 11DD36462107EB8700CBE1DE /* scripting-masscan.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36452107EB8700CBE1DE /* scripting-masscan.c */; }; - 11DD36492108DCBB00CBE1DE /* versioning.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36472108DCBB00CBE1DE /* versioning.c */; }; + 11DD36492108DCBB00CBE1DE /* proto-versioning.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD36472108DCBB00CBE1DE /* proto-versioning.c */; }; 11DD364B2108E0CB00CBE1DE /* scripting-banner.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DD364A2108E0CB00CBE1DE /* scripting-banner.c */; }; 11DE129620ABC2650041135D /* proto-smb.c in Sources */ = {isa = PBXBuildFile; fileRef = 11DE129520ABC2650041135D /* proto-smb.c */; }; 11E76DB41889BC5200061F45 /* pixie-backtrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 11E76DB21889BC5200061F45 /* pixie-backtrace.c */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ + 118D683A2B02DD6F00271F7F /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 11A9218317DBCB3200DDFD32 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -156,7 +281,7 @@ 11420DDA19A84A9E00DB5BFE /* proto-smtp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-smtp.c"; sourceTree = ""; }; 11420DDC19A8F2D200DB5BFE /* proto-pop3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "proto-pop3.h"; sourceTree = ""; }; 11420DDD19A8FDE300DB5BFE /* proto-pop3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-pop3.c"; sourceTree = ""; }; - 11420DDF19A90CB300DB5BFE /* proto-interactive.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-interactive.c"; sourceTree = ""; }; + 11420DDF19A90CB300DB5BFE /* stack-tcp-app.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "stack-tcp-app.c"; sourceTree = ""; }; 11420DE119A9361500DB5BFE /* proto-imap4.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "proto-imap4.h"; sourceTree = ""; }; 11420DE219A9363A00DB5BFE /* proto-imap4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-imap4.c"; sourceTree = ""; }; 11469CA02295D80A00FA76BE /* misc-rstfilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "misc-rstfilter.h"; sourceTree = ""; }; @@ -185,7 +310,10 @@ 118B9B2F25A00FA900F5FB0B /* massip-parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "massip-parse.c"; sourceTree = ""; }; 118B9B3025A00FA900F5FB0B /* massip-parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "massip-parse.h"; sourceTree = ""; }; 118B9B3125A00FA900F5FB0B /* massip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = massip.c; sourceTree = ""; }; - 118E115325859D2400618314 /* proto-interactive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-interactive.h"; sourceTree = ""; }; + 118D67C12B02CBA000271F7F /* util-errormsg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "util-errormsg.h"; sourceTree = ""; }; + 118D67C22B02CBA000271F7F /* util-errormsg.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "util-errormsg.c"; sourceTree = ""; }; + 118D683E2B02DD6F00271F7F /* masscan copy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "masscan copy"; sourceTree = BUILT_PRODUCTS_DIR; }; + 118E115325859D2400618314 /* stack-tcp-api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "stack-tcp-api.h"; sourceTree = ""; }; 118E115425859D5200618314 /* util-bool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "util-bool.h"; sourceTree = ""; }; 118E115525859D5300618314 /* util-checksum.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "util-checksum.c"; sourceTree = ""; }; 118E115625859D5300618314 /* util-checksum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "util-checksum.h"; sourceTree = ""; }; @@ -219,8 +347,8 @@ 11A9218517DBCB3200DDFD32 /* masscan */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = masscan; sourceTree = BUILT_PRODUCTS_DIR; }; 11A9219317DBCC7E00DDFD32 /* event-timeout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "event-timeout.c"; sourceTree = ""; }; 11A9219417DBCC7E00DDFD32 /* event-timeout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "event-timeout.h"; sourceTree = ""; }; - 11A9219517DBCC7E00DDFD32 /* logger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = logger.c; sourceTree = ""; }; - 11A9219617DBCC7E00DDFD32 /* logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logger.h; sourceTree = ""; }; + 11A9219517DBCC7E00DDFD32 /* util-logger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "util-logger.c"; sourceTree = ""; }; + 11A9219617DBCC7E00DDFD32 /* util-logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "util-logger.h"; sourceTree = ""; }; 11A9219717DBCC7E00DDFD32 /* main-conf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "main-conf.c"; sourceTree = ""; }; 11A9219817DBCC7E00DDFD32 /* main-dedup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "main-dedup.c"; sourceTree = ""; }; 11A9219917DBCC7E00DDFD32 /* main-dedup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "main-dedup.h"; sourceTree = ""; }; @@ -237,7 +365,6 @@ 11A921A417DBCC7E00DDFD32 /* out-xml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "out-xml.c"; sourceTree = ""; }; 11A921A517DBCC7E00DDFD32 /* output.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = output.c; sourceTree = ""; }; 11A921A617DBCC7E00DDFD32 /* output.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = output.h; sourceTree = ""; }; - 11A921A717DBCC7E00DDFD32 /* packet-queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "packet-queue.h"; sourceTree = ""; }; 11A921A817DBCC7E00DDFD32 /* pixie-threads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pixie-threads.c"; sourceTree = ""; }; 11A921A917DBCC7E00DDFD32 /* pixie-threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "pixie-threads.h"; sourceTree = ""; }; 11A921AA17DBCC7E00DDFD32 /* pixie-timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "pixie-timer.c"; sourceTree = ""; }; @@ -248,8 +375,8 @@ 11A921AF17DBCC7E00DDFD32 /* proto-banner1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-banner1.h"; sourceTree = ""; }; 11A921B017DBCC7E00DDFD32 /* proto-preprocess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-preprocess.c"; sourceTree = ""; }; 11A921B117DBCC7E00DDFD32 /* proto-preprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-preprocess.h"; sourceTree = ""; }; - 11A921B217DBCC7E00DDFD32 /* proto-tcp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-tcp.c"; sourceTree = ""; }; - 11A921B317DBCC7E00DDFD32 /* proto-tcp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-tcp.h"; sourceTree = ""; }; + 11A921B217DBCC7E00DDFD32 /* stack-tcp-core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "stack-tcp-core.c"; sourceTree = ""; }; + 11A921B317DBCC7E00DDFD32 /* stack-tcp-core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "stack-tcp-core.h"; sourceTree = ""; }; 11A921B417DBCC7E00DDFD32 /* crypto-blackrock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "crypto-blackrock.c"; sourceTree = ""; }; 11A921B517DBCC7E00DDFD32 /* crypto-blackrock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "crypto-blackrock.h"; sourceTree = ""; }; 11A921B617DBCC7E00DDFD32 /* crypto-lcg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "crypto-lcg.c"; sourceTree = ""; }; @@ -321,6 +448,9 @@ 11BE532E25A62C4100451F95 /* massip-port.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "massip-port.h"; sourceTree = ""; }; 11BE533425A6441100451F95 /* massip-addr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "massip-addr.h"; sourceTree = ""; }; 11BE533525A6441100451F95 /* massip-addr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "massip-addr.c"; sourceTree = ""; }; + 11C000632AFDA178001EB0EB /* proto-isakmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-isakmp.c"; sourceTree = ""; }; + 11C000642AFDA179001EB0EB /* proto-isakmp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-isakmp.h"; sourceTree = ""; }; + 11C000672B01CB16001EB0EB /* stack-tcp-app.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "stack-tcp-app.h"; sourceTree = ""; }; 11C936BF1EDCE77F0023D32E /* in-filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "in-filter.c"; sourceTree = ""; }; 11C936C01EDCE77F0023D32E /* in-filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "in-filter.h"; sourceTree = ""; }; 11C936C11EDCE77F0023D32E /* in-report.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "in-report.c"; sourceTree = ""; }; @@ -339,8 +469,8 @@ 11DD363F2107E7ED00CBE1DE /* vulncheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vulncheck.c; sourceTree = ""; }; 11DD36402107E7ED00CBE1DE /* vulncheck-ntp-monlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "vulncheck-ntp-monlist.c"; sourceTree = ""; }; 11DD36452107EB8700CBE1DE /* scripting-masscan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "scripting-masscan.c"; sourceTree = ""; }; - 11DD36472108DCBB00CBE1DE /* versioning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = versioning.c; sourceTree = ""; }; - 11DD36482108DCBB00CBE1DE /* versioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = versioning.h; sourceTree = ""; }; + 11DD36472108DCBB00CBE1DE /* proto-versioning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-versioning.c"; sourceTree = ""; }; + 11DD36482108DCBB00CBE1DE /* proto-versioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-versioning.h"; sourceTree = ""; }; 11DD364A2108E0CB00CBE1DE /* scripting-banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "scripting-banner.c"; sourceTree = ""; }; 11DE129420ABC2650041135D /* proto-smb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "proto-smb.h"; sourceTree = ""; }; 11DE129520ABC2650041135D /* proto-smb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "proto-smb.c"; sourceTree = ""; }; @@ -349,6 +479,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 118D68392B02DD6F00271F7F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 11A9218217DBCB3200DDFD32 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -393,6 +530,7 @@ 118E114E2585931800618314 /* stack */ = { isa = PBXGroup; children = ( + 11C000672B01CB16001EB0EB /* stack-tcp-app.h */, 1124DD6D25B4FF3C00EEFC2C /* stack-arpv4.c */, 1124DD6E25B4FF3C00EEFC2C /* stack-arpv4.h */, 1124DD6C25B4FF3C00EEFC2C /* stack-if.c */, @@ -400,6 +538,10 @@ 11B6297825995AA100D4786F /* stack-ndpv6.h */, 11B6297525995AA100D4786F /* stack-queue.c */, 11B6297725995AA100D4786F /* stack-queue.h */, + 11A921B217DBCC7E00DDFD32 /* stack-tcp-core.c */, + 11A921B317DBCC7E00DDFD32 /* stack-tcp-core.h */, + 118E115325859D2400618314 /* stack-tcp-api.h */, + 11420DDF19A90CB300DB5BFE /* stack-tcp-app.c */, 11A8680B1816F3A7008E00B8 /* stack-src.c */, 11A8680C1816F3A7008E00B8 /* stack-src.h */, ); @@ -409,6 +551,8 @@ 118E114F25859CFD00618314 /* util */ = { isa = PBXGroup; children = ( + 118D67C22B02CBA000271F7F /* util-errormsg.c */, + 118D67C12B02CBA000271F7F /* util-errormsg.h */, 115C0CAA18035BC5004E6CD7 /* unusedparm.h */, 11B5897C21C0785B00DD6248 /* util-malloc.h */, 11B5897D21C0785B00DD6248 /* util-malloc.c */, @@ -432,6 +576,7 @@ isa = PBXGroup; children = ( 11A9218517DBCB3200DDFD32 /* masscan */, + 118D683E2B02DD6F00271F7F /* masscan copy */, ); name = Products; sourceTree = ""; @@ -534,7 +679,8 @@ 11B360CA1F9016C00020F3A3 /* proto */ = { isa = PBXGroup; children = ( - 1155CF172AF8509A001B235A /* templ-opts.h */, + 11DD36482108DCBB00CBE1DE /* proto-versioning.h */, + 11DD36472108DCBB00CBE1DE /* proto-versioning.c */, 11A921AC17DBCC7E00DDFD32 /* proto-arp.c */, 11A921AD17DBCC7E00DDFD32 /* proto-arp.h */, 11A921AE17DBCC7E00DDFD32 /* proto-banner1.c */, @@ -554,8 +700,8 @@ 11AC80EA17E0DAD4001BCE3A /* proto-icmp.h */, 11420DE219A9363A00DB5BFE /* proto-imap4.c */, 11420DE119A9361500DB5BFE /* proto-imap4.h */, - 11420DDF19A90CB300DB5BFE /* proto-interactive.c */, - 118E115325859D2400618314 /* proto-interactive.h */, + 11C000632AFDA178001EB0EB /* proto-isakmp.c */, + 11C000642AFDA179001EB0EB /* proto-isakmp.h */, 1155CF0F2AF2FE12001B235A /* proto-mc.c */, 1155CF0E2AF2FE12001B235A /* proto-mc.h */, 119AB2042051FFED008E4DDD /* proto-memcached.c */, @@ -590,8 +736,6 @@ 1107E9B0228DF7BB003384B3 /* proto-tcp-rdp.h */, 11BA296018902CEE0064A759 /* proto-tcp-telnet.c */, 11BA296118902CEE0064A759 /* proto-tcp-telnet.h */, - 11A921B217DBCC7E00DDFD32 /* proto-tcp.c */, - 11A921B317DBCC7E00DDFD32 /* proto-tcp.h */, 11B039C517E7834000925E7E /* proto-udp.c */, 11B039C617E7834000925E7E /* proto-udp.h */, 11420DD219A2D47A00DB5BFE /* proto-vnc.c */, @@ -602,6 +746,7 @@ 11A8681D1819A6F7008E00B8 /* proto-zeroaccess.h */, 1155CF112AF6EF72001B235A /* templ-nmap-payloads.c */, 1155CF122AF6EF72001B235A /* templ-nmap-payloads.h */, + 1155CF172AF8509A001B235A /* templ-opts.h */, 11B2DD9C17DE4DD8007FC363 /* templ-payloads.c */, 11B2DD9D17DE4DD8007FC363 /* templ-payloads.h */, 11A921D117DBCC7E00DDFD32 /* templ-pkt.c */, @@ -663,11 +808,10 @@ 11A921CC17DBCC7E00DDFD32 /* smackqueue.h */, 11A921CD17DBCC7E00DDFD32 /* string_s.c */, 11A921CE17DBCC7E00DDFD32 /* string_s.h */, - 11A921A717DBCC7E00DDFD32 /* packet-queue.h */, 11A9219317DBCC7E00DDFD32 /* event-timeout.c */, 11A9219417DBCC7E00DDFD32 /* event-timeout.h */, - 11A9219517DBCC7E00DDFD32 /* logger.c */, - 11A9219617DBCC7E00DDFD32 /* logger.h */, + 11A9219517DBCC7E00DDFD32 /* util-logger.c */, + 11A9219617DBCC7E00DDFD32 /* util-logger.h */, ); name = misc; sourceTree = ""; @@ -676,8 +820,6 @@ isa = PBXGroup; children = ( 11DD364A2108E0CB00CBE1DE /* scripting-banner.c */, - 11DD36472108DCBB00CBE1DE /* versioning.c */, - 11DD36482108DCBB00CBE1DE /* versioning.h */, 11DD36452107EB8700CBE1DE /* scripting-masscan.c */, 11DD363C2107E7ED00CBE1DE /* vulncheck-heartbleed.c */, 11DD36402107E7ED00CBE1DE /* vulncheck-ntp-monlist.c */, @@ -693,6 +835,23 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 118D67C52B02DD6F00271F7F /* masscan copy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 118D683B2B02DD6F00271F7F /* Build configuration list for PBXNativeTarget "masscan copy" */; + buildPhases = ( + 118D67C62B02DD6F00271F7F /* Sources */, + 118D68392B02DD6F00271F7F /* Frameworks */, + 118D683A2B02DD6F00271F7F /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "masscan copy"; + productName = xcode4; + productReference = 118D683E2B02DD6F00271F7F /* masscan copy */; + productType = "com.apple.product-type.tool"; + }; 11A9218417DBCB3200DDFD32 /* masscan */ = { isa = PBXNativeTarget; buildConfigurationList = 11A9218F17DBCB3200DDFD32 /* Build configuration list for PBXNativeTarget "masscan" */; @@ -732,11 +891,133 @@ projectRoot = ""; targets = ( 11A9218417DBCB3200DDFD32 /* masscan */, + 118D67C52B02DD6F00271F7F /* masscan copy */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ + 118D67C62B02DD6F00271F7F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 118D67C72B02DD6F00271F7F /* stack-queue.c in Sources */, + 118D67C82B02DD6F00271F7F /* event-timeout.c in Sources */, + 118D67C92B02DD6F00271F7F /* vulncheck-heartbleed.c in Sources */, + 118D67CA2B02DD6F00271F7F /* massip-rangesv6.c in Sources */, + 118D67CB2B02DD6F00271F7F /* util-logger.c in Sources */, + 118D67CC2B02DD6F00271F7F /* stub-pfring.c in Sources */, + 118D67CD2B02DD6F00271F7F /* main-conf.c in Sources */, + 118D67CE2B02DD6F00271F7F /* main-dedup.c in Sources */, + 118D67CF2B02DD6F00271F7F /* main-initadapter.c in Sources */, + 118D67D02B02DD6F00271F7F /* main-status.c in Sources */, + 118D67D12B02DD6F00271F7F /* rawsock-getip6.c in Sources */, + 118D67D22B02DD6F00271F7F /* main-throttle.c in Sources */, + 118D67D32B02DD6F00271F7F /* main.c in Sources */, + 118D67D42B02DD6F00271F7F /* vulncheck-sslv3.c in Sources */, + 118D67D52B02DD6F00271F7F /* out-binary.c in Sources */, + 118D67D62B02DD6F00271F7F /* out-null.c in Sources */, + 118D67D72B02DD6F00271F7F /* proto-ntlmssp.c in Sources */, + 118D67D82B02DD6F00271F7F /* out-text.c in Sources */, + 118D67D92B02DD6F00271F7F /* out-xml.c in Sources */, + 118D67DA2B02DD6F00271F7F /* output.c in Sources */, + 118D67DB2B02DD6F00271F7F /* pixie-threads.c in Sources */, + 118D67DC2B02DD6F00271F7F /* pixie-timer.c in Sources */, + 118D67DD2B02DD6F00271F7F /* read-service-probes.c in Sources */, + 118D67DE2B02DD6F00271F7F /* proto-arp.c in Sources */, + 118D67DF2B02DD6F00271F7F /* proto-banner1.c in Sources */, + 118D67E02B02DD6F00271F7F /* stub-pcap.c in Sources */, + 118D67E12B02DD6F00271F7F /* proto-tcp-rdp.c in Sources */, + 118D67E22B02DD6F00271F7F /* proto-preprocess.c in Sources */, + 118D67E32B02DD6F00271F7F /* stack-tcp-core.c in Sources */, + 118D67E42B02DD6F00271F7F /* crypto-blackrock.c in Sources */, + 118D67E52B02DD6F00271F7F /* crypto-lcg.c in Sources */, + 118D67E62B02DD6F00271F7F /* crypto-primegen.c in Sources */, + 118D67E72B02DD6F00271F7F /* rawsock-getif.c in Sources */, + 118D67E82B02DD6F00271F7F /* rawsock-getip.c in Sources */, + 118D67E92B02DD6F00271F7F /* proto-isakmp.c in Sources */, + 118D67EA2B02DD6F00271F7F /* templ-tcp-hdr.c in Sources */, + 118D67EB2B02DD6F00271F7F /* rawsock-getmac.c in Sources */, + 118D67EC2B02DD6F00271F7F /* util-malloc.c in Sources */, + 118D67ED2B02DD6F00271F7F /* rawsock-getroute.c in Sources */, + 118D67EE2B02DD6F00271F7F /* proto-versioning.c in Sources */, + 118D67EF2B02DD6F00271F7F /* proto-coap.c in Sources */, + 118D67F02B02DD6F00271F7F /* in-report.c in Sources */, + 118D67F12B02DD6F00271F7F /* rawsock-pcapfile.c in Sources */, + 118D67F22B02DD6F00271F7F /* rawsock.c in Sources */, + 118D67F32B02DD6F00271F7F /* scripting-banner.c in Sources */, + 118D67F42B02DD6F00271F7F /* rte-ring.c in Sources */, + 118D67F52B02DD6F00271F7F /* smack1.c in Sources */, + 118D67F62B02DD6F00271F7F /* massip-rangesv4.c in Sources */, + 118D67F72B02DD6F00271F7F /* smackqueue.c in Sources */, + 118D67F82B02DD6F00271F7F /* string_s.c in Sources */, + 118D67F92B02DD6F00271F7F /* stack-ndpv6.c in Sources */, + 118D67FA2B02DD6F00271F7F /* syn-cookie.c in Sources */, + 118D67FB2B02DD6F00271F7F /* stack-arpv4.c in Sources */, + 118D67FC2B02DD6F00271F7F /* templ-nmap-payloads.c in Sources */, + 118D67FD2B02DD6F00271F7F /* util-errormsg.c in Sources */, + 118D67FE2B02DD6F00271F7F /* templ-pkt.c in Sources */, + 118D67FF2B02DD6F00271F7F /* xring.c in Sources */, + 118D68002B02DD6F00271F7F /* proto-smb.c in Sources */, + 118D68012B02DD6F00271F7F /* templ-payloads.c in Sources */, + 118D68022B02DD6F00271F7F /* proto-http.c in Sources */, + 118D68032B02DD6F00271F7F /* proto-icmp.c in Sources */, + 118D68042B02DD6F00271F7F /* proto-ssh.c in Sources */, + 118D68052B02DD6F00271F7F /* main-ptrace.c in Sources */, + 118D68062B02DD6F00271F7F /* proto-memcached.c in Sources */, + 118D68072B02DD6F00271F7F /* scripting-masscan.c in Sources */, + 118D68082B02DD6F00271F7F /* massip.c in Sources */, + 118D68092B02DD6F00271F7F /* proto-mc.c in Sources */, + 118D680A2B02DD6F00271F7F /* massip-addr.c in Sources */, + 118D680B2B02DD6F00271F7F /* main-listscan.c in Sources */, + 118D680C2B02DD6F00271F7F /* proto-dns.c in Sources */, + 118D680D2B02DD6F00271F7F /* proto-udp.c in Sources */, + 118D680E2B02DD6F00271F7F /* proto-snmp.c in Sources */, + 118D680F2B02DD6F00271F7F /* proto-netbios.c in Sources */, + 118D68102B02DD6F00271F7F /* vulncheck.c in Sources */, + 118D68112B02DD6F00271F7F /* proto-ssl.c in Sources */, + 118D68122B02DD6F00271F7F /* in-binary.c in Sources */, + 118D68132B02DD6F00271F7F /* stack-src.c in Sources */, + 118D68142B02DD6F00271F7F /* vulncheck-ntp-monlist.c in Sources */, + 118D68152B02DD6F00271F7F /* misc-rstfilter.c in Sources */, + 118D68162B02DD6F00271F7F /* masscan-app.c in Sources */, + 118D68172B02DD6F00271F7F /* out-redis.c in Sources */, + 118D68182B02DD6F00271F7F /* pixie-file.c in Sources */, + 118D68192B02DD6F00271F7F /* crypto-siphash24.c in Sources */, + 118D681A2B02DD6F00271F7F /* stack-if.c in Sources */, + 118D681B2B02DD6F00271F7F /* proto-zeroaccess.c in Sources */, + 118D681C2B02DD6F00271F7F /* proto-banout.c in Sources */, + 118D681D2B02DD6F00271F7F /* proto-ssl-test.c in Sources */, + 118D681E2B02DD6F00271F7F /* util-checksum.c in Sources */, + 118D681F2B02DD6F00271F7F /* proto-x509.c in Sources */, + 118D68202B02DD6F00271F7F /* crypto-base64.c in Sources */, + 118D68212B02DD6F00271F7F /* pixie-backtrace.c in Sources */, + 118D68222B02DD6F00271F7F /* proto-sctp.c in Sources */, + 118D68232B02DD6F00271F7F /* out-grepable.c in Sources */, + 118D68242B02DD6F00271F7F /* proto-tcp-telnet.c in Sources */, + 118D68252B02DD6F00271F7F /* proto-ntp.c in Sources */, + 118D68262B02DD6F00271F7F /* scripting.c in Sources */, + 118D68272B02DD6F00271F7F /* crypto-blackrock2.c in Sources */, + 118D68282B02DD6F00271F7F /* out-ndjson.c in Sources */, + 118D68292B02DD6F00271F7F /* main-readrange.c in Sources */, + 118D682A2B02DD6F00271F7F /* out-json.c in Sources */, + 118D682B2B02DD6F00271F7F /* out-certs.c in Sources */, + 118D682C2B02DD6F00271F7F /* out-unicornscan.c in Sources */, + 118D682D2B02DD6F00271F7F /* proto-vnc.c in Sources */, + 118D682E2B02DD6F00271F7F /* in-filter.c in Sources */, + 118D682F2B02DD6F00271F7F /* proto-ftp.c in Sources */, + 118D68302B02DD6F00271F7F /* proto-oproto.c in Sources */, + 118D68312B02DD6F00271F7F /* proto-smtp.c in Sources */, + 118D68322B02DD6F00271F7F /* out-tcp-services.c in Sources */, + 118D68332B02DD6F00271F7F /* proto-pop3.c in Sources */, + 118D68342B02DD6F00271F7F /* stack-tcp-app.c in Sources */, + 118D68352B02DD6F00271F7F /* proto-imap4.c in Sources */, + 118D68362B02DD6F00271F7F /* massip-parse.c in Sources */, + 118D68372B02DD6F00271F7F /* out-hostonly.c in Sources */, + 118D68382B02DD6F00271F7F /* stub-lua.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 11A9218117DBCB3200DDFD32 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -745,7 +1026,7 @@ 11A921D517DBCC7E00DDFD32 /* event-timeout.c in Sources */, 11DD36412107E7ED00CBE1DE /* vulncheck-heartbleed.c in Sources */, 118B9B3325A00FA900F5FB0B /* massip-rangesv6.c in Sources */, - 11A921D617DBCC7E00DDFD32 /* logger.c in Sources */, + 11A921D617DBCC7E00DDFD32 /* util-logger.c in Sources */, 119969002141AB3600E82767 /* stub-pfring.c in Sources */, 11A921D717DBCC7E00DDFD32 /* main-conf.c in Sources */, 11A921D817DBCC7E00DDFD32 /* main-dedup.c in Sources */, @@ -769,17 +1050,18 @@ 119969012141AB3600E82767 /* stub-pcap.c in Sources */, 1107E9B2228DF7BB003384B3 /* proto-tcp-rdp.c in Sources */, 11A921E617DBCC7E00DDFD32 /* proto-preprocess.c in Sources */, - 11A921E717DBCC7E00DDFD32 /* proto-tcp.c in Sources */, + 11A921E717DBCC7E00DDFD32 /* stack-tcp-core.c in Sources */, 11A921E817DBCC7E00DDFD32 /* crypto-blackrock.c in Sources */, 11A921E917DBCC7E00DDFD32 /* crypto-lcg.c in Sources */, 11A921EA17DBCC7E00DDFD32 /* crypto-primegen.c in Sources */, 11A921ED17DBCC7E00DDFD32 /* rawsock-getif.c in Sources */, 11A921EE17DBCC7E00DDFD32 /* rawsock-getip.c in Sources */, + 11C000652AFDA179001EB0EB /* proto-isakmp.c in Sources */, 1155CF162AF8311C001B235A /* templ-tcp-hdr.c in Sources */, 11A921EF17DBCC7E00DDFD32 /* rawsock-getmac.c in Sources */, 11B5897E21C0785C00DD6248 /* util-malloc.c in Sources */, 11A921F017DBCC7E00DDFD32 /* rawsock-getroute.c in Sources */, - 11DD36492108DCBB00CBE1DE /* versioning.c in Sources */, + 11DD36492108DCBB00CBE1DE /* proto-versioning.c in Sources */, 11D0FAFB22763F4900332FA7 /* proto-coap.c in Sources */, 11C936C41EDCE77F0023D32E /* in-report.c in Sources */, 11A921F117DBCC7E00DDFD32 /* rawsock-pcapfile.c in Sources */, @@ -794,6 +1076,7 @@ 11A921F817DBCC7E00DDFD32 /* syn-cookie.c in Sources */, 1124DD7025B4FF3C00EEFC2C /* stack-arpv4.c in Sources */, 1155CF132AF6EF72001B235A /* templ-nmap-payloads.c in Sources */, + 118D67C42B02D58F00271F7F /* util-errormsg.c in Sources */, 11A921F917DBCC7E00DDFD32 /* templ-pkt.c in Sources */, 11A921FA17DBCC7E00DDFD32 /* xring.c in Sources */, 11DE129620ABC2650041135D /* proto-smb.c in Sources */, @@ -848,7 +1131,7 @@ 11420DDB19A84A9F00DB5BFE /* proto-smtp.c in Sources */, 11DD363421067BD400CBE1DE /* out-tcp-services.c in Sources */, 11420DDE19A8FDE300DB5BFE /* proto-pop3.c in Sources */, - 11420DE019A90CB300DB5BFE /* proto-interactive.c in Sources */, + 11420DE019A90CB300DB5BFE /* stack-tcp-app.c in Sources */, 11420DE319A9363B00DB5BFE /* proto-imap4.c in Sources */, 118B9B3425A00FA900F5FB0B /* massip-parse.c in Sources */, 1124DD6B25B4FF1600EEFC2C /* out-hostonly.c in Sources */, @@ -859,6 +1142,53 @@ /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ + 118D683C2B02DD6F00271F7F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO; + CONFIGURATION_BUILD_DIR = ../bin; + CONFIGURATION_TEMP_DIR = ../tmp; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = NO; + OBJROOT = ../tmp; + OTHER_LDFLAGS = "-lpcap"; + "OTHER_TEST_FLAGS[sdk=*]" = "--selftest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + SYMROOT = ../bin; + TEST_AFTER_BUILD = YES; + }; + name = Debug; + }; + 118D683D2B02DD6F00271F7F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = NO; + CONFIGURATION_BUILD_DIR = ../bin; + CONFIGURATION_TEMP_DIR = ../tmp; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = NO; + OBJROOT = ../tmp; + OTHER_LDFLAGS = "-lpcap"; + OTHER_TEST_FLAGS = "--selftest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SYMROOT = ../bin; + TEST_AFTER_BUILD = YES; + }; + name = Release; + }; 11A9218D17DBCB3200DDFD32 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -918,9 +1248,10 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = NO; + GCC_WARN_UNUSED_VARIABLE = NO; OBJROOT = ../tmp; OTHER_LDFLAGS = "-lpcap"; - "OTHER_TEST_FLAGS[sdk=*]" = "--selftest"; + "OTHER_TEST_FLAGS[sdk=macosx*]" = "--selftest"; PRODUCT_NAME = masscan; RUN_CLANG_STATIC_ANALYZER = YES; SYMROOT = ../bin; @@ -942,6 +1273,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = NO; + GCC_WARN_UNUSED_VARIABLE = NO; OBJROOT = ../tmp; OTHER_LDFLAGS = "-lpcap"; OTHER_TEST_FLAGS = "--selftest"; @@ -954,6 +1286,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 118D683B2B02DD6F00271F7F /* Build configuration list for PBXNativeTarget "masscan copy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 118D683C2B02DD6F00271F7F /* Debug */, + 118D683D2B02DD6F00271F7F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 11A9217F17DBCB3200DDFD32 /* Build configuration list for PBXProject "masscan" */ = { isa = XCConfigurationList; buildConfigurations = (