/[gentoo-x86]/net-misc/stunnel/files/stunnel-4.54-xforwarded-for.patch
Gentoo

Contents of /net-misc/stunnel/files/stunnel-4.54-xforwarded-for.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations) (download)
Tue Dec 25 04:25:06 2012 UTC (2 years, 7 months ago) by ramereth
Branch: MAIN
Version bump, fix init script, fixes #448298 & #436268

(Portage version: 2.1.11.31/cvs/Linux x86_64, signed Manifest commit with key 27F4B742)

1 --- src/client.c
2 +++ src/client.c
3 @@ -75,6 +75,12 @@
4 c=str_alloc(sizeof(CLI));
5 str_detach(c);
6 c->opt=opt;
7 + /* some options need space to add some information */
8 + if (c->opt->option.xforwardedfor)
9 + c->buffsize = BUFFSIZE - BUFF_RESERVED;
10 + else
11 + c->buffsize = BUFFSIZE;
12 + c->crlf_seen=0;
13 c->local_rfd.fd=rfd;
14 c->local_wfd.fd=wfd;
15 return c;
16 @@ -496,6 +502,28 @@
17 }
18 #endif
19
20 +/* Moves all data from the buffer <buffer> between positions <start> and <stop>
21 + * to insert <string> of length <len>. <start> and <stop> are updated to their
22 + * new respective values, and the number of characters inserted is returned.
23 + * If <len> is too long, nothing is done and -1 is returned.
24 + * Note that neither <string> nor <buffer> can be NULL.
25 + */
26 +static int buffer_insert_with_len(char *buffer, int *start, int *stop, int limit, char *string, int len) {
27 + if (len > limit - *stop)
28 + return -1;
29 + if (*start > *stop)
30 + return -1;
31 + memmove(buffer + *start + len, buffer + *start, *stop - *start);
32 + memcpy(buffer + *start, string, len);
33 + *start += len;
34 + *stop += len;
35 + return len;
36 +}
37 +
38 +static int buffer_insert(char *buffer, int *start, int *stop, int limit, char *string) {
39 + return buffer_insert_with_len(buffer, start, stop, limit, string, strlen(string));
40 +}
41 +
42 /****************************** transfer data */
43 static void transfer(CLI *c) {
44 int watchdog=0; /* a counter to detect an infinite loop */
45 @@ -514,7 +542,7 @@
46 do { /* main loop of client data transfer */
47 /****************************** initialize *_wants_* */
48 read_wants_read=!(SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN)
49 - && c->ssl_ptr<BUFFSIZE && !read_wants_write;
50 + && c->ssl_ptr<c->buffsize && !read_wants_write;
51 write_wants_write=!(SSL_get_shutdown(c->ssl)&SSL_SENT_SHUTDOWN)
52 && c->sock_ptr && !write_wants_read;
53
54 @@ -523,7 +551,7 @@
55 /* for plain socket open data strem = open file descriptor */
56 /* make sure to add each open socket to receive exceptions! */
57 if(sock_open_rd)
58 - s_poll_add(c->fds, c->sock_rfd->fd, c->sock_ptr<BUFFSIZE, 0);
59 + s_poll_add(c->fds, c->sock_rfd->fd, c->sock_ptr<c->buffsize, 0);
60 if(sock_open_wr)
61 s_poll_add(c->fds, c->sock_wfd->fd, 0, c->ssl_ptr);
62 /* for SSL assume that sockets are open if there any pending requests */
63 @@ -650,7 +678,7 @@
64 /****************************** read from socket */
65 if(sock_open_rd && sock_can_rd) {
66 num=readsocket(c->sock_rfd->fd,
67 - c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr);
68 + c->sock_buff+c->sock_ptr, c->buffsize-c->sock_ptr);
69 switch(num) {
70 case -1:
71 if(parse_socket_error(c, "readsocket"))
72 @@ -687,7 +715,7 @@
73 /****************************** update *_wants_* based on new *_ptr */
74 /* this update is also required for SSL_pending() to be used */
75 read_wants_read=!(SSL_get_shutdown(c->ssl)&SSL_RECEIVED_SHUTDOWN)
76 - && c->ssl_ptr<BUFFSIZE && !read_wants_write;
77 + && c->ssl_ptr<c->buffsize && !read_wants_write;
78 write_wants_write=!(SSL_get_shutdown(c->ssl)&SSL_SENT_SHUTDOWN)
79 && c->sock_ptr && !write_wants_read;
80
81 @@ -697,12 +725,73 @@
82 * writesocket() above made some room in c->ssl_buff */
83 (read_wants_write && ssl_can_wr)) {
84 read_wants_write=0;
85 - num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr);
86 + num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, c->buffsize-c->ssl_ptr);
87 switch(err=SSL_get_error(c->ssl, num)) {
88 case SSL_ERROR_NONE:
89 if(num==0)
90 s_log(LOG_DEBUG, "SSL_read returned 0");
91 - c->ssl_ptr+=num;
92 + if (c->buffsize != BUFFSIZE && c->opt->option.xforwardedfor) { /* some work left to do */
93 + int last = c->ssl_ptr;
94 + c->ssl_ptr += num;
95 +
96 + /* Look for end of HTTP headers between last and ssl_ptr.
97 + * To achieve this reliably, we have to count the number of
98 + * successive [CR]LF and to memorize it in case it's spread
99 + * over multiple segments. --WT.
100 + */
101 + while (last < c->ssl_ptr) {
102 + if (c->ssl_buff[last] == '\n') {
103 + if (++c->crlf_seen == 2)
104 + break;
105 + } else if (last < c->ssl_ptr - 1 &&
106 + c->ssl_buff[last] == '\r' &&
107 + c->ssl_buff[last+1] == '\n') {
108 + if (++c->crlf_seen == 2)
109 + break;
110 + last++;
111 + } else if (c->ssl_buff[last] != '\r')
112 + /* don't refuse '\r' because we may get a '\n' on next read */
113 + c->crlf_seen = 0;
114 + last++;
115 + }
116 + if (c->crlf_seen >= 2) {
117 + /* We have all the HTTP headers now. We don't need to
118 + * reserve any space anymore. <ssl_ptr> points to the
119 + * first byte of unread data, and <last> points to the
120 + * exact location where we want to insert our headers,
121 + * which is right before the empty line.
122 + */
123 + c->buffsize = BUFFSIZE;
124 +
125 + if (c->opt->option.xforwardedfor) {
126 + /* X-Forwarded-For: xxxx \r\n\0 */
127 + char xforw[17 + IPLEN + 3];
128 +
129 + /* We will insert our X-Forwarded-For: header here.
130 + * We need to write the IP address, but if we use
131 + * sprintf, it will pad with the terminating 0.
132 + * So we will pass via a temporary buffer allocated
133 + * on the stack.
134 + */
135 + memcpy(xforw, "X-Forwarded-For: ", 17);
136 + if (getnameinfo(&c->peer_addr.sa,
137 + c->peer_addr_len,
138 + xforw + 17, IPLEN, NULL, 0,
139 + NI_NUMERICHOST) == 0) {
140 + strcat(xforw + 17, "\r\n");
141 + buffer_insert(c->ssl_buff, &last, &c->ssl_ptr,
142 + c->buffsize, xforw);
143 + }
144 + /* last still points to the \r\n and ssl_ptr to the
145 + * end of the buffer, so we may add as many headers
146 + * as wee need to.
147 + */
148 + }
149 + }
150 + }
151 + else
152 + c->ssl_ptr+=num;
153 +
154 watchdog=0; /* reset watchdog */
155 break;
156 case SSL_ERROR_WANT_WRITE:
157 --- src/common.h
158 +++ src/common.h
159 @@ -52,6 +52,12 @@
160 /* I/O buffer size - 18432 is the maximum size of SSL record payload */
161 #define BUFFSIZE 18432
162
163 +/* maximum space reserved for header insertion in BUFFSIZE */
164 +#define BUFF_RESERVED 1024
165 +
166 +/* IP address and TCP port textual representation length */
167 +#define IPLEN 128
168 +
169 /* how many bytes of random input to read from files for PRNG */
170 /* OpenSSL likes at least 128 bits, so 64 bytes seems plenty. */
171 #define RANDOM_BYTES 64
172 --- src/options.c
173 +++ src/options.c
174 @@ -853,6 +853,29 @@
175 }
176 #endif
177
178 + /* xforwardedfor */
179 + switch(cmd) {
180 + case CMD_BEGIN:
181 + section->option.xforwardedfor=0;
182 + break;
183 + case CMD_EXEC:
184 + if(strcasecmp(opt, "xforwardedfor"))
185 + break;
186 + if(!strcasecmp(arg, "yes"))
187 + section->option.xforwardedfor=1;
188 + else if(!strcasecmp(arg, "no"))
189 + section->option.xforwardedfor=0;
190 + else
191 + return "argument should be either 'yes' or 'no'";
192 + return NULL; /* OK */
193 + case CMD_DEFAULT:
194 + break;
195 + case CMD_HELP:
196 + s_log(LOG_NOTICE, "%-15s = yes|no append an HTTP X-Forwarded-For header",
197 + "xforwardedfor");
198 + break;
199 + }
200 +
201 /* exec */
202 switch(cmd) {
203 case CMD_BEGIN:
204 --- src/prototypes.h
205 +++ src/prototypes.h
206 @@ -199,6 +199,7 @@
207 unsigned int accept:1; /* endpoint: accept */
208 unsigned int client:1;
209 unsigned int delayed_lookup:1;
210 + unsigned int xforwardedfor:1;
211 #ifdef USE_LIBWRAP
212 unsigned int libwrap:1;
213 #endif
214 @@ -428,6 +429,8 @@
215 FD *ssl_rfd, *ssl_wfd; /* read and write SSL descriptors */
216 int sock_bytes, ssl_bytes; /* bytes written to socket and SSL */
217 s_poll_set *fds; /* file descriptors */
218 + int buffsize; /* current buffer size, may be lower than BUFFSIZE */
219 + int crlf_seen; /* the number of successive CRLF seen */
220 } CLI;
221
222 CLI *alloc_client_session(SERVICE_OPTIONS *, int, int);

  ViewVC Help
Powered by ViewVC 1.1.20