~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/tunnel.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2006-11-11 10:32:06 UTC
  • Revision ID: james.westby@ubuntu.com-20061111103206-f3p0r9g0vq44rp3r
Tags: upstream-3.0.PRE5
ImportĀ upstreamĀ versionĀ 3.0.PRE5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * $Id: tunnel.cc,v 1.165 2006/09/19 07:56:57 adrian Exp $
 
4
 *
 
5
 * DEBUG: section 26    Secure Sockets Layer Proxy
 
6
 * AUTHOR: Duane Wessels
 
7
 *
 
8
 * SQUID Web Proxy Cache          http://www.squid-cache.org/
 
9
 * ----------------------------------------------------------
 
10
 *
 
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.
 
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
 
32
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 
33
 *
 
34
 */
 
35
 
 
36
#include "squid.h"
 
37
#include "errorpage.h"
 
38
#include "HttpRequest.h"
 
39
#include "fde.h"
 
40
#include "comm.h"
 
41
#include "client_side_request.h"
 
42
#include "ACLChecklist.h"
 
43
#if DELAY_POOLS
 
44
#include "DelayId.h"
 
45
#endif
 
46
#include "client_side.h"
 
47
#include "MemBuf.h"
 
48
#include "http.h"
 
49
 
 
50
class SslStateData
 
51
{
 
52
 
 
53
public:
 
54
 
 
55
    class Connection;
 
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);
 
62
 
 
63
    bool noConnections() const;
 
64
    char *url;
 
65
    char *host;                 /* either request->host or proxy host */
 
66
    u_short port;
 
67
    HttpRequest *request;
 
68
    FwdServer *servers;
 
69
 
 
70
    class Connection
 
71
    {
 
72
 
 
73
    public:
 
74
        Connection() : len (0),buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), fd_(-1){}
 
75
 
 
76
        ~Connection();
 
77
        int const & fd() const { return fd_;}
 
78
 
 
79
        void fd(int const newFD);
 
80
        int bytesWanted(int lower=0, int upper = INT_MAX) const;
 
81
        void bytesIn(int const &);
 
82
#if DELAY_POOLS
 
83
 
 
84
        void setDelayId(DelayId const &);
 
85
#endif
 
86
 
 
87
        void error(int const xerrno);
 
88
        int debugLevelForError(int const xerrno) const;
 
89
        void closeIfOpen();
 
90
        void dataSent (size_t amount);
 
91
        int len;
 
92
        char *buf;
 
93
        size_t *size_ptr;               /* pointer to size in an ConnStateData for logging */
 
94
 
 
95
    private:
 
96
        int fd_;
 
97
#if DELAY_POOLS
 
98
 
 
99
        DelayId delayId;
 
100
#endif
 
101
 
 
102
    };
 
103
 
 
104
    Connection client, server;
 
105
    int *status_ptr;            /* pointer to status for logging */
 
106
    void copyRead(Connection &from, IOCB *completion);
 
107
 
 
108
private:
 
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);
 
115
};
 
116
 
 
117
static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
 
118
 
 
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 *);
 
128
 
 
129
static void
 
130
sslServerClosed(int fd, void *data)
 
131
{
 
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);
 
136
 
 
137
    if (sslState->noConnections())
 
138
        sslStateFree(sslState);
 
139
}
 
140
 
 
141
static void
 
142
sslClientClosed(int fd, void *data)
 
143
{
 
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);
 
148
 
 
149
    if (sslState->noConnections())
 
150
        sslStateFree(sslState);
 
151
}
 
152
 
 
153
static void
 
154
sslStateFree(SslStateData * sslState)
 
155
{
 
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);
 
163
    delete sslState;
 
164
}
 
165
 
 
166
SslStateData::Connection::~Connection()
 
167
{
 
168
    safe_free (buf);
 
169
}
 
170
 
 
171
int
 
172
SslStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
 
173
{
 
174
#if DELAY_POOLS
 
175
    return delayId.bytesWanted(lowerbound, upperbound);
 
176
#else
 
177
 
 
178
    return upperbound;
 
179
#endif
 
180
}
 
181
 
 
182
void
 
183
SslStateData::Connection::bytesIn(int const &count)
 
184
{
 
185
#if DELAY_POOLS
 
186
    delayId.bytesIn(count);
 
187
#endif
 
188
 
 
189
    len += count;
 
190
}
 
191
 
 
192
int
 
193
SslStateData::Connection::debugLevelForError(int const xerrno) const
 
194
{
 
195
#ifdef ECONNRESET
 
196
 
 
197
    if (xerrno == ECONNRESET)
 
198
        return 2;
 
199
 
 
200
#endif
 
201
 
 
202
    if (ignoreErrno(xerrno))
 
203
        return 3;
 
204
 
 
205
    return 1;
 
206
}
 
207
 
 
208
/* Read from server side and queue it for writing to the client */
 
209
void
 
210
SslStateData::ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
 
211
{
 
212
    SslStateData *sslState = (SslStateData *)data;
 
213
    assert (cbdataReferenceValid (sslState));
 
214
 
 
215
    assert(fd == sslState->server.fd());
 
216
    sslState->readServer(buf, len, errcode, xerrno);
 
217
}
 
218
 
 
219
void
 
220
SslStateData::readServer(char *buf, size_t len, comm_err_t errcode, int xerrno)
 
221
{
 
222
    /*
 
223
     * Bail out early on COMM_ERR_CLOSING
 
224
     * - close handlers will tidy up for us 
 
225
     */
 
226
 
 
227
    if (errcode == COMM_ERR_CLOSING)
 
228
        return;
 
229
 
 
230
    debug(26, 3) ("sslReadServer: FD %d, read   %d bytes\n", server.fd(), (int)len);
 
231
 
 
232
    if (len > 0) {
 
233
        server.bytesIn(len);
 
234
        kb_incr(&statCounter.server.all.kbytes_in, len);
 
235
        kb_incr(&statCounter.server.other.kbytes_in, len);
 
236
    }
 
237
 
 
238
    copy (len, errcode, xerrno, server, client, WriteClientDone);
 
239
}
 
240
 
 
241
void
 
242
SslStateData::Connection::error(int const xerrno)
 
243
{
 
244
    /* XXX fixme xstrerror and xerrno... */
 
245
    errno = xerrno;
 
246
 
 
247
    if (xerrno == COMM_ERR_CLOSING)
 
248
        return;
 
249
 
 
250
    debug(50, debugLevelForError(xerrno))
 
251
    ("sslReadServer: FD %d: read failure: %s\n", fd(), xstrerror());
 
252
 
 
253
    if (!ignoreErrno(xerrno))
 
254
        comm_close(fd());
 
255
}
 
256
 
 
257
/* Read from client side and queue it for writing to the server */
 
258
void
 
259
SslStateData::ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
 
260
{
 
261
    SslStateData *sslState = (SslStateData *)data;
 
262
    assert (cbdataReferenceValid (sslState));
 
263
 
 
264
    assert(fd == sslState->client.fd());
 
265
    sslState->readClient(buf, len, errcode, xerrno);
 
266
}
 
267
 
 
268
void
 
269
SslStateData::readClient(char *buf, size_t len, comm_err_t errcode, int xerrno)
 
270
{
 
271
    /*
 
272
     * Bail out early on COMM_ERR_CLOSING
 
273
     * - close handlers will tidy up for us 
 
274
     */
 
275
 
 
276
    if (errcode == COMM_ERR_CLOSING)
 
277
        return;
 
278
 
 
279
    debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", client.fd(), (int) len);
 
280
 
 
281
    if (len > 0) {
 
282
        client.bytesIn(len);
 
283
        kb_incr(&statCounter.client_http.kbytes_in, len);
 
284
    }
 
285
 
 
286
    copy (len, errcode, xerrno, client, server, WriteServerDone);
 
287
}
 
288
 
 
289
void
 
290
SslStateData::copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOCB *completion)
 
291
{
 
292
    /* I think this is to prevent free-while-in-a-callback behaviour
 
293
     * - RBC 20030229 
 
294
     */
 
295
    cbdataInternalLock(this);   /* ??? should be locked by the caller... */
 
296
 
 
297
    if (len < 0 || errcode)
 
298
        from.error (xerrno);
 
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 */
 
302
 
 
303
        if (from.len == 0 && to.fd() != -1) {
 
304
            comm_close(to.fd());
 
305
        }
 
306
    } else if (cbdataReferenceValid(this))
 
307
        comm_write(to.fd(), from.buf, len, completion, this, NULL);
 
308
 
 
309
    cbdataInternalUnlock(this); /* ??? */
 
310
}
 
311
 
 
312
/* Writes data from the client buffer to the server side */
 
313
void
 
314
SslStateData::WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
 
315
{
 
316
    SslStateData *sslState = (SslStateData *)data;
 
317
    assert (cbdataReferenceValid (sslState));
 
318
 
 
319
    assert(fd == sslState->server.fd());
 
320
    sslState->writeServerDone(buf, len, flag, xerrno);
 
321
}
 
322
 
 
323
void
 
324
SslStateData::writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno)
 
325
{
 
326
    debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", server.fd(), (int)len);
 
327
    /* Valid data */
 
328
 
 
329
    if (len > 0) {
 
330
        kb_incr(&statCounter.server.all.kbytes_out, len);
 
331
        kb_incr(&statCounter.server.other.kbytes_out, len);
 
332
        client.dataSent(len);
 
333
    }
 
334
 
 
335
    /* EOF */
 
336
    if (len == 0) {
 
337
        comm_close(server.fd());
 
338
        return;
 
339
    }
 
340
 
 
341
    /* If the other end has closed, so should we */
 
342
    if (client.fd() == -1) {
 
343
        comm_close(server.fd());
 
344
        return;
 
345
    }
 
346
 
 
347
    cbdataInternalLock(this);   /* ??? should be locked by the caller... */
 
348
    /* Error? */
 
349
 
 
350
    if (len < 0)
 
351
        server.error(xerrno);
 
352
    else if (cbdataReferenceValid(this))
 
353
        copyRead(client, ReadClient);
 
354
 
 
355
    cbdataInternalUnlock(this); /* ??? */
 
356
}
 
357
 
 
358
/* Writes data from the server buffer to the client side */
 
359
void
 
360
SslStateData::WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
 
361
{
 
362
    SslStateData *sslState = (SslStateData *)data;
 
363
    assert (cbdataReferenceValid (sslState));
 
364
 
 
365
    assert(fd == sslState->client.fd());
 
366
    sslState->writeClientDone(buf, len, flag, xerrno);
 
367
}
 
368
 
 
369
void
 
370
SslStateData::Connection::dataSent (size_t amount)
 
371
{
 
372
    assert(amount == (size_t)len);
 
373
    len =0;
 
374
    /* increment total object size */
 
375
 
 
376
    if (size_ptr)
 
377
        *size_ptr += amount;
 
378
}
 
379
 
 
380
void
 
381
SslStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno)
 
382
{
 
383
    debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", client.fd(), (int)len);
 
384
 
 
385
    if (len > 0) {
 
386
        kb_incr(&statCounter.client_http.kbytes_out, len);
 
387
        server.dataSent(len);
 
388
    }
 
389
 
 
390
    /* EOF */
 
391
    if (len == 0) {
 
392
        comm_close(client.fd());
 
393
        return;
 
394
    }
 
395
 
 
396
    /* If the other end has closed, so should we */
 
397
    if (server.fd() == -1) {
 
398
        comm_close(client.fd());
 
399
        return;
 
400
    }
 
401
 
 
402
    cbdataInternalLock(this);   /* ??? should be locked by the caller... */
 
403
    /* Error? */
 
404
 
 
405
    if (len < 0)
 
406
        client.error(xerrno);
 
407
    else if (cbdataReferenceValid(this))
 
408
        copyRead(server, ReadServer);
 
409
 
 
410
    cbdataInternalUnlock(this); /* ??? */
 
411
}
 
412
 
 
413
static void
 
414
sslTimeout(int fd, void *data)
 
415
{
 
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);
 
420
 
 
421
    sslState->client.closeIfOpen();
 
422
    sslState->server.closeIfOpen();
 
423
    cbdataInternalUnlock(sslState);
 
424
}
 
425
 
 
426
void
 
427
SslStateData::Connection::closeIfOpen()
 
428
{
 
429
    if (fd() != -1)
 
430
        comm_close(fd());
 
431
}
 
432
 
 
433
void
 
434
SslStateData::copyRead(Connection &from, IOCB *completion)
 
435
{
 
436
    assert(from.len == 0);
 
437
    comm_read(from.fd(), from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), completion, this);
 
438
}
 
439
 
 
440
static void
 
441
sslConnectTimeout(int fd, void *data)
 
442
{
 
443
    SslStateData *sslState = (SslStateData *)data;
 
444
    HttpRequest *request = sslState->request;
 
445
    ErrorState *err = NULL;
 
446
 
 
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);
 
453
    else
 
454
        hierarchyNote(&sslState->request->hier, sslState->servers->code,
 
455
                      sslState->host);
 
456
 
 
457
    comm_close(fd);
 
458
 
 
459
    err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
 
460
 
 
461
    *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
 
462
 
 
463
    err->xerrno = ETIMEDOUT;
 
464
 
 
465
    err->port = sslState->port;
 
466
 
 
467
    err->callback = sslErrorComplete;
 
468
 
 
469
    err->callback_data = sslState;
 
470
 
 
471
    errorSend(sslState->client.fd(), err);
 
472
}
 
473
 
 
474
static void
 
475
sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
 
476
{
 
477
    SslStateData *sslState = (SslStateData *)data;
 
478
 
 
479
    if (flag != COMM_OK) {
 
480
        sslErrorComplete(fd, data, 0);
 
481
        return;
 
482
    }
 
483
 
 
484
    if (cbdataReferenceValid(sslState)) {
 
485
        sslState->copyRead(sslState->server, SslStateData::ReadServer);
 
486
        sslState->copyRead(sslState->client, SslStateData::ReadClient);
 
487
    }
 
488
}
 
489
 
 
490
/*
 
491
 * handle the write completion from a proxy request to an upstream proxy
 
492
 */
 
493
static void
 
494
sslProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
 
495
{
 
496
    sslConnectedWriteDone(fd, buf, size, flag, xerrno, data);
 
497
}
 
498
 
 
499
static void
 
500
sslConnected(int fd, void *data)
 
501
{
 
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);
 
507
}
 
508
 
 
509
static void
 
510
sslErrorComplete(int fdnotused, void *data, size_t sizenotused)
 
511
{
 
512
    SslStateData *sslState = (SslStateData *)data;
 
513
    assert(sslState != NULL);
 
514
    /* temporary lock to save our own feets (comm_close -> sslClientClosed -> Free) */
 
515
    cbdataInternalLock(sslState);
 
516
 
 
517
    if (sslState->client.fd() > -1)
 
518
        comm_close(sslState->client.fd());
 
519
 
 
520
    if (sslState->server.fd() > -1)
 
521
        comm_close(sslState->server.fd());
 
522
 
 
523
    cbdataInternalUnlock(sslState);
 
524
}
 
525
 
 
526
 
 
527
static void
 
528
sslConnectDone(int fdnotused, comm_err_t status, int xerrno, void *data)
 
529
{
 
530
    SslStateData *sslState = (SslStateData *)data;
 
531
    HttpRequest *request = sslState->request;
 
532
    ErrorState *err = NULL;
 
533
 
 
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);
 
540
    else
 
541
        hierarchyNote(&sslState->request->hier, sslState->servers->code,
 
542
                      sslState->host);
 
543
 
 
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);
 
560
    } else {
 
561
        if (sslState->servers->_peer)
 
562
            sslProxyConnected(sslState->server.fd(), sslState);
 
563
        else {
 
564
            sslConnected(sslState->server.fd(), sslState);
 
565
        }
 
566
 
 
567
        commSetTimeout(sslState->server.fd(),
 
568
                       Config.Timeout.read,
 
569
                       sslTimeout,
 
570
                       sslState);
 
571
    }
 
572
}
 
573
 
 
574
void
 
575
sslStart(ClientHttpRequest * http, size_t * size_ptr, int *status_ptr)
 
576
{
 
577
    /* Create state structure. */
 
578
    SslStateData *sslState = NULL;
 
579
    int sock;
 
580
    ErrorState *err = NULL;
 
581
    int answer;
 
582
    int fd = http->getConn()->fd;
 
583
    HttpRequest *request = http->request;
 
584
    char *url = http->uri;
 
585
    /*
 
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.
 
589
     */
 
590
 
 
591
    if (request->client_addr.s_addr != no_addr.s_addr) {
 
592
        /*
 
593
         * Check if this host is allowed to fetch MISSES from us (miss_access)
 
594
         */
 
595
        ACLChecklist ch;
 
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();
 
603
 
 
604
        if (answer == 0) {
 
605
            err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN, request);
 
606
            *status_ptr = HTTP_FORBIDDEN;
 
607
            errorSend(fd, err);
 
608
            return;
 
609
        }
 
610
    }
 
611
 
 
612
    debug(26, 3) ("sslStart: '%s %s'\n",
 
613
                  RequestMethodStr[request->method], url);
 
614
    statCounter.server.all.requests++;
 
615
    statCounter.server.other.requests++;
 
616
    /* Create socket. */
 
617
    sock = comm_openex(SOCK_STREAM,
 
618
                       IPPROTO_TCP,
 
619
                       getOutgoingAddr(request),
 
620
                       0,
 
621
                       COMM_NONBLOCKING,
 
622
                       getOutgoingTOS(request),
 
623
                       url);
 
624
 
 
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;
 
629
        err->xerrno = errno;
 
630
        errorSend(fd, err);
 
631
        return;
 
632
    }
 
633
 
 
634
    sslState = new SslStateData;
 
635
#if DELAY_POOLS
 
636
 
 
637
    sslState->server.setDelayId(DelayId::DelayClient(http));
 
638
#endif
 
639
 
 
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(),
 
647
                           sslServerClosed,
 
648
                           sslState);
 
649
    comm_add_close_handler(sslState->client.fd(),
 
650
                           sslClientClosed,
 
651
                           sslState);
 
652
    commSetTimeout(sslState->client.fd(),
 
653
                   Config.Timeout.lifetime,
 
654
                   sslTimeout,
 
655
                   sslState);
 
656
    commSetTimeout(sslState->server.fd(),
 
657
                   Config.Timeout.connect,
 
658
                   sslConnectTimeout,
 
659
                   sslState);
 
660
    peerSelect(request,
 
661
               NULL,
 
662
               sslPeerSelectComplete,
 
663
               sslState);
 
664
    /*
 
665
     * Disable the client read handler until peer selection is complete
 
666
     * Take control away from client_side.c.
 
667
     */
 
668
    commSetSelect(sslState->client.fd(), COMM_SELECT_READ, NULL, NULL, 0);
 
669
}
 
670
 
 
671
static void
 
672
sslProxyConnected(int fd, void *data)
 
673
{
 
674
    SslStateData *sslState = (SslStateData *)data;
 
675
    HttpHeader hdr_out(hoRequest);
 
676
    Packer p;
 
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;
 
681
    MemBuf mb;
 
682
    mb.init();
 
683
    mb.Printf("CONNECT %s HTTP/1.0\r\n", sslState->url);
 
684
    HttpStateData::httpBuildRequestHeader(sslState->request,
 
685
                                          sslState->request,
 
686
                                          NULL,                 /* StoreEntry */
 
687
                                          &hdr_out,
 
688
                                          flags);                       /* flags */
 
689
    packerToMemInit(&p, &mb);
 
690
    hdr_out.packInto(&p);
 
691
    hdr_out.clean();
 
692
    packerClean(&p);
 
693
    mb.append("\r\n", 2);
 
694
 
 
695
    comm_write_mbuf(sslState->server.fd(), &mb, sslProxyConnectedWriteDone, sslState);
 
696
    commSetTimeout(sslState->server.fd(), Config.Timeout.read, sslTimeout, sslState);
 
697
}
 
698
 
 
699
static void
 
700
sslPeerSelectComplete(FwdServer * fs, void *data)
 
701
{
 
702
    SslStateData *sslState = (SslStateData *)data;
 
703
    HttpRequest *request = sslState->request;
 
704
    peer *g = NULL;
 
705
 
 
706
    if (fs == NULL) {
 
707
        ErrorState *err;
 
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);
 
713
        return;
 
714
    }
 
715
 
 
716
    sslState->servers = fs;
 
717
    sslState->host = fs->_peer ? fs->_peer->host : request->host;
 
718
 
 
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;
 
725
    } else {
 
726
        sslState->port = CACHE_HTTP_PORT;
 
727
    }
 
728
 
 
729
    if (fs->_peer) {
 
730
        sslState->request->peer_login = fs->_peer->login;
 
731
        sslState->request->flags.proxying = 1;
 
732
    } else {
 
733
        sslState->request->peer_login = NULL;
 
734
        sslState->request->flags.proxying = 0;
 
735
    }
 
736
 
 
737
#if DELAY_POOLS
 
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());
 
741
 
 
742
#endif
 
743
 
 
744
    commConnectStart(sslState->server.fd(),
 
745
                     sslState->host,
 
746
                     sslState->port,
 
747
                     sslConnectDone,
 
748
                     sslState);
 
749
}
 
750
 
 
751
CBDATA_CLASS_INIT(SslStateData);
 
752
 
 
753
void *
 
754
SslStateData::operator new (size_t)
 
755
{
 
756
    CBDATA_INIT_TYPE(SslStateData);
 
757
    SslStateData *result = cbdataAlloc(SslStateData);
 
758
    return result;
 
759
}
 
760
 
 
761
void
 
762
SslStateData::operator delete (void *address)
 
763
{
 
764
    SslStateData *t = static_cast<SslStateData *>(address);
 
765
    cbdataFree(t);
 
766
}
 
767
 
 
768
void
 
769
SslStateData::Connection::fd(int const newFD)
 
770
{
 
771
    fd_ = newFD;
 
772
}
 
773
 
 
774
bool
 
775
SslStateData::noConnections() const
 
776
{
 
777
    return (server.fd() == -1) && (client.fd() == -1);
 
778
}
 
779
 
 
780
#if DELAY_POOLS
 
781
void
 
782
SslStateData::Connection::setDelayId(DelayId const &newDelay)
 
783
{
 
784
    delayId = newDelay;
 
785
}
 
786
 
 
787
#endif