]>
Commit | Line | Data |
---|---|---|
95d659f0 | 1 | |
983061ed | 2 | /* |
190154cf | 3 | * $Id: tunnel.cc,v 1.145 2003/08/10 11:00:44 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 | |
a46d2c0e | 45 | #include "client_side.h" |
983061ed | 46 | |
a46d2c0e | 47 | class SslStateData |
62e76326 | 48 | { |
a46d2c0e | 49 | |
50 | public: | |
51 | ||
52 | class Connection; | |
53 | void *operator new(size_t); | |
54 | void operator delete (void *); | |
a46d2c0e | 55 | static void ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data); |
56 | static void ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data); | |
57 | static void WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data); | |
58 | static void WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data); | |
59 | ||
60 | bool noConnections() const; | |
983061ed | 61 | char *url; |
98ffb7e4 | 62 | char *host; /* either request->host or proxy host */ |
63 | u_short port; | |
190154cf | 64 | HttpRequest *request; |
64d8034e | 65 | FwdServer *servers; |
62e76326 | 66 | |
a46d2c0e | 67 | class Connection |
62e76326 | 68 | { |
a46d2c0e | 69 | |
70 | public: | |
71 | Connection() : len (0),buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), fd_(-1){} | |
72 | ||
73 | ~Connection(); | |
74 | int const & fd() const { return fd_;} | |
75 | ||
76 | void fd(int const newFD); | |
77 | int bytesWanted(int lower=0, int upper = INT_MAX) const; | |
78 | void bytesIn(int const &); | |
79 | #if DELAY_POOLS | |
80 | ||
81 | void setDelayId(DelayId const &); | |
82 | #endif | |
83 | ||
84 | void error(int const xerrno); | |
85 | int Connection::debugLevelForError(int const xerrno) const; | |
86 | void closeIfOpen(); | |
87 | void dataSent (size_t amount); | |
62e76326 | 88 | int len; |
89 | char *buf; | |
a46d2c0e | 90 | size_t *size_ptr; /* pointer to size in an ConnStateData for logging */ |
62e76326 | 91 | |
a46d2c0e | 92 | private: |
93 | int fd_; | |
59715b38 | 94 | #if DELAY_POOLS |
62e76326 | 95 | |
a46d2c0e | 96 | DelayId delayId; |
59715b38 | 97 | #endif |
62e76326 | 98 | |
a46d2c0e | 99 | }; |
100 | ||
101 | Connection client, server; | |
102 | int *status_ptr; /* pointer to status for logging */ | |
103 | void copyRead(Connection &from, IOCB *completion); | |
104 | ||
105 | private: | |
106 | CBDATA_CLASS(SslStateData); | |
107 | void copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOWCB *); | |
108 | void readServer(char *buf, size_t len, comm_err_t errcode, int xerrno); | |
109 | void readClient(char *buf, size_t len, comm_err_t errcode, int xerrno); | |
110 | void writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno); | |
111 | void writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno); | |
112 | }; | |
983061ed | 113 | |
0ee4272b | 114 | static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n"; |
983061ed | 115 | |
54cff85f | 116 | static CNCB sslConnectDone; |
117 | static ERCB sslErrorComplete; | |
adb78bd4 | 118 | static PF sslServerClosed; |
54cff85f | 119 | static PF sslClientClosed; |
5c5783a2 | 120 | static PF sslTimeout; |
54cff85f | 121 | static PSC sslPeerSelectComplete; |
adb78bd4 | 122 | static void sslStateFree(SslStateData * sslState); |
f5b8bbc4 | 123 | static void sslConnected(int fd, void *); |
124 | static void sslProxyConnected(int fd, void *); | |
30a4f2a8 | 125 | |
b8d8561b | 126 | static void |
adb78bd4 | 127 | sslServerClosed(int fd, void *data) |
30a4f2a8 | 128 | { |
e6ccf245 | 129 | SslStateData *sslState = (SslStateData *)data; |
adb78bd4 | 130 | debug(26, 3) ("sslServerClosed: FD %d\n", fd); |
a46d2c0e | 131 | assert(fd == sslState->server.fd()); |
132 | sslState->server.fd(-1); | |
62e76326 | 133 | |
a46d2c0e | 134 | if (sslState->noConnections()) |
62e76326 | 135 | sslStateFree(sslState); |
30a4f2a8 | 136 | } |
137 | ||
b177367b | 138 | static void |
139 | sslClientClosed(int fd, void *data) | |
30a4f2a8 | 140 | { |
e6ccf245 | 141 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 142 | debug(26, 3) ("sslClientClosed: FD %d\n", fd); |
a46d2c0e | 143 | assert(fd == sslState->client.fd()); |
144 | sslState->client.fd(-1); | |
62e76326 | 145 | |
a46d2c0e | 146 | if (sslState->noConnections()) |
62e76326 | 147 | sslStateFree(sslState); |
30a4f2a8 | 148 | } |
983061ed | 149 | |
b177367b | 150 | static void |
adb78bd4 | 151 | sslStateFree(SslStateData * sslState) |
983061ed | 152 | { |
adb78bd4 | 153 | debug(26, 3) ("sslStateFree: sslState=%p\n", sslState); |
154 | assert(sslState != NULL); | |
a46d2c0e | 155 | assert(sslState->noConnections()); |
adb78bd4 | 156 | safe_free(sslState->url); |
64d8034e | 157 | fwdServersFree(&sslState->servers); |
adb78bd4 | 158 | sslState->host = NULL; |
30a4f2a8 | 159 | requestUnlink(sslState->request); |
7dd44885 | 160 | sslState->request = NULL; |
00d77d6b | 161 | delete sslState; |
983061ed | 162 | } |
163 | ||
a46d2c0e | 164 | SslStateData::Connection::~Connection() |
165 | { | |
166 | safe_free (buf); | |
167 | } | |
168 | ||
169 | int | |
170 | SslStateData::Connection::bytesWanted(int lowerbound, int upperbound) const | |
447e176b | 171 | { |
a46d2c0e | 172 | #if DELAY_POOLS |
173 | return delayId.bytesWanted(lowerbound, upperbound); | |
174 | #else | |
62e76326 | 175 | |
a46d2c0e | 176 | return INT_MAX; |
177 | #endif | |
178 | } | |
62e76326 | 179 | |
a46d2c0e | 180 | void |
181 | SslStateData::Connection::bytesIn(int const &count) | |
182 | { | |
183 | #if DELAY_POOLS | |
184 | delayId.bytesIn(count); | |
185 | #endif | |
62e76326 | 186 | |
a46d2c0e | 187 | len += count; |
447e176b | 188 | } |
62e76326 | 189 | |
a46d2c0e | 190 | int |
191 | SslStateData::Connection::debugLevelForError(int const xerrno) const | |
192 | { | |
193 | #ifdef ECONNRESET | |
194 | ||
195 | if (xerrno == ECONNRESET) | |
196 | return 2; | |
197 | ||
447e176b | 198 | #endif |
199 | ||
a46d2c0e | 200 | if (ignoreErrno(xerrno)) |
201 | return 3; | |
202 | ||
203 | return 1; | |
204 | } | |
adb78bd4 | 205 | |
983061ed | 206 | /* Read from server side and queue it for writing to the client */ |
a46d2c0e | 207 | void |
208 | SslStateData::ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data) | |
983061ed | 209 | { |
e6ccf245 | 210 | SslStateData *sslState = (SslStateData *)data; |
a46d2c0e | 211 | assert (cbdataReferenceValid (sslState)); |
c4b7a5a9 | 212 | |
a46d2c0e | 213 | assert(fd == sslState->server.fd()); |
214 | sslState->readServer(buf, len, errcode, xerrno); | |
215 | } | |
62e76326 | 216 | |
a46d2c0e | 217 | void |
218 | SslStateData::readServer(char *buf, size_t len, comm_err_t errcode, int xerrno) | |
219 | { | |
220 | /* | |
221 | * Bail out early on COMM_ERR_CLOSING | |
222 | * - close handlers will tidy up for us | |
223 | */ | |
a55f4cea | 224 | |
a46d2c0e | 225 | if (errcode == COMM_ERR_CLOSING) |
226 | return; | |
62e76326 | 227 | |
a46d2c0e | 228 | debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", server.fd(), (int)len); |
62e76326 | 229 | |
ee1679df | 230 | if (len > 0) { |
a46d2c0e | 231 | server.bytesIn(len); |
62e76326 | 232 | kb_incr(&statCounter.server.all.kbytes_in, len); |
233 | kb_incr(&statCounter.server.other.kbytes_in, len); | |
ee1679df | 234 | } |
62e76326 | 235 | |
a46d2c0e | 236 | copy (len, errcode, xerrno, server, client, WriteClientDone); |
237 | } | |
238 | ||
239 | void | |
240 | SslStateData::Connection::error(int const xerrno) | |
241 | { | |
242 | /* XXX fixme xstrerror and xerrno... */ | |
243 | errno = xerrno; | |
244 | ||
245 | if (xerrno == COMM_ERR_CLOSING) | |
a55f4cea | 246 | return; |
62e76326 | 247 | |
a46d2c0e | 248 | debug(50, debugLevelForError(xerrno)) |
249 | ("sslReadServer: FD %d: read failure: %s\n", fd(), xstrerror()); | |
62e76326 | 250 | |
a46d2c0e | 251 | if (!ignoreErrno(xerrno)) |
252 | comm_close(fd()); | |
983061ed | 253 | } |
254 | ||
255 | /* Read from client side and queue it for writing to the server */ | |
a46d2c0e | 256 | void |
257 | SslStateData::ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data) | |
983061ed | 258 | { |
e6ccf245 | 259 | SslStateData *sslState = (SslStateData *)data; |
a46d2c0e | 260 | assert (cbdataReferenceValid (sslState)); |
62e76326 | 261 | |
a46d2c0e | 262 | assert(fd == sslState->client.fd()); |
263 | sslState->readClient(buf, len, errcode, xerrno); | |
264 | } | |
62e76326 | 265 | |
a46d2c0e | 266 | void |
267 | SslStateData::readClient(char *buf, size_t len, comm_err_t errcode, int xerrno) | |
268 | { | |
269 | /* | |
270 | * Bail out early on COMM_ERR_CLOSING | |
271 | * - close handlers will tidy up for us | |
272 | */ | |
a55f4cea | 273 | |
a46d2c0e | 274 | if (errcode == COMM_ERR_CLOSING) |
275 | return; | |
a55f4cea | 276 | |
a46d2c0e | 277 | debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", client.fd(), (int) len); |
62e76326 | 278 | |
a46d2c0e | 279 | if (len > 0) { |
280 | client.bytesIn(len); | |
281 | kb_incr(&statCounter.client_http.kbytes_in, len); | |
282 | } | |
62e76326 | 283 | |
a46d2c0e | 284 | copy (len, errcode, xerrno, client, server, WriteServerDone); |
285 | } | |
62e76326 | 286 | |
a46d2c0e | 287 | void |
288 | SslStateData::copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOWCB *completion) | |
289 | { | |
290 | /* I think this is to prevent free-while-in-a-callback behaviour | |
291 | * - RBC 20030229 | |
292 | */ | |
293 | cbdataInternalLock(this); /* ??? should be locked by the caller... */ | |
62e76326 | 294 | |
a46d2c0e | 295 | if (len < 0 || errcode) |
296 | from.error (xerrno); | |
297 | else if (len == 0 || to.fd() == -1) { | |
298 | comm_close(from.fd()); | |
62e76326 | 299 | /* Only close the remote end if we've finished queueing data to it */ |
300 | ||
a46d2c0e | 301 | if (from.len == 0 && to.fd() != -1) { |
302 | comm_close(to.fd()); | |
c4b7a5a9 | 303 | } |
a46d2c0e | 304 | } else if (cbdataReferenceValid(this)) |
305 | comm_write(to.fd(), from.buf, len, completion, this); | |
a55f4cea | 306 | |
a46d2c0e | 307 | cbdataInternalUnlock(this); /* ??? */ |
983061ed | 308 | } |
309 | ||
310 | /* Writes data from the client buffer to the server side */ | |
a46d2c0e | 311 | void |
312 | SslStateData::WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) | |
983061ed | 313 | { |
e6ccf245 | 314 | SslStateData *sslState = (SslStateData *)data; |
a46d2c0e | 315 | assert (cbdataReferenceValid (sslState)); |
316 | ||
317 | assert(fd == sslState->server.fd()); | |
318 | sslState->writeServerDone(buf, len, flag, xerrno); | |
319 | } | |
a55f4cea | 320 | |
a46d2c0e | 321 | void |
322 | SslStateData::writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno) | |
323 | { | |
324 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", server.fd(), (int)len); | |
c4b7a5a9 | 325 | /* Valid data */ |
62e76326 | 326 | |
ee1679df | 327 | if (len > 0) { |
62e76326 | 328 | kb_incr(&statCounter.server.all.kbytes_out, len); |
329 | kb_incr(&statCounter.server.other.kbytes_out, len); | |
a46d2c0e | 330 | client.dataSent(len); |
c4b7a5a9 | 331 | } |
62e76326 | 332 | |
a46d2c0e | 333 | /* EOF */ |
334 | if (len == 0) { | |
335 | comm_close(server.fd()); | |
336 | return; | |
337 | } | |
62e76326 | 338 | |
a46d2c0e | 339 | /* If the other end has closed, so should we */ |
340 | if (client.fd() == -1) { | |
341 | comm_close(server.fd()); | |
a55f4cea | 342 | return; |
c4b7a5a9 | 343 | } |
62e76326 | 344 | |
a46d2c0e | 345 | cbdataInternalLock(this); /* ??? should be locked by the caller... */ |
346 | /* Error? */ | |
347 | ||
348 | if (len < 0) | |
349 | server.error(xerrno); | |
350 | else if (cbdataReferenceValid(this)) | |
351 | copyRead(client, ReadClient); | |
352 | ||
353 | cbdataInternalUnlock(this); /* ??? */ | |
983061ed | 354 | } |
355 | ||
356 | /* Writes data from the server buffer to the client side */ | |
a46d2c0e | 357 | void |
358 | SslStateData::WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) | |
983061ed | 359 | { |
e6ccf245 | 360 | SslStateData *sslState = (SslStateData *)data; |
a46d2c0e | 361 | assert (cbdataReferenceValid (sslState)); |
362 | ||
363 | assert(fd == sslState->client.fd()); | |
364 | sslState->writeClientDone(buf, len, flag, xerrno); | |
365 | } | |
366 | ||
367 | void | |
368 | SslStateData::Connection::dataSent (size_t amount) | |
369 | { | |
370 | assert(amount == (size_t)len); | |
371 | len =0; | |
372 | /* increment total object size */ | |
373 | ||
374 | if (size_ptr) | |
375 | *size_ptr += amount; | |
376 | } | |
377 | ||
378 | void | |
379 | SslStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno) | |
380 | { | |
381 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", client.fd(), (int)len); | |
62e76326 | 382 | |
ee1679df | 383 | if (len > 0) { |
62e76326 | 384 | kb_incr(&statCounter.client_http.kbytes_out, len); |
a46d2c0e | 385 | server.dataSent(len); |
c4b7a5a9 | 386 | } |
62e76326 | 387 | |
a55f4cea | 388 | /* EOF */ |
a46d2c0e | 389 | if (len == 0) { |
390 | comm_close(client.fd()); | |
62e76326 | 391 | return; |
983061ed | 392 | } |
62e76326 | 393 | |
a46d2c0e | 394 | /* If the other end has closed, so should we */ |
395 | if (server.fd() == -1) { | |
396 | comm_close(client.fd()); | |
a55f4cea | 397 | return; |
983061ed | 398 | } |
62e76326 | 399 | |
a46d2c0e | 400 | cbdataInternalLock(this); /* ??? should be locked by the caller... */ |
401 | /* Error? */ | |
a55f4cea | 402 | |
a46d2c0e | 403 | if (len < 0) |
404 | client.error(xerrno); | |
405 | else if (cbdataReferenceValid(this)) | |
406 | copyRead(server, ReadServer); | |
2c202d66 | 407 | |
a46d2c0e | 408 | cbdataInternalUnlock(this); /* ??? */ |
983061ed | 409 | } |
410 | ||
b8d8561b | 411 | static void |
5c5783a2 | 412 | sslTimeout(int fd, void *data) |
983061ed | 413 | { |
e6ccf245 | 414 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 415 | debug(26, 3) ("sslTimeout: FD %d\n", fd); |
a46d2c0e | 416 | /* Temporary lock to protect our own feets (comm_close -> sslClientClosed -> Free) */ |
417 | cbdataInternalLock(sslState); | |
a55f4cea | 418 | |
a46d2c0e | 419 | sslState->client.closeIfOpen(); |
420 | sslState->server.closeIfOpen(); | |
421 | cbdataInternalUnlock(sslState); | |
422 | } | |
62e76326 | 423 | |
a46d2c0e | 424 | void |
425 | SslStateData::Connection::closeIfOpen() | |
426 | { | |
427 | if (fd() != -1) | |
428 | comm_close(fd()); | |
429 | } | |
430 | ||
431 | void | |
432 | SslStateData::copyRead(Connection &from, IOCB *completion) | |
433 | { | |
434 | assert(from.len == 0); | |
435 | comm_read(from.fd(), from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), completion, this); | |
983061ed | 436 | } |
437 | ||
a46d2c0e | 438 | |
c4b7a5a9 | 439 | static void |
4dcb4cc5 | 440 | sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data) |
c4b7a5a9 | 441 | { |
62e76326 | 442 | SslStateData *sslState = (SslStateData *)data; |
443 | ||
444 | if (flag != COMM_OK) { | |
445 | sslErrorComplete(fd, data, 0); | |
446 | return; | |
447 | } | |
448 | ||
449 | if (cbdataReferenceValid(sslState)) { | |
a46d2c0e | 450 | sslState->copyRead(sslState->server, SslStateData::ReadServer); |
451 | sslState->copyRead(sslState->client, SslStateData::ReadClient); | |
62e76326 | 452 | } |
c4b7a5a9 | 453 | } |
454 | ||
c4b7a5a9 | 455 | /* |
456 | * handle the write completion from a proxy request to an upstream proxy | |
457 | */ | |
458 | static void | |
459 | sslProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, void *data) | |
460 | { | |
a46d2c0e | 461 | sslConnectedWriteDone(fd, buf, size, flag, 0, data); |
c4b7a5a9 | 462 | } |
463 | ||
b8d8561b | 464 | static void |
b177367b | 465 | sslConnected(int fd, void *data) |
983061ed | 466 | { |
e6ccf245 | 467 | SslStateData *sslState = (SslStateData *)data; |
a3d5953d | 468 | debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState); |
974ba0ee | 469 | *sslState->status_ptr = HTTP_OK; |
a46d2c0e | 470 | comm_write(sslState->client.fd(), conn_established, strlen(conn_established), |
62e76326 | 471 | sslConnectedWriteDone, sslState); |
983061ed | 472 | } |
473 | ||
b8d8561b | 474 | static void |
adb78bd4 | 475 | sslErrorComplete(int fdnotused, void *data, size_t sizenotused) |
30a4f2a8 | 476 | { |
e6ccf245 | 477 | SslStateData *sslState = (SslStateData *)data; |
9b312a19 | 478 | assert(sslState != NULL); |
62e76326 | 479 | |
a46d2c0e | 480 | if (sslState->client.fd() > -1) |
481 | comm_close(sslState->client.fd()); | |
62e76326 | 482 | |
a46d2c0e | 483 | if (sslState->server.fd() > -1) |
484 | comm_close(sslState->server.fd()); | |
30a4f2a8 | 485 | } |
486 | ||
983061ed | 487 | |
b8d8561b | 488 | static void |
f3400a93 | 489 | sslConnectDone(int fdnotused, comm_err_t status, int xerrno, void *data) |
983061ed | 490 | { |
e6ccf245 | 491 | SslStateData *sslState = (SslStateData *)data; |
190154cf | 492 | HttpRequest *request = sslState->request; |
9b312a19 | 493 | ErrorState *err = NULL; |
62e76326 | 494 | |
29b8d8d6 | 495 | if (sslState->servers->_peer) |
62e76326 | 496 | hierarchyNote(&sslState->request->hier, sslState->servers->code, |
497 | sslState->servers->_peer->host); | |
890b0fa8 | 498 | else if (Config.onoff.log_ip_on_direct) |
62e76326 | 499 | hierarchyNote(&sslState->request->hier, sslState->servers->code, |
a46d2c0e | 500 | fd_table[sslState->server.fd()].ipaddr); |
890b0fa8 | 501 | else |
62e76326 | 502 | hierarchyNote(&sslState->request->hier, sslState->servers->code, |
503 | sslState->host); | |
504 | ||
edeb28fd | 505 | if (status == COMM_ERR_DNS) { |
62e76326 | 506 | debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); |
507 | err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); | |
508 | *sslState->status_ptr = HTTP_NOT_FOUND; | |
509 | err->request = requestLink(request); | |
510 | err->dnsserver_msg = xstrdup(dns_error_message); | |
511 | err->callback = sslErrorComplete; | |
512 | err->callback_data = sslState; | |
a46d2c0e | 513 | errorSend(sslState->client.fd(), err); |
edeb28fd | 514 | } else if (status != COMM_OK) { |
62e76326 | 515 | err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); |
516 | *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; | |
f3400a93 | 517 | err->xerrno = xerrno; |
62e76326 | 518 | err->host = xstrdup(sslState->host); |
519 | err->port = sslState->port; | |
520 | err->request = requestLink(request); | |
521 | err->callback = sslErrorComplete; | |
522 | err->callback_data = sslState; | |
a46d2c0e | 523 | errorSend(sslState->client.fd(), err); |
fe40a877 | 524 | } else { |
62e76326 | 525 | if (sslState->servers->_peer) |
a46d2c0e | 526 | sslProxyConnected(sslState->server.fd(), sslState); |
62e76326 | 527 | else { |
a46d2c0e | 528 | sslConnected(sslState->server.fd(), sslState); |
62e76326 | 529 | } |
530 | ||
a46d2c0e | 531 | commSetTimeout(sslState->server.fd(), |
62e76326 | 532 | Config.Timeout.read, |
533 | sslTimeout, | |
534 | sslState); | |
983061ed | 535 | } |
983061ed | 536 | } |
30a4f2a8 | 537 | |
770f051d | 538 | void |
d5964d58 | 539 | sslStart(clientHttpRequest * http, size_t * size_ptr, int *status_ptr) |
30a4f2a8 | 540 | { |
541 | /* Create state structure. */ | |
542 | SslStateData *sslState = NULL; | |
543 | int sock; | |
9b312a19 | 544 | ErrorState *err = NULL; |
f1003989 | 545 | int answer; |
98242069 | 546 | int fd = http->getConn()->fd; |
190154cf | 547 | HttpRequest *request = http->request; |
d5964d58 | 548 | char *url = http->uri; |
f1003989 | 549 | /* |
a4b8110e | 550 | * client_addr == no_addr indicates this is an "internal" request |
551 | * from peer_digest.c, asn.c, netdb.c, etc and should always | |
552 | * be allowed. yuck, I know. | |
553 | */ | |
62e76326 | 554 | |
f1003989 | 555 | if (request->client_addr.s_addr != no_addr.s_addr) { |
62e76326 | 556 | /* |
557 | * Check if this host is allowed to fetch MISSES from us (miss_access) | |
558 | */ | |
559 | ACLChecklist ch; | |
560 | ch.src_addr = request->client_addr; | |
561 | ch.my_addr = request->my_addr; | |
562 | ch.my_port = request->my_port; | |
563 | ch.request = requestLink(request); | |
564 | answer = aclCheckFast(Config.accessList.miss, &ch); | |
565 | ||
566 | if (answer == 0) { | |
567 | err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); | |
568 | *status_ptr = HTTP_FORBIDDEN; | |
569 | err->request = requestLink(request); | |
570 | err->src_addr = request->client_addr; | |
571 | errorSend(fd, err); | |
572 | return; | |
573 | } | |
f1003989 | 574 | } |
62e76326 | 575 | |
a3d5953d | 576 | debug(26, 3) ("sslStart: '%s %s'\n", |
62e76326 | 577 | RequestMethodStr[request->method], url); |
83704487 | 578 | statCounter.server.all.requests++; |
579 | statCounter.server.other.requests++; | |
30a4f2a8 | 580 | /* Create socket. */ |
d6827718 | 581 | sock = comm_openex(SOCK_STREAM, |
bdb741f4 | 582 | IPPROTO_TCP, |
62e76326 | 583 | getOutgoingAddr(request), |
584 | 0, | |
585 | COMM_NONBLOCKING, | |
586 | getOutgoingTOS(request), | |
587 | url); | |
588 | ||
30a4f2a8 | 589 | if (sock == COMM_ERROR) { |
62e76326 | 590 | debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); |
591 | err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); | |
592 | *status_ptr = HTTP_INTERNAL_SERVER_ERROR; | |
593 | err->xerrno = errno; | |
594 | err->request = requestLink(request); | |
595 | errorSend(fd, err); | |
596 | return; | |
30a4f2a8 | 597 | } |
62e76326 | 598 | |
a46d2c0e | 599 | sslState = new SslStateData; |
59715b38 | 600 | #if DELAY_POOLS |
62e76326 | 601 | |
a46d2c0e | 602 | sslState->server.setDelayId(DelayId::DelayClient(http)); |
59715b38 | 603 | #endif |
62e76326 | 604 | |
30a4f2a8 | 605 | sslState->url = xstrdup(url); |
606 | sslState->request = requestLink(request); | |
a46d2c0e | 607 | sslState->server.size_ptr = size_ptr; |
974ba0ee | 608 | sslState->status_ptr = status_ptr; |
a46d2c0e | 609 | sslState->client.fd(fd); |
610 | sslState->server.fd(sock); | |
611 | comm_add_close_handler(sslState->server.fd(), | |
62e76326 | 612 | sslServerClosed, |
613 | sslState); | |
a46d2c0e | 614 | comm_add_close_handler(sslState->client.fd(), |
62e76326 | 615 | sslClientClosed, |
616 | sslState); | |
a46d2c0e | 617 | commSetTimeout(sslState->client.fd(), |
62e76326 | 618 | Config.Timeout.lifetime, |
619 | sslTimeout, | |
620 | sslState); | |
a46d2c0e | 621 | commSetTimeout(sslState->server.fd(), |
62e76326 | 622 | Config.Timeout.connect, |
623 | sslTimeout, | |
624 | sslState); | |
b6c0e933 | 625 | peerSelect(request, |
62e76326 | 626 | NULL, |
627 | sslPeerSelectComplete, | |
628 | sslState); | |
adb78bd4 | 629 | /* |
630 | * Disable the client read handler until peer selection is complete | |
631 | * Take control away from client_side.c. | |
632 | */ | |
a46d2c0e | 633 | commSetSelect(sslState->client.fd(), COMM_SELECT_READ, NULL, NULL, 0); |
30a4f2a8 | 634 | } |
98ffb7e4 | 635 | |
b8d8561b | 636 | static void |
b177367b | 637 | sslProxyConnected(int fd, void *data) |
98ffb7e4 | 638 | { |
e6ccf245 | 639 | SslStateData *sslState = (SslStateData *)data; |
e1e72f06 | 640 | MemBuf mb; |
75faaa7a | 641 | HttpHeader hdr_out(hoRequest); |
e1e72f06 | 642 | Packer p; |
b4b5fd95 | 643 | http_state_flags flags; |
a3d5953d | 644 | debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState); |
b4b5fd95 | 645 | memset(&flags, '\0', sizeof(flags)); |
2f2b4d20 | 646 | flags.proxying = sslState->request->flags.proxying; |
e1e72f06 | 647 | memBufDefInit(&mb); |
648 | memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url); | |
649 | httpBuildRequestHeader(sslState->request, | |
62e76326 | 650 | sslState->request, |
651 | NULL, /* StoreEntry */ | |
652 | &hdr_out, | |
653 | flags); /* flags */ | |
e1e72f06 | 654 | packerToMemInit(&p, &mb); |
655 | httpHeaderPackInto(&hdr_out, &p); | |
656 | httpHeaderClean(&hdr_out); | |
657 | packerClean(&p); | |
658 | memBufAppend(&mb, "\r\n", 2); | |
c4b7a5a9 | 659 | |
a46d2c0e | 660 | comm_old_write_mbuf(sslState->server.fd(), mb, sslProxyConnectedWriteDone, sslState); |
c4b7a5a9 | 661 | |
a46d2c0e | 662 | commSetTimeout(sslState->server.fd(), |
62e76326 | 663 | Config.Timeout.read, |
664 | sslTimeout, | |
665 | sslState); | |
98ffb7e4 | 666 | } |
33ea9fff | 667 | |
33ea9fff | 668 | static void |
db1cd23c | 669 | sslPeerSelectComplete(FwdServer * fs, void *data) |
33ea9fff | 670 | { |
e6ccf245 | 671 | SslStateData *sslState = (SslStateData *)data; |
190154cf | 672 | HttpRequest *request = sslState->request; |
deb79f06 | 673 | peer *g = NULL; |
62e76326 | 674 | |
db1cd23c | 675 | if (fs == NULL) { |
62e76326 | 676 | ErrorState *err; |
677 | err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); | |
678 | *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE; | |
679 | err->request = requestLink(sslState->request); | |
680 | err->callback = sslErrorComplete; | |
681 | err->callback_data = sslState; | |
a46d2c0e | 682 | errorSend(sslState->client.fd(), err); |
62e76326 | 683 | return; |
db1cd23c | 684 | } |
62e76326 | 685 | |
64d8034e | 686 | sslState->servers = fs; |
29b8d8d6 | 687 | sslState->host = fs->_peer ? fs->_peer->host : request->host; |
62e76326 | 688 | |
29b8d8d6 | 689 | if (fs->_peer == NULL) { |
62e76326 | 690 | sslState->port = request->port; |
29b8d8d6 | 691 | } else if (fs->_peer->http_port != 0) { |
62e76326 | 692 | sslState->port = fs->_peer->http_port; |
29b8d8d6 | 693 | } else if ((g = peerFindByName(fs->_peer->host))) { |
62e76326 | 694 | sslState->port = g->http_port; |
33ea9fff | 695 | } else { |
62e76326 | 696 | sslState->port = CACHE_HTTP_PORT; |
33ea9fff | 697 | } |
62e76326 | 698 | |
29b8d8d6 | 699 | if (fs->_peer) { |
62e76326 | 700 | sslState->request->peer_login = fs->_peer->login; |
701 | sslState->request->flags.proxying = 1; | |
1f38f50a | 702 | } else { |
62e76326 | 703 | sslState->request->peer_login = NULL; |
704 | sslState->request->flags.proxying = 0; | |
1f38f50a | 705 | } |
62e76326 | 706 | |
59715b38 | 707 | #if DELAY_POOLS |
708 | /* no point using the delayIsNoDelay stuff since ssl is nice and simple */ | |
a46d2c0e | 709 | if (g && g->options.no_delay) |
710 | sslState->server.setDelayId(DelayId()); | |
62e76326 | 711 | |
59715b38 | 712 | #endif |
a46d2c0e | 713 | |
714 | commConnectStart(sslState->server.fd(), | |
62e76326 | 715 | sslState->host, |
716 | sslState->port, | |
717 | sslConnectDone, | |
718 | sslState); | |
33ea9fff | 719 | } |
a46d2c0e | 720 | |
721 | CBDATA_CLASS_INIT(SslStateData); | |
722 | ||
723 | void * | |
724 | SslStateData::operator new (size_t) | |
725 | { | |
726 | CBDATA_INIT_TYPE(SslStateData); | |
727 | SslStateData *result = cbdataAlloc(SslStateData); | |
728 | return result; | |
729 | } | |
730 | ||
731 | void | |
732 | SslStateData::operator delete (void *address) | |
733 | { | |
734 | SslStateData *t = static_cast<SslStateData *>(address); | |
735 | cbdataFree(t); | |
736 | } | |
737 | ||
a46d2c0e | 738 | void |
739 | SslStateData::Connection::fd(int const newFD) | |
740 | { | |
741 | fd_ = newFD; | |
742 | } | |
743 | ||
744 | bool | |
745 | SslStateData::noConnections() const | |
746 | { | |
747 | return (server.fd() == -1) && (client.fd() == -1); | |
748 | } | |
749 | ||
750 | #if DELAY_POOLS | |
751 | void | |
752 | SslStateData::Connection::setDelayId(DelayId const &newDelay) | |
753 | { | |
754 | delayId = newDelay; | |
755 | } | |
756 | ||
757 | #endif |