mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
proxy: request line logged up to 4 KB, added headers written in place
REQMAX is 4 KB: a log line holds 4000 characters, so a longer copy of the request line was cut by the log before "..." could show. The headers this proxy adds are written straight after the header block, HDRRESERVE (2 KB, what they come to at most) asked to be free there first: in the side's buffer that is the room hdrread() left, so nothing is copied, and the buffer on the stack they were built in is gone. The scheme and authority of a request are no longer kept in a buffer of their own: req, the line in absolute form as logged, has them, and where the authority begins and ends in it is kept instead, for the next request on the connection to be compared with and for a parent proxy to be given. An authority beyond what req keeps of the line is refused. A line a request filter rewrote is logged only when the rewrite is applied. Tests: a 5 KB line through a parent arrives whole in absolute form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
96adc6d9cd
commit
63a736c693
183
src/proxy.c
183
src/proxy.c
@ -139,17 +139,18 @@ char * proxy_stringtable[] = {
|
|||||||
Proxy-Authorization carrying an encoded user and password */
|
Proxy-Authorization carrying an encoded user and password */
|
||||||
/* what of a request line is logged, into a line of CLIENTTMPBUFSIZE (8 KB)
|
/* what of a request line is logged, into a line of CLIENTTMPBUFSIZE (8 KB)
|
||||||
with the rest of the log line; a longer one is cut there */
|
with the rest of the log line; a longer one is cut there */
|
||||||
#define REQMAX 6144
|
#define REQMAX 4096
|
||||||
/* the authority of a request, user:password@host:port, at most */
|
/* a Host header put in a request line for a parent proxy, at most */
|
||||||
#define AUTHMAX (USERNAMELEN * 2 + HOSTNAMELEN + 16)
|
#define AUTHMAX (HOSTNAMELEN + 16)
|
||||||
#define HDRRESERVE 1024
|
#define HDRRESERVE 2048
|
||||||
/* what a request keeps free before its header block, for its line to be
|
/* what a request keeps free before its header block, for its line to be
|
||||||
put back into the absolute form a parent proxy is sent: http://, a host
|
put back into the absolute form a parent proxy is sent: http://, a host
|
||||||
name of up to 256 characters and :port */
|
name of up to 256 characters and :port */
|
||||||
#define HDRFRONT 300
|
#define HDRFRONT 300
|
||||||
/* what the headers this proxy adds come to at most, built before they are
|
/* what the headers this proxy adds come to at most: what is asked to be
|
||||||
put after the header block */
|
free after the header block before they are written there, which
|
||||||
#define HDRADD 2048
|
HDRRESERVE leaves in the side's buffer */
|
||||||
|
#define HDRADD HDRRESERVE
|
||||||
#define BUFSIZE (LINESIZE*2)
|
#define BUFSIZE (LINESIZE*2)
|
||||||
#define FTPBUFSIZE 1536
|
#define FTPBUFSIZE 1536
|
||||||
|
|
||||||
@ -365,17 +366,14 @@ static unsigned char *logline(const unsigned char *line, size_t len){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The request line in absolute form into dst: of line, which has a path
|
/* The request line in absolute form into dst: of line, which has a path
|
||||||
only, its method and the space after it (sp bytes), then scheme and
|
only, its method and the space after it (sp bytes), then the scheme and
|
||||||
authority, then the rest of it (len bytes in all). dst holds len +
|
authority in sa (salen bytes), then the rest of it (len bytes in all).
|
||||||
strlen(scheme) + authlen bytes and does not overlap line. */
|
dst holds len + salen bytes and overlaps neither. */
|
||||||
static int absline(unsigned char *dst, const unsigned char *line, int len, int sp, const char *scheme, const unsigned char *auth, int authlen){
|
static int absline(unsigned char *dst, const unsigned char *line, int len, int sp, const unsigned char *sa, int salen){
|
||||||
int sl = (int)strlen(scheme);
|
|
||||||
|
|
||||||
memcpy(dst, line, sp);
|
memcpy(dst, line, sp);
|
||||||
memcpy(dst + sp, scheme, sl);
|
memcpy(dst + sp, sa, salen);
|
||||||
memcpy(dst + sp + sl, auth, authlen);
|
memcpy(dst + sp + salen, line + sp, len - sp);
|
||||||
memcpy(dst + sp + sl + authlen, line + sp, len - sp);
|
return len + salen;
|
||||||
return len + sl + authlen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Whether a request line names the host the previous one did, whatever its
|
/* Whether a request line names the host the previous one did, whatever its
|
||||||
@ -514,12 +512,11 @@ void * proxychild(struct clientparam* param) {
|
|||||||
int isconnect = 0;
|
int isconnect = 0;
|
||||||
int redirect = 0;
|
int redirect = 0;
|
||||||
int ckeepalive=0;
|
int ckeepalive=0;
|
||||||
/* the request's scheme and authority, as its line had them (or the Host
|
/* where in req, the request line in absolute form as logged, its
|
||||||
header, for a request with a path only): put back for a parent proxy;
|
authority begins and ends: what is put back for a parent proxy, from
|
||||||
the authority of the last one is what the next one is compared with */
|
ssoff (scheme and authority), and what the next request is compared
|
||||||
unsigned char auth[AUTHMAX];
|
with; none (authend 0) for a line with a path only and no Host */
|
||||||
int authlen = 0;
|
int authofs = 0, authend = 0;
|
||||||
const char *scheme = "http://";
|
|
||||||
int ftp = 0;
|
int ftp = 0;
|
||||||
int ssoff = 0;
|
int ssoff = 0;
|
||||||
#ifndef ANONYMOUS
|
#ifndef ANONYMOUS
|
||||||
@ -541,9 +538,6 @@ void * proxychild(struct clientparam* param) {
|
|||||||
int hlen0, hdrsdone = 0;
|
int hlen0, hdrsdone = 0;
|
||||||
/* free before buf in the side's buffer, while buf is in it */
|
/* free before buf in the side's buffer, while buf is in it */
|
||||||
int hfront = 0;
|
int hfront = 0;
|
||||||
/* the headers this proxy adds, built before they go after the block */
|
|
||||||
char add[HDRADD];
|
|
||||||
int alen;
|
|
||||||
/* buf is the headers' own buffer, not the side's they were read into */
|
/* buf is the headers' own buffer, not the side's they were read into */
|
||||||
int bufown = 0;
|
int bufown = 0;
|
||||||
#ifndef WITHMAIN
|
#ifndef WITHMAIN
|
||||||
@ -605,7 +599,7 @@ for(;;){
|
|||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
|
|
||||||
if(req) {
|
if(req) {
|
||||||
if(!param->transparent && !param->srv->transparent && !samehost(buf, i, auth, authlen)){
|
if(!param->transparent && !param->srv->transparent && !samehost(buf, i, req + authofs, authend - authofs)){
|
||||||
ckeepalive = 0;
|
ckeepalive = 0;
|
||||||
if(param->remsock != INVALID_SOCKET){
|
if(param->remsock != INVALID_SOCKET){
|
||||||
param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR);
|
param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR);
|
||||||
@ -623,8 +617,7 @@ for(;;){
|
|||||||
/* for the log only */
|
/* for the log only */
|
||||||
req = logline(buf, (size_t)i);
|
req = logline(buf, (size_t)i);
|
||||||
if(!req){RETURN(510);}
|
if(!req){RETURN(510);}
|
||||||
authlen = 0;
|
authofs = authend = 0;
|
||||||
scheme = "http://";
|
|
||||||
if(i<10) {
|
if(i<10) {
|
||||||
RETURN(511);
|
RETURN(511);
|
||||||
}
|
}
|
||||||
@ -643,7 +636,6 @@ for(;;){
|
|||||||
else if (!strncasecmp((char *)sb, "ftp://", 6)) {
|
else if (!strncasecmp((char *)sb, "ftp://", 6)) {
|
||||||
if(!param->srv->allowftp) RETURN(513);
|
if(!param->srv->allowftp) RETURN(513);
|
||||||
ftp = 1;
|
ftp = 1;
|
||||||
scheme = "ftp://";
|
|
||||||
sb += 6;
|
sb += 6;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -666,10 +658,11 @@ for(;;){
|
|||||||
if(se > sg) se=sg;
|
if(se > sg) se=sg;
|
||||||
*se = 0;
|
*se = 0;
|
||||||
}
|
}
|
||||||
/* the authority, before the line is made one with a path only */
|
/* where the authority is in req, the line as it came: it has to be
|
||||||
if(se - sb >= AUTHMAX) RETURN(100);
|
in what is kept of it */
|
||||||
authlen = (int)(se - sb);
|
authofs = (int)(sb - buf);
|
||||||
memcpy(auth, sb, authlen);
|
authend = (int)(se - buf);
|
||||||
|
if(authend > REQMAX) RETURN(100);
|
||||||
su = (unsigned char*)strrchr((char *)sb, '@');
|
su = (unsigned char*)strrchr((char *)sb, '@');
|
||||||
if(su) {
|
if(su) {
|
||||||
su = (unsigned char *)strdup((char *)sb);
|
su = (unsigned char *)strdup((char *)sb);
|
||||||
@ -776,22 +769,24 @@ for(;;){
|
|||||||
/* the authority a parent proxy is given, and the line logged, in
|
/* the authority a parent proxy is given, and the line logged, in
|
||||||
absolute form: method, http://, the host, the rest of the line */
|
absolute form: method, http://, the host, the rest of the line */
|
||||||
if(strlen((char *)sb) >= AUTHMAX) RETURN(100);
|
if(strlen((char *)sb) >= AUTHMAX) RETURN(100);
|
||||||
authlen = (int)strlen((char *)sb);
|
|
||||||
memcpy(auth, sb, authlen);
|
|
||||||
{
|
{
|
||||||
size_t ll = (size_t)reqlen + 7 + (size_t)authlen;
|
int hl = (int)strlen((char *)sb);
|
||||||
|
size_t ll = (size_t)reqlen + 7 + (size_t)hl;
|
||||||
unsigned char *l = malloc(ll + 1);
|
unsigned char *l = malloc(ll + 1);
|
||||||
|
|
||||||
if(l){
|
if(!l) RETURN(21);
|
||||||
memcpy(l, buf, ssoff);
|
memcpy(l, buf, ssoff);
|
||||||
memcpy(l + ssoff, "http://", 7);
|
memcpy(l + ssoff, "http://", 7);
|
||||||
memcpy(l + ssoff + 7, auth, authlen);
|
memcpy(l + ssoff + 7, sb, hl);
|
||||||
memcpy(l + ssoff + 7 + authlen, buf + ssoff, reqlen - ssoff);
|
memcpy(l + ssoff + 7 + hl, buf + ssoff, reqlen - ssoff);
|
||||||
l[ll] = 0;
|
l[ll] = 0;
|
||||||
freeptr(&req);
|
freeptr(&req);
|
||||||
req = logline(l, ll);
|
req = logline(l, ll);
|
||||||
free(l);
|
free(l);
|
||||||
}
|
if(!req) RETURN(21);
|
||||||
|
authofs = ssoff + 7;
|
||||||
|
authend = authofs + hl;
|
||||||
|
if(authend > REQMAX) RETURN(100);
|
||||||
}
|
}
|
||||||
if(se)*se = c;
|
if(se)*se = c;
|
||||||
}
|
}
|
||||||
@ -869,11 +864,11 @@ for(;;){
|
|||||||
/* The request filters are given the line as the client sent it, in
|
/* The request filters are given the line as the client sent it, in
|
||||||
absolute form, in a buffer of its own: only when there are some. */
|
absolute form, in a buffer of its own: only when there are some. */
|
||||||
if(param->nreqfilters){
|
if(param->nreqfilters){
|
||||||
int abs = (!isconnect && authlen > 0);
|
int abs = (!isconnect && authend > authofs);
|
||||||
|
|
||||||
reqbufsize = (int)reqlen + (abs? (int)strlen(scheme) + authlen : 0) + 1;
|
reqbufsize = (int)reqlen + (abs? authend - ssoff : 0) + 1;
|
||||||
if(!(fline = malloc(reqbufsize))) RETURN(21);
|
if(!(fline = malloc(reqbufsize))) RETURN(21);
|
||||||
if(abs) reqsize = absline(fline, buf, (int)reqlen, ssoff, scheme, auth, authlen);
|
if(abs) reqsize = absline(fline, buf, (int)reqlen, ssoff, req + ssoff, authend - ssoff);
|
||||||
else {
|
else {
|
||||||
memcpy(fline, buf, reqlen);
|
memcpy(fline, buf, reqlen);
|
||||||
reqsize = (int)reqlen;
|
reqsize = (int)reqlen;
|
||||||
@ -891,11 +886,6 @@ for(;;){
|
|||||||
freeptr(&fline);
|
freeptr(&fline);
|
||||||
RETURN(517);
|
RETURN(517);
|
||||||
}
|
}
|
||||||
/* the rewritten line is the one logged */
|
|
||||||
if(strcmp((char *)fline, (char *)origreq)){
|
|
||||||
freeptr(&req);
|
|
||||||
req = logline(fline, strlen((char *)fline));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only the filters' copy was rewritten. The server is sent the request
|
/* Only the filters' copy was rewritten. The server is sent the request
|
||||||
@ -922,11 +912,22 @@ for(;;){
|
|||||||
int delta = newlen - ((int)reqlen - ssoff);
|
int delta = newlen - ((int)reqlen - ssoff);
|
||||||
|
|
||||||
if(ssoff > 0 && (int)reqlen >= ssoff && inbuf + delta < bufsize - 1){
|
if(ssoff > 0 && (int)reqlen >= ssoff && inbuf + delta < bufsize - 1){
|
||||||
|
unsigned char *nr;
|
||||||
|
|
||||||
memmove(buf + ssoff + newlen, buf + reqlen, inbuf - reqlen + 1);
|
memmove(buf + ssoff + newlen, buf + reqlen, inbuf - reqlen + 1);
|
||||||
memcpy(buf + ssoff, newpath, newlen);
|
memcpy(buf + ssoff, newpath, newlen);
|
||||||
inbuf += delta;
|
inbuf += delta;
|
||||||
reqlen += delta;
|
reqlen += delta;
|
||||||
buf[inbuf] = 0;
|
buf[inbuf] = 0;
|
||||||
|
/* the rewritten line is the one logged, and put back for a
|
||||||
|
parent proxy: its authority is the one it had */
|
||||||
|
if(newhost && (nr = logline(fline, strlen((char *)fline)))){
|
||||||
|
freeptr(&req);
|
||||||
|
req = nr;
|
||||||
|
authofs = (int)(newhost - fline);
|
||||||
|
authend = authofs + newhostlen;
|
||||||
|
if(authend > REQMAX) authofs = authend = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1262,67 +1263,63 @@ for(;;){
|
|||||||
unsigned char *out, *own = NULL;
|
unsigned char *out, *own = NULL;
|
||||||
int outlen, al;
|
int outlen, al;
|
||||||
|
|
||||||
alen = 0;
|
/* written after the header block, with HDRADD free there for them */
|
||||||
|
if(hdrroom(&buf, &bufown, &bufsize, hlen + HDRADD)) RETURN(21);
|
||||||
#ifndef ANONYMOUS
|
#ifndef ANONYMOUS
|
||||||
if(!anonymous){
|
if(!anonymous){
|
||||||
alen += sprintf(add + alen, "Forwarded: for=");
|
hlen += sprintf((char *)buf + hlen, "Forwarded: for=");
|
||||||
if(*SAFAMILY(¶m->sincr) == AF_INET6) alen += sprintf(add + alen, "\"[");
|
if(*SAFAMILY(¶m->sincr) == AF_INET6) hlen += sprintf((char *)buf + hlen, "\"[");
|
||||||
alen += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), add + alen, 128);
|
hlen += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + hlen, 128);
|
||||||
if(*SAFAMILY(¶m->sincr) == AF_INET6) alen += sprintf(add + alen, "]:%d\";by=", (int)ntohs(*SAPORT(¶m->sincr)));
|
if(*SAFAMILY(¶m->sincr) == AF_INET6) hlen += sprintf((char *)buf + hlen, "]:%d\";by=", (int)ntohs(*SAPORT(¶m->sincr)));
|
||||||
else alen += sprintf(add + alen, ":%d;by=", (int)ntohs(*SAPORT(¶m->sincr)));
|
else hlen += sprintf((char *)buf + hlen, ":%d;by=", (int)ntohs(*SAPORT(¶m->sincr)));
|
||||||
gethostname(add + alen, 256);
|
gethostname((char *)buf + hlen, 256);
|
||||||
add[alen + 255] = 0;
|
buf[hlen + 255] = 0;
|
||||||
alen += (int)strlen(add + alen);
|
hlen += (int)strlen((char *)buf + hlen);
|
||||||
alen += sprintf(add + alen, ":%d\r\n", (int)ntohs(*SAPORT(¶m->sincl)));
|
hlen += sprintf((char *)buf + hlen, ":%d\r\n", (int)ntohs(*SAPORT(¶m->sincl)));
|
||||||
}
|
}
|
||||||
else if(anonymous>1){
|
else if(anonymous>1){
|
||||||
alen += sprintf(add + alen, "Via: 1.1 ");
|
hlen += sprintf((char *)buf + hlen, "Via: 1.1 ");
|
||||||
gethostname(add + alen, 256);
|
gethostname((char *)buf + hlen, 256);
|
||||||
add[alen + 255] = 0;
|
buf[hlen + 255] = 0;
|
||||||
alen += (int)strlen(add + alen);
|
hlen += (int)strlen((char *)buf + hlen);
|
||||||
alen += snprintf(add + alen, 400, ":%d (%.100s %.100s)\r\nX-Forwarded-For: ", (int)ntohs(*SAPORT(¶m->srv->intsa)), runconf->stringtable?(char *)runconf->stringtable[2]:"", runconf->stringtable?(char *)runconf->stringtable[3]:"");
|
hlen += snprintf((char *)buf + hlen, 400, ":%d (%.100s %.100s)\r\nX-Forwarded-For: ", (int)ntohs(*SAPORT(¶m->srv->intsa)), runconf->stringtable?(char *)runconf->stringtable[2]:"", runconf->stringtable?(char *)runconf->stringtable[3]:"");
|
||||||
if(anonymous != 2)alen += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), add + alen, 128);
|
if(anonymous != 2)hlen += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + hlen, 128);
|
||||||
else {
|
else {
|
||||||
uint32_t tmp = myrand();
|
uint32_t tmp = myrand();
|
||||||
alen += myinet_ntop(AF_INET, &tmp, add + alen, 64);
|
hlen += myinet_ntop(AF_INET, &tmp, (char *)buf + hlen, 64);
|
||||||
}
|
}
|
||||||
alen += sprintf(add + alen, "\r\n");
|
hlen += sprintf((char *)buf + hlen, "\r\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(keepalive <= 1) {
|
if(keepalive <= 1) {
|
||||||
alen += sprintf(add + alen, "Connection: %s\r\n", keepalive? "keep-alive":"close");
|
hlen += sprintf((char *)buf + hlen, "Connection: %s\r\n", keepalive? "keep-alive":"close");
|
||||||
}
|
}
|
||||||
if(*param->extusername){
|
if(*param->extusername){
|
||||||
alen += sprintf(add + alen, "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization");
|
hlen += sprintf((char *)buf + hlen, "%s: Basic ", (redirect)?"Proxy-Authorization":"Authorization");
|
||||||
sprintf((char*)username, "%.128s:%.128s", param->extusername, param->extpassword);
|
sprintf((char*)username, "%.128s:%.128s", param->extusername, param->extpassword);
|
||||||
/* room kept for the line end, the empty line and the 0 after it */
|
/* room kept for the line end, the empty line and the 0 after it */
|
||||||
if(!(sb = en64(username, (unsigned char *)add + alen, (int)strlen((char *)username), HDRADD - 5 - alen))) {RETURN(21);}
|
if(!(sb = en64(username, buf + hlen, (int)strlen((char *)username), bufsize - 5 - hlen))) {RETURN(21);}
|
||||||
alen = (int)((char *)sb - add);
|
hlen = (int)(sb - buf);
|
||||||
alen += sprintf(add + alen, "\r\n");
|
hlen += sprintf((char *)buf + hlen, "\r\n");
|
||||||
}
|
}
|
||||||
alen += sprintf(add + alen, "\r\n");
|
hlen += sprintf((char *)buf + hlen, "\r\n");
|
||||||
/* after the block, in the room left there, or in a buffer of its own */
|
|
||||||
if(hdrroom(&buf, &bufown, &bufsize, hlen + alen + 1)) RETURN(21);
|
|
||||||
memcpy(buf + hlen, add, alen);
|
|
||||||
hlen += alen;
|
|
||||||
buf[hlen] = 0;
|
|
||||||
out = buf;
|
out = buf;
|
||||||
outlen = hlen;
|
outlen = hlen;
|
||||||
if(redirect && !isconnect && authlen > 0){
|
if(redirect && !isconnect && authend > authofs){
|
||||||
/* scheme and authority put back after the method: in the room before
|
/* scheme and authority, from req, put back after the method: in the
|
||||||
the headers in the side's buffer, the method moved down into it,
|
room before the headers in the side's buffer, the method moved down
|
||||||
else in one buffer of their own; sent in one piece either way */
|
into it, else in one buffer of their own; sent in one piece either
|
||||||
al = (int)strlen(scheme) + authlen;
|
way */
|
||||||
|
al = authend - ssoff;
|
||||||
if(!bufown && al <= hfront){
|
if(!bufown && al <= hfront){
|
||||||
out = buf - al;
|
out = buf - al;
|
||||||
/* method and space move down by al: the regions may overlap */
|
/* method and space move down by al: the regions may overlap */
|
||||||
memmove(out, buf, ssoff);
|
memmove(out, buf, ssoff);
|
||||||
memcpy(out + ssoff, scheme, strlen(scheme));
|
memcpy(out + ssoff, req + ssoff, al);
|
||||||
memcpy(out + ssoff + strlen(scheme), auth, authlen);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(!(own = malloc(hlen + al))) RETURN(21);
|
if(!(own = malloc(hlen + al))) RETURN(21);
|
||||||
absline(own, buf, hlen, ssoff, scheme, auth, authlen);
|
absline(own, buf, hlen, ssoff, req + ssoff, al);
|
||||||
out = own;
|
out = own;
|
||||||
}
|
}
|
||||||
outlen = hlen + al;
|
outlen = hlen + al;
|
||||||
@ -1519,21 +1516,17 @@ for(;;){
|
|||||||
if(!isconnect || param->operation){
|
if(!isconnect || param->operation){
|
||||||
int hlen = (int)strlen((char *)buf);
|
int hlen = (int)strlen((char *)buf);
|
||||||
|
|
||||||
alen = 0;
|
/* written after the header block, with HDRADD free there for them */
|
||||||
if(authenticate && !param->transparent) alen += sprintf(add + alen,
|
if(hdrroom(&buf, &bufown, &bufsize, hlen + HDRADD)) RETURN(21);
|
||||||
|
if(authenticate && !param->transparent) hlen += sprintf((char *)buf + hlen,
|
||||||
"Proxy-support: Session-Based-Authentication\r\n"
|
"Proxy-support: Session-Based-Authentication\r\n"
|
||||||
"Connection: Proxy-support\r\n"
|
"Connection: Proxy-support\r\n"
|
||||||
);
|
);
|
||||||
if(!param->srv->transparent && res>=200){
|
if(!param->srv->transparent && res>=200){
|
||||||
if(ckeepalive <= 1) alen += sprintf(add + alen, "Connection: %s\r\n",
|
if(ckeepalive <= 1) hlen += sprintf((char *)buf + hlen, "Connection: %s\r\n",
|
||||||
(hascontent && ckeepalive)?"keep-alive":"close");
|
(hascontent && ckeepalive)?"keep-alive":"close");
|
||||||
}
|
}
|
||||||
alen += sprintf(add + alen, "\r\n");
|
hlen += sprintf((char *)buf + hlen, "\r\n");
|
||||||
/* after the block, in the room left there, or in a buffer of its own */
|
|
||||||
if(hdrroom(&buf, &bufown, &bufsize, hlen + alen + 1)) RETURN(21);
|
|
||||||
memcpy(buf + hlen, add, alen);
|
|
||||||
hlen += alen;
|
|
||||||
buf[hlen] = 0;
|
|
||||||
if(socksend(param, param->clisock, buf, hlen, param->srv->timeouts[STRING_S]) != hlen) {
|
if(socksend(param, param->clisock, buf, hlen, param->srv->timeouts[STRING_S]) != hlen) {
|
||||||
RETURN(521);
|
RETURN(521);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -203,7 +203,7 @@ def run(t):
|
|||||||
t.fail("its line is in absolute form, put together with the headers", want, head[:120])
|
t.fail("its line is in absolute form, put together with the headers", want, head[:120])
|
||||||
t.eq(body, rbody, "and its body whole")
|
t.eq(body, rbody, "and its body whole")
|
||||||
|
|
||||||
# --- a long request line: served whole, logged up to REQMAX (6 KB) ----
|
# --- a long request line: served whole, logged cut at REQMAX (4 KB) ---
|
||||||
origin.answer = ok
|
origin.answer = ok
|
||||||
origin.requests.clear()
|
origin.requests.clear()
|
||||||
got = session(proxy, request(b"/" + b"q" * 7000), 1)
|
got = session(proxy, request(b"/" + b"q" * 7000), 1)
|
||||||
@ -214,11 +214,20 @@ def run(t):
|
|||||||
deadline = time.time() + 3
|
deadline = time.time() + 3
|
||||||
while time.time() < deadline and "q" * 3000 not in server.output():
|
while time.time() < deadline and "q" * 3000 not in server.output():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
# the log line holds 4000 characters (log.c): cut there before REQMAX
|
|
||||||
logged = [l for l in server.output().splitlines() if "qqqq" in l]
|
logged = [l for l in server.output().splitlines() if "qqqq" in l]
|
||||||
t.ok("and it is logged, cut") if logged and "q" * 7000 not in logged[-1] else \
|
t.ok("and it is logged, cut") if logged and "q" * 4100 not in logged[-1] else \
|
||||||
t.fail("and it is logged, cut", "a log line", logged[-1][-60:] if logged else None)
|
t.fail("and it is logged, cut", "a log line", logged[-1][-60:] if logged else None)
|
||||||
|
|
||||||
|
# through a parent: authority put back from the log copy, a path long
|
||||||
|
# enough for that copy to be cut
|
||||||
|
origin.requests.clear()
|
||||||
|
got = session(viaparent, request(b"/" + b"r" * 5000), 1)
|
||||||
|
t.contains(got.decode("latin-1"), "200 OK", "a 5 KB line through a parent is answered")
|
||||||
|
head = origin.requests[0][0] if origin.requests else b""
|
||||||
|
want = b"GET " + base.encode() + b"/" + b"r" * 5000 + b" HTTP/1.1\r\n"
|
||||||
|
t.ok("in absolute form, whole") if head.startswith(want) else \
|
||||||
|
t.fail("in absolute form, whole", "GET http://.../rrr", head[:80])
|
||||||
|
|
||||||
# --- a request too big for any buffer is refused, and the proxy stays --
|
# --- a request too big for any buffer is refused, and the proxy stays --
|
||||||
huge = b"".join(b"X-Huge-%d: %s\r\n" % (i, b"H" * 30000) for i in range(20))
|
huge = b"".join(b"X-Huge-%d: %s\r\n" % (i, b"H" * 30000) for i in range(20))
|
||||||
got = session(proxy, request(b"/huge", huge), 1, timeout=3)
|
got = session(proxy, request(b"/huge", huge), 1, timeout=3)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user