]>
Commit | Line | Data |
---|---|---|
95d659f0 | 1 | |
983061ed | 2 | /* |
7e3ce7b9 | 3 | * $Id: tunnel.cc,v 1.101 1999/12/30 17:36:51 wessels Exp $ |
983061ed | 4 | * |
30a4f2a8 | 5 | * DEBUG: section 26 Secure Sockets Layer Proxy |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
e25c139f | 9 | * ---------------------------------------------------------- |
30a4f2a8 | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
15 | * Duane Wessels and the University of California San Diego. Please | |
16 | * see the COPYRIGHT file for full details. Squid incorporates | |
17 | * software developed and/or copyrighted by other sources. Please see | |
18 | * 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 */ |
59715b38 | 50 | #if DELAY_POOLS |
51 | delay_id delay_id; | |
52 | #endif | |
983061ed | 53 | } SslStateData; |
54 | ||
0ee4272b | 55 | static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n"; |
983061ed | 56 | |
54cff85f | 57 | static CNCB sslConnectDone; |
58 | static ERCB sslErrorComplete; | |
adb78bd4 | 59 | static PF sslServerClosed; |
54cff85f | 60 | static PF sslClientClosed; |
61 | static PF sslReadClient; | |
62 | static PF sslReadServer; | |
5c5783a2 | 63 | static PF sslTimeout; |
54cff85f | 64 | static PF sslWriteClient; |
65 | static PF sslWriteServer; | |
66 | static PSC sslPeerSelectComplete; | |
adb78bd4 | 67 | static void sslStateFree(SslStateData * sslState); |
f5b8bbc4 | 68 | static void sslConnected(int fd, void *); |
69 | static void sslProxyConnected(int fd, void *); | |
adb78bd4 | 70 | static void sslSetSelect(SslStateData * sslState); |
447e176b | 71 | #if DELAY_POOLS |
72 | static DEFER sslDeferServerRead; | |
73 | #endif | |
30a4f2a8 | 74 | |
b8d8561b | 75 | static void |
adb78bd4 | 76 | sslServerClosed(int fd, void *data) |
30a4f2a8 | 77 | { |
adb78bd4 | 78 | SslStateData *sslState = data; |
79 | debug(26, 3) ("sslServerClosed: FD %d\n", fd); | |
80 | assert(fd == sslState->server.fd); | |
81 | sslState->server.fd = -1; | |
82 | if (sslState->client.fd == -1) | |
83 | sslStateFree(sslState); | |
30a4f2a8 | 84 | } |
85 | ||
b177367b | 86 | static void |
87 | sslClientClosed(int fd, void *data) | |
30a4f2a8 | 88 | { |
b177367b | 89 | SslStateData *sslState = data; |
a3d5953d | 90 | debug(26, 3) ("sslClientClosed: FD %d\n", fd); |
adb78bd4 | 91 | assert(fd == sslState->client.fd); |
92 | sslState->client.fd = -1; | |
93 | if (sslState->server.fd == -1) | |
94 | sslStateFree(sslState); | |
30a4f2a8 | 95 | } |
983061ed | 96 | |
b177367b | 97 | static void |
adb78bd4 | 98 | sslStateFree(SslStateData * sslState) |
983061ed | 99 | { |
adb78bd4 | 100 | debug(26, 3) ("sslStateFree: sslState=%p\n", sslState); |
101 | assert(sslState != NULL); | |
102 | assert(sslState->client.fd == -1); | |
103 | assert(sslState->server.fd == -1); | |
983061ed | 104 | safe_free(sslState->server.buf); |
105 | safe_free(sslState->client.buf); | |
adb78bd4 | 106 | safe_free(sslState->url); |
64d8034e | 107 | fwdServersFree(&sslState->servers); |
adb78bd4 | 108 | sslState->host = NULL; |
30a4f2a8 | 109 | requestUnlink(sslState->request); |
7dd44885 | 110 | sslState->request = NULL; |
b6a2f15e | 111 | #if DELAY_POOLS |
112 | delayUnregisterDelayIdPtr(&sslState->delay_id); | |
113 | #endif | |
7dd44885 | 114 | cbdataFree(sslState); |
983061ed | 115 | } |
116 | ||
447e176b | 117 | #if DELAY_POOLS |
118 | static int | |
119 | sslDeferServerRead(int fdnotused, void *data) | |
120 | { | |
59715b38 | 121 | SslStateData *s = data; |
7e3ce7b9 | 122 | int i = delayBytesWanted(s->delay_id, 0, INT_MAX); |
123 | if (i == INT_MAX) | |
124 | return 0; | |
125 | if (i == 0) | |
126 | return 1; | |
127 | return -1; | |
447e176b | 128 | } |
129 | #endif | |
130 | ||
adb78bd4 | 131 | static void |
132 | sslSetSelect(SslStateData * sslState) | |
133 | { | |
447e176b | 134 | size_t read_sz = SQUID_TCP_SO_RCVBUF; |
adb78bd4 | 135 | assert(sslState->server.fd > -1 || sslState->client.fd > -1); |
136 | if (sslState->client.fd > -1) { | |
137 | if (sslState->server.len > 0) { | |
138 | commSetSelect(sslState->client.fd, | |
139 | COMM_SELECT_WRITE, | |
140 | sslWriteClient, | |
141 | sslState, | |
142 | 0); | |
143 | } | |
447e176b | 144 | if (sslState->client.len < read_sz) { |
adb78bd4 | 145 | commSetSelect(sslState->client.fd, |
146 | COMM_SELECT_READ, | |
147 | sslReadClient, | |
148 | sslState, | |
149 | Config.Timeout.read); | |
150 | } | |
151 | } else if (sslState->client.len == 0) { | |
152 | comm_close(sslState->server.fd); | |
153 | } | |
154 | if (sslState->server.fd > -1) { | |
155 | if (sslState->client.len > 0) { | |
156 | commSetSelect(sslState->server.fd, | |
157 | COMM_SELECT_WRITE, | |
158 | sslWriteServer, | |
159 | sslState, | |
160 | 0); | |
161 | } | |
447e176b | 162 | #if DELAY_POOLS |
7e3ce7b9 | 163 | /* |
164 | * If this was allowed to return 0, there would be a possibility | |
e82d6d21 | 165 | * of the socket becoming "hung" with data accumulating but no |
166 | * write handler (server.len==0) and no read handler (!(0<0)) and | |
167 | * no data flowing in the other direction. Hence the argument of | |
168 | * 1 as min. | |
169 | */ | |
59715b38 | 170 | read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz); |
447e176b | 171 | #endif |
172 | if (sslState->server.len < read_sz) { | |
adb78bd4 | 173 | /* Have room to read more */ |
174 | commSetSelect(sslState->server.fd, | |
175 | COMM_SELECT_READ, | |
176 | sslReadServer, | |
177 | sslState, | |
178 | Config.Timeout.read); | |
179 | } | |
180 | } else if (sslState->client.fd == -1) { | |
181 | /* client already closed, nothing more to do */ | |
182 | } else if (sslState->server.len == 0) { | |
183 | comm_close(sslState->client.fd); | |
184 | } | |
185 | } | |
186 | ||
983061ed | 187 | /* Read from server side and queue it for writing to the client */ |
b8d8561b | 188 | static void |
b177367b | 189 | sslReadServer(int fd, void *data) |
983061ed | 190 | { |
b177367b | 191 | SslStateData *sslState = data; |
983061ed | 192 | int len; |
447e176b | 193 | size_t read_sz = SQUID_TCP_SO_RCVBUF - sslState->server.len; |
adb78bd4 | 194 | assert(fd == sslState->server.fd); |
195 | debug(26, 3) ("sslReadServer: FD %d, reading %d bytes at offset %d\n", | |
447e176b | 196 | fd, read_sz, sslState->server.len); |
197 | errno = 0; | |
198 | #if DELAY_POOLS | |
59715b38 | 199 | read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz); |
447e176b | 200 | #endif |
886f2785 | 201 | Counter.syscalls.sock.reads++; |
447e176b | 202 | len = read(fd, sslState->server.buf + sslState->server.len, read_sz); |
adb78bd4 | 203 | debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", fd, len); |
ee1679df | 204 | if (len > 0) { |
adb78bd4 | 205 | fd_bytes(fd, len, FD_READ); |
447e176b | 206 | #if DELAY_POOLS |
59715b38 | 207 | delayBytesIn(sslState->delay_id, len); |
447e176b | 208 | #endif |
a0f32775 | 209 | kb_incr(&Counter.server.all.kbytes_in, len); |
210 | kb_incr(&Counter.server.other.kbytes_in, len); | |
adb78bd4 | 211 | sslState->server.len += len; |
ee1679df | 212 | } |
adb78bd4 | 213 | cbdataLock(sslState); |
983061ed | 214 | if (len < 0) { |
9bc73deb | 215 | debug(50, ignoreErrno(errno) ? 3 : 1) |
216 | ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror()); | |
adb78bd4 | 217 | if (!ignoreErrno(errno)) |
218 | comm_close(fd); | |
983061ed | 219 | } else if (len == 0) { |
adb78bd4 | 220 | comm_close(sslState->server.fd); |
983061ed | 221 | } |
adb78bd4 | 222 | if (cbdataValid(sslState)) |
223 | sslSetSelect(sslState); | |
224 | cbdataUnlock(sslState); | |
983061ed | 225 | } |
226 | ||
227 | /* Read from client side and queue it for writing to the server */ | |
b8d8561b | 228 | static void |
b177367b | 229 | sslReadClient(int fd, void *data) |
983061ed | 230 | { |
b177367b | 231 | SslStateData *sslState = data; |
983061ed | 232 | int len; |
adb78bd4 | 233 | assert(fd == sslState->client.fd); |
234 | debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %d\n", | |
235 | fd, SQUID_TCP_SO_RCVBUF - sslState->client.len, | |
236 | sslState->client.len); | |
886f2785 | 237 | Counter.syscalls.sock.reads++; |
adb78bd4 | 238 | len = read(fd, |
239 | sslState->client.buf + sslState->client.len, | |
240 | SQUID_TCP_SO_RCVBUF - sslState->client.len); | |
241 | debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", fd, len); | |
ee1679df | 242 | if (len > 0) { |
adb78bd4 | 243 | fd_bytes(fd, len, FD_READ); |
ee1679df | 244 | kb_incr(&Counter.client_http.kbytes_in, len); |
adb78bd4 | 245 | sslState->client.len += len; |
ee1679df | 246 | } |
adb78bd4 | 247 | cbdataLock(sslState); |
983061ed | 248 | if (len < 0) { |
eb824054 | 249 | debug(50, ECONNRESET == errno ? 3 : 1) ("sslReadClient: FD %d: read failure: %s\n", |
983061ed | 250 | fd, xstrerror()); |
adb78bd4 | 251 | if (!ignoreErrno(errno)) |
252 | comm_close(fd); | |
983061ed | 253 | } else if (len == 0) { |
adb78bd4 | 254 | comm_close(fd); |
983061ed | 255 | } |
adb78bd4 | 256 | if (cbdataValid(sslState)) |
257 | sslSetSelect(sslState); | |
258 | cbdataUnlock(sslState); | |
983061ed | 259 | } |
260 | ||
261 | /* Writes data from the client buffer to the server side */ | |
b8d8561b | 262 | static void |
b177367b | 263 | sslWriteServer(int fd, void *data) |
983061ed | 264 | { |
b177367b | 265 | SslStateData *sslState = data; |
983061ed | 266 | int len; |
adb78bd4 | 267 | assert(fd == sslState->server.fd); |
268 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes to write\n", | |
269 | fd, sslState->client.len); | |
886f2785 | 270 | Counter.syscalls.sock.writes++; |
adb78bd4 | 271 | len = write(fd, |
272 | sslState->client.buf, | |
273 | sslState->client.len); | |
274 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", fd, len); | |
ee1679df | 275 | if (len > 0) { |
adb78bd4 | 276 | fd_bytes(fd, len, FD_WRITE); |
a0f32775 | 277 | kb_incr(&Counter.server.all.kbytes_out, len); |
278 | kb_incr(&Counter.server.other.kbytes_out, len); | |
adb78bd4 | 279 | assert(len <= sslState->client.len); |
280 | sslState->client.len -= len; | |
281 | if (sslState->client.len > 0) { | |
282 | /* we didn't write the whole thing */ | |
283 | xmemmove(sslState->client.buf, | |
284 | sslState->client.buf + len, | |
285 | sslState->client.len); | |
0a0bf5db | 286 | } |
983061ed | 287 | } |
adb78bd4 | 288 | cbdataLock(sslState); |
289 | if (len < 0) { | |
9bc73deb | 290 | debug(50, ignoreErrno(errno) ? 3 : 1) |
291 | ("sslWriteServer: FD %d: write failure: %s.\n", fd, xstrerror()); | |
adb78bd4 | 292 | if (!ignoreErrno(errno)) |
293 | comm_close(fd); | |
983061ed | 294 | } |
adb78bd4 | 295 | if (cbdataValid(sslState)) |
296 | sslSetSelect(sslState); | |
297 | cbdataUnlock(sslState); | |
983061ed | 298 | } |
299 | ||
300 | /* Writes data from the server buffer to the client side */ | |
b8d8561b | 301 | static void |
b177367b | 302 | sslWriteClient(int fd, void *data) |
983061ed | 303 | { |
b177367b | 304 | SslStateData *sslState = data; |
983061ed | 305 | int len; |
adb78bd4 | 306 | assert(fd == sslState->client.fd); |
307 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes to write\n", | |
308 | fd, sslState->server.len); | |
886f2785 | 309 | Counter.syscalls.sock.writes++; |
adb78bd4 | 310 | len = write(fd, |
311 | sslState->server.buf, | |
312 | sslState->server.len); | |
313 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, len); | |
ee1679df | 314 | if (len > 0) { |
adb78bd4 | 315 | fd_bytes(fd, len, FD_WRITE); |
ee1679df | 316 | kb_incr(&Counter.client_http.kbytes_out, len); |
adb78bd4 | 317 | assert(len <= sslState->server.len); |
318 | sslState->server.len -= len; | |
319 | /* increment total object size */ | |
320 | if (sslState->size_ptr) | |
321 | *sslState->size_ptr += len; | |
322 | if (sslState->server.len > 0) { | |
323 | /* we didn't write the whole thing */ | |
324 | xmemmove(sslState->server.buf, | |
325 | sslState->server.buf + len, | |
326 | sslState->server.len); | |
0a0bf5db | 327 | } |
983061ed | 328 | } |
adb78bd4 | 329 | cbdataLock(sslState); |
330 | if (len < 0) { | |
9bc73deb | 331 | debug(50, ignoreErrno(errno) ? 3 : 1) |
332 | ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror()); | |
adb78bd4 | 333 | if (!ignoreErrno(errno)) |
334 | comm_close(fd); | |
983061ed | 335 | } |
adb78bd4 | 336 | if (cbdataValid(sslState)) |
337 | sslSetSelect(sslState); | |
338 | cbdataUnlock(sslState); | |
983061ed | 339 | } |
340 | ||
b8d8561b | 341 | static void |
5c5783a2 | 342 | sslTimeout(int fd, void *data) |
983061ed | 343 | { |
b177367b | 344 | SslStateData *sslState = data; |
a3d5953d | 345 | debug(26, 3) ("sslTimeout: FD %d\n", fd); |
adb78bd4 | 346 | if (sslState->client.fd > -1) |
347 | comm_close(sslState->client.fd); | |
348 | if (sslState->server.fd > -1) | |
349 | comm_close(sslState->server.fd); | |
983061ed | 350 | } |
351 | ||
b8d8561b | 352 | static void |
b177367b | 353 | sslConnected(int fd, void *data) |
983061ed | 354 | { |
b177367b | 355 | SslStateData *sslState = data; |
a3d5953d | 356 | debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState); |
54cff85f | 357 | xstrncpy(sslState->server.buf, conn_established, SQUID_TCP_SO_RCVBUF); |
983061ed | 358 | sslState->server.len = strlen(conn_established); |
adb78bd4 | 359 | sslSetSelect(sslState); |
983061ed | 360 | } |
361 | ||
b8d8561b | 362 | static void |
adb78bd4 | 363 | sslErrorComplete(int fdnotused, void *data, size_t sizenotused) |
30a4f2a8 | 364 | { |
adb78bd4 | 365 | SslStateData *sslState = data; |
9b312a19 | 366 | assert(sslState != NULL); |
adb78bd4 | 367 | if (sslState->client.fd > -1) |
368 | comm_close(sslState->client.fd); | |
369 | if (sslState->server.fd > -1) | |
370 | comm_close(sslState->server.fd); | |
30a4f2a8 | 371 | } |
372 | ||
983061ed | 373 | |
b8d8561b | 374 | static void |
79d39a72 | 375 | sslConnectDone(int fdnotused, int status, void *data) |
983061ed | 376 | { |
b15fe823 | 377 | SslStateData *sslState = data; |
30a4f2a8 | 378 | request_t *request = sslState->request; |
9b312a19 | 379 | ErrorState *err = NULL; |
edeb28fd | 380 | if (status == COMM_ERR_DNS) { |
a3d5953d | 381 | debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); |
fe40a877 | 382 | err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); |
9b312a19 | 383 | err->request = requestLink(request); |
384 | err->dnsserver_msg = xstrdup(dns_error_message); | |
385 | err->callback = sslErrorComplete; | |
386 | err->callback_data = sslState; | |
387 | errorSend(sslState->client.fd, err); | |
edeb28fd | 388 | } else if (status != COMM_OK) { |
fe40a877 | 389 | err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); |
c45ed9ad | 390 | err->xerrno = errno; |
9b312a19 | 391 | err->host = xstrdup(sslState->host); |
392 | err->port = sslState->port; | |
393 | err->request = requestLink(request); | |
394 | err->callback = sslErrorComplete; | |
395 | err->callback_data = sslState; | |
396 | errorSend(sslState->client.fd, err); | |
fe40a877 | 397 | } else { |
64d8034e | 398 | if (sslState->servers->peer) |
fe40a877 | 399 | sslProxyConnected(sslState->server.fd, sslState); |
4e3f29eb | 400 | else |
fe40a877 | 401 | sslConnected(sslState->server.fd, sslState); |
1afe05c5 | 402 | commSetTimeout(sslState->server.fd, |
403 | Config.Timeout.read, | |
404 | sslTimeout, | |
405 | sslState); | |
447e176b | 406 | #if DELAY_POOLS |
59715b38 | 407 | commSetDefer(sslState->server.fd, sslDeferServerRead, sslState); |
447e176b | 408 | #endif |
983061ed | 409 | } |
983061ed | 410 | } |
30a4f2a8 | 411 | |
770f051d | 412 | void |
9b312a19 | 413 | sslStart(int fd, const char *url, request_t * request, size_t * size_ptr) |
30a4f2a8 | 414 | { |
415 | /* Create state structure. */ | |
416 | SslStateData *sslState = NULL; | |
417 | int sock; | |
9b312a19 | 418 | ErrorState *err = NULL; |
a3d5953d | 419 | debug(26, 3) ("sslStart: '%s %s'\n", |
30a4f2a8 | 420 | RequestMethodStr[request->method], url); |
a0f32775 | 421 | Counter.server.all.requests++; |
422 | Counter.server.other.requests++; | |
30a4f2a8 | 423 | /* Create socket. */ |
16b204c4 | 424 | sock = comm_open(SOCK_STREAM, |
425 | 0, | |
426 | Config.Addrs.tcp_outgoing, | |
427 | 0, | |
428 | COMM_NONBLOCKING, | |
429 | url); | |
30a4f2a8 | 430 | if (sock == COMM_ERROR) { |
a3d5953d | 431 | debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); |
fe40a877 | 432 | err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); |
c45ed9ad | 433 | err->xerrno = errno; |
9b312a19 | 434 | err->request = requestLink(request); |
435 | errorSend(fd, err); | |
770f051d | 436 | return; |
30a4f2a8 | 437 | } |
438 | sslState = xcalloc(1, sizeof(SslStateData)); | |
db1cd23c | 439 | cbdataAdd(sslState, cbdataXfree, 0); |
59715b38 | 440 | #if DELAY_POOLS |
441 | sslState->delay_id = delayClient(request); | |
b6a2f15e | 442 | delayRegisterDelayIdPtr(&sslState->delay_id); |
59715b38 | 443 | #endif |
30a4f2a8 | 444 | sslState->url = xstrdup(url); |
445 | sslState->request = requestLink(request); | |
30a4f2a8 | 446 | sslState->size_ptr = size_ptr; |
447 | sslState->client.fd = fd; | |
448 | sslState->server.fd = sock; | |
449 | sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF); | |
450 | sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF); | |
451 | comm_add_close_handler(sslState->server.fd, | |
adb78bd4 | 452 | sslServerClosed, |
cd1fb0eb | 453 | sslState); |
30a4f2a8 | 454 | comm_add_close_handler(sslState->client.fd, |
b177367b | 455 | sslClientClosed, |
cd1fb0eb | 456 | sslState); |
5c5783a2 | 457 | commSetTimeout(sslState->client.fd, |
4f92c80c | 458 | Config.Timeout.lifetime, |
459 | sslTimeout, | |
460 | sslState); | |
cf1edeae | 461 | commSetTimeout(sslState->server.fd, |
462 | Config.Timeout.connect, | |
463 | sslTimeout, | |
464 | sslState); | |
b6c0e933 | 465 | peerSelect(request, |
641941c0 | 466 | NULL, |
b6c0e933 | 467 | sslPeerSelectComplete, |
b6c0e933 | 468 | sslState); |
adb78bd4 | 469 | /* |
470 | * Disable the client read handler until peer selection is complete | |
471 | * Take control away from client_side.c. | |
472 | */ | |
473 | commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); | |
30a4f2a8 | 474 | } |
98ffb7e4 | 475 | |
b8d8561b | 476 | static void |
b177367b | 477 | sslProxyConnected(int fd, void *data) |
98ffb7e4 | 478 | { |
b177367b | 479 | SslStateData *sslState = data; |
e1e72f06 | 480 | MemBuf mb; |
481 | HttpHeader hdr_out; | |
482 | Packer p; | |
b4b5fd95 | 483 | http_state_flags flags; |
a3d5953d | 484 | debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState); |
b4b5fd95 | 485 | memset(&flags, '\0', sizeof(flags)); |
e1e72f06 | 486 | memBufDefInit(&mb); |
487 | memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url); | |
488 | httpBuildRequestHeader(sslState->request, | |
489 | sslState->request, | |
5999b776 | 490 | NULL, /* StoreEntry */ |
e1e72f06 | 491 | &hdr_out, |
492 | sslState->client.fd, | |
b4b5fd95 | 493 | flags); /* flags */ |
e1e72f06 | 494 | packerToMemInit(&p, &mb); |
495 | httpHeaderPackInto(&hdr_out, &p); | |
496 | httpHeaderClean(&hdr_out); | |
497 | packerClean(&p); | |
498 | memBufAppend(&mb, "\r\n", 2); | |
499 | xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF); | |
500 | debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf); | |
501 | sslState->client.len = mb.size; | |
e1e72f06 | 502 | memBufClean(&mb); |
86cf9987 | 503 | commSetTimeout(sslState->server.fd, |
504 | Config.Timeout.read, | |
505 | sslTimeout, | |
506 | sslState); | |
adb78bd4 | 507 | sslSetSelect(sslState); |
98ffb7e4 | 508 | } |
33ea9fff | 509 | |
33ea9fff | 510 | static void |
db1cd23c | 511 | sslPeerSelectComplete(FwdServer * fs, void *data) |
33ea9fff | 512 | { |
513 | SslStateData *sslState = data; | |
514 | request_t *request = sslState->request; | |
deb79f06 | 515 | peer *g = NULL; |
db1cd23c | 516 | if (fs == NULL) { |
517 | ErrorState *err; | |
518 | err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); | |
519 | err->request = requestLink(sslState->request); | |
520 | err->callback = sslErrorComplete; | |
521 | err->callback_data = sslState; | |
522 | errorSend(sslState->client.fd, err); | |
523 | return; | |
524 | } | |
64d8034e | 525 | sslState->servers = fs; |
db1cd23c | 526 | sslState->host = fs->peer ? fs->peer->host : request->host; |
527 | if (fs->peer == NULL) { | |
b3b64e58 | 528 | sslState->port = request->port; |
db1cd23c | 529 | } else if (fs->peer->http_port != 0) { |
530 | sslState->port = fs->peer->http_port; | |
531 | } else if ((g = peerFindByName(fs->peer->host))) { | |
b3b64e58 | 532 | sslState->port = g->http_port; |
33ea9fff | 533 | } else { |
b3b64e58 | 534 | sslState->port = CACHE_HTTP_PORT; |
33ea9fff | 535 | } |
1f38f50a | 536 | if (fs->peer) { |
537 | sslState->request->peer_login = fs->peer->login; | |
538 | sslState->request->flags.proxying = 1; | |
539 | } else { | |
540 | sslState->request->flags.proxying = 0; | |
541 | } | |
59715b38 | 542 | #if DELAY_POOLS |
543 | /* no point using the delayIsNoDelay stuff since ssl is nice and simple */ | |
1ecaa0a0 | 544 | if (g && g->options.no_delay && sslState->delay_id) { |
545 | delayUnregisterDelayIdPtr(&sslState->delay_id); | |
59715b38 | 546 | sslState->delay_id = 0; |
1ecaa0a0 | 547 | } |
59715b38 | 548 | #endif |
64d8034e | 549 | hierarchyNote(&sslState->request->hier, |
550 | fs->peer ? fs->code : DIRECT, | |
551 | sslState->host); | |
edeb28fd | 552 | commConnectStart(sslState->server.fd, |
553 | sslState->host, | |
554 | sslState->port, | |
555 | sslConnectDone, | |
33ea9fff | 556 | sslState); |
557 | } |