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