]>
Commit | Line | Data |
---|---|---|
95d659f0 | 1 | |
983061ed | 2 | /* |
b67e2c8c | 3 | * $Id: ssl.cc,v 1.134 2003/02/05 10:36:54 robertc 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" |
528b2c61 | 37 | #include "HttpRequest.h" |
38 | #include "fde.h" | |
9f518b4a | 39 | #include "comm.h" |
528b2c61 | 40 | #include "client_side_request.h" |
4fb35c3c | 41 | #include "ACLChecklist.h" |
b67e2c8c | 42 | #if DELAY_POOLS |
43 | #include "DelayId.h" | |
44 | #endif | |
983061ed | 45 | |
46 | typedef struct { | |
47 | char *url; | |
98ffb7e4 | 48 | char *host; /* either request->host or proxy host */ |
49 | u_short port; | |
983061ed | 50 | request_t *request; |
64d8034e | 51 | FwdServer *servers; |
983061ed | 52 | struct { |
53 | int fd; | |
54 | int len; | |
983061ed | 55 | char *buf; |
56 | } client, server; | |
88738790 | 57 | size_t *size_ptr; /* pointer to size in an ConnStateData for logging */ |
974ba0ee | 58 | int *status_ptr; /* pointer to status for logging */ |
59715b38 | 59 | #if DELAY_POOLS |
b67e2c8c | 60 | DelayId delayId; |
59715b38 | 61 | #endif |
983061ed | 62 | } SslStateData; |
63 | ||
0ee4272b | 64 | static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n"; |
983061ed | 65 | |
54cff85f | 66 | static CNCB sslConnectDone; |
67 | static ERCB sslErrorComplete; | |
adb78bd4 | 68 | static PF sslServerClosed; |
54cff85f | 69 | static PF sslClientClosed; |
c4b7a5a9 | 70 | static IOCB sslReadClient; |
71 | static IOCB sslReadServer; | |
5c5783a2 | 72 | static PF sslTimeout; |
9f518b4a | 73 | static IOWCB sslWriteClientDone; |
74 | static IOWCB sslWriteServerDone; | |
54cff85f | 75 | static PSC sslPeerSelectComplete; |
adb78bd4 | 76 | static void sslStateFree(SslStateData * sslState); |
f5b8bbc4 | 77 | static void sslConnected(int fd, void *); |
78 | static void sslProxyConnected(int fd, void *); | |
447e176b | 79 | #if DELAY_POOLS |
80 | static DEFER sslDeferServerRead; | |
81 | #endif | |
30a4f2a8 | 82 | |
b8d8561b | 83 | static void |
adb78bd4 | 84 | sslServerClosed(int fd, void *data) |
30a4f2a8 | 85 | { |
e6ccf245 | 86 | SslStateData *sslState = (SslStateData *)data; |
adb78bd4 | 87 | debug(26, 3) ("sslServerClosed: FD %d\n", fd); |
88 | assert(fd == sslState->server.fd); | |
89 | sslState->server.fd = -1; | |
90 | if (sslState->client.fd == -1) | |
91 | sslStateFree(sslState); | |
30a4f2a8 | 92 | } |
93 | ||
b177367b | 94 | static void |
95 | sslClientClosed(int fd, void *data) | |
30a4f2a8 | 96 | { |
e6ccf245 | 97 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 98 | debug(26, 3) ("sslClientClosed: FD %d\n", fd); |
adb78bd4 | 99 | assert(fd == sslState->client.fd); |
100 | sslState->client.fd = -1; | |
101 | if (sslState->server.fd == -1) | |
102 | sslStateFree(sslState); | |
30a4f2a8 | 103 | } |
983061ed | 104 | |
b177367b | 105 | static void |
adb78bd4 | 106 | sslStateFree(SslStateData * sslState) |
983061ed | 107 | { |
adb78bd4 | 108 | debug(26, 3) ("sslStateFree: sslState=%p\n", sslState); |
109 | assert(sslState != NULL); | |
110 | assert(sslState->client.fd == -1); | |
111 | assert(sslState->server.fd == -1); | |
983061ed | 112 | safe_free(sslState->server.buf); |
113 | safe_free(sslState->client.buf); | |
adb78bd4 | 114 | safe_free(sslState->url); |
64d8034e | 115 | fwdServersFree(&sslState->servers); |
adb78bd4 | 116 | sslState->host = NULL; |
30a4f2a8 | 117 | requestUnlink(sslState->request); |
7dd44885 | 118 | sslState->request = NULL; |
119 | cbdataFree(sslState); | |
983061ed | 120 | } |
121 | ||
447e176b | 122 | #if DELAY_POOLS |
123 | static int | |
124 | sslDeferServerRead(int fdnotused, void *data) | |
125 | { | |
e6ccf245 | 126 | SslStateData *s = (SslStateData *)data; |
b67e2c8c | 127 | int i = s->delayId.bytesWanted(0, INT_MAX); |
7e3ce7b9 | 128 | if (i == INT_MAX) |
129 | return 0; | |
130 | if (i == 0) | |
131 | return 1; | |
132 | return -1; | |
447e176b | 133 | } |
134 | #endif | |
135 | ||
adb78bd4 | 136 | |
983061ed | 137 | /* Read from server side and queue it for writing to the client */ |
b8d8561b | 138 | static void |
c4b7a5a9 | 139 | sslReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data) |
983061ed | 140 | { |
e6ccf245 | 141 | SslStateData *sslState = (SslStateData *)data; |
c4b7a5a9 | 142 | |
adb78bd4 | 143 | assert(fd == sslState->server.fd); |
447e176b | 144 | errno = 0; |
145 | #if DELAY_POOLS | |
b67e2c8c | 146 | len = sslState->delayId.bytesWanted(1, len); |
447e176b | 147 | #endif |
c4b7a5a9 | 148 | /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ |
149 | if (errcode == COMM_ERR_CLOSING) { | |
150 | return; | |
151 | } | |
152 | debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", fd, (int)len); | |
ee1679df | 153 | if (len > 0) { |
447e176b | 154 | #if DELAY_POOLS |
b67e2c8c | 155 | sslState->delayId.bytesIn(len); |
447e176b | 156 | #endif |
83704487 | 157 | kb_incr(&statCounter.server.all.kbytes_in, len); |
158 | kb_incr(&statCounter.server.other.kbytes_in, len); | |
adb78bd4 | 159 | sslState->server.len += len; |
ee1679df | 160 | } |
fa80a8ef | 161 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
983061ed | 162 | if (len < 0) { |
9bc73deb | 163 | debug(50, ignoreErrno(errno) ? 3 : 1) |
164 | ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror()); | |
adb78bd4 | 165 | if (!ignoreErrno(errno)) |
166 | comm_close(fd); | |
983061ed | 167 | } else if (len == 0) { |
adb78bd4 | 168 | comm_close(sslState->server.fd); |
c4b7a5a9 | 169 | /* Only close the remote end if we've finished queueing data to it */ |
170 | if (sslState->server.len == 0 && sslState->client.fd != -1) { | |
171 | comm_close(sslState->client.fd); | |
172 | } | |
173 | } else if (cbdataReferenceValid(sslState)) | |
9f518b4a | 174 | comm_write(sslState->client.fd, sslState->server.buf, len, sslWriteClientDone, sslState); |
fa80a8ef | 175 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 176 | } |
177 | ||
178 | /* Read from client side and queue it for writing to the server */ | |
b8d8561b | 179 | static void |
c4b7a5a9 | 180 | sslReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data) |
983061ed | 181 | { |
e6ccf245 | 182 | SslStateData *sslState = (SslStateData *)data; |
adb78bd4 | 183 | assert(fd == sslState->client.fd); |
c4b7a5a9 | 184 | |
185 | /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ | |
186 | if (errcode == COMM_ERR_CLOSING) { | |
187 | return; | |
188 | } | |
189 | ||
190 | debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", fd, (int) len); | |
ee1679df | 191 | if (len > 0) { |
83704487 | 192 | kb_incr(&statCounter.client_http.kbytes_in, len); |
adb78bd4 | 193 | sslState->client.len += len; |
ee1679df | 194 | } |
fa80a8ef | 195 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
983061ed | 196 | if (len < 0) { |
7e0453ea | 197 | int level = 1; |
198 | #ifdef ECONNRESET | |
c4b7a5a9 | 199 | if (xerrno == ECONNRESET) |
7e0453ea | 200 | level = 2; |
201 | #endif | |
c4b7a5a9 | 202 | if (ignoreErrno(xerrno)) |
7e0453ea | 203 | level = 3; |
c4b7a5a9 | 204 | /* XXX xstrerror() should be changed to take errno as an arg! */ |
205 | errno = xerrno; | |
7e0453ea | 206 | debug(50, level) ("sslReadClient: FD %d: read failure: %s\n", |
983061ed | 207 | fd, xstrerror()); |
c4b7a5a9 | 208 | if (!ignoreErrno(xerrno)) |
adb78bd4 | 209 | comm_close(fd); |
983061ed | 210 | } else if (len == 0) { |
c4b7a5a9 | 211 | comm_close(sslState->client.fd); |
212 | /* Only close the remote end if we've finished queueing data to it */ | |
213 | if (sslState->client.len == 0 && sslState->server.fd != -1) { | |
214 | comm_close(sslState->server.fd); | |
215 | } | |
216 | } else if (cbdataReferenceValid(sslState)) | |
9f518b4a | 217 | comm_write(sslState->server.fd, sslState->client.buf, len, sslWriteServerDone, sslState); |
fa80a8ef | 218 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 219 | } |
220 | ||
221 | /* Writes data from the client buffer to the server side */ | |
b8d8561b | 222 | static void |
9f518b4a | 223 | sslWriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) |
983061ed | 224 | { |
e6ccf245 | 225 | SslStateData *sslState = (SslStateData *)data; |
adb78bd4 | 226 | assert(fd == sslState->server.fd); |
c4b7a5a9 | 227 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", fd, (int)len); |
228 | /* Valid data */ | |
ee1679df | 229 | if (len > 0) { |
83704487 | 230 | kb_incr(&statCounter.server.all.kbytes_out, len); |
231 | kb_incr(&statCounter.server.other.kbytes_out, len); | |
c4b7a5a9 | 232 | assert(len == (size_t)sslState->client.len); |
233 | sslState->client.len = 0; | |
234 | } | |
235 | /* EOF */ | |
236 | if (len == 0) { | |
237 | comm_close(sslState->server.fd); | |
238 | return; | |
239 | } | |
240 | /* If the other end has closed, so should we */ | |
241 | if (sslState->client.fd == -1) { | |
242 | comm_close(sslState->server.fd); | |
243 | return; | |
983061ed | 244 | } |
fa80a8ef | 245 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
c4b7a5a9 | 246 | /* Error? */ |
adb78bd4 | 247 | if (len < 0) { |
9bc73deb | 248 | debug(50, ignoreErrno(errno) ? 3 : 1) |
249 | ("sslWriteServer: FD %d: write failure: %s.\n", fd, xstrerror()); | |
adb78bd4 | 250 | if (!ignoreErrno(errno)) |
251 | comm_close(fd); | |
983061ed | 252 | } |
c4b7a5a9 | 253 | if (cbdataReferenceValid(sslState)) { |
254 | assert(sslState->client.len == 0); | |
255 | comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF, | |
256 | sslReadClient, sslState); | |
257 | } | |
fa80a8ef | 258 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 259 | } |
260 | ||
261 | /* Writes data from the server buffer to the client side */ | |
b8d8561b | 262 | static void |
9f518b4a | 263 | sslWriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) |
983061ed | 264 | { |
e6ccf245 | 265 | SslStateData *sslState = (SslStateData *)data; |
adb78bd4 | 266 | assert(fd == sslState->client.fd); |
c4b7a5a9 | 267 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, (int)len); |
ee1679df | 268 | if (len > 0) { |
83704487 | 269 | kb_incr(&statCounter.client_http.kbytes_out, len); |
c4b7a5a9 | 270 | assert(len == (size_t)sslState->server.len); |
271 | sslState->server.len =0; | |
adb78bd4 | 272 | /* increment total object size */ |
273 | if (sslState->size_ptr) | |
274 | *sslState->size_ptr += len; | |
c4b7a5a9 | 275 | } |
276 | /* EOF */ | |
277 | if (len == 0) { | |
278 | comm_close(sslState->client.fd); | |
279 | return; | |
280 | } | |
281 | /* If the other end has closed, so should we */ | |
282 | if (sslState->server.fd == -1) { | |
283 | comm_close(sslState->client.fd); | |
284 | return; | |
983061ed | 285 | } |
fa80a8ef | 286 | cbdataInternalLock(sslState); /* ??? should be locked by the caller... */ |
c4b7a5a9 | 287 | /* Error? */ |
adb78bd4 | 288 | if (len < 0) { |
9bc73deb | 289 | debug(50, ignoreErrno(errno) ? 3 : 1) |
290 | ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror()); | |
adb78bd4 | 291 | if (!ignoreErrno(errno)) |
292 | comm_close(fd); | |
983061ed | 293 | } |
c4b7a5a9 | 294 | if (cbdataReferenceValid(sslState)) { |
295 | assert(sslState->server.len == 0); | |
296 | comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF, | |
297 | sslReadServer, sslState); | |
298 | } | |
fa80a8ef | 299 | cbdataInternalUnlock(sslState); /* ??? */ |
983061ed | 300 | } |
301 | ||
b8d8561b | 302 | static void |
5c5783a2 | 303 | sslTimeout(int fd, void *data) |
983061ed | 304 | { |
e6ccf245 | 305 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 306 | debug(26, 3) ("sslTimeout: FD %d\n", fd); |
1e438d1b | 307 | /* Temporary lock to protect our own feets (comm_close -> sslClientClosed -> Free) */ |
308 | cbdataInternalLock(sslState); | |
adb78bd4 | 309 | if (sslState->client.fd > -1) |
310 | comm_close(sslState->client.fd); | |
311 | if (sslState->server.fd > -1) | |
312 | comm_close(sslState->server.fd); | |
1e438d1b | 313 | cbdataInternalUnlock(sslState); |
983061ed | 314 | } |
315 | ||
c4b7a5a9 | 316 | static void |
4dcb4cc5 | 317 | sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data) |
c4b7a5a9 | 318 | { |
319 | SslStateData *sslState = (SslStateData *)data; | |
320 | if (flag != COMM_OK) { | |
321 | sslErrorComplete(fd, data, 0); | |
322 | return; | |
323 | } | |
324 | if (cbdataReferenceValid(sslState)) { | |
325 | assert(sslState->server.len == 0); | |
326 | comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF, | |
327 | sslReadServer, sslState); | |
328 | comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF, | |
329 | sslReadClient, sslState); | |
330 | } | |
331 | } | |
332 | ||
333 | ||
334 | /* | |
335 | * handle the write completion from a proxy request to an upstream proxy | |
336 | */ | |
337 | static void | |
338 | sslProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, void *data) | |
339 | { | |
340 | SslStateData *sslState = (SslStateData *)data; | |
341 | if (flag != COMM_OK) { | |
342 | sslErrorComplete(fd, data, 0); | |
343 | return; | |
344 | } | |
345 | if (cbdataReferenceValid(sslState)) { | |
346 | assert(sslState->server.len == 0); | |
347 | comm_read(sslState->server.fd, sslState->server.buf, SQUID_TCP_SO_RCVBUF, | |
348 | sslReadServer, sslState); | |
349 | comm_read(sslState->client.fd, sslState->client.buf, SQUID_TCP_SO_RCVBUF, | |
350 | sslReadClient, sslState); | |
351 | } | |
352 | } | |
353 | ||
b8d8561b | 354 | static void |
b177367b | 355 | sslConnected(int fd, void *data) |
983061ed | 356 | { |
e6ccf245 | 357 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 358 | debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState); |
974ba0ee | 359 | *sslState->status_ptr = HTTP_OK; |
4dcb4cc5 | 360 | comm_write(sslState->client.fd, conn_established, strlen(conn_established), |
361 | sslConnectedWriteDone, sslState); | |
983061ed | 362 | } |
363 | ||
b8d8561b | 364 | static void |
adb78bd4 | 365 | sslErrorComplete(int fdnotused, void *data, size_t sizenotused) |
30a4f2a8 | 366 | { |
e6ccf245 | 367 | SslStateData *sslState = (SslStateData *)data; |
9b312a19 | 368 | assert(sslState != NULL); |
adb78bd4 | 369 | if (sslState->client.fd > -1) |
370 | comm_close(sslState->client.fd); | |
371 | if (sslState->server.fd > -1) | |
372 | comm_close(sslState->server.fd); | |
30a4f2a8 | 373 | } |
374 | ||
983061ed | 375 | |
b8d8561b | 376 | static void |
3d7e9d7c | 377 | sslConnectDone(int fdnotused, comm_err_t status, void *data) |
983061ed | 378 | { |
e6ccf245 | 379 | SslStateData *sslState = (SslStateData *)data; |
30a4f2a8 | 380 | request_t *request = sslState->request; |
9b312a19 | 381 | ErrorState *err = NULL; |
29b8d8d6 | 382 | if (sslState->servers->_peer) |
890b0fa8 | 383 | hierarchyNote(&sslState->request->hier, sslState->servers->code, |
29b8d8d6 | 384 | sslState->servers->_peer->host); |
890b0fa8 | 385 | else if (Config.onoff.log_ip_on_direct) |
386 | hierarchyNote(&sslState->request->hier, sslState->servers->code, | |
a4b8110e | 387 | fd_table[sslState->server.fd].ipaddr); |
890b0fa8 | 388 | else |
389 | hierarchyNote(&sslState->request->hier, sslState->servers->code, | |
a4b8110e | 390 | sslState->host); |
edeb28fd | 391 | if (status == COMM_ERR_DNS) { |
a3d5953d | 392 | debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); |
fe40a877 | 393 | err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); |
974ba0ee | 394 | *sslState->status_ptr = HTTP_NOT_FOUND; |
9b312a19 | 395 | err->request = requestLink(request); |
396 | err->dnsserver_msg = xstrdup(dns_error_message); | |
397 | err->callback = sslErrorComplete; | |
398 | err->callback_data = sslState; | |
399 | errorSend(sslState->client.fd, err); | |
edeb28fd | 400 | } else if (status != COMM_OK) { |
fe40a877 | 401 | err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); |
974ba0ee | 402 | *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; |
c45ed9ad | 403 | err->xerrno = errno; |
9b312a19 | 404 | err->host = xstrdup(sslState->host); |
405 | err->port = sslState->port; | |
406 | err->request = requestLink(request); | |
407 | err->callback = sslErrorComplete; | |
408 | err->callback_data = sslState; | |
409 | errorSend(sslState->client.fd, err); | |
fe40a877 | 410 | } else { |
29b8d8d6 | 411 | if (sslState->servers->_peer) |
fe40a877 | 412 | sslProxyConnected(sslState->server.fd, sslState); |
c4b7a5a9 | 413 | else { |
fe40a877 | 414 | sslConnected(sslState->server.fd, sslState); |
c4b7a5a9 | 415 | } |
1afe05c5 | 416 | commSetTimeout(sslState->server.fd, |
417 | Config.Timeout.read, | |
418 | sslTimeout, | |
419 | sslState); | |
447e176b | 420 | #if DELAY_POOLS |
59715b38 | 421 | commSetDefer(sslState->server.fd, sslDeferServerRead, sslState); |
447e176b | 422 | #endif |
983061ed | 423 | } |
983061ed | 424 | } |
30a4f2a8 | 425 | |
28c60158 | 426 | CBDATA_TYPE(SslStateData); |
770f051d | 427 | void |
d5964d58 | 428 | sslStart(clientHttpRequest * http, size_t * size_ptr, int *status_ptr) |
30a4f2a8 | 429 | { |
430 | /* Create state structure. */ | |
431 | SslStateData *sslState = NULL; | |
432 | int sock; | |
9b312a19 | 433 | ErrorState *err = NULL; |
f1003989 | 434 | int answer; |
d5964d58 | 435 | int fd = http->conn->fd; |
436 | request_t *request = http->request; | |
437 | char *url = http->uri; | |
f1003989 | 438 | /* |
a4b8110e | 439 | * client_addr == no_addr indicates this is an "internal" request |
440 | * from peer_digest.c, asn.c, netdb.c, etc and should always | |
441 | * be allowed. yuck, I know. | |
442 | */ | |
f1003989 | 443 | if (request->client_addr.s_addr != no_addr.s_addr) { |
444 | /* | |
a4b8110e | 445 | * Check if this host is allowed to fetch MISSES from us (miss_access) |
446 | */ | |
4fb35c3c | 447 | ACLChecklist ch; |
f1003989 | 448 | ch.src_addr = request->client_addr; |
449 | ch.my_addr = request->my_addr; | |
450 | ch.my_port = request->my_port; | |
451 | ch.request = request; | |
452 | answer = aclCheckFast(Config.accessList.miss, &ch); | |
453 | if (answer == 0) { | |
454 | err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); | |
3b3ce25a | 455 | *status_ptr = HTTP_FORBIDDEN; |
f1003989 | 456 | err->request = requestLink(request); |
457 | err->src_addr = request->client_addr; | |
458 | errorSend(fd, err); | |
459 | return; | |
460 | } | |
461 | } | |
a3d5953d | 462 | debug(26, 3) ("sslStart: '%s %s'\n", |
30a4f2a8 | 463 | RequestMethodStr[request->method], url); |
83704487 | 464 | statCounter.server.all.requests++; |
465 | statCounter.server.other.requests++; | |
30a4f2a8 | 466 | /* Create socket. */ |
d6827718 | 467 | sock = comm_openex(SOCK_STREAM, |
16b204c4 | 468 | 0, |
d6827718 | 469 | getOutgoingAddr(request), |
16b204c4 | 470 | 0, |
471 | COMM_NONBLOCKING, | |
d6827718 | 472 | getOutgoingTOS(request), |
16b204c4 | 473 | url); |
30a4f2a8 | 474 | if (sock == COMM_ERROR) { |
a3d5953d | 475 | debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); |
fe40a877 | 476 | err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); |
3b3ce25a | 477 | *status_ptr = HTTP_INTERNAL_SERVER_ERROR; |
c45ed9ad | 478 | err->xerrno = errno; |
9b312a19 | 479 | err->request = requestLink(request); |
480 | errorSend(fd, err); | |
770f051d | 481 | return; |
30a4f2a8 | 482 | } |
28c60158 | 483 | CBDATA_INIT_TYPE(SslStateData); |
72711e31 | 484 | sslState = cbdataAlloc(SslStateData); |
59715b38 | 485 | #if DELAY_POOLS |
b67e2c8c | 486 | sslState->delayId = DelayId::DelayClient(http); |
59715b38 | 487 | #endif |
30a4f2a8 | 488 | sslState->url = xstrdup(url); |
489 | sslState->request = requestLink(request); | |
30a4f2a8 | 490 | sslState->size_ptr = size_ptr; |
974ba0ee | 491 | sslState->status_ptr = status_ptr; |
30a4f2a8 | 492 | sslState->client.fd = fd; |
493 | sslState->server.fd = sock; | |
e6ccf245 | 494 | sslState->server.buf = (char *)xmalloc(SQUID_TCP_SO_RCVBUF); |
495 | sslState->client.buf = (char *)xmalloc(SQUID_TCP_SO_RCVBUF); | |
30a4f2a8 | 496 | comm_add_close_handler(sslState->server.fd, |
adb78bd4 | 497 | sslServerClosed, |
cd1fb0eb | 498 | sslState); |
30a4f2a8 | 499 | comm_add_close_handler(sslState->client.fd, |
b177367b | 500 | sslClientClosed, |
cd1fb0eb | 501 | sslState); |
5c5783a2 | 502 | commSetTimeout(sslState->client.fd, |
4f92c80c | 503 | Config.Timeout.lifetime, |
504 | sslTimeout, | |
505 | sslState); | |
cf1edeae | 506 | commSetTimeout(sslState->server.fd, |
507 | Config.Timeout.connect, | |
508 | sslTimeout, | |
509 | sslState); | |
b6c0e933 | 510 | peerSelect(request, |
641941c0 | 511 | NULL, |
b6c0e933 | 512 | sslPeerSelectComplete, |
b6c0e933 | 513 | sslState); |
adb78bd4 | 514 | /* |
515 | * Disable the client read handler until peer selection is complete | |
516 | * Take control away from client_side.c. | |
517 | */ | |
518 | commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); | |
30a4f2a8 | 519 | } |
98ffb7e4 | 520 | |
b8d8561b | 521 | static void |
b177367b | 522 | sslProxyConnected(int fd, void *data) |
98ffb7e4 | 523 | { |
e6ccf245 | 524 | SslStateData *sslState = (SslStateData *)data; |
e1e72f06 | 525 | MemBuf mb; |
526 | HttpHeader hdr_out; | |
527 | Packer p; | |
b4b5fd95 | 528 | http_state_flags flags; |
a3d5953d | 529 | debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState); |
b4b5fd95 | 530 | memset(&flags, '\0', sizeof(flags)); |
2f2b4d20 | 531 | flags.proxying = sslState->request->flags.proxying; |
e1e72f06 | 532 | memBufDefInit(&mb); |
533 | memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url); | |
534 | httpBuildRequestHeader(sslState->request, | |
535 | sslState->request, | |
5999b776 | 536 | NULL, /* StoreEntry */ |
e1e72f06 | 537 | &hdr_out, |
b4b5fd95 | 538 | flags); /* flags */ |
e1e72f06 | 539 | packerToMemInit(&p, &mb); |
540 | httpHeaderPackInto(&hdr_out, &p); | |
541 | httpHeaderClean(&hdr_out); | |
542 | packerClean(&p); | |
543 | memBufAppend(&mb, "\r\n", 2); | |
c4b7a5a9 | 544 | |
d4cb310b | 545 | comm_old_write_mbuf(sslState->server.fd, mb, sslProxyConnectedWriteDone, sslState); |
c4b7a5a9 | 546 | |
86cf9987 | 547 | commSetTimeout(sslState->server.fd, |
548 | Config.Timeout.read, | |
549 | sslTimeout, | |
550 | sslState); | |
98ffb7e4 | 551 | } |
33ea9fff | 552 | |
33ea9fff | 553 | static void |
db1cd23c | 554 | sslPeerSelectComplete(FwdServer * fs, void *data) |
33ea9fff | 555 | { |
e6ccf245 | 556 | SslStateData *sslState = (SslStateData *)data; |
33ea9fff | 557 | request_t *request = sslState->request; |
deb79f06 | 558 | peer *g = NULL; |
db1cd23c | 559 | if (fs == NULL) { |
560 | ErrorState *err; | |
561 | err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); | |
974ba0ee | 562 | *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; |
db1cd23c | 563 | err->request = requestLink(sslState->request); |
564 | err->callback = sslErrorComplete; | |
565 | err->callback_data = sslState; | |
566 | errorSend(sslState->client.fd, err); | |
567 | return; | |
568 | } | |
64d8034e | 569 | sslState->servers = fs; |
29b8d8d6 | 570 | sslState->host = fs->_peer ? fs->_peer->host : request->host; |
571 | if (fs->_peer == NULL) { | |
b3b64e58 | 572 | sslState->port = request->port; |
29b8d8d6 | 573 | } else if (fs->_peer->http_port != 0) { |
574 | sslState->port = fs->_peer->http_port; | |
575 | } else if ((g = peerFindByName(fs->_peer->host))) { | |
b3b64e58 | 576 | sslState->port = g->http_port; |
33ea9fff | 577 | } else { |
b3b64e58 | 578 | sslState->port = CACHE_HTTP_PORT; |
33ea9fff | 579 | } |
29b8d8d6 | 580 | if (fs->_peer) { |
581 | sslState->request->peer_login = fs->_peer->login; | |
1f38f50a | 582 | sslState->request->flags.proxying = 1; |
583 | } else { | |
94439e4e | 584 | sslState->request->peer_login = NULL; |
1f38f50a | 585 | sslState->request->flags.proxying = 0; |
586 | } | |
59715b38 | 587 | #if DELAY_POOLS |
588 | /* no point using the delayIsNoDelay stuff since ssl is nice and simple */ | |
4326a9b6 | 589 | if (g && g->options.no_delay && sslState->delayId) { |
b67e2c8c | 590 | sslState->delayId = DelayId(); |
1ecaa0a0 | 591 | } |
59715b38 | 592 | #endif |
edeb28fd | 593 | commConnectStart(sslState->server.fd, |
594 | sslState->host, | |
595 | sslState->port, | |
596 | sslConnectDone, | |
33ea9fff | 597 | sslState); |
598 | } |