예제 #1
0
/* 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);
    }
}
예제 #2
0
/* 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);
    }
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
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));

}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #8
0
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;
}
예제 #9
0
/* 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);
}
예제 #10
0
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);
}