]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/PeerConnector.cc
Fixed chunked parsing by mimicking psChunkEnd state removed in trunk r14108.
[thirdparty/squid.git] / src / ssl / PeerConnector.cc
CommitLineData
a23223bf 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
a23223bf 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
a23223bf
CT
7 */
8
bbc27441
AJ
9/* DEBUG: section 17 Request Forwarding */
10
a23223bf
CT
11#include "squid.h"
12#include "acl/FilledChecklist.h"
13#include "base/AsyncCbdataCalls.h"
14#include "CachePeer.h"
15#include "client_side.h"
16#include "comm/Loops.h"
17#include "errorpage.h"
18#include "fde.h"
19#include "globals.h"
24438ec5 20#include "helper/ResultCode.h"
a23223bf
CT
21#include "HttpRequest.h"
22#include "neighbors.h"
7f4e9b73 23#include "SquidConfig.h"
31855516 24#include "ssl/bio.h"
a23223bf
CT
25#include "ssl/cert_validate_message.h"
26#include "ssl/Config.h"
27#include "ssl/ErrorDetail.h"
28#include "ssl/helper.h"
29#include "ssl/PeerConnector.h"
30#include "ssl/ServerBump.h"
31#include "ssl/support.h"
a23223bf
CT
32
33CBDATA_NAMESPACED_CLASS_INIT(Ssl, PeerConnector);
1b091aec
CT
34CBDATA_NAMESPACED_CLASS_INIT(Ssl, BlindPeerConnector);
35CBDATA_NAMESPACED_CLASS_INIT(Ssl, PeekingPeerConnector);
a23223bf 36
37611b26 37Ssl::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const time_t timeout) :
f53969cc 38 AsyncJob("Ssl::PeerConnector"),
f53969cc 39 serverConn(aServerConn),
79fe57c2 40 certErrors(NULL),
f53969cc
SM
41 callback(aCallback),
42 negotiationTimeout(timeout),
43 startTime(squid_curtime),
1b091aec 44 useCertValidator_(false)
a23223bf
CT
45{
46 // if this throws, the caller's cb dialer is not our CbDialer
47 Must(dynamic_cast<CbDialer*>(callback->getDialer()));
48}
49
50Ssl::PeerConnector::~PeerConnector()
51{
1b091aec 52 cbdataReferenceDone(certErrors);
a23223bf
CT
53 debugs(83, 5, "Peer connector " << this << " gone");
54}
55
56bool Ssl::PeerConnector::doneAll() const
57{
58 return (!callback || callback->canceled()) && AsyncJob::doneAll();
59}
60
61/// Preps connection and SSL state. Calls negotiate().
62void
63Ssl::PeerConnector::start()
64{
65 AsyncJob::start();
66
1b091aec 67 if (prepareSocket() && (initializeSsl() != NULL))
a23223bf 68 negotiateSsl();
a23223bf
CT
69}
70
71void
72Ssl::PeerConnector::commCloseHandler(const CommCloseCbParams &params)
73{
74 debugs(83, 5, "FD " << params.fd << ", Ssl::PeerConnector=" << params.data);
75 connectionClosed("Ssl::PeerConnector::commCloseHandler");
76}
77
78void
79Ssl::PeerConnector::connectionClosed(const char *reason)
80{
81 mustStop(reason);
82 callback = NULL;
83}
84
85bool
86Ssl::PeerConnector::prepareSocket()
87{
88 const int fd = serverConnection()->fd;
89 if (!Comm::IsConnOpen(serverConn) || fd_table[serverConn->fd].closing()) {
90 connectionClosed("Ssl::PeerConnector::prepareSocket");
91 return false;
92 }
93
94 // watch for external connection closures
95 typedef CommCbMemFunT<Ssl::PeerConnector, CommCloseCbParams> Dialer;
96 closeHandler = JobCallback(9, 5, Dialer, this, Ssl::PeerConnector::commCloseHandler);
97 comm_add_close_handler(fd, closeHandler);
98 return true;
99}
100
1b091aec 101SSL *
a23223bf
CT
102Ssl::PeerConnector::initializeSsl()
103{
1b091aec 104 SSL_CTX *sslContext = getSslContext();
a23223bf
CT
105 assert(sslContext);
106
1b091aec
CT
107 const int fd = serverConnection()->fd;
108
31855516
CT
109 SSL *ssl = Ssl::CreateClient(sslContext, fd, "server https start");
110 if (!ssl) {
a23223bf
CT
111 ErrorState *anErr = new ErrorState(ERR_SOCKET_FAILURE, Http::scInternalServerError, request.getRaw());
112 anErr->xerrno = errno;
113 debugs(83, DBG_IMPORTANT, "Error allocating SSL handle: " << ERR_error_string(ERR_get_error(), NULL));
76b64c80 114
1b091aec
CT
115 noteNegotiationDone(anErr);
116 bail(anErr);
117 return NULL;
a23223bf
CT
118 }
119
120 // If CertValidation Helper used do not lookup checklist for errors,
121 // but keep a list of errors to send it to CertValidator
122 if (!Ssl::TheConfig.ssl_crt_validator) {
123 // Create the ACL check list now, while we have access to more info.
124 // The list is used in ssl_verify_cb() and is freed in ssl_free().
125 if (acl_access *acl = ::Config.ssl_client.cert_error) {
126 ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
127 // check->fd(fd); XXX: need client FD here
128 SSL_set_ex_data(ssl, ssl_ex_index_cert_error_check, check);
129 }
130 }
1b091aec 131 return ssl;
a23223bf
CT
132}
133
8aec3e1b
CT
134void
135Ssl::PeerConnector::setReadTimeout()
136{
137 int timeToRead;
138 if (negotiationTimeout) {
139 const int timeUsed = squid_curtime - startTime;
140 const int timeLeft = max(0, static_cast<int>(negotiationTimeout - timeUsed));
141 timeToRead = min(static_cast<int>(::Config.Timeout.read), timeLeft);
142 } else
143 timeToRead = ::Config.Timeout.read;
144 AsyncCall::Pointer nil;
145 commSetConnTimeout(serverConnection(), timeToRead, nil);
146}
147
a23223bf
CT
148void
149Ssl::PeerConnector::negotiateSsl()
150{
151 if (!Comm::IsConnOpen(serverConnection()) || fd_table[serverConnection()->fd].closing())
152 return;
153
154 const int fd = serverConnection()->fd;
155 SSL *ssl = fd_table[fd].ssl;
156 const int result = SSL_connect(ssl);
157 if (result <= 0) {
158 handleNegotiateError(result);
159 return; // we might be gone by now
160 }
161
c91d4d4e
CT
162 if (!sslFinalized())
163 return;
164
165 callBack();
166}
167
168bool
169Ssl::PeerConnector::sslFinalized()
170{
1b091aec
CT
171 if (Ssl::TheConfig.ssl_crt_validator && useCertValidator_) {
172 const int fd = serverConnection()->fd;
173 SSL *ssl = fd_table[fd].ssl;
a23223bf 174
a23223bf
CT
175 Ssl::CertValidationRequest validationRequest;
176 // WARNING: Currently we do not use any locking for any of the
177 // members of the Ssl::CertValidationRequest class. In this code the
178 // Ssl::CertValidationRequest object used only to pass data to
179 // Ssl::CertValidationHelper::submit method.
180 validationRequest.ssl = ssl;
5c51bffb 181 validationRequest.domainName = request->url.host();
a23223bf
CT
182 if (Ssl::CertErrors *errs = static_cast<Ssl::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)))
183 // validationRequest disappears on return so no need to cbdataReference
184 validationRequest.errors = errs;
185 else
186 validationRequest.errors = NULL;
187 try {
188 debugs(83, 5, "Sending SSL certificate for validation to ssl_crtvd.");
189 Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, sslCrtvdHandleReplyWrapper, this);
c91d4d4e 190 return false;
a23223bf
CT
191 } catch (const std::exception &e) {
192 debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
193 "request for " << validationRequest.domainName <<
194 " certificate: " << e.what() << "; will now block to " <<
195 "validate that certificate.");
196 // fall through to do blocking in-process generation.
197 ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
1b091aec
CT
198
199 noteNegotiationDone(anErr);
a23223bf 200 bail(anErr);
a23223bf 201 serverConn->close();
c91d4d4e 202 return true;
a23223bf
CT
203 }
204 }
1b091aec
CT
205
206 noteNegotiationDone(NULL);
c91d4d4e 207 return true;
a23223bf
CT
208}
209
c91d4d4e 210void switchToTunnel(HttpRequest *request, Comm::ConnectionPointer & clientConn, Comm::ConnectionPointer &srvConn);
7f4e9b73 211
31855516 212void
1b091aec 213Ssl::PeekingPeerConnector::cbCheckForPeekAndSpliceDone(allow_t answer, void *data)
7f4e9b73 214{
1b091aec 215 Ssl::PeekingPeerConnector *peerConnect = (Ssl::PeekingPeerConnector *) data;
566f8310
AR
216 // Use job calls to add done() checks and other job logic/protections.
217 CallJobHere1(83, 7, CbcPointer<PeekingPeerConnector>(peerConnect), Ssl::PeekingPeerConnector, checkForPeekAndSpliceDone, answer);
218}
219
220void
221Ssl::PeekingPeerConnector::checkForPeekAndSpliceDone(allow_t answer)
222{
223 const Ssl::BumpMode finalAction = (answer.code == ACCESS_ALLOWED) ?
2d5fa7fa
SM
224 static_cast<Ssl::BumpMode>(answer.kind):
225 checkForPeekAndSpliceGuess();
566f8310 226 checkForPeekAndSpliceMatched(finalAction);
7f4e9b73
CT
227}
228
a9c2dd2f 229void
1b091aec 230Ssl::PeekingPeerConnector::checkForPeekAndSplice()
31855516 231{
5d65362c
CT
232 // Mark Step3 of bumping
233 if (request->clientConnectionManager.valid()) {
234 if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
235 serverBump->step = Ssl::bumpStep3;
236 }
237 }
238
69f69080
CT
239 handleServerCertificate();
240
a9c2dd2f
CT
241 ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(
242 ::Config.accessList.ssl_bump,
243 request.getRaw(), NULL);
640fe8fb
CT
244 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpNone));
245 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpPeek));
246 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpStare));
247 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpClientFirst));
248 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpServerFirst));
249 SSL *ssl = fd_table[serverConn->fd].ssl;
250 BIO *b = SSL_get_rbio(ssl);
251 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
252 if (!srvBio->canSplice())
253 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpSplice));
254 if (!srvBio->canBump())
255 acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpBump));
1b091aec 256 acl_checklist->nonBlockingCheck(Ssl::PeekingPeerConnector::cbCheckForPeekAndSpliceDone, this);
a9c2dd2f 257}
789dda8d 258
a9c2dd2f 259void
566f8310 260Ssl::PeekingPeerConnector::checkForPeekAndSpliceMatched(const Ssl::BumpMode action)
a9c2dd2f
CT
261{
262 SSL *ssl = fd_table[serverConn->fd].ssl;
31855516
CT
263 BIO *b = SSL_get_rbio(ssl);
264 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
8693472e 265 debugs(83,5, "Will check for peek and splice on FD " << serverConn->fd);
7f4e9b73 266
a9c2dd2f 267 Ssl::BumpMode finalAction = action;
640fe8fb 268 Must(finalAction == Ssl::bumpSplice || finalAction == Ssl::bumpBump || finalAction == Ssl::bumpTerminate);
a9c2dd2f 269 // Record final decision
68bd0182 270 if (request->clientConnectionManager.valid()) {
a9c2dd2f 271 request->clientConnectionManager->sslBumpMode = finalAction;
68bd0182
CT
272 request->clientConnectionManager->serverBump()->act.step3 = finalAction;
273 }
a9c2dd2f
CT
274
275 if (finalAction == Ssl::bumpTerminate) {
b54a7c5a
CT
276 serverConn->close();
277 clientConn->close();
a9c2dd2f 278 } else if (finalAction != Ssl::bumpSplice) {
31855516
CT
279 //Allow write, proceed with the connection
280 srvBio->holdWrite(false);
281 srvBio->recordInput(false);
8693472e 282 debugs(83,5, "Retry the fwdNegotiateSSL on FD " << serverConn->fd);
1b091aec 283 Ssl::PeerConnector::noteWantWrite();
93ead3fd 284 } else {
c91d4d4e 285 splice = true;
f53969cc 286 // Ssl Negotiation stops here. Last SSL checks for valid certificates
c91d4d4e 287 // and if done, switch to tunnel mode
1b091aec
CT
288 if (sslFinalized()) {
289 debugs(83,5, "Abort NegotiateSSL on FD " << serverConn->fd << " and splice the connection");
290 }
31855516
CT
291 }
292}
293
566f8310
AR
294Ssl::BumpMode
295Ssl::PeekingPeerConnector::checkForPeekAndSpliceGuess() const
296{
297 if (const ConnStateData *csd = request->clientConnectionManager.valid()) {
298 const Ssl::BumpMode currentMode = csd->sslBumpMode;
299 if (currentMode == Ssl::bumpStare) {
300 debugs(83,5, "default to bumping after staring");
301 return Ssl::bumpBump;
302 }
303 debugs(83,5, "default to splicing after " << currentMode);
304 } else {
305 debugs(83,3, "default to splicing due to missing info");
306 }
307
308 return Ssl::bumpSplice;
309}
310
a23223bf
CT
311void
312Ssl::PeerConnector::sslCrtvdHandleReplyWrapper(void *data, Ssl::CertValidationResponse const &validationResponse)
313{
314 Ssl::PeerConnector *connector = (Ssl::PeerConnector *)(data);
315 connector->sslCrtvdHandleReply(validationResponse);
316}
317
318void
319Ssl::PeerConnector::sslCrtvdHandleReply(Ssl::CertValidationResponse const &validationResponse)
320{
321 Ssl::CertErrors *errs = NULL;
322 Ssl::ErrorDetail *errDetails = NULL;
323 bool validatorFailed = false;
324 if (!Comm::IsConnOpen(serverConnection())) {
325 return;
326 }
327
5c51bffb 328 debugs(83,5, request->url.host() << " cert validation result: " << validationResponse.resultCode);
a23223bf 329
2428ce02 330 if (validationResponse.resultCode == ::Helper::Error)
a23223bf 331 errs = sslCrtvdCheckForErrors(validationResponse, errDetails);
2428ce02 332 else if (validationResponse.resultCode != ::Helper::Okay)
a23223bf
CT
333 validatorFailed = true;
334
335 if (!errDetails && !validatorFailed) {
1b091aec
CT
336 noteNegotiationDone(NULL);
337 callBack();
a23223bf
CT
338 return;
339 }
340
1b091aec
CT
341 if (errs) {
342 if (certErrors)
343 cbdataReferenceDone(certErrors);
344 certErrors = cbdataReference(errs);
345 }
346
a23223bf
CT
347 ErrorState *anErr = NULL;
348 if (validatorFailed) {
349 anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
350 } else {
a23223bf
CT
351 anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, request.getRaw());
352 anErr->detail = errDetails;
353 /*anErr->xerrno= Should preserved*/
354 }
355
1b091aec 356 noteNegotiationDone(anErr);
a23223bf 357 bail(anErr);
a23223bf
CT
358 serverConn->close();
359 return;
360}
361
362/// Checks errors in the cert. validator response against sslproxy_cert_error.
363/// The first honored error, if any, is returned via errDetails parameter.
364/// The method returns all seen errors except SSL_ERROR_NONE as Ssl::CertErrors.
365Ssl::CertErrors *
366Ssl::PeerConnector::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &resp, Ssl::ErrorDetail *& errDetails)
367{
368 Ssl::CertErrors *errs = NULL;
369
370 ACLFilledChecklist *check = NULL;
371 if (acl_access *acl = ::Config.ssl_client.cert_error)
372 check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
373
374 SSL *ssl = fd_table[serverConnection()->fd].ssl;
375 typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
376 for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) {
377 debugs(83, 7, "Error item: " << i->error_no << " " << i->error_reason);
378
379 assert(i->error_no != SSL_ERROR_NONE);
380
381 if (!errDetails) {
382 bool allowed = false;
383 if (check) {
384 check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get()));
385 if (check->fastCheck() == ACCESS_ALLOWED)
386 allowed = true;
387 }
388 // else the Config.ssl_client.cert_error access list is not defined
389 // and the first error will cause the error page
390
391 if (allowed) {
392 debugs(83, 3, "bypassing SSL error " << i->error_no << " in " << "buffer");
393 } else {
394 debugs(83, 5, "confirming SSL error " << i->error_no);
395 X509 *brokenCert = i->cert.get();
f97700a0 396 Security::CertPointer peerCert(SSL_get_peer_certificate(ssl));
a23223bf
CT
397 const char *aReason = i->error_reason.empty() ? NULL : i->error_reason.c_str();
398 errDetails = new Ssl::ErrorDetail(i->error_no, peerCert.get(), brokenCert, aReason);
399 }
400 if (check) {
401 delete check->sslErrors;
402 check->sslErrors = NULL;
403 }
404 }
405
406 if (!errs)
407 errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get()));
408 else
409 errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get()));
410 }
411 if (check)
412 delete check;
413
414 return errs;
415}
416
417/// A wrapper for Comm::SetSelect() notifications.
418void
419Ssl::PeerConnector::NegotiateSsl(int, void *data)
420{
421 PeerConnector *pc = static_cast<PeerConnector*>(data);
422 // Use job calls to add done() checks and other job logic/protections.
423 CallJobHere(83, 7, pc, Ssl::PeerConnector, negotiateSsl);
424}
425
426void
427Ssl::PeerConnector::handleNegotiateError(const int ret)
428{
429 const int fd = serverConnection()->fd;
430 unsigned long ssl_lib_error = SSL_ERROR_NONE;
431 SSL *ssl = fd_table[fd].ssl;
f5518dca 432 const int ssl_error = SSL_get_error(ssl, ret);
a23223bf 433
e2849af8 434 switch (ssl_error) {
e2849af8 435 case SSL_ERROR_WANT_READ:
1b091aec 436 noteWantRead();
e2849af8 437 return;
a23223bf 438
e2849af8 439 case SSL_ERROR_WANT_WRITE:
1b091aec 440 noteWantWrite();
e2849af8 441 return;
a23223bf 442
e2849af8
A
443 case SSL_ERROR_SSL:
444 case SSL_ERROR_SYSCALL:
445 ssl_lib_error = ERR_get_error();
1b091aec
CT
446 // proceed to the general error handling code
447 break;
448 default:
449 // no special error handling for all other errors
450 break;
451 }
452 noteSslNegotiationError(ret, ssl_error, ssl_lib_error);
453}
a23223bf 454
1b091aec
CT
455void
456Ssl::PeerConnector::noteWantRead()
457{
458 setReadTimeout();
459 const int fd = serverConnection()->fd;
460 Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, this, 0);
461}
7f4e9b73 462
1b091aec
CT
463void
464Ssl::PeerConnector::noteWantWrite()
465{
466 const int fd = serverConnection()->fd;
467 Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
468 return;
469}
a23223bf 470
1b091aec
CT
471void
472Ssl::PeerConnector::noteSslNegotiationError(const int ret, const int ssl_error, const int ssl_lib_error)
473{
474#ifdef EPROTO
475 int sysErrNo = EPROTO;
476#else
477 int sysErrNo = EACCES;
478#endif
a23223bf 479
1b091aec
CT
480 // store/report errno when ssl_error is SSL_ERROR_SYSCALL, ssl_lib_error is 0, and ret is -1
481 if (ssl_error == SSL_ERROR_SYSCALL && ret == -1 && ssl_lib_error == 0)
482 sysErrNo = errno;
a23223bf 483
1b091aec
CT
484 const int fd = serverConnection()->fd;
485 debugs(83, DBG_IMPORTANT, "Error negotiating SSL on FD " << fd <<
486 ": " << ERR_error_string(ssl_lib_error, NULL) << " (" <<
487 ssl_error << "/" << ret << "/" << errno << ")");
a23223bf 488
1b091aec
CT
489 ErrorState *anErr = NULL;
490 if (request != NULL)
491 anErr = ErrorState::NewForwarding(ERR_SECURE_CONNECT_FAIL, request.getRaw());
492 else
493 anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, NULL);
a23223bf
CT
494 anErr->xerrno = sysErrNo;
495
1b091aec 496 SSL *ssl = fd_table[fd].ssl;
a23223bf
CT
497 Ssl::ErrorDetail *errFromFailure = (Ssl::ErrorDetail *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail);
498 if (errFromFailure != NULL) {
499 // The errFromFailure is attached to the ssl object
500 // and will be released when ssl object destroyed.
501 // Copy errFromFailure to a new Ssl::ErrorDetail object
502 anErr->detail = new Ssl::ErrorDetail(*errFromFailure);
503 } else {
504 // server_cert can be NULL here
505 X509 *server_cert = SSL_get_peer_certificate(ssl);
506 anErr->detail = new Ssl::ErrorDetail(SQUID_ERR_SSL_HANDSHAKE, server_cert, NULL);
507 X509_free(server_cert);
508 }
509
510 if (ssl_lib_error != SSL_ERROR_NONE)
511 anErr->detail->setLibError(ssl_lib_error);
512
1b091aec
CT
513 assert(certErrors == NULL);
514 // remember validation errors, if any
515 if (Ssl::CertErrors *errs = static_cast<Ssl::CertErrors*>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)))
516 certErrors = cbdataReference(errs);
a23223bf 517
1b091aec 518 noteNegotiationDone(anErr);
a23223bf
CT
519 bail(anErr);
520}
521
522void
523Ssl::PeerConnector::bail(ErrorState *error)
524{
525 Must(error); // or the recepient will not know there was a problem
a23223bf
CT
526 Must(callback != NULL);
527 CbDialer *dialer = dynamic_cast<CbDialer*>(callback->getDialer());
528 Must(dialer);
529 dialer->answer().error = error;
530
531 callBack();
532 // Our job is done. The callabck recepient will probably close the failed
533 // peer connection and try another peer or go direct (if possible). We
534 // can close the connection ourselves (our error notification would reach
535 // the recepient before the fd-closure notification), but we would rather
536 // minimize the number of fd-closure notifications and let the recepient
537 // manage the TCP state of the connection.
538}
539
540void
541Ssl::PeerConnector::callBack()
542{
543 AsyncCall::Pointer cb = callback;
544 // Do this now so that if we throw below, swanSong() assert that we _tried_
545 // to call back holds.
546 callback = NULL; // this should make done() true
547
548 // remove close handler
549 comm_remove_close_handler(serverConnection()->fd, closeHandler);
550
551 CbDialer *dialer = dynamic_cast<CbDialer*>(cb->getDialer());
552 Must(dialer);
553 dialer->answer().conn = serverConnection();
554 ScheduleCallHere(cb);
555}
556
a23223bf
CT
557void
558Ssl::PeerConnector::swanSong()
559{
560 // XXX: unregister fd-closure monitoring and CommSetSelect interest, if any
561 AsyncJob::swanSong();
566f8310
AR
562 if (callback != NULL) { // paranoid: we have left the caller waiting
563 debugs(83, DBG_IMPORTANT, "BUG: Unexpected state while connecting to a cache_peer or origin server");
564 ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
565 bail(anErr);
566 assert(!callback);
567 return;
568 }
a23223bf
CT
569}
570
571const char *
572Ssl::PeerConnector::status() const
573{
574 static MemBuf buf;
575 buf.reset();
576
577 // TODO: redesign AsyncJob::status() API to avoid this
578 // id and stop reason reporting duplication.
579 buf.append(" [", 2);
580 if (stopReason != NULL) {
07e6d76e
AJ
581 buf.append("Stopped, reason:", 16);
582 buf.appendf("%s",stopReason);
a23223bf
CT
583 }
584 if (serverConn != NULL)
07e6d76e
AJ
585 buf.appendf(" FD %d", serverConn->fd);
586 buf.appendf(" %s%u]", id.Prefix, id.value);
a23223bf
CT
587 buf.terminate();
588
589 return buf.content();
590}
591
1b091aec
CT
592SSL_CTX *
593Ssl::BlindPeerConnector::getSslContext()
594{
595 if (const CachePeer *peer = serverConnection()->getPeer()) {
596 assert(peer->secure.encryptTransport);
597 SSL_CTX *sslContext = peer->sslContext;
598 return sslContext;
599 }
600 return NULL;
601}
602
603SSL *
604Ssl::BlindPeerConnector::initializeSsl()
605{
606 SSL *ssl = Ssl::PeerConnector::initializeSsl();
607 if (!ssl)
608 return NULL;
609
610 const CachePeer *peer = serverConnection()->getPeer();
611 assert(peer);
612
613 // NP: domain may be a raw-IP but it is now always set
614 assert(!peer->secure.sslDomain.isEmpty());
615
616 // const loss is okay here, ssl_ex_index_server is only read and not assigned a destructor
617 SBuf *host = new SBuf(peer->secure.sslDomain);
618 SSL_set_ex_data(ssl, ssl_ex_index_server, host);
619
620 if (peer->sslSession)
621 SSL_set_session(ssl, peer->sslSession);
622
623 return ssl;
624}
625
626void
627Ssl::BlindPeerConnector::noteNegotiationDone(ErrorState *error)
628{
629 if (error) {
630 // XXX: forward.cc calls peerConnectSucceeded() after an OK TCP connect but
631 // we call peerConnectFailed() if SSL failed afterwards. Is that OK?
632 // It is not clear whether we should call peerConnectSucceeded/Failed()
633 // based on TCP results, SSL results, or both. And the code is probably not
634 // consistent in this aspect across tunnelling and forwarding modules.
635 if (CachePeer *p = serverConnection()->getPeer())
636 peerConnectFailed(p);
637 return;
638 }
639
640 const int fd = serverConnection()->fd;
641 SSL *ssl = fd_table[fd].ssl;
642 if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
643 if (serverConnection()->getPeer()->sslSession)
644 SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
645
646 serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
647 }
648}
649
650SSL_CTX *
651Ssl::PeekingPeerConnector::getSslContext()
652{
653 // XXX: locate a per-server context in Security:: instead
654 return ::Config.ssl_client.sslContext;
655}
656
657SSL *
658Ssl::PeekingPeerConnector::initializeSsl()
659{
660 SSL *ssl = Ssl::PeerConnector::initializeSsl();
661 if (!ssl)
662 return NULL;
663
664 if (ConnStateData *csd = request->clientConnectionManager.valid()) {
665
666 // client connection is required in the case we need to splice
667 // or terminate client and server connections
668 assert(clientConn != NULL);
669 SBuf *hostName = NULL;
670 Ssl::ClientBio *cltBio = NULL;
671
672 //Enable Status_request tls extension, required to bump some clients
673 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
674
675 // In server-first bumping mode, clientSsl is NULL.
676 if (SSL *clientSsl = fd_table[clientConn->fd].ssl) {
677 BIO *b = SSL_get_rbio(clientSsl);
678 cltBio = static_cast<Ssl::ClientBio *>(b->ptr);
679 const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
680 if (!features.serverName.isEmpty())
681 hostName = new SBuf(features.serverName);
682 }
683
684 if (!hostName) {
685 // While we are peeking at the certificate, we may not know the server
686 // name that the client will request (after interception or CONNECT)
687 // unless it was the CONNECT request with a user-typed address.
688 const bool isConnectRequest = !csd->port->flags.isIntercepted();
689 if (!request->flags.sslPeek || isConnectRequest)
5c51bffb 690 hostName = new SBuf(request->url.host());
1b091aec
CT
691 }
692
693 if (hostName)
694 SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
695
696 Must(!csd->serverBump() || csd->serverBump()->step <= Ssl::bumpStep2);
697 if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
698 assert(cltBio);
699 const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
700 if (features.sslVersion != -1) {
701 features.applyToSSL(ssl, csd->sslBumpMode);
702 // Should we allow it for all protocols?
703 if (features.sslVersion >= 3) {
704 BIO *b = SSL_get_rbio(ssl);
705 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
706 // Inherite client features, like SSL version, SNI and other
707 srvBio->setClientFeatures(features);
708 srvBio->recordInput(true);
709 srvBio->mode(csd->sslBumpMode);
710 }
711 }
712 } else {
713 // Set client SSL options
714 SSL_set_options(ssl, ::Security::ProxyOutgoingConfig.parsedOptions);
715
716 // Use SNI TLS extension only when we connect directly
717 // to the origin server and we know the server host name.
c52a4693
AW
718 const char *sniServer = NULL;
719 const bool redirected = request->flags.redirected && ::Config.onoff.redir_rewrites_host;
720 if (!hostName || redirected)
721 sniServer = !request->url.hostIsNumeric() ? request->url.host() : NULL;
722 else
723 sniServer = hostName->c_str();
724
1b091aec
CT
725 if (sniServer)
726 Ssl::setClientSNI(ssl, sniServer);
727 }
728
729 // store peeked cert to check SQUID_X509_V_ERR_CERT_CHANGE
730 X509 *peeked_cert;
731 if (csd->serverBump() &&
732 (peeked_cert = csd->serverBump()->serverCert.get())) {
733 CRYPTO_add(&(peeked_cert->references),1,CRYPTO_LOCK_X509);
734 SSL_set_ex_data(ssl, ssl_ex_index_ssl_peeked_cert, peeked_cert);
735 }
736 }
737
738 return ssl;
739}
740
741void
742Ssl::PeekingPeerConnector::noteNegotiationDone(ErrorState *error)
743{
744 SSL *ssl = fd_table[serverConnection()->fd].ssl;
745
746 // Check the list error with
747 if (!request->clientConnectionManager.valid() || ! ssl)
748 return;
749
750 // remember the server certificate from the ErrorDetail object
751 if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
752 // remember validation errors, if any
753 if (certErrors) {
754 if (serverBump->sslErrors)
755 cbdataReferenceDone(serverBump->sslErrors);
756 serverBump->sslErrors = cbdataReference(certErrors);
757 }
758
759 if (!serverBump->serverCert.get()) {
760 // remember the server certificate from the ErrorDetail object
761 if (error && error->detail && error->detail->peerCert())
762 serverBump->serverCert.resetAndLock(error->detail->peerCert());
763 else {
764 handleServerCertificate();
765 }
766 }
767
768 if (error) {
769 // For intercepted connections, set the host name to the server
770 // certificate CN. Otherwise, we just hope that CONNECT is using
771 // a user-entered address (a host name or a user-entered IP).
772 const bool isConnectRequest = !request->clientConnectionManager->port->flags.isIntercepted();
773 if (request->flags.sslPeek && !isConnectRequest) {
774 if (X509 *srvX509 = serverBump->serverCert.get()) {
775 if (const char *name = Ssl::CommonHostName(srvX509)) {
851feda6 776 request->url.host(name);
1b091aec
CT
777 debugs(83, 3, "reset request host: " << name);
778 }
779 }
780 }
781 }
782 }
783
ce74a2eb
CT
784 if (!error) {
785 serverCertificateVerified();
786 if (splice)
787 switchToTunnel(request.getRaw(), clientConn, serverConn);
788 }
1b091aec
CT
789}
790
791void
792Ssl::PeekingPeerConnector::noteWantWrite()
793{
794 const int fd = serverConnection()->fd;
795 SSL *ssl = fd_table[fd].ssl;
796 BIO *b = SSL_get_rbio(ssl);
797 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
798
799 if ((srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) {
800 debugs(81, DBG_IMPORTANT, "hold write on SSL connection on FD " << fd);
801 checkForPeekAndSplice();
802 return;
803 }
804
805 Ssl::PeerConnector::noteWantWrite();
806}
807
808void
809Ssl::PeekingPeerConnector::noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error)
810{
811 const int fd = serverConnection()->fd;
812 SSL *ssl = fd_table[fd].ssl;
813 BIO *b = SSL_get_rbio(ssl);
814 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
815
816 // In Peek mode, the ClientHello message sent to the server. If the
817 // server resuming a previous (spliced) SSL session with the client,
818 // then probably we are here because local SSL object does not know
819 // anything about the session being resumed.
820 //
821 if (srvBio->bumpMode() == Ssl::bumpPeek && (resumingSession = srvBio->resumingSession())) {
822 // we currently splice all resumed sessions unconditionally
823 if (const bool spliceResumed = true) {
824 bypassCertValidator();
566f8310 825 checkForPeekAndSpliceMatched(Ssl::bumpSplice);
1b091aec
CT
826 return;
827 } // else fall through to find a matching ssl_bump action (with limited info)
828 }
829
830 // If we are in peek-and-splice mode and still we did not write to
831 // server yet, try to see if we should splice.
832 // In this case the connection can be saved.
833 // If the checklist decision is do not splice a new error will
834 // occur in the next SSL_connect call, and we will fail again.
835 // Abort on certificate validation errors to avoid splicing and
836 // thus hiding them.
837 // Abort if no certificate found probably because of malformed or
838 // unsupported server Hello message (TODO: make configurable).
839 if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) &&
840 (srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) {
f97700a0 841 Security::CertPointer serverCert(SSL_get_peer_certificate(ssl));
1b091aec
CT
842 if (serverCert.get()) {
843 debugs(81, 3, "Error (" << ERR_error_string(ssl_lib_error, NULL) << ") but, hold write on SSL connection on FD " << fd);
844 checkForPeekAndSplice();
845 return;
846 }
847 }
848
849 // else call parent noteNegotiationError to produce an error page
850 Ssl::PeerConnector::noteSslNegotiationError(result, ssl_error, ssl_lib_error);
851}
852
853void
854Ssl::PeekingPeerConnector::handleServerCertificate()
855{
856 if (serverCertificateHandled)
857 return;
858
859 if (ConnStateData *csd = request->clientConnectionManager.valid()) {
860 const int fd = serverConnection()->fd;
861 SSL *ssl = fd_table[fd].ssl;
f97700a0 862 Security::CertPointer serverCert(SSL_get_peer_certificate(ssl));
1b091aec
CT
863 if (!serverCert.get())
864 return;
865
866 serverCertificateHandled = true;
867
1b091aec
CT
868 // remember the server certificate for later use
869 if (Ssl::ServerBump *serverBump = csd->serverBump()) {
870 serverBump->serverCert.reset(serverCert.release());
871 }
872 }
873}
7fe542fe 874
ce74a2eb
CT
875void
876Ssl::PeekingPeerConnector::serverCertificateVerified()
877{
878 if (ConnStateData *csd = request->clientConnectionManager.valid()) {
f97700a0 879 Security::CertPointer serverCert;
ce74a2eb
CT
880 if(Ssl::ServerBump *serverBump = csd->serverBump())
881 serverCert.resetAndLock(serverBump->serverCert.get());
882 else {
883 const int fd = serverConnection()->fd;
884 SSL *ssl = fd_table[fd].ssl;
885 serverCert.reset(SSL_get_peer_certificate(ssl));
886 }
887 if (serverCert.get()) {
888 csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get()));
889 debugs(83, 5, "HTTPS server CN: " << csd->sslCommonName() <<
890 " bumped: " << *serverConnection());
891 }
892 }
893}
894