]>
Commit | Line | Data |
---|---|---|
95d659f0 | 1 | |
983061ed | 2 | /* |
4326a9b6 | 3 | * $Id: tunnel.cc,v 1.125 2002/10/14 07:35:46 hno Exp $ |
983061ed | 4 | * |
30a4f2a8 | 5 | * DEBUG: section 26 Secure Sockets Layer Proxy |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 9 | * ---------------------------------------------------------- |
30a4f2a8 | 10 | * |
2b6662ba | 11 | * Squid is the result of efforts by numerous individuals from |
12 | * the Internet community; see the CONTRIBUTORS file for full | |
13 | * details. Many organizations have provided support for Squid's | |
14 | * development; see the SPONSORS file for full details. Squid is | |
15 | * Copyrighted (C) 2001 by the Regents of the University of | |
16 | * California; see the COPYRIGHT file for full details. Squid | |
17 | * incorporates software developed and/or copyrighted by other | |
18 | * sources; see the CREDITS file for full details. | |
30a4f2a8 | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
983061ed | 34 | */ |
983061ed | 35 | |
30a4f2a8 | 36 | #include "squid.h" |
983061ed | 37 | |
38 | typedef struct { | |
39 | char *url; | |
98ffb7e4 | 40 | char *host; /* either request->host or proxy host */ |
41 | u_short port; | |
983061ed | 42 | request_t *request; |
64d8034e | 43 | FwdServer *servers; |
983061ed | 44 | struct { |
45 | int fd; | |
46 | int len; | |
983061ed | 47 | char *buf; |
48 | } client, server; | |
88738790 | 49 | size_t *size_ptr; /* pointer to size in an ConnStateData for logging */ |
974ba0ee | 50 | int *status_ptr; /* pointer to status for logging */ |
59715b38 | 51 | #if DELAY_POOLS |
4326a9b6 | 52 | delay_id delayId; |
59715b38 | 53 | #endif |
983061ed | 54 | } SslStateData; |
55 | ||
0ee4272b | 56 | static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n"; |
983061ed | 57 | |
54cff85f | 58 | static CNCB sslConnectDone; |
59 | static ERCB sslErrorComplete; | |
adb78bd4 | 60 | static PF sslServerClosed; |
54cff85f | 61 | static PF sslClientClosed; |
62 | static PF sslReadClient; | |
63 | static PF sslReadServer; | |
5c5783a2 | 64 | static PF sslTimeout; |
54cff85f | 65 | static PF sslWriteClient; |
66 | static PF sslWriteServer; | |
67 | static PSC sslPeerSelectComplete; | |
adb78bd4 | 68 | static void sslStateFree(SslStateData * sslState); |
f5b8bbc4 | 69 | static void sslConnected(int fd, void *); |
70 | static void sslProxyConnected(int fd, void *); | |
adb78bd4 | 71 | static void sslSetSelect(SslStateData * sslState); |
447e176b | 72 | #if DELAY_POOLS |
73 | static DEFER sslDeferServerRead; | |
74 | #endif | |
30a4f2a8 | 75 | |
b8d8561b | 76 | static void |
adb78bd4 | 77 | sslServerClosed(int fd, void *data) |
30a4f2a8 | 78 | { |
e6ccf245 | 79 | SslStateData *sslState = (SslStateData *)data; |
adb78bd4 | 80 | debug(26, 3) ("sslServerClosed: FD %d\n", fd); |
81 | assert(fd == sslState->server.fd); | |
82 | sslState->server.fd = -1; | |
83 | if (sslState->client.fd == -1) | |
84 | sslStateFree(sslState); | |
30a4f2a8 | 85 | } |
86 | ||
b177367b | 87 | static void |
88 | sslClientClosed(int fd, void *data) | |
30a4f2a8 | 89 | { |
e6ccf245 | 90 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 91 | debug(26, 3) ("sslClientClosed: FD %d\n", fd); |
adb78bd4 | 92 | assert(fd == sslState->client.fd); |
93 | sslState->client.fd = -1; | |
94 | if (sslState->server.fd == -1) | |
95 | sslStateFree(sslState); | |
30a4f2a8 | 96 | } |
983061ed | 97 | |
b177367b | 98 | static void |
adb78bd4 | 99 | sslStateFree(SslStateData * sslState) |
983061ed | 100 | { |
adb78bd4 | 101 | debug(26, 3) ("sslStateFree: sslState=%p\n", sslState); |
102 | assert(sslState != NULL); | |
103 | assert(sslState->client.fd == -1); | |
104 | assert(sslState->server.fd == -1); | |
983061ed | 105 | safe_free(sslState->server.buf); |
106 | safe_free(sslState->client.buf); | |
adb78bd4 | 107 | safe_free(sslState->url); |
64d8034e | 108 | fwdServersFree(&sslState->servers); |
adb78bd4 | 109 | sslState->host = NULL; |
30a4f2a8 | 110 | requestUnlink(sslState->request); |
7dd44885 | 111 | sslState->request = NULL; |
b6a2f15e | 112 | #if DELAY_POOLS |
4326a9b6 | 113 | delayUnregisterDelayIdPtr(&sslState->delayId); |
b6a2f15e | 114 | #endif |
7dd44885 | 115 | cbdataFree(sslState); |
983061ed | 116 | } |
117 | ||
447e176b | 118 | #if DELAY_POOLS |
119 | static int | |
120 | sslDeferServerRead(int fdnotused, void *data) | |
121 | { | |
e6ccf245 | 122 | SslStateData *s = (SslStateData *)data; |
4326a9b6 | 123 | int i = delayBytesWanted(s->delayId, 0, INT_MAX); |
7e3ce7b9 | 124 | if (i == INT_MAX) |
125 | return 0; | |
126 | if (i == 0) | |
127 | return 1; | |
128 | return -1; | |
447e176b | 129 | } |
130 | #endif | |
131 | ||
adb78bd4 | 132 | static void |
133 | sslSetSelect(SslStateData * sslState) | |
134 | { | |
447e176b | 135 | size_t read_sz = SQUID_TCP_SO_RCVBUF; |
adb78bd4 | 136 | assert(sslState->server.fd > -1 || sslState->client.fd > -1); |
137 | if (sslState->client.fd > -1) { | |
138 | if (sslState->server.len > 0) { | |
139 | commSetSelect(sslState->client.fd, | |
140 | COMM_SELECT_WRITE, | |
141 | sslWriteClient, | |
142 | sslState, | |
143 | 0); | |
144 | } | |
e6ccf245 | 145 | if ((size_t)sslState->client.len < read_sz) { |
adb78bd4 | 146 | commSetSelect(sslState->client.fd, |
147 | COMM_SELECT_READ, | |
148 | sslReadClient, | |
149 | sslState, | |
150 | Config.Timeout.read); | |
151 | } | |
152 | } else if (sslState->client.len == 0) { | |
153 | comm_close(sslState->server.fd); | |
154 | } | |
155 | if (sslState->server.fd > -1) { | |
156 | if (sslState->client.len > 0) { | |
157 | commSetSelect(sslState->server.fd, | |
158 | COMM_SELECT_WRITE, | |
159 | sslWriteServer, | |
160 | sslState, | |
161 | 0); | |
162 | } | |
447e176b | 163 | #if DELAY_POOLS |
7e3ce7b9 | 164 | /* |
165 | * If this was allowed to return 0, there would be a possibility | |
e82d6d21 | 166 | * of the socket becoming "hung" with data accumulating but no |
167 | * write handler (server.len==0) and no read handler (!(0<0)) and | |
168 | * no data flowing in the other direction. Hence the argument of | |
169 | * 1 as min. | |
170 | */ | |
4326a9b6 | 171 | read_sz = delayBytesWanted(sslState->delayId, 1, read_sz); |
447e176b | 172 | #endif |
e6ccf245 | 173 | if ((size_t)sslState->server.len < read_sz) { |
adb78bd4 | 174 | /* Have room to read more */ |
175 | commSetSelect(sslState->server.fd, | |
176 | COMM_SELECT_READ, | |
177 | sslReadServer, | |
178 | sslState, | |
179 | Config.Timeout.read); | |
180 | } | |
181 | } else if (sslState->client.fd == -1) { | |
182 | /* client already closed, nothing more to do */ | |
183 | } else if (sslState->server.len == 0) { | |
184 | comm_close(sslState->client.fd); | |
185 | } | |
186 | } | |
187 | ||
983061ed | 188 | /* Read from server side and queue it for writing to the client */ |
b8d8561b | 189 | static void |
b177367b | 190 | sslReadServer(int fd, void *data) |
983061ed | 191 | { |
e6ccf245 | 192 | SslStateData *sslState = (SslStateData *)data; |
983061ed | 193 | int len; |
447e176b | 194 | size_t read_sz = SQUID_TCP_SO_RCVBUF - sslState->server.len; |
adb78bd4 | 195 | assert(fd == sslState->server.fd); |
196 | debug(26, 3) ("sslReadServer: FD %d, reading %d bytes at offset %d\n", | |
ed19251a | 197 | fd, (int) read_sz, sslState->server.len); |
447e176b | 198 | errno = 0; |
199 | #if DELAY_POOLS | |
4326a9b6 | 200 | read_sz = delayBytesWanted(sslState->delayId, 1, read_sz); |
447e176b | 201 | #endif |
83704487 | 202 | statCounter.syscalls.sock.reads++; |
1f7c9178 | 203 | len = FD_READ_METHOD(fd, sslState->server.buf + sslState->server.len, read_sz); |
adb78bd4 | 204 | debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", fd, len); |
ee1679df | 205 | if (len > 0) { |
adb78bd4 | 206 | fd_bytes(fd, len, FD_READ); |
447e176b | 207 | #if DELAY_POOLS |
4326a9b6 | 208 | delayBytesIn(sslState->delayId, len); |
447e176b | 209 | #endif |
83704487 | 210 | kb_incr(&statCounter.server.all.kbytes_in, len); |
211 | kb_incr(&statCounter.server.other.kbytes_in, len); | |
adb78bd4 | 212 | sslState->server.len += len; |
ee1679df | 213 | } |
fa80a8ef | 214 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
983061ed | 215 | if (len < 0) { |
9bc73deb | 216 | debug(50, ignoreErrno(errno) ? 3 : 1) |
217 | ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror()); | |
adb78bd4 | 218 | if (!ignoreErrno(errno)) |
219 | comm_close(fd); | |
983061ed | 220 | } else if (len == 0) { |
adb78bd4 | 221 | comm_close(sslState->server.fd); |
983061ed | 222 | } |
fa80a8ef | 223 | if (cbdataReferenceValid(sslState)) |
adb78bd4 | 224 | sslSetSelect(sslState); |
fa80a8ef | 225 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 226 | } |
227 | ||
228 | /* Read from client side and queue it for writing to the server */ | |
b8d8561b | 229 | static void |
b177367b | 230 | sslReadClient(int fd, void *data) |
983061ed | 231 | { |
e6ccf245 | 232 | SslStateData *sslState = (SslStateData *)data; |
983061ed | 233 | int len; |
adb78bd4 | 234 | assert(fd == sslState->client.fd); |
235 | debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %d\n", | |
236 | fd, SQUID_TCP_SO_RCVBUF - sslState->client.len, | |
237 | sslState->client.len); | |
83704487 | 238 | statCounter.syscalls.sock.reads++; |
1f7c9178 | 239 | len = FD_READ_METHOD(fd, |
adb78bd4 | 240 | sslState->client.buf + sslState->client.len, |
241 | SQUID_TCP_SO_RCVBUF - sslState->client.len); | |
242 | debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", fd, len); | |
ee1679df | 243 | if (len > 0) { |
adb78bd4 | 244 | fd_bytes(fd, len, FD_READ); |
83704487 | 245 | kb_incr(&statCounter.client_http.kbytes_in, len); |
adb78bd4 | 246 | sslState->client.len += len; |
ee1679df | 247 | } |
fa80a8ef | 248 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
983061ed | 249 | if (len < 0) { |
7e0453ea | 250 | int level = 1; |
251 | #ifdef ECONNRESET | |
252 | if (errno == ECONNRESET) | |
253 | level = 2; | |
254 | #endif | |
255 | if (ignoreErrno(errno)) | |
256 | level = 3; | |
257 | debug(50, level) ("sslReadClient: FD %d: read failure: %s\n", | |
983061ed | 258 | fd, xstrerror()); |
adb78bd4 | 259 | if (!ignoreErrno(errno)) |
260 | comm_close(fd); | |
983061ed | 261 | } else if (len == 0) { |
adb78bd4 | 262 | comm_close(fd); |
983061ed | 263 | } |
fa80a8ef | 264 | if (cbdataReferenceValid(sslState)) |
adb78bd4 | 265 | sslSetSelect(sslState); |
fa80a8ef | 266 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 267 | } |
268 | ||
269 | /* Writes data from the client buffer to the server side */ | |
b8d8561b | 270 | static void |
b177367b | 271 | sslWriteServer(int fd, void *data) |
983061ed | 272 | { |
e6ccf245 | 273 | SslStateData *sslState = (SslStateData *)data; |
983061ed | 274 | int len; |
adb78bd4 | 275 | assert(fd == sslState->server.fd); |
276 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes to write\n", | |
277 | fd, sslState->client.len); | |
83704487 | 278 | statCounter.syscalls.sock.writes++; |
1f7c9178 | 279 | len = FD_WRITE_METHOD(fd, |
adb78bd4 | 280 | sslState->client.buf, |
281 | sslState->client.len); | |
282 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", fd, len); | |
ee1679df | 283 | if (len > 0) { |
adb78bd4 | 284 | fd_bytes(fd, len, FD_WRITE); |
83704487 | 285 | kb_incr(&statCounter.server.all.kbytes_out, len); |
286 | kb_incr(&statCounter.server.other.kbytes_out, len); | |
adb78bd4 | 287 | assert(len <= sslState->client.len); |
288 | sslState->client.len -= len; | |
289 | if (sslState->client.len > 0) { | |
290 | /* we didn't write the whole thing */ | |
291 | xmemmove(sslState->client.buf, | |
292 | sslState->client.buf + len, | |
293 | sslState->client.len); | |
0a0bf5db | 294 | } |
983061ed | 295 | } |
fa80a8ef | 296 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
adb78bd4 | 297 | if (len < 0) { |
9bc73deb | 298 | debug(50, ignoreErrno(errno) ? 3 : 1) |
299 | ("sslWriteServer: FD %d: write failure: %s.\n", fd, xstrerror()); | |
adb78bd4 | 300 | if (!ignoreErrno(errno)) |
301 | comm_close(fd); | |
983061ed | 302 | } |
fa80a8ef | 303 | if (cbdataReferenceValid(sslState)) |
adb78bd4 | 304 | sslSetSelect(sslState); |
fa80a8ef | 305 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 306 | } |
307 | ||
308 | /* Writes data from the server buffer to the client side */ | |
b8d8561b | 309 | static void |
b177367b | 310 | sslWriteClient(int fd, void *data) |
983061ed | 311 | { |
e6ccf245 | 312 | SslStateData *sslState = (SslStateData *)data; |
983061ed | 313 | int len; |
adb78bd4 | 314 | assert(fd == sslState->client.fd); |
315 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes to write\n", | |
316 | fd, sslState->server.len); | |
83704487 | 317 | statCounter.syscalls.sock.writes++; |
1f7c9178 | 318 | len = FD_WRITE_METHOD(fd, |
adb78bd4 | 319 | sslState->server.buf, |
320 | sslState->server.len); | |
321 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, len); | |
ee1679df | 322 | if (len > 0) { |
adb78bd4 | 323 | fd_bytes(fd, len, FD_WRITE); |
83704487 | 324 | kb_incr(&statCounter.client_http.kbytes_out, len); |
adb78bd4 | 325 | assert(len <= sslState->server.len); |
326 | sslState->server.len -= len; | |
327 | /* increment total object size */ | |
328 | if (sslState->size_ptr) | |
329 | *sslState->size_ptr += len; | |
330 | if (sslState->server.len > 0) { | |
331 | /* we didn't write the whole thing */ | |
332 | xmemmove(sslState->server.buf, | |
333 | sslState->server.buf + len, | |
334 | sslState->server.len); | |
0a0bf5db | 335 | } |
983061ed | 336 | } |
fa80a8ef | 337 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
adb78bd4 | 338 | if (len < 0) { |
9bc73deb | 339 | debug(50, ignoreErrno(errno) ? 3 : 1) |
340 | ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror()); | |
adb78bd4 | 341 | if (!ignoreErrno(errno)) |
342 | comm_close(fd); | |
983061ed | 343 | } |
fa80a8ef | 344 | if (cbdataReferenceValid(sslState)) |
adb78bd4 | 345 | sslSetSelect(sslState); |
fa80a8ef | 346 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 347 | } |
348 | ||
b8d8561b | 349 | static void |
5c5783a2 | 350 | sslTimeout(int fd, void *data) |
983061ed | 351 | { |
e6ccf245 | 352 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 353 | debug(26, 3) ("sslTimeout: FD %d\n", fd); |
adb78bd4 | 354 | if (sslState->client.fd > -1) |
355 | comm_close(sslState->client.fd); | |
356 | if (sslState->server.fd > -1) | |
357 | comm_close(sslState->server.fd); | |
983061ed | 358 | } |
359 | ||
b8d8561b | 360 | static void |
b177367b | 361 | sslConnected(int fd, void *data) |
983061ed | 362 | { |
e6ccf245 | 363 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 364 | debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState); |
974ba0ee | 365 | *sslState->status_ptr = HTTP_OK; |
54cff85f | 366 | xstrncpy(sslState->server.buf, conn_established, SQUID_TCP_SO_RCVBUF); |
983061ed | 367 | sslState->server.len = strlen(conn_established); |
adb78bd4 | 368 | sslSetSelect(sslState); |
983061ed | 369 | } |
370 | ||
b8d8561b | 371 | static void |
adb78bd4 | 372 | sslErrorComplete(int fdnotused, void *data, size_t sizenotused) |
30a4f2a8 | 373 | { |
e6ccf245 | 374 | SslStateData *sslState = (SslStateData *)data; |
9b312a19 | 375 | assert(sslState != NULL); |
adb78bd4 | 376 | if (sslState->client.fd > -1) |
377 | comm_close(sslState->client.fd); | |
378 | if (sslState->server.fd > -1) | |
379 | comm_close(sslState->server.fd); | |
30a4f2a8 | 380 | } |
381 | ||
983061ed | 382 | |
b8d8561b | 383 | static void |
3d7e9d7c | 384 | sslConnectDone(int fdnotused, comm_err_t status, void *data) |
983061ed | 385 | { |
e6ccf245 | 386 | SslStateData *sslState = (SslStateData *)data; |
30a4f2a8 | 387 | request_t *request = sslState->request; |
9b312a19 | 388 | ErrorState *err = NULL; |
29b8d8d6 | 389 | if (sslState->servers->_peer) |
890b0fa8 | 390 | hierarchyNote(&sslState->request->hier, sslState->servers->code, |
29b8d8d6 | 391 | sslState->servers->_peer->host); |
890b0fa8 | 392 | else if (Config.onoff.log_ip_on_direct) |
393 | hierarchyNote(&sslState->request->hier, sslState->servers->code, | |
a4b8110e | 394 | fd_table[sslState->server.fd].ipaddr); |
890b0fa8 | 395 | else |
396 | hierarchyNote(&sslState->request->hier, sslState->servers->code, | |
a4b8110e | 397 | sslState->host); |
edeb28fd | 398 | if (status == COMM_ERR_DNS) { |
a3d5953d | 399 | debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); |
fe40a877 | 400 | err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); |
974ba0ee | 401 | *sslState->status_ptr = HTTP_NOT_FOUND; |
9b312a19 | 402 | err->request = requestLink(request); |
403 | err->dnsserver_msg = xstrdup(dns_error_message); | |
404 | err->callback = sslErrorComplete; | |
405 | err->callback_data = sslState; | |
406 | errorSend(sslState->client.fd, err); | |
edeb28fd | 407 | } else if (status != COMM_OK) { |
fe40a877 | 408 | err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); |
974ba0ee | 409 | *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; |
c45ed9ad | 410 | err->xerrno = errno; |
9b312a19 | 411 | err->host = xstrdup(sslState->host); |
412 | err->port = sslState->port; | |
413 | err->request = requestLink(request); | |
414 | err->callback = sslErrorComplete; | |
415 | err->callback_data = sslState; | |
416 | errorSend(sslState->client.fd, err); | |
fe40a877 | 417 | } else { |
29b8d8d6 | 418 | if (sslState->servers->_peer) |
fe40a877 | 419 | sslProxyConnected(sslState->server.fd, sslState); |
4e3f29eb | 420 | else |
fe40a877 | 421 | sslConnected(sslState->server.fd, sslState); |
1afe05c5 | 422 | commSetTimeout(sslState->server.fd, |
423 | Config.Timeout.read, | |
424 | sslTimeout, | |
425 | sslState); | |
447e176b | 426 | #if DELAY_POOLS |
59715b38 | 427 | commSetDefer(sslState->server.fd, sslDeferServerRead, sslState); |
447e176b | 428 | #endif |
983061ed | 429 | } |
983061ed | 430 | } |
30a4f2a8 | 431 | |
28c60158 | 432 | CBDATA_TYPE(SslStateData); |
770f051d | 433 | void |
d5964d58 | 434 | sslStart(clientHttpRequest * http, size_t * size_ptr, int *status_ptr) |
30a4f2a8 | 435 | { |
436 | /* Create state structure. */ | |
437 | SslStateData *sslState = NULL; | |
438 | int sock; | |
9b312a19 | 439 | ErrorState *err = NULL; |
f1003989 | 440 | aclCheck_t ch; |
441 | int answer; | |
d5964d58 | 442 | int fd = http->conn->fd; |
443 | request_t *request = http->request; | |
444 | char *url = http->uri; | |
f1003989 | 445 | /* |
a4b8110e | 446 | * client_addr == no_addr indicates this is an "internal" request |
447 | * from peer_digest.c, asn.c, netdb.c, etc and should always | |
448 | * be allowed. yuck, I know. | |
449 | */ | |
f1003989 | 450 | if (request->client_addr.s_addr != no_addr.s_addr) { |
451 | /* | |
a4b8110e | 452 | * Check if this host is allowed to fetch MISSES from us (miss_access) |
453 | */ | |
f1003989 | 454 | memset(&ch, '\0', sizeof(aclCheck_t)); |
455 | ch.src_addr = request->client_addr; | |
456 | ch.my_addr = request->my_addr; | |
457 | ch.my_port = request->my_port; | |
458 | ch.request = request; | |
459 | answer = aclCheckFast(Config.accessList.miss, &ch); | |
460 | if (answer == 0) { | |
461 | err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); | |
3b3ce25a | 462 | *status_ptr = HTTP_FORBIDDEN; |
f1003989 | 463 | err->request = requestLink(request); |
464 | err->src_addr = request->client_addr; | |
465 | errorSend(fd, err); | |
466 | return; | |
467 | } | |
468 | } | |
a3d5953d | 469 | debug(26, 3) ("sslStart: '%s %s'\n", |
30a4f2a8 | 470 | RequestMethodStr[request->method], url); |
83704487 | 471 | statCounter.server.all.requests++; |
472 | statCounter.server.other.requests++; | |
30a4f2a8 | 473 | /* Create socket. */ |
d6827718 | 474 | sock = comm_openex(SOCK_STREAM, |
16b204c4 | 475 | 0, |
d6827718 | 476 | getOutgoingAddr(request), |
16b204c4 | 477 | 0, |
478 | COMM_NONBLOCKING, | |
d6827718 | 479 | getOutgoingTOS(request), |
16b204c4 | 480 | url); |
30a4f2a8 | 481 | if (sock == COMM_ERROR) { |
a3d5953d | 482 | debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); |
fe40a877 | 483 | err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); |
3b3ce25a | 484 | *status_ptr = HTTP_INTERNAL_SERVER_ERROR; |
c45ed9ad | 485 | err->xerrno = errno; |
9b312a19 | 486 | err->request = requestLink(request); |
487 | errorSend(fd, err); | |
770f051d | 488 | return; |
30a4f2a8 | 489 | } |
28c60158 | 490 | CBDATA_INIT_TYPE(SslStateData); |
72711e31 | 491 | sslState = cbdataAlloc(SslStateData); |
59715b38 | 492 | #if DELAY_POOLS |
4326a9b6 | 493 | sslState->delayId = delayClient(http); |
494 | delayRegisterDelayIdPtr(&sslState->delayId); | |
59715b38 | 495 | #endif |
30a4f2a8 | 496 | sslState->url = xstrdup(url); |
497 | sslState->request = requestLink(request); | |
30a4f2a8 | 498 | sslState->size_ptr = size_ptr; |
974ba0ee | 499 | sslState->status_ptr = status_ptr; |
30a4f2a8 | 500 | sslState->client.fd = fd; |
501 | sslState->server.fd = sock; | |
e6ccf245 | 502 | sslState->server.buf = (char *)xmalloc(SQUID_TCP_SO_RCVBUF); |
503 | sslState->client.buf = (char *)xmalloc(SQUID_TCP_SO_RCVBUF); | |
30a4f2a8 | 504 | comm_add_close_handler(sslState->server.fd, |
adb78bd4 | 505 | sslServerClosed, |
cd1fb0eb | 506 | sslState); |
30a4f2a8 | 507 | comm_add_close_handler(sslState->client.fd, |
b177367b | 508 | sslClientClosed, |
cd1fb0eb | 509 | sslState); |
5c5783a2 | 510 | commSetTimeout(sslState->client.fd, |
4f92c80c | 511 | Config.Timeout.lifetime, |
512 | sslTimeout, | |
513 | sslState); | |
cf1edeae | 514 | commSetTimeout(sslState->server.fd, |
515 | Config.Timeout.connect, | |
516 | sslTimeout, | |
517 | sslState); | |
b6c0e933 | 518 | peerSelect(request, |
641941c0 | 519 | NULL, |
b6c0e933 | 520 | sslPeerSelectComplete, |
b6c0e933 | 521 | sslState); |
adb78bd4 | 522 | /* |
523 | * Disable the client read handler until peer selection is complete | |
524 | * Take control away from client_side.c. | |
525 | */ | |
526 | commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); | |
30a4f2a8 | 527 | } |
98ffb7e4 | 528 | |
b8d8561b | 529 | static void |
b177367b | 530 | sslProxyConnected(int fd, void *data) |
98ffb7e4 | 531 | { |
e6ccf245 | 532 | SslStateData *sslState = (SslStateData *)data; |
e1e72f06 | 533 | MemBuf mb; |
534 | HttpHeader hdr_out; | |
535 | Packer p; | |
b4b5fd95 | 536 | http_state_flags flags; |
a3d5953d | 537 | debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState); |
b4b5fd95 | 538 | memset(&flags, '\0', sizeof(flags)); |
2f2b4d20 | 539 | flags.proxying = sslState->request->flags.proxying; |
e1e72f06 | 540 | memBufDefInit(&mb); |
541 | memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url); | |
542 | httpBuildRequestHeader(sslState->request, | |
543 | sslState->request, | |
5999b776 | 544 | NULL, /* StoreEntry */ |
e1e72f06 | 545 | &hdr_out, |
b4b5fd95 | 546 | flags); /* flags */ |
e1e72f06 | 547 | packerToMemInit(&p, &mb); |
548 | httpHeaderPackInto(&hdr_out, &p); | |
549 | httpHeaderClean(&hdr_out); | |
550 | packerClean(&p); | |
551 | memBufAppend(&mb, "\r\n", 2); | |
552 | xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF); | |
553 | debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf); | |
554 | sslState->client.len = mb.size; | |
e1e72f06 | 555 | memBufClean(&mb); |
86cf9987 | 556 | commSetTimeout(sslState->server.fd, |
557 | Config.Timeout.read, | |
558 | sslTimeout, | |
559 | sslState); | |
adb78bd4 | 560 | sslSetSelect(sslState); |
98ffb7e4 | 561 | } |
33ea9fff | 562 | |
33ea9fff | 563 | static void |
db1cd23c | 564 | sslPeerSelectComplete(FwdServer * fs, void *data) |
33ea9fff | 565 | { |
e6ccf245 | 566 | SslStateData *sslState = (SslStateData *)data; |
33ea9fff | 567 | request_t *request = sslState->request; |
deb79f06 | 568 | peer *g = NULL; |
db1cd23c | 569 | if (fs == NULL) { |
570 | ErrorState *err; | |
571 | err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); | |
974ba0ee | 572 | *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; |
db1cd23c | 573 | err->request = requestLink(sslState->request); |
574 | err->callback = sslErrorComplete; | |
575 | err->callback_data = sslState; | |
576 | errorSend(sslState->client.fd, err); | |
577 | return; | |
578 | } | |
64d8034e | 579 | sslState->servers = fs; |
29b8d8d6 | 580 | sslState->host = fs->_peer ? fs->_peer->host : request->host; |
581 | if (fs->_peer == NULL) { | |
b3b64e58 | 582 | sslState->port = request->port; |
29b8d8d6 | 583 | } else if (fs->_peer->http_port != 0) { |
584 | sslState->port = fs->_peer->http_port; | |
585 | } else if ((g = peerFindByName(fs->_peer->host))) { | |
b3b64e58 | 586 | sslState->port = g->http_port; |
33ea9fff | 587 | } else { |
b3b64e58 | 588 | sslState->port = CACHE_HTTP_PORT; |
33ea9fff | 589 | } |
29b8d8d6 | 590 | if (fs->_peer) { |
591 | sslState->request->peer_login = fs->_peer->login; | |
1f38f50a | 592 | sslState->request->flags.proxying = 1; |
593 | } else { | |
94439e4e | 594 | sslState->request->peer_login = NULL; |
1f38f50a | 595 | sslState->request->flags.proxying = 0; |
596 | } | |
59715b38 | 597 | #if DELAY_POOLS |
598 | /* no point using the delayIsNoDelay stuff since ssl is nice and simple */ | |
4326a9b6 | 599 | if (g && g->options.no_delay && sslState->delayId) { |
600 | delayUnregisterDelayIdPtr(&sslState->delayId); | |
601 | sslState->delayId = 0; | |
1ecaa0a0 | 602 | } |
59715b38 | 603 | #endif |
edeb28fd | 604 | commConnectStart(sslState->server.fd, |
605 | sslState->host, | |
606 | sslState->port, | |
607 | sslConnectDone, | |
33ea9fff | 608 | sslState); |
609 | } |