"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "http.c" between
Pound-2.7.tgz and Pound-2.8.tgz

About: Pound is a reverse proxy, load balancer and HTTPS front-end for Web server(s).

http.c  (Pound-2.7.tgz):http.c  (Pound-2.8.tgz)
skipping to change at line 34 skipping to change at line 34
* Switzerland * Switzerland
* EMail: roseg@apsis.ch * EMail: roseg@apsis.ch
*/ */
#include "pound.h" #include "pound.h"
/* HTTP error replies */ /* HTTP error replies */
static char *h500 = "500 Internal Server Error", static char *h500 = "500 Internal Server Error",
*h501 = "501 Not Implemented", *h501 = "501 Not Implemented",
*h503 = "503 Service Unavailable", *h503 = "503 Service Unavailable",
*h414 = "414 Request URI too long"; *h414 = "414 Request URI too long",
*h400 = "Bad Request";
static char *err_response = "HTTP/1.0 %s\r\nContent-Type: text/html\r\nContent-L ength: %d\r\nExpires: now\r\nPragma: no-cache\r\nCache-control: no-cache,no-stor e\r\n\r\n%s"; static char *err_response = "HTTP/1.0 %s\r\nContent-Type: text/html\r\nContent-L ength: %d\r\nExpires: now\r\nPragma: no-cache\r\nCache-control: no-cache,no-stor e\r\n\r\n%s";
/* /*
* Reply with an error * Reply with an error
*/ */
static void static void
err_reply(BIO *const c, const char *head, const char *txt) err_reply(BIO *const c, const char *head, const char *txt)
{ {
BIO_printf(c, err_response, head, strlen(txt), txt); BIO_printf(c, err_response, head, strlen(txt), txt);
skipping to change at line 86 skipping to change at line 87
safe_url[j++] = url[i]; safe_url[j++] = url[i];
else { else {
sprintf(safe_url + j, "%%%02x", url[i]); sprintf(safe_url + j, "%%%02x", url[i]);
j += 3; j += 3;
} }
snprintf(cont, sizeof(cont), snprintf(cont, sizeof(cont),
"<html><head><title>Redirect</title></head><body><h1>Redirect</h1><p>You should go to <a href=\"%s\">%s</a></p></body></html>", "<html><head><title>Redirect</title></head><body><h1>Redirect</h1><p>You should go to <a href=\"%s\">%s</a></p></body></html>",
safe_url, safe_url); safe_url, safe_url);
snprintf(rep, sizeof(rep), snprintf(rep, sizeof(rep),
"HTTP/1.0 %d %s\r\nLocation: %s\r\nContent-Type: text/html\r\nContent-Le ngth: %d\r\n\r\n", "HTTP/1.0 %d %s\r\nLocation: %s\r\nContent-Type: text/html\r\nContent-Le ngth: %d\r\n\r\n",
code, code_msg, safe_url, strlen(cont)); code, code_msg, safe_url, (int)strlen(cont));
BIO_write(c, rep, strlen(rep)); BIO_write(c, rep, strlen(rep));
BIO_write(c, cont, strlen(cont)); BIO_write(c, cont, strlen(cont));
BIO_flush(c); BIO_flush(c);
return; return;
} }
/* /*
* Read and write some binary data * Read and write some binary data
*/ */
static int static int
skipping to change at line 129 skipping to change at line 130
/* /*
* Get a "line" from a BIO, strip the trailing newline, skip the input stream if buffer too small * Get a "line" from a BIO, strip the trailing newline, skip the input stream if buffer too small
* The result buffer is NULL terminated * The result buffer is NULL terminated
* Return 0 on success * Return 0 on success
*/ */
static int static int
get_line(BIO *const in, char *const buf, const int bufsize) get_line(BIO *const in, char *const buf, const int bufsize)
{ {
char tmp; char tmp;
int i, n_read; int i, n_read, seen_cr;
memset(buf, 0, bufsize); memset(buf, 0, bufsize);
for(n_read = 0;;) for(i = 0, seen_cr = 0; i < bufsize - 1; i++)
switch(BIO_gets(in, buf + n_read, bufsize - n_read - 1)) { switch(BIO_read(in, &tmp, 1)) {
case -2: case -2:
/* BIO_gets not implemented */ /* BIO_gets not implemented */
return -1; return -1;
case 0: case 0:
case -1: case -1:
return 1; return 1;
default: default:
for(i = n_read; i < bufsize && buf[i]; i++) if(seen_cr)
if(buf[i] == '\n' || buf[i] == '\r') { if(tmp != '\n') {
buf[i] = '\0'; /* we have CR not followed by NL */
do {
if(BIO_read(in, &tmp, 1) < 0)
return 1;
} while(tmp != '\n');
return 1;
} else {
buf[i - 1] = '\0';
return 0; return 0;
} }
if(i < bufsize) {
n_read = i; if(!iscntrl(tmp) || tmp == '\t') {
buf[i] = tmp;
continue; continue;
} }
logmsg(LOG_NOTICE, "(%lx) line too long: %s", pthread_self(), buf);
/* skip rest of "line" */ if(tmp == '\r') {
tmp = '\0'; seen_cr = 1;
while(tmp != '\n') continue;
if(BIO_read(in, &tmp, 1) != 1) }
if(tmp == '\n') {
/* line ends in NL only (no CR) */
buf[i] = 0;
return 0;
}
/* all other control characters cause an error */
do {
if(BIO_read(in, &tmp, 1) < 0)
return 1; return 1;
break; } while(tmp != '\n');
return 1;
} }
return 0;
/* line too long */
do {
if(BIO_read(in, &tmp, 1) < 0)
return 1;
} while(tmp != '\n');
return 1;
} }
/* /*
* Strip trailing CRLF * Strip trailing CRLF
*/ */
static int static int
strip_eol(char *lin) strip_eol(char *lin)
{ {
while(*lin) while(*lin)
if(*lin == '\n' || (*lin == '\r' && *(lin + 1) == '\n')) { if(*lin == '\n' || (*lin == '\r' && *(lin + 1) == '\n')) {
skipping to change at line 396 skipping to change at line 422
} }
static char ** static char **
get_headers(BIO *const in, BIO *const cl, const LISTENER *lstn) get_headers(BIO *const in, BIO *const cl, const LISTENER *lstn)
{ {
char **headers, buf[MAXBUF]; char **headers, buf[MAXBUF];
int res, n, has_eol; int res, n, has_eol;
/* HTTP/1.1 allows leading CRLF */ /* HTTP/1.1 allows leading CRLF */
memset(buf, 0, MAXBUF); memset(buf, 0, MAXBUF);
while((res = BIO_gets(in, buf, MAXBUF - 1)) > 0) { while((res = get_line(in, buf, MAXBUF)) == 0)
has_eol = strip_eol(buf);
if(buf[0]) if(buf[0])
break; break;
}
if(res <= 0) { if(res < 0) {
/* this is expected to occur only on client reads */ /* this is expected to occur only on client reads */
/* logmsg(LOG_NOTICE, "headers: bad starting read"); */ /* logmsg(LOG_NOTICE, "headers: bad starting read"); */
return NULL; return NULL;
} else if(!has_eol) {
/* check for request length limit */
logmsg(LOG_WARNING, "(%lx) e414 headers: request URI too long", pthread_
self());
err_reply(cl, h414, lstn->err414);
return NULL;
} }
if((headers = (char **)calloc(MAXHEADERS, sizeof(char *))) == NULL) { if((headers = (char **)calloc(MAXHEADERS, sizeof(char *))) == NULL) {
logmsg(LOG_WARNING, "(%lx) e500 headers: out of memory", pthread_self()) ; logmsg(LOG_WARNING, "(%lx) e500 headers: out of memory", pthread_self()) ;
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
return NULL; return NULL;
} }
if((headers[0] = (char *)malloc(MAXBUF)) == NULL) { if((headers[0] = (char *)malloc(MAXBUF)) == NULL) {
free_headers(headers); free_headers(headers);
logmsg(LOG_WARNING, "(%lx) e500 header: out of memory", pthread_self()); logmsg(LOG_WARNING, "(%lx) e500 header: out of memory", pthread_self());
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
return NULL; return NULL;
} }
memset(headers[0], 0, MAXBUF); memset(headers[0], 0, MAXBUF);
strncpy(headers[0], buf, MAXBUF - 1); strncpy(headers[0], buf, MAXBUF - 1);
for(n = 1; n < MAXHEADERS; n++) { for(n = 1; n < MAXHEADERS; n++) {
if(get_line(in, buf, MAXBUF)) { if(get_line(in, buf, MAXBUF)) {
free_headers(headers); free_headers(headers);
/* this is not necessarily an error, EOF/timeout are possible
logmsg(LOG_WARNING, "(%lx) e500 can't read header", pthread_self()); logmsg(LOG_WARNING, "(%lx) e500 can't read header", pthread_self());
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
*/
return NULL; return NULL;
} }
if(!buf[0]) if(!buf[0])
return headers; return headers;
if((headers[n] = (char *)malloc(MAXBUF)) == NULL) { if((headers[n] = (char *)malloc(MAXBUF)) == NULL) {
free_headers(headers); free_headers(headers);
logmsg(LOG_WARNING, "(%lx) e500 header: out of memory", pthread_self ()); logmsg(LOG_WARNING, "(%lx) e500 header: out of memory", pthread_self ());
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
return NULL; return NULL;
} }
skipping to change at line 716 skipping to change at line 738
strcpy(referer, buf); strcpy(referer, buf);
break; break;
case HEADER_USER_AGENT: case HEADER_USER_AGENT:
strcpy(u_agent, buf); strcpy(u_agent, buf);
break; break;
case HEADER_CONNECTION: case HEADER_CONNECTION:
if(!strcasecmp("close", buf)) if(!strcasecmp("close", buf))
conn_closed = 1; conn_closed = 1;
break; break;
case HEADER_TRANSFER_ENCODING: case HEADER_TRANSFER_ENCODING:
if(cont >= L0) if(!strcasecmp("chunked", buf))
headers_ok[n] = 0; chunked = 1;
else if(!strcasecmp("chunked", buf)) else {
if(chunked) addr2str(caddr, MAXBUF - 1, &from_host, 1);
headers_ok[n] = 0; logmsg(LOG_NOTICE, "(%lx) e400 multiple Transfer-encoding \"
else %s\" from %s", pthread_self(), url, caddr);
chunked = 1; err_reply(cl, h400, "Bad request: multiple Transfer-encoding
values");
free_headers(headers);
clean_all();
return;
}
break; break;
case HEADER_CONTENT_LENGTH: case HEADER_CONTENT_LENGTH:
if(chunked || cont >= 0L) if(cont != L_1 || strchr(buf, ',')) {
headers_ok[n] = 0; addr2str(caddr, MAXBUF - 1, &from_host, 1);
else { logmsg(LOG_NOTICE, "(%lx) e400 multiple Content-length \"%s\
if((cont = ATOL(buf)) < 0L) " from %s", pthread_self(), url, caddr);
headers_ok[n] = 0; err_reply(cl, h400, "Bad request: multiple Content-length va
if(is_rpc == 1 && (cont < 0x20000L || cont > 0x80000000L)) lues");
is_rpc = -1; free_headers(headers);
clean_all();
return;
} }
for(mh = buf; *mh; mh++)
if(!isdigit(*mh)) {
addr2str(caddr, MAXBUF - 1, &from_host, 1);
logmsg(LOG_NOTICE, "(%lx) e400 Content-length bad value
\"%s\" from %s", pthread_self(), url, caddr);
err_reply(cl, h400, "Bad request: Content-length bad val
ue");
free_headers(headers);
clean_all();
return;
}
if((cont = ATOL(buf)) < 0L)
headers_ok[n] = 0;
if(is_rpc == 1 && (cont < 0x20000L || cont > 0x80000000L))
is_rpc = -1;
break; break;
case HEADER_EXPECT: case HEADER_EXPECT:
/* /*
* we do NOT support the "Expect: 100-continue" headers * we do NOT support the "Expect: 100-continue" headers
* support may involve severe performance penalties (non-respond ing back-end, etc) * support may involve severe performance penalties (non-respond ing back-end, etc)
* as a stop-gap measure we just skip these headers * as a stop-gap measure we just skip these headers
*/ */
if(!strcasecmp("100-continue", buf)) if(!strcasecmp("100-continue", buf))
headers_ok[n] = 0; headers_ok[n] = 0;
break; break;
skipping to change at line 790 skipping to change at line 828
BIO_free_all(b64); BIO_free_all(b64);
if((mh = strchr(buf, ':')) == NULL) { if((mh = strchr(buf, ':')) == NULL) {
logmsg(LOG_WARNING, "(%lx) Unknown authentication", pthread_ self()); logmsg(LOG_WARNING, "(%lx) Unknown authentication", pthread_ self());
continue; continue;
} }
*mh = '\0'; *mh = '\0';
strcpy(u_name, buf); strcpy(u_name, buf);
} }
} }
/* check for possible request smuggling attempt */
if(chunked != 0 && cont != L_1) {
addr2str(caddr, MAXBUF - 1, &from_host, 1);
logmsg(LOG_NOTICE, "(%lx) e501 Transfer-encoding and Content-length
\"%s\" from %s", pthread_self(), url, caddr);
err_reply(cl, h400, "Bad request: Transfer-encoding and Content-leng
th headers present");
free_headers(headers);
clean_all();
return;
}
/* possibly limited request size */ /* possibly limited request size */
if(lstn->max_req > L0 && cont > L0 && cont > lstn->max_req && is_rpc != 1) { if(lstn->max_req > L0 && cont > L0 && cont > lstn->max_req && is_rpc != 1) {
addr2str(caddr, MAXBUF - 1, &from_host, 1); addr2str(caddr, MAXBUF - 1, &from_host, 1);
logmsg(LOG_NOTICE, "(%lx) e501 request too large (%ld) from %s", pth read_self(), cont, caddr); logmsg(LOG_NOTICE, "(%lx) e501 request too large (%ld) from %s", pth read_self(), cont, caddr);
err_reply(cl, h501, lstn->err501); err_reply(cl, h501, lstn->err501);
free_headers(headers); free_headers(headers);
clean_all(); clean_all();
return; return;
} }
skipping to change at line 1091 skipping to change at line 1139
if(BIO_printf(be, "X-SSL-serial: %ld\r\n", ASN1_INTEGER_get(X509 _get_serialNumber(x509))) <= 0) { if(BIO_printf(be, "X-SSL-serial: %ld\r\n", ASN1_INTEGER_get(X509 _get_serialNumber(x509))) <= 0) {
str_be(buf, MAXBUF - 1, cur_backend); str_be(buf, MAXBUF - 1, cur_backend);
end_req = cur_time(); end_req = cur_time();
logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-serial to %s: %s (%.3f sec)", logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-serial to %s: %s (%.3f sec)",
pthread_self(), buf, strerror(errno), (end_req - start_r eq) / 1000000.0); pthread_self(), buf, strerror(errno), (end_req - start_r eq) / 1000000.0);
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
BIO_free_all(bb); BIO_free_all(bb);
clean_all(); clean_all();
return; return;
} }
#ifdef CERT1L
PEM_write_bio_X509(bb, x509); PEM_write_bio_X509(bb, x509);
get_line(bb, buf, MAXBUF); get_line(bb, buf, MAXBUF);
if(BIO_printf(be, "X-SSL-certificate: %s", buf) <= 0) { if(BIO_printf(be, "X-SSL-certificate: %s", buf) <= 0) {
str_be(buf, MAXBUF - 1, cur_backend); str_be(buf, MAXBUF - 1, cur_backend);
end_req = cur_time(); end_req = cur_time();
logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificat e to %s: %s (%.3f sec)", logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificat e to %s: %s (%.3f sec)",
pthread_self(), buf, strerror(errno), (end_req - start_r eq) / 1000000.0); pthread_self(), buf, strerror(errno), (end_req - start_r eq) / 1000000.0);
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
BIO_free_all(bb); BIO_free_all(bb);
clean_all(); clean_all();
skipping to change at line 1116 skipping to change at line 1163
str_be(buf, MAXBUF - 1, cur_backend); str_be(buf, MAXBUF - 1, cur_backend);
end_req = cur_time(); end_req = cur_time();
logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certif icate to %s: %s (%.3f sec)", logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certif icate to %s: %s (%.3f sec)",
pthread_self(), buf, strerror(errno), (end_req - sta rt_req) / 1000000.0); pthread_self(), buf, strerror(errno), (end_req - sta rt_req) / 1000000.0);
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
BIO_free_all(bb); BIO_free_all(bb);
clean_all(); clean_all();
return; return;
} }
} }
if(BIO_printf(be, "\r\n", buf) <= 0) { if(BIO_printf(be, "\r\n") <= 0) {
str_be(buf, MAXBUF - 1, cur_backend);
end_req = cur_time();
logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificat
e to %s: %s (%.3f sec)",
pthread_self(), buf, strerror(errno), (end_req - start_r
eq) / 1000000.0);
err_reply(cl, h500, lstn->err500);
BIO_free_all(bb);
clean_all();
return;
}
#else
PEM_write_bio_X509(bb, x509);
get_line(bb, buf, MAXBUF);
if(BIO_printf(be, "X-SSL-certificate: %s\r\n", buf) <= 0) {
str_be(buf, MAXBUF - 1, cur_backend); str_be(buf, MAXBUF - 1, cur_backend);
end_req = cur_time(); end_req = cur_time();
logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificat e to %s: %s (%.3f sec)", logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certificat e to %s: %s (%.3f sec)",
pthread_self(), buf, strerror(errno), (end_req - start_r eq) / 1000000.0); pthread_self(), buf, strerror(errno), (end_req - start_r eq) / 1000000.0);
err_reply(cl, h500, lstn->err500); err_reply(cl, h500, lstn->err500);
BIO_free_all(bb); BIO_free_all(bb);
clean_all(); clean_all();
return; return;
} }
while(get_line(bb, buf, MAXBUF) == 0) {
if(BIO_printf(be, "\t%s\r\n", buf) <= 0) {
str_be(buf, MAXBUF - 1, cur_backend);
end_req = cur_time();
logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-certif
icate to %s: %s (%.3f sec)",
pthread_self(), buf, strerror(errno), (end_req - sta
rt_req) / 1000000.0);
err_reply(cl, h500, lstn->err500);
BIO_free_all(bb);
clean_all();
return;
}
}
#endif
BIO_free_all(bb); BIO_free_all(bb);
} }
} }
/* put additional client IP header */ /* put additional client IP header */
if(cur_backend->be_type == 0) { if(cur_backend->be_type == 0) {
addr2str(caddr, MAXBUF - 1, &from_host, 1); addr2str(caddr, MAXBUF - 1, &from_host, 1);
BIO_printf(be, "X-Forwarded-For: %s\r\n", caddr); BIO_printf(be, "X-Forwarded-For: %s\r\n", caddr);
/* final CRLF */ /* final CRLF */
BIO_puts(be, "\r\n"); BIO_puts(be, "\r\n");
skipping to change at line 1556 skipping to change at line 1577
if(errno) { if(errno) {
addr2str(caddr, MAXBUF - 1, &from_host, 1); addr2str(caddr, MAXBUF - 1, &from_host, 1);
logmsg(LOG_NOTICE, "(%lx) error final flush to %s: %s", pthread_self(), caddr, strerror(errno)); logmsg(LOG_NOTICE, "(%lx) error final flush to %s: %s", pthread_self(), caddr, strerror(errno));
} }
clean_all(); clean_all();
return; return;
} }
} }
} }
end_req = cur_time(); end_req = cur_time();
upd_be(svc, cur_backend, end_req - start_req);
/* log what happened */ /* log what happened */
memset(s_res_bytes, 0, LOG_BYTES_SIZE); memset(s_res_bytes, 0, LOG_BYTES_SIZE);
log_bytes(s_res_bytes, res_bytes); log_bytes(s_res_bytes, res_bytes);
addr2str(caddr, MAXBUF - 1, &from_host, 1); addr2str(caddr, MAXBUF - 1, &from_host, 1);
if(anonymise) { if(anonymise) {
char *last; char *last;
if((last = strrchr(caddr, '.')) != NULL || (last = strrchr(caddr, ': ')) != NULL) if((last = strrchr(caddr, '.')) != NULL || (last = strrchr(caddr, ': ')) != NULL)
strcpy(++last, "0"); strcpy(++last, "0");
 End of changes. 24 change blocks. 
74 lines changed or deleted 97 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)