Lines 84-89
Link Here
|
84 |
return NULL; |
84 |
return NULL; |
85 |
} |
85 |
} |
86 |
c->opt=opt; |
86 |
c->opt=opt; |
|
|
87 |
/* some options need space to add some information */ |
88 |
if (c->opt->option.xforwardedfor) |
89 |
c->buffsize = BUFFSIZE - BUFF_RESERVED; |
90 |
else |
91 |
c->buffsize = BUFFSIZE; |
92 |
c->crlf_seen=0; |
87 |
c->local_rfd.fd=rfd; |
93 |
c->local_rfd.fd=rfd; |
88 |
c->local_wfd.fd=wfd; |
94 |
c->local_wfd.fd=wfd; |
89 |
return c; |
95 |
return c; |
Lines 372-377
Link Here
|
372 |
} |
378 |
} |
373 |
} |
379 |
} |
374 |
|
380 |
|
|
|
381 |
/* Moves all data from the buffer <buffer> between positions <start> and <stop> |
382 |
* to insert <string> of length <len>. <start> and <stop> are updated to their |
383 |
* new respective values, and the number of characters inserted is returned. |
384 |
* If <len> is too long, nothing is done and -1 is returned. |
385 |
* Note that neither <string> nor <buffer> can be NULL. |
386 |
*/ |
387 |
static int buffer_insert_with_len(char *buffer, int *start, int *stop, int limit, char *string, int len) { |
388 |
if (len > limit - *stop) |
389 |
return -1; |
390 |
if (*start > *stop) |
391 |
return -1; |
392 |
memmove(buffer + *start + len, buffer + *start, *stop - *start); |
393 |
memcpy(buffer + *start, string, len); |
394 |
*start += len; |
395 |
*stop += len; |
396 |
return len; |
397 |
} |
398 |
|
399 |
static int buffer_insert(char *buffer, int *start, int *stop, int limit, char *string) { |
400 |
return buffer_insert_with_len(buffer, start, stop, limit, string, strlen(string)); |
401 |
} |
402 |
|
375 |
/****************************** transfer data */ |
403 |
/****************************** transfer data */ |
376 |
static void transfer(CLI *c) { |
404 |
static void transfer(CLI *c) { |
377 |
int watchdog=0; /* a counter to detect an infinite loop */ |
405 |
int watchdog=0; /* a counter to detect an infinite loop */ |
Lines 390-396
Link Here
|
390 |
do { /* main loop of client data transfer */ |
418 |
do { /* main loop of client data transfer */ |
391 |
/****************************** initialize *_wants_* */ |
419 |
/****************************** initialize *_wants_* */ |
392 |
read_wants_read= |
420 |
read_wants_read= |
393 |
ssl_open_rd && c->ssl_ptr<BUFFSIZE && !read_wants_write; |
421 |
ssl_open_rd && c->ssl_ptr<c->buffsize && !read_wants_write; |
394 |
write_wants_write= |
422 |
write_wants_write= |
395 |
ssl_open_wr && c->sock_ptr && !write_wants_read; |
423 |
ssl_open_wr && c->sock_ptr && !write_wants_read; |
396 |
|
424 |
|
Lines 399-405
Link Here
|
399 |
/* for plain socket open data strem = open file descriptor */ |
427 |
/* for plain socket open data strem = open file descriptor */ |
400 |
/* make sure to add each open socket to receive exceptions! */ |
428 |
/* make sure to add each open socket to receive exceptions! */ |
401 |
if(sock_open_rd) |
429 |
if(sock_open_rd) |
402 |
s_poll_add(&c->fds, c->sock_rfd->fd, c->sock_ptr<BUFFSIZE, 0); |
430 |
s_poll_add(&c->fds, c->sock_rfd->fd, c->sock_ptr<c->buffsize, 0); |
403 |
if(sock_open_wr) |
431 |
if(sock_open_wr) |
404 |
s_poll_add(&c->fds, c->sock_wfd->fd, 0, c->ssl_ptr); |
432 |
s_poll_add(&c->fds, c->sock_wfd->fd, 0, c->ssl_ptr); |
405 |
/* for SSL assume that sockets are open if there any pending requests */ |
433 |
/* for SSL assume that sockets are open if there any pending requests */ |
Lines 531-537
Link Here
|
531 |
/****************************** read from socket */ |
559 |
/****************************** read from socket */ |
532 |
if(sock_open_rd && sock_can_rd) { |
560 |
if(sock_open_rd && sock_can_rd) { |
533 |
num=readsocket(c->sock_rfd->fd, |
561 |
num=readsocket(c->sock_rfd->fd, |
534 |
c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr); |
562 |
c->sock_buff+c->sock_ptr, c->buffsize-c->sock_ptr); |
535 |
switch(num) { |
563 |
switch(num) { |
536 |
case -1: |
564 |
case -1: |
537 |
parse_socket_error(c, "readsocket"); |
565 |
parse_socket_error(c, "readsocket"); |
Lines 567-573
Link Here
|
567 |
/****************************** update *_wants_* based on new *_ptr */ |
595 |
/****************************** update *_wants_* based on new *_ptr */ |
568 |
/* this update is also required for SSL_pending() to be used */ |
596 |
/* this update is also required for SSL_pending() to be used */ |
569 |
read_wants_read= |
597 |
read_wants_read= |
570 |
ssl_open_rd && c->ssl_ptr<BUFFSIZE && !read_wants_write; |
598 |
ssl_open_rd && c->ssl_ptr<c->buffsize && !read_wants_write; |
571 |
write_wants_write= |
599 |
write_wants_write= |
572 |
ssl_open_wr && c->sock_ptr && !write_wants_read; |
600 |
ssl_open_wr && c->sock_ptr && !write_wants_read; |
573 |
|
601 |
|
Lines 577-586
Link Here
|
577 |
* writesocket() above made some room in c->ssl_buff */ |
605 |
* writesocket() above made some room in c->ssl_buff */ |
578 |
(read_wants_write && ssl_can_wr)) { |
606 |
(read_wants_write && ssl_can_wr)) { |
579 |
read_wants_write=0; |
607 |
read_wants_write=0; |
580 |
num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr); |
608 |
num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, c->buffsize-c->ssl_ptr); |
581 |
switch(err=SSL_get_error(c->ssl, num)) { |
609 |
switch(err=SSL_get_error(c->ssl, num)) { |
582 |
case SSL_ERROR_NONE: |
610 |
case SSL_ERROR_NONE: |
583 |
c->ssl_ptr+=num; |
611 |
if (c->buffsize != BUFFSIZE && c->opt->option.xforwardedfor) { /* some work left to do */ |
|
|
612 |
int last = c->ssl_ptr; |
613 |
c->ssl_ptr += num; |
614 |
|
615 |
/* Look for end of HTTP headers between last and ssl_ptr. |
616 |
* To achieve this reliably, we have to count the number of |
617 |
* successive [CR]LF and to memorize it in case it's spread |
618 |
* over multiple segments. --WT. |
619 |
*/ |
620 |
while (last < c->ssl_ptr) { |
621 |
if (c->ssl_buff[last] == '\n') { |
622 |
if (++c->crlf_seen == 2) |
623 |
break; |
624 |
} else if (last < c->ssl_ptr - 1 && |
625 |
c->ssl_buff[last] == '\r' && |
626 |
c->ssl_buff[last+1] == '\n') { |
627 |
if (++c->crlf_seen == 2) |
628 |
break; |
629 |
last++; |
630 |
} else if (c->ssl_buff[last] != '\r') |
631 |
/* don't refuse '\r' because we may get a '\n' on next read */ |
632 |
c->crlf_seen = 0; |
633 |
last++; |
634 |
} |
635 |
if (c->crlf_seen >= 2) { |
636 |
/* We have all the HTTP headers now. We don't need to |
637 |
* reserve any space anymore. <ssl_ptr> points to the |
638 |
* first byte of unread data, and <last> points to the |
639 |
* exact location where we want to insert our headers, |
640 |
* which is right before the empty line. |
641 |
*/ |
642 |
c->buffsize = BUFFSIZE; |
643 |
|
644 |
if (c->opt->option.xforwardedfor) { |
645 |
/* X-Forwarded-For: xxxx \r\n\0 */ |
646 |
char xforw[17 + IPLEN + 3]; |
647 |
|
648 |
/* We will insert our X-Forwarded-For: header here. |
649 |
* We need to write the IP address, but if we use |
650 |
* sprintf, it will pad with the terminating 0. |
651 |
* So we will pass via a temporary buffer allocated |
652 |
* on the stack. |
653 |
*/ |
654 |
memcpy(xforw, "X-Forwarded-For: ", 17); |
655 |
if (getnameinfo(&c->peer_addr.addr[0].sa, |
656 |
addr_len(c->peer_addr.addr[0]), |
657 |
xforw + 17, IPLEN, NULL, 0, |
658 |
NI_NUMERICHOST) == 0) { |
659 |
strcat(xforw + 17, "\r\n"); |
660 |
buffer_insert(c->ssl_buff, &last, &c->ssl_ptr, |
661 |
c->buffsize, xforw); |
662 |
} |
663 |
/* last still points to the \r\n and ssl_ptr to the |
664 |
* end of the buffer, so we may add as many headers |
665 |
* as wee need to. |
666 |
*/ |
667 |
} |
668 |
} |
669 |
} |
670 |
else |
671 |
c->ssl_ptr+=num; |
672 |
|
584 |
watchdog=0; /* reset watchdog */ |
673 |
watchdog=0; /* reset watchdog */ |
585 |
break; |
674 |
break; |
586 |
case SSL_ERROR_WANT_WRITE: |
675 |
case SSL_ERROR_WANT_WRITE: |