/* XFF version: takes IP from X-Forwarded-For header */ void vcl_geoip_country_set_header_xff(const struct sess *sp) { vcl_string hval[HEADER_MAXLEN]; vcl_string *ip = VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-For:"); if (ip) { geoip_lookup_country(ip, hval); VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", hval, vrt_magic_string_end); } else { VCL_Log("geoip: no ip from X-Forwarded-For"); VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", "", vrt_magic_string_end); } }
/* Sets "X-Geo-IP" header with the geoip resolved information */ void vcl_geoip_set_header(const struct sess *sp) { vcl_string hval[HEADER_MAXLEN]; vcl_string *ip = VRT_IP_string(sp, VRT_r_client_ip(sp)); if (geoip_lookup(ip, hval)) { VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", hval, vrt_magic_string_end); } else { /* Send an empty header */ VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", "", vrt_magic_string_end); } }
unsigned url_encode_setHdr(struct sess *sp, char* url,char *head,int *encoded_size){ char *copy; char buf[3075]; int size = 3 * strlen(url) + 3; if(size > 3075){ /////////////////////////////////////////////// //use ws int u = WS_Reserve(sp->wrk->ws, 0); if(u < size){ #ifdef DEBUG_SYSLOG syslog(6,"parse:url_encode_setHdr more ws size"); #endif return 0; } copy = (char*)sp->wrk->ws->f; /////////////////////////////////////////////// }else{ copy = buf; } __url_encode(url,encoded_size,copy); *encoded_size += strlen(copy) + head[0] +1; if(size > 3075){ WS_Release(sp->wrk->ws,strlen(copy)+1); } //sethdr VRT_SetHdr(sp, HDR_REQ, head, copy, vrt_magic_string_end); return(1); }
int decodeForm_urlencoded(struct sess *sp,char *body,const char *paramPrefix){ char head[256]; char *sc_eq,*sc_amp; char *tmpbody = body; int hsize; char tmp; int prefix_len = strlen(paramPrefix); while(1){ ////////////////////////////// //search word if(!(sc_eq = strchr(tmpbody,'='))){ break; } if(!(sc_amp = strchr(tmpbody,'&'))){ sc_amp = sc_eq + strlen(tmpbody); } ////////////////////////////// //build head tmp = sc_eq[0]; sc_eq[0] = 0;// = -> null hsize = strlen(tmpbody) + prefix_len + 1; if(hsize > 255){ #ifdef DEBUG_SYSLOG syslog(6,"parse:decodeForm_urlencoded head size > 255"); #endif return -5; } head[0] = hsize; head[1] = 0; snprintf(head +1,255,"%s%s:", paramPrefix, tmpbody); sc_eq[0] = tmp; ////////////////////////////// //build body tmpbody = sc_eq + 1; tmp = sc_amp[0]; sc_amp[0] = 0;// & -> null ////////////////////////////// //set header VRT_SetHdr(sp, HDR_REQ, head, tmpbody, vrt_magic_string_end); sc_amp[0] = tmp; tmpbody = sc_amp + 1; } return 1; }
static int vmod_Hook_vcl_error(struct sess *sp){ int status=VRT_r_obj_status(sp); if ( status == 301 || status == 302 || status == 303 ){ char * location = VRT_GetHdr(sp, HDR_REQ, "\030X-VMODREDIRECT-Location:"); if(location != 0){ VRT_SetHdr(sp, HDR_OBJ, "\011Location:" , location , vrt_magic_string_end); VRT_done(sp, VCL_RET_DELIVER); } } return(vmod_redirect_Hook_vcl_error(sp)); }
int vmod_location(struct sess *sp, int status, const char*p,...) { if ( status == 301 || status == 302 || status == 303 ){ if(hook_done == 1 && sp->vcl->error_func != vmod_Hook_vcl_error) hook_done = 0; if(hook_done == 0){ AZ(pthread_mutex_lock(&vmod_redirect_mutex)); if(hook_done == 0) { vmod_redirect_Hook_vcl_error = sp->vcl->error_func; sp->vcl->error_func = vmod_Hook_vcl_error; hook_done = 1; } AZ(pthread_mutex_unlock(&vmod_redirect_mutex)); } //build location string va_list ap; char *location; va_start(ap, p); location = VRT_String(sp->wrk->ws, NULL, p, ap); va_end(ap); //set location header VRT_SetHdr(sp, HDR_REQ, "\030X-VMODREDIRECT-Location:", location, vrt_magic_string_end ); } return (status); }
int vmod_parse(struct sess *sp,const char* tgHeadName,unsigned setParam,const char* paramPrefix,unsigned parseMulti,unsigned parseFile){ #ifdef DEBUG_SYSLOG syslog(6,"parse:start"); #endif /* struct sess *sp, OK const char* tgHeadName, OK const char* paramPrefix, url, unsigned setParam, url, unsigned parseMulti, OK unsigned parseFile OK */ //デバッグでReInitとかrestartの時に不具合でないかチェック(ロールバックも) //Content = pipeline.e-bの時はRxbuf確保をしない(必要ないので) //mix形式をurlencodeに切り替える(組み換えで安全に)<-完了 /* string(41) "submitter\"=a&submitter2=b&submitter3=vcc" string(42) "submitter%5C=a&submitter2=b&submitter3=vcc" string(39) "submitter=a&submitter2=b&submitter3=vcc" string(39) "submitter=a&submitter2=b&submitter3=vcc" string(83) "submitter=%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a&submitter2=b&submitter3=vcc" string(83) "submitter=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A&submitter2=b&submitter3=vcc" 1 =成功 -1 =エラー ワークスペースサイズが足りない -2 =エラー target/ContentLengthがない/不正 -3 =エラー 指定ContentLengthに満たないデータ -4 =エラー 未対応形式 if (!( !VRT_strcmp(VRT_r_req_request(sp), "POST") || !VRT_strcmp(VRT_r_req_request(sp), "PUT") )){return "";} */ unsigned long content_length,orig_content_length; char *h_clen_ptr, *h_ctype_ptr, *body; int buf_size, rsize; char buf[1024],tgHead[256]; unsigned multipart = 0; ////////////////////////////// //build tgHead int hsize = strlen(tgHeadName) +1; if(hsize > 1){ if(hsize > 255){ #ifdef DEBUG_SYSLOG syslog(6,"parse:err -2"); #endif return -2; } tgHead[0] = hsize; tgHead[1] = 0; snprintf(tgHead +1,255,"%s:",tgHeadName); }else{ tgHead[0] = 0; } ////////////////////////////// //check Content-Type #ifdef DEBUG_SYSLOG syslog(6,"GetHdr Content-Type:"); #endif h_ctype_ptr = VRT_GetHdr(sp, HDR_REQ, "\015Content-Type:"); if(h_ctype_ptr != NULL){ if (h_ctype_ptr == strstr(h_ctype_ptr, "application/x-www-form-urlencoded")) { //application/x-www-form-urlencoded }else if(h_ctype_ptr == strstr(h_ctype_ptr, "multipart/form-data") && parseMulti){ //multipart/form-data multipart = 1; }else{ #ifdef DEBUG_SYSLOG syslog(6,"parse:err -4"); #endif return -4; } }else{ //none support type #ifdef DEBUG_SYSLOG syslog(6,"parse:err -4"); #endif return -4; } ////////////////////////////// //check Content-Length #ifdef DEBUG_SYSLOG syslog(6,"GetHdr Content-Length:"); #endif h_clen_ptr = VRT_GetHdr(sp, HDR_REQ, "\017Content-Length:"); if (!h_clen_ptr) { //can't get #ifdef DEBUG_SYSLOG syslog(6,"parse:err -2"); #endif return -2; } orig_content_length = content_length = strtoul(h_clen_ptr, NULL, 10); if (content_length <= 0) { //illegal length #ifdef DEBUG_SYSLOG syslog(6,"parse:err -2"); #endif return -2; } ////////////////////////////// //Check POST data is loaded #ifdef DEBUG_HTCREAD if(0 == 1){ #else if(sp->htc->pipeline.b != NULL && Tlen(sp->htc->pipeline) == content_length){ #endif #ifdef DEBUG_SYSLOG syslog(6,"noread"); #endif //complete read body = sp->htc->pipeline.b; }else{ #ifdef DEBUG_SYSLOG syslog(6,"read"); #endif //incomplete read int rxbuf_size = Tlen(sp->htc->rxbuf); /////////////////////////////////////////////// //use ws int u = WS_Reserve(sp->wrk->ws, 0); if(u < content_length + rxbuf_size + 1){ #ifdef DEBUG_SYSLOG syslog(6,"parse:err -1"); #endif return -1; } body = (char*)sp->wrk->ws->f; memcpy(body, sp->htc->rxbuf.b, rxbuf_size); sp->htc->rxbuf.b = body; body += rxbuf_size; body[0]= 0; sp->htc->rxbuf.e = body; WS_Release(sp->wrk->ws,content_length + rxbuf_size + 1); /////////////////////////////////////////////// ////////////////////////////// //read post data while (content_length) { if (content_length > sizeof(buf)) { buf_size = sizeof(buf) - 1; } else { buf_size = content_length; } // read body data into 'buf' //rsize = HTC_Read(sp->htc, buf, buf_size); rsize = vmod_HTC_Read(sp->wrk, sp->htc, buf, buf_size); if (rsize <= 0) { #ifdef DEBUG_SYSLOG syslog(6,"parse:err -3"); #endif return -3; } hsize += rsize; content_length -= rsize; strncat(body, buf, buf_size); } sp->htc->pipeline.b = body; sp->htc->pipeline.e = body + orig_content_length; } ////////////////////////////// //decode form #ifdef DEBUG_SYSLOG syslog(6,"content-size (orig)%d (read)%d",orig_content_length,strlen(body)); #endif int ret = 1; if(multipart){ ret = decodeForm_multipart(sp, body,tgHead,parseFile,paramPrefix,setParam); }else{ if(tgHead[0] != 0) VRT_SetHdr(sp, HDR_REQ, tgHead, body, vrt_magic_string_end); if(setParam) ret = decodeForm_urlencoded(sp, body,paramPrefix); } #ifdef DEBUG_SYSLOG syslog(6,"parse:end %d",ret); #endif return ret; }
int decodeForm_multipart(struct sess *sp,char *body,char *tgHead,unsigned parseFile,const char *paramPrefix, unsigned setParam){ char *prefix; char defPrefix[] = "X-VMODPOST-"; if(!setParam){ prefix = defPrefix; }else{ prefix = (char*)paramPrefix; } int prefix_len = strlen(prefix); char tmp; char head[256]; char sk_boundary[258]; char *raw_boundary, *h_ctype_ptr; char *p_start, *p_end, *p_body_end, *name_line_end, *name_line_end_tmp, *start_body, *sc_name, *sc_filename; int hsize, boundary_size ,idx; char *tmpbody = body; int encoded_size= 0; char *basehead = 0; char *curhead; int ll_u, ll_head_len, ll_size; int ll_entry_count = 0; int u; char *orig_cv_body, *cv_body, *h_val; ////////////////////////////// //get boundary #ifdef DEBUG_SYSLOG syslog(6,"GetHdr Content-Type:"); #endif h_ctype_ptr = VRT_GetHdr(sp, HDR_REQ, "\015Content-Type:"); raw_boundary = strstr(h_ctype_ptr,"; boundary="); if(!raw_boundary || strlen(raw_boundary) > 255){ #ifdef DEBUG_SYSLOG syslog(6,"parse:decodeForm_multipart boudary size>255"); #endif return -5; } raw_boundary +=11; sk_boundary[0] = '-'; sk_boundary[1] = '-'; sk_boundary[2] = 0; strncat(sk_boundary,raw_boundary,strlen(raw_boundary)); boundary_size = strlen(sk_boundary); p_start = strstr(tmpbody,sk_boundary); while(1){ /////////////////////////////////////////////// //search data if(!p_start) break; //boundary p_end = strstr(p_start + 1,sk_boundary); if(!p_end) break; //name sc_name = strstr(p_start +boundary_size,"name=\""); if(!sc_name) break; sc_name+=6; //line end name_line_end = strstr(sc_name,"\"\r\n"); name_line_end_tmp = strstr(sc_name,"\"; "); if(!name_line_end) break; if(name_line_end_tmp && name_line_end_tmp < name_line_end) name_line_end = name_line_end_tmp; //body start_body = strstr(sc_name,"\r\n\r\n"); if(!start_body) break; //filename sc_filename = strstr(sc_name,"; filename"); /////////////////////////////////////////////// //build head if((name_line_end -1)[0]=='\\'){ idx = 1; }else{ idx=0; } tmp = name_line_end[idx]; name_line_end[idx] = 0; hsize = strlen(sc_name) + prefix_len +1; if(hsize > 255) return -5; head[0] = hsize; head[1] = 0; snprintf(head +1,255,"%s%s:",prefix,sc_name); name_line_end[idx] = tmp; /////////////////////////////////////////////// //filecheck if(!parseFile){ if(sc_filename && sc_filename < start_body){ //content is file(skip) p_start = p_end; continue; } } /////////////////////////////////////////////// //create linked list //use ws ll_u = WS_Reserve(sp->wrk->ws, 0); ll_head_len = strlen(head +1) +1; ll_size = ll_head_len + sizeof(char*)+2; if(ll_u < ll_size){ #ifdef DEBUG_SYSLOG syslog(6,"parse:decodeForm_multipart more ws size"); #endif return -1; } if(!basehead){ curhead = (char*)sp->wrk->ws->f; basehead = curhead; }else{ ((char**)curhead)[0] = (char*)sp->wrk->ws->f; curhead = (char*)sp->wrk->ws->f; } ++ll_entry_count; memcpy(curhead,head,ll_head_len); curhead +=ll_head_len; memset(curhead,0,sizeof(char*)+1); ++curhead; WS_Release(sp->wrk->ws,ll_size); /////////////////////////////////////////////// /////////////////////////////////////////////// //url encode & set header p_body_end = p_end -2; start_body +=4; tmp = p_body_end[0]; p_body_end[0] = 0; //bodyをURLエンコードする if(!url_encode_setHdr(sp,start_body,head,&encoded_size)){ //メモリない p_body_end[0] = tmp; return -1; } encoded_size -= prefix_len; p_body_end[0] = tmp; /////////////////////////////////////////////// //check last boundary if(!p_end) break; p_start = p_end; } if(tgHead[0] == 0 && !setParam){ #ifdef DEBUG_SYSLOG syslog(6,"parse:decodeForm_multipart head 0 & no set param [OK]"); #endif return 1; } ////////////// //genarate x-www-form-urlencoded format data ////////////// //use ws if(tgHead[0] == 0){ orig_cv_body = cv_body = NULL; }else{ u = WS_Reserve(sp->wrk->ws, 0); if(u < encoded_size + 1){ #ifdef DEBUG_SYSLOG syslog(6,"parse:decodeForm_multipart more ws size(2)"); #endif return -1; } orig_cv_body = cv_body = (char*)sp->wrk->ws->f; WS_Release(sp->wrk->ws,encoded_size+1); } ////////////// for(int i=0;i<ll_entry_count;++i){ if(cv_body){ hsize = basehead[0] -prefix_len; memcpy(cv_body,basehead+1+prefix_len,hsize); cv_body += hsize - 1; cv_body[0] ='='; ++cv_body; #ifdef DEBUG_SYSLOG syslog(6,"GetHdr %s",basehead +1); #endif h_val = VRT_GetHdr(sp,HDR_REQ,basehead); } if(!setParam){ //remove header VRT_SetHdr(sp, HDR_REQ, basehead, 0); } if(cv_body){ memcpy(cv_body,h_val,strlen(h_val)); cv_body +=strlen(h_val); cv_body[0] ='&'; ++cv_body; } basehead = *(char**)(basehead+strlen(basehead+1)+2); } if(cv_body){ orig_cv_body[encoded_size - 1] =0; } if(tgHead[0] == 0){ #ifdef DEBUG_SYSLOG syslog(6,"parse:decodeForm_multipart head 0 [OK]"); #endif return 1; } VRT_SetHdr(sp, HDR_REQ, tgHead, orig_cv_body, vrt_magic_string_end); return 1; }
/* Simplified version: sets "X-Geo-IP" header with the country only */ void vcl_geoip_country_set_header(const struct sess *sp) { vcl_string hval[HEADER_MAXLEN]; vcl_string *ip = VRT_IP_string(sp, VRT_r_client_ip(sp)); geoip_lookup_country(ip, hval); VRT_SetHdr(sp, HDR_REQ, "\011X-Geo-IP:", hval, vrt_magic_string_end); }
void vmod_v4_generic(const struct vrt_ctx *ctx, VCL_STRING service, //= 's3'; VCL_STRING region, //= 'ap-northeast-1'; VCL_STRING access_key, //= 'your access key'; VCL_STRING secret_key, //= 'your secret key'; VCL_STRING _signed_headers, //= 'host;';// x-amz-content-sha256;x-amz-date is appended by default. VCL_STRING _canonical_headers, //= 'host:s3-ap-northeast-1.amazonaws.com\n' VCL_BOOL feature //= reserved param(for varnish4) ){ //////////////// //get data char *method; char *requrl; struct http *hp; struct gethdr_s gs; if (ctx->http_bereq !=NULL && ctx->http_bereq->magic== HTTP_MAGIC){ //bg-thread hp = ctx->http_bereq; gs.where = HDR_BEREQ; }else{ //cl-thread hp = ctx->http_req; gs.where = HDR_REQ; } method= hp->hd[HTTP_HDR_METHOD].b; requrl= hp->hd[HTTP_HDR_URL].b; //////////////// //create date time_t tt; char amzdate[17]; char datestamp[9]; tt = time(NULL); struct tm * gmtm = gmtime(&tt); sprintf(amzdate, "%d%02d%02dT%02d%02d%02dZ", gmtm->tm_year +1900, gmtm->tm_mon +1, gmtm->tm_mday, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec ); sprintf(datestamp, "%d%02d%02d", gmtm->tm_year +1900, gmtm->tm_mon +1, gmtm->tm_mday ); //////////////// //create payload const char * payload_hash = vmod_hash_sha256(ctx, ""); //////////////// //create signed headers size_t len = strlen(_signed_headers) + 32; char *psigned_headers = WS_Alloc(ctx->ws,len); sprintf(psigned_headers,"%sx-amz-content-sha256;x-amz-date",_signed_headers); //////////////// //create canonical headers len = strlen(_canonical_headers) + 115; char *pcanonical_headers = WS_Alloc(ctx->ws,len); sprintf(pcanonical_headers,"%sx-amz-content-sha256:%s\nx-amz-date:%s\n",_canonical_headers,payload_hash,amzdate); //////////////// //create credential scope len = strlen(datestamp)+ strlen(region)+ strlen(service)+ 16; char *pcredential_scope = WS_Alloc(ctx->ws,len); sprintf(pcredential_scope,"%s/%s/%s/aws4_request",datestamp,region,service); //////////////// //create canonical request len = strlen(method)+ strlen(requrl)+ strlen(pcanonical_headers)+ strlen(psigned_headers)+ strlen(payload_hash) + 6; char *pcanonical_request = WS_Alloc(ctx->ws,len); char tmpform[32]; tmpform[0]=0; char *ptmpform = &tmpform[0]; char *adr = strchr(requrl, (int)'?'); if(adr == NULL){ sprintf(pcanonical_request,"%s\n%s\n\n%s\n%s\n%s", method, requrl, pcanonical_headers, psigned_headers, payload_hash ); }else{ sprintf(ptmpform,"%s.%lds\n%s","%s\n%",(adr - requrl),"%s\n%s\n%s\n%s"); sprintf(pcanonical_request,ptmpform, method, requrl, adr + 1, pcanonical_headers, psigned_headers, payload_hash ); } //////////////// //create string_to_sign len = strlen(amzdate)+ strlen(pcredential_scope)+ 33; char *pstring_to_sign = WS_Alloc(ctx->ws,len); sprintf(pstring_to_sign,"AWS4-HMAC-SHA256\n%s\n%s\n%s",amzdate,pcredential_scope,vmod_hash_sha256(ctx, pcanonical_request)); //////////////// //create signature const char *signature = vmod_v4_getSignature(ctx,secret_key,datestamp,region,service,pstring_to_sign); //////////////// //create authorization len = strlen(access_key)+ strlen(pcredential_scope)+ strlen(psigned_headers)+ strlen(signature)+ 58; char *pauthorization= WS_Alloc(ctx->ws,len); sprintf(pauthorization,"AWS4-HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s", access_key, pcredential_scope, psigned_headers, signature); //////////////// //Set to header gs.what = "\016Authorization:"; VRT_SetHdr(ctx, &gs , pauthorization , vrt_magic_string_end); gs.what = "\025x-amz-content-sha256:"; VRT_SetHdr(ctx, &gs , payload_hash , vrt_magic_string_end); gs.what = "\013x-amz-date:"; VRT_SetHdr(ctx, &gs , amzdate , vrt_magic_string_end); }