3
* $Id: tunnel.cc,v 1.165 2006/09/19 07:56:57 adrian Exp $
5
* DEBUG: section 26 Secure Sockets Layer Proxy
6
* AUTHOR: Duane Wessels
8
* SQUID Web Proxy Cache http://www.squid-cache.org/
9
* ----------------------------------------------------------
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.
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.
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.
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
32
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37
#include "errorpage.h"
38
#include "HttpRequest.h"
41
#include "client_side_request.h"
42
#include "ACLChecklist.h"
46
#include "client_side.h"
56
void *operator new(size_t);
57
void operator delete (void *);
58
static void ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data);
59
static void ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data);
60
static void WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data);
61
static void WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data);
63
bool noConnections() const;
65
char *host; /* either request->host or proxy host */
74
Connection() : len (0),buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), fd_(-1){}
77
int const & fd() const { return fd_;}
79
void fd(int const newFD);
80
int bytesWanted(int lower=0, int upper = INT_MAX) const;
81
void bytesIn(int const &);
84
void setDelayId(DelayId const &);
87
void error(int const xerrno);
88
int debugLevelForError(int const xerrno) const;
90
void dataSent (size_t amount);
93
size_t *size_ptr; /* pointer to size in an ConnStateData for logging */
104
Connection client, server;
105
int *status_ptr; /* pointer to status for logging */
106
void copyRead(Connection &from, IOCB *completion);
109
CBDATA_CLASS(SslStateData);
110
void copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOCB *);
111
void readServer(char *buf, size_t len, comm_err_t errcode, int xerrno);
112
void readClient(char *buf, size_t len, comm_err_t errcode, int xerrno);
113
void writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno);
114
void writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno);
117
static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
119
static CNCB sslConnectDone;
120
static ERCB sslErrorComplete;
121
static PF sslServerClosed;
122
static PF sslClientClosed;
123
static PF sslTimeout;
124
static PSC sslPeerSelectComplete;
125
static void sslStateFree(SslStateData * sslState);
126
static void sslConnected(int fd, void *);
127
static void sslProxyConnected(int fd, void *);
130
sslServerClosed(int fd, void *data)
132
SslStateData *sslState = (SslStateData *)data;
133
debug(26, 3) ("sslServerClosed: FD %d\n", fd);
134
assert(fd == sslState->server.fd());
135
sslState->server.fd(-1);
137
if (sslState->noConnections())
138
sslStateFree(sslState);
142
sslClientClosed(int fd, void *data)
144
SslStateData *sslState = (SslStateData *)data;
145
debug(26, 3) ("sslClientClosed: FD %d\n", fd);
146
assert(fd == sslState->client.fd());
147
sslState->client.fd(-1);
149
if (sslState->noConnections())
150
sslStateFree(sslState);
154
sslStateFree(SslStateData * sslState)
156
debug(26, 3) ("sslStateFree: sslState=%p\n", sslState);
157
assert(sslState != NULL);
158
assert(sslState->noConnections());
159
safe_free(sslState->url);
160
FwdState::serversFree(&sslState->servers);
161
sslState->host = NULL;
162
HTTPMSGUNLOCK(sslState->request);
166
SslStateData::Connection::~Connection()
172
SslStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
175
return delayId.bytesWanted(lowerbound, upperbound);
183
SslStateData::Connection::bytesIn(int const &count)
186
delayId.bytesIn(count);
193
SslStateData::Connection::debugLevelForError(int const xerrno) const
197
if (xerrno == ECONNRESET)
202
if (ignoreErrno(xerrno))
208
/* Read from server side and queue it for writing to the client */
210
SslStateData::ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
212
SslStateData *sslState = (SslStateData *)data;
213
assert (cbdataReferenceValid (sslState));
215
assert(fd == sslState->server.fd());
216
sslState->readServer(buf, len, errcode, xerrno);
220
SslStateData::readServer(char *buf, size_t len, comm_err_t errcode, int xerrno)
223
* Bail out early on COMM_ERR_CLOSING
224
* - close handlers will tidy up for us
227
if (errcode == COMM_ERR_CLOSING)
230
debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", server.fd(), (int)len);
234
kb_incr(&statCounter.server.all.kbytes_in, len);
235
kb_incr(&statCounter.server.other.kbytes_in, len);
238
copy (len, errcode, xerrno, server, client, WriteClientDone);
242
SslStateData::Connection::error(int const xerrno)
244
/* XXX fixme xstrerror and xerrno... */
247
if (xerrno == COMM_ERR_CLOSING)
250
debug(50, debugLevelForError(xerrno))
251
("sslReadServer: FD %d: read failure: %s\n", fd(), xstrerror());
253
if (!ignoreErrno(xerrno))
257
/* Read from client side and queue it for writing to the server */
259
SslStateData::ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
261
SslStateData *sslState = (SslStateData *)data;
262
assert (cbdataReferenceValid (sslState));
264
assert(fd == sslState->client.fd());
265
sslState->readClient(buf, len, errcode, xerrno);
269
SslStateData::readClient(char *buf, size_t len, comm_err_t errcode, int xerrno)
272
* Bail out early on COMM_ERR_CLOSING
273
* - close handlers will tidy up for us
276
if (errcode == COMM_ERR_CLOSING)
279
debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", client.fd(), (int) len);
283
kb_incr(&statCounter.client_http.kbytes_in, len);
286
copy (len, errcode, xerrno, client, server, WriteServerDone);
290
SslStateData::copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOCB *completion)
292
/* I think this is to prevent free-while-in-a-callback behaviour
295
cbdataInternalLock(this); /* ??? should be locked by the caller... */
297
if (len < 0 || errcode)
299
else if (len == 0 || to.fd() == -1) {
300
comm_close(from.fd());
301
/* Only close the remote end if we've finished queueing data to it */
303
if (from.len == 0 && to.fd() != -1) {
306
} else if (cbdataReferenceValid(this))
307
comm_write(to.fd(), from.buf, len, completion, this, NULL);
309
cbdataInternalUnlock(this); /* ??? */
312
/* Writes data from the client buffer to the server side */
314
SslStateData::WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
316
SslStateData *sslState = (SslStateData *)data;
317
assert (cbdataReferenceValid (sslState));
319
assert(fd == sslState->server.fd());
320
sslState->writeServerDone(buf, len, flag, xerrno);
324
SslStateData::writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno)
326
debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", server.fd(), (int)len);
330
kb_incr(&statCounter.server.all.kbytes_out, len);
331
kb_incr(&statCounter.server.other.kbytes_out, len);
332
client.dataSent(len);
337
comm_close(server.fd());
341
/* If the other end has closed, so should we */
342
if (client.fd() == -1) {
343
comm_close(server.fd());
347
cbdataInternalLock(this); /* ??? should be locked by the caller... */
351
server.error(xerrno);
352
else if (cbdataReferenceValid(this))
353
copyRead(client, ReadClient);
355
cbdataInternalUnlock(this); /* ??? */
358
/* Writes data from the server buffer to the client side */
360
SslStateData::WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
362
SslStateData *sslState = (SslStateData *)data;
363
assert (cbdataReferenceValid (sslState));
365
assert(fd == sslState->client.fd());
366
sslState->writeClientDone(buf, len, flag, xerrno);
370
SslStateData::Connection::dataSent (size_t amount)
372
assert(amount == (size_t)len);
374
/* increment total object size */
381
SslStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno)
383
debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", client.fd(), (int)len);
386
kb_incr(&statCounter.client_http.kbytes_out, len);
387
server.dataSent(len);
392
comm_close(client.fd());
396
/* If the other end has closed, so should we */
397
if (server.fd() == -1) {
398
comm_close(client.fd());
402
cbdataInternalLock(this); /* ??? should be locked by the caller... */
406
client.error(xerrno);
407
else if (cbdataReferenceValid(this))
408
copyRead(server, ReadServer);
410
cbdataInternalUnlock(this); /* ??? */
414
sslTimeout(int fd, void *data)
416
SslStateData *sslState = (SslStateData *)data;
417
debug(26, 3) ("sslTimeout: FD %d\n", fd);
418
/* Temporary lock to protect our own feets (comm_close -> sslClientClosed -> Free) */
419
cbdataInternalLock(sslState);
421
sslState->client.closeIfOpen();
422
sslState->server.closeIfOpen();
423
cbdataInternalUnlock(sslState);
427
SslStateData::Connection::closeIfOpen()
434
SslStateData::copyRead(Connection &from, IOCB *completion)
436
assert(from.len == 0);
437
comm_read(from.fd(), from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), completion, this);
441
sslConnectTimeout(int fd, void *data)
443
SslStateData *sslState = (SslStateData *)data;
444
HttpRequest *request = sslState->request;
445
ErrorState *err = NULL;
447
if (sslState->servers->_peer)
448
hierarchyNote(&sslState->request->hier, sslState->servers->code,
449
sslState->servers->_peer->host);
450
else if (Config.onoff.log_ip_on_direct)
451
hierarchyNote(&sslState->request->hier, sslState->servers->code,
452
fd_table[sslState->server.fd()].ipaddr);
454
hierarchyNote(&sslState->request->hier, sslState->servers->code,
459
err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
461
*sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
463
err->xerrno = ETIMEDOUT;
465
err->port = sslState->port;
467
err->callback = sslErrorComplete;
469
err->callback_data = sslState;
471
errorSend(sslState->client.fd(), err);
475
sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
477
SslStateData *sslState = (SslStateData *)data;
479
if (flag != COMM_OK) {
480
sslErrorComplete(fd, data, 0);
484
if (cbdataReferenceValid(sslState)) {
485
sslState->copyRead(sslState->server, SslStateData::ReadServer);
486
sslState->copyRead(sslState->client, SslStateData::ReadClient);
491
* handle the write completion from a proxy request to an upstream proxy
494
sslProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
496
sslConnectedWriteDone(fd, buf, size, flag, xerrno, data);
500
sslConnected(int fd, void *data)
502
SslStateData *sslState = (SslStateData *)data;
503
debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState);
504
*sslState->status_ptr = HTTP_OK;
505
comm_write(sslState->client.fd(), conn_established, strlen(conn_established),
506
sslConnectedWriteDone, sslState, NULL);
510
sslErrorComplete(int fdnotused, void *data, size_t sizenotused)
512
SslStateData *sslState = (SslStateData *)data;
513
assert(sslState != NULL);
514
/* temporary lock to save our own feets (comm_close -> sslClientClosed -> Free) */
515
cbdataInternalLock(sslState);
517
if (sslState->client.fd() > -1)
518
comm_close(sslState->client.fd());
520
if (sslState->server.fd() > -1)
521
comm_close(sslState->server.fd());
523
cbdataInternalUnlock(sslState);
528
sslConnectDone(int fdnotused, comm_err_t status, int xerrno, void *data)
530
SslStateData *sslState = (SslStateData *)data;
531
HttpRequest *request = sslState->request;
532
ErrorState *err = NULL;
534
if (sslState->servers->_peer)
535
hierarchyNote(&sslState->request->hier, sslState->servers->code,
536
sslState->servers->_peer->host);
537
else if (Config.onoff.log_ip_on_direct)
538
hierarchyNote(&sslState->request->hier, sslState->servers->code,
539
fd_table[sslState->server.fd()].ipaddr);
541
hierarchyNote(&sslState->request->hier, sslState->servers->code,
544
if (status == COMM_ERR_DNS) {
545
debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host);
546
err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND, request);
547
*sslState->status_ptr = HTTP_NOT_FOUND;
548
err->dnsserver_msg = xstrdup(dns_error_message);
549
err->callback = sslErrorComplete;
550
err->callback_data = sslState;
551
errorSend(sslState->client.fd(), err);
552
} else if (status != COMM_OK) {
553
err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
554
*sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
555
err->xerrno = xerrno;
556
err->port = sslState->port;
557
err->callback = sslErrorComplete;
558
err->callback_data = sslState;
559
errorSend(sslState->client.fd(), err);
561
if (sslState->servers->_peer)
562
sslProxyConnected(sslState->server.fd(), sslState);
564
sslConnected(sslState->server.fd(), sslState);
567
commSetTimeout(sslState->server.fd(),
575
sslStart(ClientHttpRequest * http, size_t * size_ptr, int *status_ptr)
577
/* Create state structure. */
578
SslStateData *sslState = NULL;
580
ErrorState *err = NULL;
582
int fd = http->getConn()->fd;
583
HttpRequest *request = http->request;
584
char *url = http->uri;
586
* client_addr == no_addr indicates this is an "internal" request
587
* from peer_digest.c, asn.c, netdb.c, etc and should always
588
* be allowed. yuck, I know.
591
if (request->client_addr.s_addr != no_addr.s_addr) {
593
* Check if this host is allowed to fetch MISSES from us (miss_access)
596
ch.src_addr = request->client_addr;
597
ch.my_addr = request->my_addr;
598
ch.my_port = request->my_port;
599
ch.request = HTTPMSGLOCK(request);
600
ch.accessList = cbdataReference(Config.accessList.miss);
601
/* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
602
answer = ch.fastCheck();
605
err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN, request);
606
*status_ptr = HTTP_FORBIDDEN;
612
debug(26, 3) ("sslStart: '%s %s'\n",
613
RequestMethodStr[request->method], url);
614
statCounter.server.all.requests++;
615
statCounter.server.other.requests++;
617
sock = comm_openex(SOCK_STREAM,
619
getOutgoingAddr(request),
622
getOutgoingTOS(request),
625
if (sock == COMM_ERROR) {
626
debug(26, 4) ("sslStart: Failed because we're out of sockets.\n");
627
err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
628
*status_ptr = HTTP_INTERNAL_SERVER_ERROR;
634
sslState = new SslStateData;
637
sslState->server.setDelayId(DelayId::DelayClient(http));
640
sslState->url = xstrdup(url);
641
sslState->request = HTTPMSGLOCK(request);
642
sslState->server.size_ptr = size_ptr;
643
sslState->status_ptr = status_ptr;
644
sslState->client.fd(fd);
645
sslState->server.fd(sock);
646
comm_add_close_handler(sslState->server.fd(),
649
comm_add_close_handler(sslState->client.fd(),
652
commSetTimeout(sslState->client.fd(),
653
Config.Timeout.lifetime,
656
commSetTimeout(sslState->server.fd(),
657
Config.Timeout.connect,
662
sslPeerSelectComplete,
665
* Disable the client read handler until peer selection is complete
666
* Take control away from client_side.c.
668
commSetSelect(sslState->client.fd(), COMM_SELECT_READ, NULL, NULL, 0);
672
sslProxyConnected(int fd, void *data)
674
SslStateData *sslState = (SslStateData *)data;
675
HttpHeader hdr_out(hoRequest);
677
http_state_flags flags;
678
debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState);
679
memset(&flags, '\0', sizeof(flags));
680
flags.proxying = sslState->request->flags.proxying;
683
mb.Printf("CONNECT %s HTTP/1.0\r\n", sslState->url);
684
HttpStateData::httpBuildRequestHeader(sslState->request,
686
NULL, /* StoreEntry */
689
packerToMemInit(&p, &mb);
690
hdr_out.packInto(&p);
693
mb.append("\r\n", 2);
695
comm_write_mbuf(sslState->server.fd(), &mb, sslProxyConnectedWriteDone, sslState);
696
commSetTimeout(sslState->server.fd(), Config.Timeout.read, sslTimeout, sslState);
700
sslPeerSelectComplete(FwdServer * fs, void *data)
702
SslStateData *sslState = (SslStateData *)data;
703
HttpRequest *request = sslState->request;
708
err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
709
*sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
710
err->callback = sslErrorComplete;
711
err->callback_data = sslState;
712
errorSend(sslState->client.fd(), err);
716
sslState->servers = fs;
717
sslState->host = fs->_peer ? fs->_peer->host : request->host;
719
if (fs->_peer == NULL) {
720
sslState->port = request->port;
721
} else if (fs->_peer->http_port != 0) {
722
sslState->port = fs->_peer->http_port;
723
} else if ((g = peerFindByName(fs->_peer->host))) {
724
sslState->port = g->http_port;
726
sslState->port = CACHE_HTTP_PORT;
730
sslState->request->peer_login = fs->_peer->login;
731
sslState->request->flags.proxying = 1;
733
sslState->request->peer_login = NULL;
734
sslState->request->flags.proxying = 0;
738
/* no point using the delayIsNoDelay stuff since ssl is nice and simple */
739
if (g && g->options.no_delay)
740
sslState->server.setDelayId(DelayId());
744
commConnectStart(sslState->server.fd(),
751
CBDATA_CLASS_INIT(SslStateData);
754
SslStateData::operator new (size_t)
756
CBDATA_INIT_TYPE(SslStateData);
757
SslStateData *result = cbdataAlloc(SslStateData);
762
SslStateData::operator delete (void *address)
764
SslStateData *t = static_cast<SslStateData *>(address);
769
SslStateData::Connection::fd(int const newFD)
775
SslStateData::noConnections() const
777
return (server.fd() == -1) && (client.fd() == -1);
782
SslStateData::Connection::setDelayId(DelayId const &newDelay)