欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

http.c

Google 推出一套免費的 Web 安全評估工具
C
第 1 页 / 共 3 页
字号:
  /* Populate HTTP envelope data with higher-level CONNECT     information if one present. */  if (ssl_host) {    ret->host = ssl_host;    ret->port = ssl_port;    ret->from_ssl = 1;  }  if (!ret->host[0])    http_error(client,"Host name is missing",1);  ret->host = strdup(ret->host);  if (!ret->host) fatal("out of memory");  /* Grab query data */  if (!ret->is_connect && (x = strchr(ret->path,'?'))) {    *(x++) = 0;    ret->query = strdup(x);    if (!ret->query) fatal("out of memory");  }  /* Grab path data */  if (!ret->is_connect) {    ret->path = strdup(ret->path);    if (!ret->path) fatal("out of memory");        x = strrchr(ret->path,'.');    if (x) ret->ext = x + 1;  }  /* Request target is now fully parsed. Let's collect headers, if any. */  while (1) {    line = grab_line(client);    if (!line) http_error(client,"Incomplete or malformed request headers",1);    /* Empty line == end of headers */    if (!line[0]) break;    x = strchr(line,':');    if (!x) http_error(client,"Invalid request header",1);    *x = 0;    while (isspace(*(++x)));    if (!strcasecmp(line,"Content-Length")) {       ret->payload_len = atoi(x);       if (ret->payload_len > MAXPAYLOAD)        http_error(client,"Payload size limit exceeded",1);    }    if (!strncasecmp(line,"Cookie",6))      parse_cookies(x,&ret->cookies);    if (!strcasecmp(line,"Referer")) {      _u8* rh;      ret->referer = strdup(x);      if (!ret->referer) fatal("out of memory");      /* Extract referer host to simplify other checks later on. */      if ((rh = strstr(x,"://"))) {        _u8* x;        rh = strdup(rh + 3);        if (!rh) fatal("out of memory");        if ((x = strchr(rh,'/'))) *x = 0;        if ((x = strchr(rh,':'))) *x = 0;        ret->ref_host = rh;      }    }    if (!strcasecmp(line,"X-Ratproxy-Loop"))       http_error(client,"Proxy loop detected",1);    /* These are specific to publicly documented anti-XSRF features of       Google Web Toolkit and Google Data APIs; this might be further       extended to accomodate other custom schemes in popular frameworks. */    if (!strcasecmp(line,"Authorization") && !strncasecmp(x,"GoogleLogin auth=",17)) {      ret->xsrf_safe = 1;      ret->authsub = 1;    }    if (!strcasecmp(line,"Content-Type")) {      if (rp_strcasestr(x,"text/x-gwt-rpc")) { ret->xsrf_safe = 1; ret->authsub = 1; }      if (rp_strcasestr(x,"multipart/form-data")) ret->multipart = 1;      else if (!rp_strcasestr(x,"application/x-www-form-urlencoded")) ret->non_param = 1;    }    DYN_ADD2(ret->h,line,x);  }  /* Get POST payload */  if (ret->payload_len) {    ret->payload = malloc(ret->payload_len + 1);    if (!ret->payload) fatal("out of memory");    if (fread(ret->payload,ret->payload_len,1,client) != 1)       http_error(client,"Premature end of payload data",0);    /* To make string matching safe. */    ret->payload[ret->payload_len] = 0;  }  /* Parse GET/POST parameters */  if (ret->query) parse_urlencoded(&ret->p, ret->query);  ret->ppar_bound = ret->p.c;  /* Do not parse payloads of arcane types. */  if (ret->payload && !ret->non_param) {    if (ret->multipart) parse_multipart(&ret->p, ret->payload, ret->payload_len);     else parse_urlencoded(&ret->p, ret->payload);  }  /* Locate XSRF tokens, if any */  /* Do not perform contains_token() checks on file fields. */  for (i=0;i<ret->p.c;i++)    if (!ret->p.fn[i][0] && contains_token(ret->p.v1[i],ret->p.v2[i]))      { ret->xsrf_safe = 1; break; }  return ret;}/* Connect to server */static FILE* open_server(FILE* client, _u8* host, _u32 port) {  FILE* ret;  struct sockaddr_in sin;  struct hostent* he;  _s32 ss;  if (!(he = gethostbyname(host)) || !(he->h_addr_list[0]))     http_error(client,"Unable to find target host",0);  ss = socket(PF_INET, SOCK_STREAM, 0);  if (ss < 0) pfatal("socket() failed");  sin.sin_family = PF_INET;  sin.sin_port   = htons(port);  memcpy(&sin.sin_addr, he->h_addr_list[0], 4);  if (connect(ss,(struct sockaddr*)&sin,sizeof(struct sockaddr_in)))    http_error(client,"Connection to target failed",0);  ret = fdopen(ss,"w+");  if (!ret) fatal("fdopen() failed");  setvbuf(ret, srv_buf, _IOFBF, sizeof(srv_buf));  return ret;}/* Connect to server, take proxy CONNECT handling into account */FILE* open_server_complete(FILE* client, struct http_request* r) {  FILE* ret;  _u8* l;  if (use_proxy)     ret = open_server(client, use_proxy, proxy_port);  else     ret = open_server(client, r->host, r->port);  if (r->is_connect) {    if (use_proxy) {      fprintf(ret,"CONNECT %s:%u HTTP/1.0\r\n\r\n",r->host,r->port);      fflush(ret);      setvbuf(ret, srv_buf, _IONBF, 0);      /* Sink proxy response */      while ((l=grab_line(ret)) && l[0]);    }    if (client) {      fprintf(client,"HTTP/1.0 200 Go ahead, please.\r\n\r\n");      fflush(client);    }  }   return ret;}#define NEEDS_URLENC(x) \   (!(x) || !strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.",toupper(x)))/* Rewrite GET and POST parameters as needed. */void reconstruct_request(struct http_request* r) {  struct dyn_str p = { 0, 0 }, q = { 0, 0 };  _u32 cp = 0, i;  _u8 c;  _u8 tmp[32];  /* Encode params to query string, until ppar boundary is hit. */  for (;cp<r->p.c;cp++) {    if (cp == r->ppar_bound) break;    if (q.l) STR_APPEND_CHAR(q,'&');    i = 0;    while ((c=r->p.v1[cp][i])) {      if (NEEDS_URLENC(c)) {        sprintf(tmp,"%%%02X",c);      } else {        tmp[0] = c;        tmp[1] = 0;      }      STR_APPEND(q,tmp);      i++;    }    STR_APPEND_CHAR(q,'=');    i = 0;    while ((c=r->p.v2[cp][i])) {      if (NEEDS_URLENC(c)) {        sprintf(tmp,"%%%02X",c);      } else {        tmp[0] = c;        tmp[1] = 0;      }      STR_APPEND(q,tmp);      i++;    }  }  /* Update query string. */  if (q.l) r->query = q.v;  /* Deal with the rest of parameters, putting them in a multipart     envelope or as urlencoded payload, as needed. */    if (r->multipart) {    /* Update boundary; be just random enough to prevent accidents. */    sprintf(tmp,"ratproxybound%08x",rand());    r->use_boundary = strdup(tmp);    if (!r->use_boundary) fatal("out of memory");    for (;cp<r->p.c;cp++) {      STR_APPEND(p,"--");      STR_APPEND(p,r->use_boundary);      STR_APPEND(p,"\r\nContent-Disposition: form-data; name=\"");      STR_APPEND(p,r->p.v1[cp]);      if (r->p.fn[cp][0]) {        STR_APPEND(p,"\"; filename=\"");        STR_APPEND(p,r->p.fn[cp]);      }      STR_APPEND(p,"\"\r\n\r\n");      if (r->p.l2[cp]) {        STR_APPEND_RAWMEM(p,r->p.v2[cp],r->p.l2[cp]);      } else {        STR_APPEND(p,r->p.v2[cp]);      }      STR_APPEND(p,"\r\n");    }    STR_APPEND(p,"--");    STR_APPEND(p,r->use_boundary);    STR_APPEND(p,"--\r\n");      } else if (!r->non_param) {    for (;cp<r->p.c;cp++) {      if (p.l) STR_APPEND_CHAR(p,'&');      i = 0;      while ((c=r->p.v1[cp][i])) {        if (NEEDS_URLENC(c)) {          sprintf(tmp,"%%%02X",c);        } else {          tmp[0] = c;          tmp[1] = 0;        }        STR_APPEND(p,tmp);        i++;      }        STR_APPEND_CHAR(p,'=');      i = 0;      while ((c=r->p.v2[cp][i])) {        if (NEEDS_URLENC(c)) {          sprintf(tmp,"%%%02X",c);        } else {          tmp[0] = c;          tmp[1] = 0;        }        STR_APPEND(p,tmp);        i++;      }    }    if (p.l) STR_APPEND(p,"\r\n");  } else return; /* Leave payload intact. */  /* Update POST string. */  if (p.l) {    r->payload = p.v;    r->payload_len = p.l;  }  return;}/* Detect and convert GWT RPC syntax where appropriate. This is specific to   Google Web Toolkit. */static _u8* maybe_gwt_rpc(_u8* str) {  struct dyn_str p = { 0, 0 };  _u8 *c = str, *n;  _u32 num = 0;  _u32 l = strlen(str);  if (l < 3 || str[l-3] != 0xEF || str[l-2] != 0xBF || str[l-1] != 0xBF) return str;  STR_APPEND(p,"GWT_RPC[");  while ((n = strstr(c,"\xEF\xBF\xBF"))) {    *n = 0;    if (num > 4) {      if (num != 5) STR_APPEND_CHAR(p,',');         STR_APPEND_CHAR(p,'\'');      if (!strncmp(c,"[L",2)) c += 2;      if (!strncmp(c,"com.google.",11) || !strncmp(c,"java.",5)) c = strrchr(c,'.') + 1;      /* We *could* escape here, but it's probably not worth the effort. */      STR_APPEND(p,c);       STR_APPEND_CHAR(p,'\'');    }    num++;    *n = '\xEF';    c = n + 3;  }  STR_APPEND_CHAR(p,']');  return p.v;}/* Convert multipart data to URLencoded string, to simplify reporting. */_u8* stringify_payload(struct http_request* r) {  struct dyn_str p = { 0, 0 };  _u32 cp, i, c;  _u8 tmp[32];    if (!r->multipart) return maybe_gwt_rpc(r->payload);  /* Reconstruct payload from multipart boundary... */  for (cp=r->ppar_bound;cp<r->p.c;cp++) {    if (p.l) STR_APPEND_CHAR(p,'&');    i = 0;    while ((c=r->p.v1[cp][i])) {      if (NEEDS_URLENC(c)) {        sprintf(tmp,"%%%02X",c);      } else {        tmp[0] = c;        tmp[1] = 0;      }      STR_APPEND(p,tmp);      i++;    }    STR_APPEND_CHAR(p,'=');    /* When dealing with a file field, use field name, rather than       field data. */    if (r->p.fn[cp][0]) {      STR_APPEND(p,"FILE[");      i = 0;      while ((c=r->p.fn[cp][i])) {        if (NEEDS_URLENC(c)) {          sprintf(tmp,"%%%02X",c);        } else {          tmp[0] = c;          tmp[1] = 0;        }        STR_APPEND(p,tmp);        i++;      }      STR_APPEND_CHAR(p,']');    } else {      i = 0;      while ((c=r->p.v2[cp][i])) {        if (NEEDS_URLENC(c)) {          sprintf(tmp,"%%%02X",c);        } else {          tmp[0] = c;          tmp[1] = 0;        }        STR_APPEND(p,tmp);        i++;      }    }  }  return p.v;}/* Do a naive date comparison for t-1 sec/min/hr scenarios. */_u8 comp_dates(_u8* exp, _u8* dat) {  _s32 i = strlen(dat), dc = 0;  if (i != strlen(exp)) return 1;  while (--i >= 0) {    if (exp[i] != dat[i]) {      if (!isdigit(dat[i]) || exp[i] > dat[i] || ++dc > 1) return 1;    }  }  return 0;}/* Send HTTP request, collect and parse response, spot header-related problems. */struct http_response* send_request(FILE* client, FILE* server, struct http_request* r,                                   _u8 strip_state) {  struct http_response* ret;  _u8 *line, *x;  _s32 decl_clen = -1;  _u32 i;  _u8 port_spec[16] = { 0 };  _u8 *exp_value = 0, *dat_value = 0;  /* Send the request... unfortunately, we cannot specify :80 on all     standard requests, as some URL rewriters that redirect to https     will copy this over and cause problems. */  if (!r->from_ssl) {    if (r->port != 80) sprintf(port_spec,":%u",r->port);  } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -