diff --git a/src/proto-http.c b/src/proto-http.c index 671b5099..4dabda76 100644 --- a/src/proto-http.c +++ b/src/proto-http.c @@ -44,6 +44,18 @@ static struct Patterns html_fields[] = { }; extern struct ProtocolParserStream banner_http; +const char +HTTP_HELLO_TEMPLATE[] = "GET / HTTP/1.0\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" + "\r\n"; + /** * We might have an incomplete HTTP request header. Thus, as we insert @@ -128,6 +140,13 @@ http_change_requestline(unsigned char **hdr, size_t header_length, size_t offset; size_t start; + /* for non-initialized HTTP hello structure */ + if (*hdr == NULL) { + *hdr = MALLOC(strlen(HTTP_HELLO_TEMPLATE) + 1); + memcpy(*hdr, HTTP_HELLO_TEMPLATE, strlen(HTTP_HELLO_TEMPLATE)); + header_length = strlen(HTTP_HELLO_TEMPLATE); + } + /* If no length given, calculate length */ if (field_length == ~(size_t)0) field_length = strlen((const char *)field); @@ -381,20 +400,6 @@ http_change_field(unsigned char **inout_header, size_t header_length, return header_length; } -/*************************************************************************** - ***************************************************************************/ -static const char -http_hello[] = "GET / HTTP/1.0\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" - "\r\n"; - /***************************************************************************** *****************************************************************************/ @@ -460,8 +465,11 @@ http_init(struct Banner1 *b) html_fields[i].is_anchored); smack_compile(b->html_fields); - banner_http.hello = MALLOC(banner_http.hello_length); - memcpy((char*)banner_http.hello, http_hello, banner_http.hello_length); + /* initialize HTTP probe structure */ + memcpy(&banner_http, &BANNER_HTTP_TEMPLATE, sizeof(BANNER_HTTP_TEMPLATE)); + banner_http.hello = MALLOC(strlen(HTTP_HELLO_TEMPLATE) + 1); + banner_http.hello_length = strlen(HTTP_HELLO_TEMPLATE); + memcpy((char*)banner_http.hello, HTTP_HELLO_TEMPLATE, banner_http.hello_length); return b->http_fields; } @@ -943,10 +951,11 @@ http_selftest(void) /*************************************************************************** ***************************************************************************/ -struct ProtocolParserStream banner_http = { - "http", 80, http_hello, sizeof(http_hello)-1, 0, +const struct ProtocolParserStream BANNER_HTTP_TEMPLATE = { + "http", 80, NULL, 0, SF__close | SF__nowait_hello, http_selftest, http_init, http_parse, }; +struct ProtocolParserStream banner_http = BANNER_HTTP_TEMPLATE; diff --git a/src/proto-http.h b/src/proto-http.h index 30efdc72..538a6bc6 100644 --- a/src/proto-http.h +++ b/src/proto-http.h @@ -3,6 +3,8 @@ #include "proto-banner1.h" #include "util-bool.h" +extern const struct ProtocolParserStream BANNER_HTTP_TEMPLATE; +extern const char HTTP_HELLO_TEMPLATE[]; extern struct ProtocolParserStream banner_http; diff --git a/src/stack-tcp-core.c b/src/stack-tcp-core.c index 911056de..2de599cd 100644 --- a/src/stack-tcp-core.c +++ b/src/stack-tcp-core.c @@ -380,13 +380,18 @@ tcpcon_set_http_header(struct TCP_ConnectionTable *tcpcon, enum http_field_t what) { UNUSEDPARM(tcpcon); - banner_http.hello_length = http_change_field( - (unsigned char**)&banner_http.hello, - banner_http.hello_length, - name, - (const unsigned char *)value, - value_length, - what); + struct ProtocolParserStream *banner_iter = &banner_http; + /* change header on all HTTP banners in the linked-list */ + while (banner_iter != NULL) { + banner_iter->hello_length = http_change_field( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + name, + (const unsigned char *)value, + value_length, + what); + banner_iter = banner_iter->next; + } } @@ -401,25 +406,31 @@ tcpcon_set_parameter(struct TCP_ConnectionTable *tcpcon, const void *value) { struct Banner1 *banner1 = tcpcon->banner1; + struct ProtocolParserStream *banner_iter = &banner_http; if (name_equals(name, "http-payload")) { char lenstr[64]; snprintf(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); + /* change header on all HTTP banners in the linked-list */ + banner_iter = &banner_http; + while (banner_iter != NULL) { + banner_iter->hello_length = http_change_requestline( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + (const unsigned char *)value, + value_length, + 3); /* payload*/ + + banner_iter->hello_length = http_change_field( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + "Content-Length:", + (const unsigned char *)lenstr, + strlen(lenstr), + http_field_replace); + banner_iter = banner_iter->next; + } return; } @@ -430,23 +441,33 @@ tcpcon_set_parameter(struct TCP_ConnectionTable *tcpcon, * 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); + /* change header on all HTTP banners in the linked-list */ + banner_iter = &banner_http; + while (banner_iter != NULL) { + banner_iter->hello_length = http_change_field( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + "User-Agent:", + (const unsigned char *)value, + value_length, + http_field_replace); + banner_iter = banner_iter->next; + } 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); + /* change header on all HTTP banners in the linked-list */ + banner_iter = &banner_http; + while (banner_iter != NULL) { + banner_iter->hello_length = http_change_field( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + "Host:", + (const unsigned char *)value, + value_length, + http_field_replace); + banner_iter = banner_iter->next; + } return; } @@ -454,30 +475,64 @@ tcpcon_set_parameter(struct TCP_ConnectionTable *tcpcon, * 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*/ + /* change header on all HTTP banners in the linked-list */ + banner_iter = &banner_http; + while (banner_iter != NULL) { + banner_iter->hello_length = http_change_requestline( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + (const unsigned char *)value, + value_length, + 0); /* method*/ + banner_iter = banner_iter->next; + } 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 */ + /* special hack to specify multiple urls separated with "," + * e.g. --http-url "/index.html,/index.php" */ + const char *v = value; + unsigned v_len = 0; + unsigned nb_probes = 0; + struct ProtocolParserStream *banner = &banner_http; + while (v + v_len != value + value_length) { + v_len += 1; + while (v + v_len != value + value_length && v[v_len - 1] != ',' ) { + v_len += 1; + } + if (nb_probes > 0) { + banner->next = MALLOC(sizeof(*banner)); + banner = banner->next; + memcpy(banner, &banner_http, sizeof(banner_http)); + banner->hello = MALLOC(strlen(banner_http.hello) + 1); + banner->hello_length = banner_http.hello_length; + memcpy((char*)banner->hello, banner_http.hello, banner->hello_length); + } + banner->hello_length = http_change_requestline( + (unsigned char**)&banner->hello, + banner->hello_length, + (const unsigned char *)v, + v_len - ((v[v_len - 1] == ',')?1:0), + 1); /* url */ + banner->next = NULL; + nb_probes += 1; + v = v + v_len; + v_len = 0; + } 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 */ + /* change header on all HTTP banners in the linked-list */ + banner_iter = &banner_http; + while (banner_iter != NULL) { + banner_iter->hello_length = http_change_requestline( + (unsigned char**)&banner_iter->hello, + banner_iter->hello_length, + (const unsigned char *)value, + value_length, + 2); /* version */ + banner_iter = banner_iter->next; + } return; }