home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2000 January / PCW0001.ISO / software / hw / pc2000 / junkbust.exe / parsers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-07  |  12.5 KB  |  650 lines

  1. char *parsers_rcs = "$Id: parsers.c,v 1.26 1998/10/23 01:54:12 ACJC Exp $";
  2. /* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation.
  3.  * Distributed under the GNU General Public License; see the README file.
  4.  * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <stdlib.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12.  
  13. #ifndef _WIN32
  14. #include <unistd.h>
  15. #endif
  16.  
  17. #ifdef REGEX
  18. #include <gnu_regex.h>
  19. #endif
  20.  
  21. #include "jcc.h"
  22.  
  23. struct parsers client_patterns[] = {
  24.     { "referer:", /* sic */     8,    client_referrer        },
  25.     { "user-agent:",    11,    client_uagent        },
  26.     { "ua-",         3,    client_ua        },
  27.     { "from:",         5,    client_from        },
  28.     { "cookie:",         7,    client_send_cookie    },
  29.     { "x-forwarded-for:",    16,    client_x_forwarded    },
  30.     { "proxy-connection:",    17,    crumble            },
  31. /*    { "if-modified-since:", 18,    crumble            }, */
  32.     { NULL,             0,    NULL            }
  33. };
  34.  
  35. struct interceptors intercept_patterns[] = {
  36.     { "show-proxy-args",    14,    show_proxy_args        },
  37.     { "ij-blocked-url",    14,    ij_blocked_url        },
  38.     { "ij-untrusted-url",    14,    ij_untrusted_url    },
  39.     { NULL,             0,    NULL            }
  40. };
  41.  
  42. struct parsers server_patterns[] = {
  43.     { "set-cookie:",    11,    server_set_cookie    },
  44.     { "connection:",    11,    crumble            },
  45.     { NULL,             0,    NULL            }
  46. };
  47.  
  48. void (*add_client_headers[])() = {
  49.     client_cookie_adder,
  50.     client_x_forwarded_adder,
  51.     client_xtra_adder,
  52.     NULL
  53. };
  54.  
  55. void (*add_server_headers[])() = {
  56.     NULL
  57. };
  58.  
  59. struct parsers *
  60. match(char *buf, struct parsers *pats)
  61. {
  62.     struct parsers *v;
  63.  
  64.     if(buf == NULL) {
  65.         /* hit me */
  66.         fprintf(logfp, "bingo!\n");
  67.         return(NULL);
  68.     }
  69.  
  70.     for(v = pats; v->str ; v++) {
  71.         if(strncmpic(buf, v->str, v->len) == 0) {
  72.             return(v);
  73.         }
  74.     }
  75.     return(NULL);
  76. }
  77.  
  78. int
  79. flush_socket(int fd, struct client_state *csp)
  80. {
  81.     struct iob *iob = csp->iob;
  82.     int n = iob->eod - iob->cur;
  83.  
  84.     if(n <= 0) return(0);
  85.  
  86.     n = write_socket(fd, iob->cur, n);
  87.  
  88.     iob->eod = iob->cur = iob->buf;
  89.  
  90.     return(n);
  91. }
  92.  
  93. int
  94. add_to_iob(struct client_state *csp, char *buf, int n)
  95. {
  96.     struct iob *iob = csp->iob;
  97.     int have, need;
  98.     char *p;
  99.  
  100.     have = iob->eod - iob->cur;
  101.  
  102.     if(n <= 0) return(have);
  103.  
  104.     need = have + n;
  105.  
  106.     if((p = malloc(need + 1)) == NULL) {
  107.             fprintf(logfp, "%s: malloc() iob failed\n", prog);
  108.             fperror(logfp, "");
  109.             return(-1);
  110.     }
  111.  
  112.     if(have) {
  113.         /* there is something in the buffer - save it */
  114.         memcpy(p, iob->cur, have);
  115.  
  116.         /* replace the buffer with the new space */
  117.         freez(iob->buf);
  118.         iob->buf = p;
  119.  
  120.         /* point to the end of the data */
  121.         p += have;
  122.     } else {
  123.         /* the buffer is empty, free it and reinitialize */
  124.         freez(iob->buf);
  125.         iob->buf = p;
  126.     }
  127.  
  128.     /* copy the new data into the iob buffer */
  129.     memcpy(p, buf, n);
  130.  
  131.     /* point to the end of the data */
  132.      p +=   n ;
  133.  
  134.     /* null terminate == cheap insurance */
  135.     *p  = '\0';
  136.  
  137.     /* set the pointers to the new values */
  138.     iob->cur = iob->buf;
  139.     iob->eod = p;
  140.  
  141.     return(need);
  142. }
  143.  
  144. /* this (odd) routine will parse the csp->iob and return one of the following:
  145.  *
  146.  * 1) a pointer to a dynamically allocated string that contains a header line
  147.  * 2) NULL  indicating that the end of the header was reached
  148.  * 3) ""    indicating that the end of the iob was reached before finding
  149.  *          a complete header line.
  150.  */
  151.  
  152. char *
  153. get_header(struct client_state *csp)
  154. {
  155.     struct iob *iob = csp->iob;
  156.     char *p, *q, *ret;
  157.  
  158.     if((iob->cur == NULL)
  159.     || ((p = strchr(iob->cur, '\n')) == NULL)) {
  160.         return("");    /* couldn't find a complete header */
  161.     }
  162.  
  163.     *p = '\0';
  164.  
  165.     ret = strdup(iob->cur);
  166.  
  167.     iob->cur = p+1;
  168.  
  169.     if((q = strchr(ret, '\r'))) *q = '\0';
  170.  
  171.     /* is this a blank linke (i.e. the end of the header) ? */
  172.     if(*ret == '\0') {
  173.         freez(ret);
  174.         return(NULL);
  175.     }
  176.  
  177.     return(ret);
  178. }
  179.  
  180. /* h = pointer to list 'dummy' header
  181.  * s = string to add to the list
  182.  */
  183.  
  184. void
  185. enlist(struct list *h, char *s)
  186. {
  187.     struct list *n = (struct list *)malloc(sizeof(*n));
  188.     struct list *l;
  189.  
  190.     if(n) {
  191.         n->str  = strdup(s);
  192.         n->next = NULL;
  193.  
  194.         if((l = h->last)) {
  195.             l->next = n;
  196.         } else {
  197.             h->next = n;
  198.         }
  199.  
  200.         h->last = n;
  201.     }
  202. }
  203.  
  204. void
  205. destroy_list(struct list *h)
  206. {
  207.     struct list *p, *n;
  208.  
  209.     for(p = h->next; p ; p = n) {
  210.  
  211.         n = p->next;
  212.  
  213.         freez(p->str);
  214.  
  215.         freez(p);
  216.     }
  217.  
  218.     memset(h, '\0', sizeof(*h));
  219. }
  220.  
  221. char *
  222. list_to_text(struct list *h)
  223. {
  224.     struct list *p;
  225.     char *ret = NULL;
  226.     char *s;
  227.     int size;
  228.  
  229.     size = 0;
  230.  
  231.     for(p = h->next; p ; p = p->next) {
  232.         if(p->str) {
  233.             size += strlen(p->str) + 2;
  234.         }
  235.     }
  236.  
  237.     if((ret = malloc(size + 1)) == NULL) {
  238.         return(NULL);
  239.     }
  240.  
  241.     ret[size] = '\0';
  242.  
  243.     s = ret;
  244.  
  245.     for(p = h->next; p ; p = p->next) {
  246.         if(p->str) {
  247.             strcpy(s, p->str);
  248.             s += strlen(s);
  249.             *s++ = '\r'; *s++ = '\n';
  250.         }
  251.     }
  252.  
  253.     return(ret);
  254. }
  255.  
  256. /* sed(): add, delete or modify lines in the HTTP header streams.
  257.  * on entry, it receives a linked list of headers space that was
  258.  * allocated dynamically (both the list nodes and the header contents).
  259.  *
  260.  * it returns a single pointer to a fully formed header.
  261.  *
  262.  * as a side effect it frees the space used by the original header lines.
  263.  *
  264.  */
  265.  
  266. char *
  267. sed(pats, more_headers, csp)
  268. struct parsers pats[];
  269. int (*more_headers[])();
  270. struct client_state *csp;
  271. {
  272.     struct list *p;
  273.     struct parsers *v;
  274.     char *hdr;
  275.     int (**f)();
  276.  
  277.     for(p = csp->headers->next; p ; p = p->next) {
  278.  
  279.         if(DEBUG(HDR)) fprintf(logfp, "scan: %s", p->str);
  280.  
  281.         if((v = match(p->str, pats))) {
  282.             hdr = v->parser(v, p->str, csp);
  283.             freez(p->str);
  284.             p->str = hdr;
  285.         }
  286.  
  287.         if(DEBUG(HDR)) fprintf(logfp, "\n");
  288.     }
  289.  
  290.     /* place any additional headers on the csp->headers list */
  291.     for(f = more_headers; *f ; f++) {
  292.         (*f)(csp);
  293.     }
  294.  
  295.     /* add the blank line at the end of the header */
  296.     enlist(csp->headers, "");
  297.  
  298.     hdr = list_to_text(csp->headers);
  299.  
  300.     return(hdr);
  301. }
  302.  
  303. void
  304. free_http_request(struct http_request *http)
  305. {
  306.     freez(http->cmd);
  307.     freez(http->gpc);
  308.     freez(http->host);
  309.     freez(http->hostport);
  310.     freez(http->path);
  311.     freez(http->ver);
  312. }
  313.  
  314. /* parse out the host and port from the URL */
  315.  
  316. void
  317. parse_http_request(char *req, struct http_request *http, struct client_state *csp)
  318. {
  319.     char *buf, *v[10], *url, *p;
  320.     int n;
  321.  
  322.     memset(http, '\0', sizeof(*http));
  323.  
  324.     http->cmd = strdup(req);
  325.  
  326.     buf = strdup(req);
  327.  
  328.     n = ssplit(buf, " \r\n", v, SZ(v), 1, 1);
  329.  
  330.     if(n == 3) {
  331.  
  332.         /* this could be a CONNECT request */
  333.         if(strcmpic(v[0], "connect") == 0) {
  334.             http->ssl      = 1;
  335.             http->gpc      = strdup(v[0]);
  336.             http->hostport = strdup(v[1]);
  337.             http->ver      = strdup(v[2]);
  338.         }
  339.  
  340.         /* or it could be a GET or a POST */
  341.         if((strcmpic(v[0], "get")  == 0)
  342.         || (strcmpic(v[0], "head") == 0)
  343.         || (strcmpic(v[0], "post") == 0)) {
  344.  
  345.             http->ssl      = 0;
  346.             http->gpc      = strdup(v[0]);
  347.             url            =        v[1] ;
  348.             http->ver      = strdup(v[2]);
  349.  
  350.             if(strncmpic(url, "http://",  7) == 0) {
  351.                 url += 7;
  352.             } else if(strncmpic(url, "https://", 8) == 0) {
  353.                 url += 8;
  354.             } else {
  355.                 url = NULL;
  356.             }
  357.  
  358.             if(url && (p = strchr(url, '/'))) {
  359.                 http->path = strdup(p);
  360.  
  361.                 *p = '\0';
  362.  
  363.                 http->hostport = strdup(url);
  364.             }
  365.         }
  366.     }
  367.  
  368.     freez(buf);
  369.  
  370.  
  371.     if(http->hostport == NULL) {
  372.         free_http_request(http);
  373.         return;
  374.     }
  375.  
  376.     buf = strdup(http->hostport);
  377.  
  378.  
  379.     /* check if url contains password */
  380.     n = ssplit(buf, "@", v, SZ(v), 1, 1);
  381.     if (n == 2) {
  382.         char * newbuf = NULL;
  383.         newbuf = strdup(v[1]);
  384.         freez(buf);
  385.         buf = newbuf;
  386.     }
  387.  
  388.     n = ssplit(buf, ":", v, SZ(v), 1, 1);
  389.  
  390.     if(n == 1) {
  391.         http->host = strdup(v[0]);
  392.         http->port = 80;
  393.     }
  394.  
  395.     if(n == 2) {
  396.         http->host = strdup(v[0]);
  397.         http->port = atoi(v[1]);
  398.     }
  399.  
  400.     freez(buf);
  401.  
  402.     if(http->host == NULL) {
  403.         free_http_request(http);
  404.     }
  405.  
  406.     if(http->path == NULL) {
  407.         http->path = strdup("");
  408.     }
  409. }
  410.  
  411. /* here begins the family of parser functions that reformat header lines */
  412.  
  413. char *crumble(struct parsers *v, char *s, struct client_state *csp)
  414. {
  415.     if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  416.     return(NULL);
  417. }
  418.  
  419. char *client_referrer(struct parsers *v, char *s, struct client_state *csp)
  420. {
  421.     csp->referrer = strdup(s);
  422.  
  423.     if(referrer == NULL) {
  424.         if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  425.         return(NULL);
  426.     }
  427.  
  428.     if(*referrer == '.') {
  429.         return(strdup(s));
  430.     }
  431.  
  432.     if(*referrer == '@') {
  433.         if(csp->send_user_cookie) {
  434.             return(strdup(s));
  435.         } else {
  436.             if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  437.             return(NULL);
  438.         }
  439.     }
  440.  
  441.     if(DEBUG(HDR)) fprintf(logfp, " modified");
  442.  
  443.     s = strsav(NULL, "Referer: ");
  444.     s = strsav(s,     referrer  );
  445.     return(s);
  446. }
  447.  
  448. char *client_uagent(struct parsers *v, char *s, struct client_state *csp)
  449. {
  450.     if(uagent == NULL) {
  451.         if(DEBUG(HDR)) fprintf(logfp, " default");
  452.         return(strdup(DEFAULT_USER_AGENT));
  453.     }
  454.  
  455.     if(*uagent == '.') {
  456.         return(strdup(s));
  457.     }
  458.  
  459.     if(*uagent == '@') {
  460.         if(csp->send_user_cookie) {
  461.             return(strdup(s));
  462.         } else {
  463.             if(DEBUG(HDR)) fprintf(logfp, " default");
  464.             return(strdup(DEFAULT_USER_AGENT));
  465.         }
  466.     }
  467.  
  468.     if(DEBUG(HDR)) fprintf(logfp, " modified");
  469.  
  470.     s = strsav(NULL, "User-Agent: ");
  471.     s = strsav(s,     uagent   );
  472.     return(s);
  473. }
  474.  
  475. char *client_ua(struct parsers *v, char *s, struct client_state *csp)
  476. {
  477.     if(uagent == NULL) {
  478.         if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  479.         return(NULL);
  480.     }
  481.  
  482.     if(*uagent == '.') {
  483.         return(strdup(s));
  484.     }
  485.  
  486.     if(*uagent == '@') {
  487.         if(csp->send_user_cookie) {
  488.             return(strdup(s));
  489.         } else {
  490.             if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  491.             return(NULL);
  492.         }
  493.     }
  494.  
  495.     if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  496.     return(NULL);
  497. }
  498.  
  499. char *client_from(struct parsers *v, char *s, struct client_state *csp)
  500. {
  501.     /* if not set, zap it */
  502.     if(from == NULL) {
  503.         if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  504.         return(NULL);
  505.     }
  506.  
  507.     if(*from == '.') {
  508.         return(strdup(s));
  509.     }
  510.  
  511.     if(DEBUG(HDR)) fprintf(logfp, " modified");
  512.  
  513.     s = strsav(NULL, "From: ");
  514.     s = strsav(s,     from   );
  515.     return(s);
  516. }
  517.  
  518. char *client_send_cookie(struct parsers *v, char *s, struct client_state *csp)
  519. {
  520.     if(csp->send_user_cookie) {
  521.         enlist(csp->cookie_list, s + v->len + 1);
  522.     } else {
  523.         if(DEBUG(HDR)) fprintf(logfp, " crunch!");
  524.     }
  525.  
  526.     /* always return NULL here.  the cookie header will be sent
  527.      * at the end of the header.
  528.      */
  529.     return(NULL);
  530. }
  531.  
  532. char *client_x_forwarded(struct parsers *v, char *s, struct client_state *csp)
  533. {
  534.     if(add_forwarded) {
  535.         csp->x_forwarded = strdup(s);
  536.     }
  537.  
  538.     /* always return NULL, since this information
  539.      * will be sent at the end of the header.
  540.      */
  541.  
  542.     return(NULL);
  543. }
  544.  
  545. /* the following functions add headers directly to the header list */
  546. void client_cookie_adder(struct client_state *csp)
  547. {
  548.     struct list *l;
  549.     char *tmp = NULL;
  550.     char *e;
  551.  
  552.     for(l = csp->cookie_list->next; l ; l = l->next) {
  553.         if(tmp) {
  554.             tmp = strsav(tmp, "; ");
  555.         }
  556.         tmp = strsav(tmp, l->str);
  557.     }
  558.  
  559.     for(l = wafer_list->next;  l ; l = l->next) {
  560.         if(tmp) {
  561.             tmp = strsav(tmp, "; ");
  562.         }
  563.  
  564.         if((e = url_encode(cookie_code_map, l->str))) {
  565.             tmp = strsav(tmp, e);
  566.             freez(e);
  567.         }
  568.     }
  569.  
  570.     if(tmp) {
  571.         char *ret;
  572.  
  573.         ret = strdup("Cookie: ");
  574.         ret = strsav(ret, tmp);
  575.         if(DEBUG(HDR)) fprintf(logfp, "addh: %s\r\n", ret);
  576.         enlist(csp->headers, ret);
  577.         freez(tmp);
  578.         freez(ret);
  579.     }
  580. }
  581.  
  582. void client_xtra_adder(struct client_state *csp)
  583. {
  584.     struct list *l;
  585.  
  586.     for(l = xtra_list->next; l ; l = l->next) {
  587.         if(DEBUG(HDR)) fprintf(logfp, "addh: %s\r\n", l->str);
  588.         enlist(csp->headers, l->str);
  589.     }
  590. }
  591.  
  592. void client_x_forwarded_adder(struct client_state *csp)
  593. {
  594.     char *p = NULL;
  595.  
  596.     if(add_forwarded == 0) return;
  597.  
  598.     if(csp->x_forwarded) {
  599.         p = strsav(p, csp->x_forwarded);
  600.         p = strsav(p, ", ");
  601.         p = strsav(p, csp->ip_addr_str);
  602.     } else {
  603.         p = strsav(p, "X-Forwarded-For: ");
  604.         p = strsav(p, csp->ip_addr_str);
  605.     }
  606.     if(DEBUG(HDR)) fprintf(logfp, "addh: %s\r\n", p);
  607.     enlist(csp->headers, p);
  608. }
  609.  
  610. char *server_set_cookie(struct parsers *v, char *s, struct client_state *csp)
  611. {
  612.     if(jar) fprintf(jar, "%s\t%s\n", csp->http->host, (s + v->len + 1));
  613.  
  614.     if(csp->accept_server_cookie == 0) return(crumble(v, s, csp));
  615.  
  616.     return(strdup(s));
  617. }
  618.  
  619. /* case insensitive string comparison */
  620. int strcmpic(char *s1, char *s2)
  621. {
  622.     while(*s1 && *s2) {
  623.         if((        *s1  !=         *s2)
  624.         && (tolower(*s1) != tolower(*s2))) {
  625.             break;
  626.         }
  627.         s1++, s2++;
  628.     }
  629.     return(tolower(*s1) - tolower(*s2));
  630. }
  631.  
  632. int strncmpic(char *s1, char *s2, size_t n)
  633. {
  634.     if(n <= 0) return(0);
  635.  
  636.     while(*s1 && *s2) {
  637.  
  638.  
  639.         if((        *s1  !=         *s2)
  640.         && (tolower(*s1) != tolower(*s2))) {
  641.             break;
  642.         }
  643.  
  644.         if(--n <= 0) break;
  645.  
  646.         s1++, s2++;
  647.     }
  648.     return(tolower(*s1) - tolower(*s2));
  649. }
  650.