]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/PeerConnector.cc
merge from trunk r14444
[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 282 //Allow write, proceed with the connection
ffbfd5be 283 srvBio->recordInput(false);
31855516 284 srvBio->holdWrite(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++;
55369ae6
AR
649 debugs(81, 5, "OK! certificate downloaded, status: " << downloadStatus << " data size: " << obj.length());
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
657 // Parse Certificate. Assume that it is in DER format. Probably we should handle PEM or other formats too
658 const unsigned char *raw = (const unsigned char*)obj.rawContent();
659 if (X509 *cert = d2i_X509(NULL, &raw, obj.length())) {
660 char buffer[1024];
661 debugs(81, 5, "Retrieved certificate: " << X509_NAME_oneline(X509_get_subject_name(cert), buffer, 1024));
662 const Ssl::X509_STACK_Pointer &certsList = srvBio->serverCertificates();
663 if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList)) {
664 urlsOfMissingCerts.push(SBuf(issuerUri));
665 }
666 Ssl::SSL_add_untrusted_cert(ssl, cert);
667 }
668
669 // Check if has uri to donwload and add it to urlsOfMissingCerts
4e526b93 670 if (urlsOfMissingCerts.size() && certsDownloads <= MaxCertsDownloads) {
55369ae6
AR
671 startCertDownloading(urlsOfMissingCerts.front());
672 urlsOfMissingCerts.pop();
673 return;
674 }
675
676 srvBio->holdRead(false);
677 Ssl::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
678}
679
680bool
681Ssl::PeerConnector::checkForMissingCertificates ()
682{
4e526b93
CT
683 // Check for nested SSL certificates downloads. For example when the
684 // certificate located in an SSL site which requires to download a
685 // a missing certificate (... from an SSL site which requires to ...)
686 const Downloader *csd = dynamic_cast<const Downloader*>(request->clientConnectionManager.valid());
687 if (csd && csd->nestedLevel() >= MaxNestedDownloads)
688 return false;
689
55369ae6
AR
690 const int fd = serverConnection()->fd;
691 SSL *ssl = fd_table[fd].ssl;
692 BIO *b = SSL_get_rbio(ssl);
693 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
694 const Ssl::X509_STACK_Pointer &certs = srvBio->serverCertificates();
695
ffbfd5be 696 if (certs.get() && sk_X509_num(certs.get())) {
55369ae6
AR
697 debugs(83, 5, "SSL server sent " << sk_X509_num(certs.get()) << " certificates");
698 Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs);
699 if (urlsOfMissingCerts.size()) {
700 startCertDownloading(urlsOfMissingCerts.front());
701 urlsOfMissingCerts.pop();
702 return true;
703 }
704 }
705
706 return false;
707}
708
96993ee0 709Security::ContextPtr
1b091aec
CT
710Ssl::BlindPeerConnector::getSslContext()
711{
712 if (const CachePeer *peer = serverConnection()->getPeer()) {
713 assert(peer->secure.encryptTransport);
96993ee0 714 Security::ContextPtr sslContext(peer->sslContext);
1b091aec
CT
715 return sslContext;
716 }
a7300c7a 717 return ::Config.ssl_client.sslContext;
1b091aec
CT
718}
719
720SSL *
721Ssl::BlindPeerConnector::initializeSsl()
722{
723 SSL *ssl = Ssl::PeerConnector::initializeSsl();
724 if (!ssl)
725 return NULL;
726
a7300c7a
CT
727 if (const CachePeer *peer = serverConnection()->getPeer()) {
728 assert(peer);
1b091aec 729
a7300c7a
CT
730 // NP: domain may be a raw-IP but it is now always set
731 assert(!peer->secure.sslDomain.isEmpty());
1b091aec 732
a7300c7a
CT
733 // const loss is okay here, ssl_ex_index_server is only read and not assigned a destructor
734 SBuf *host = new SBuf(peer->secure.sslDomain);
735 SSL_set_ex_data(ssl, ssl_ex_index_server, host);
1b091aec 736
a7300c7a
CT
737 if (peer->sslSession)
738 SSL_set_session(ssl, peer->sslSession);
739 } else {
41e803be
CT
740 SBuf *hostName = new SBuf(request->url.host());
741 SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
a7300c7a 742 }
1b091aec
CT
743
744 return ssl;
745}
746
747void
748Ssl::BlindPeerConnector::noteNegotiationDone(ErrorState *error)
749{
750 if (error) {
751 // XXX: forward.cc calls peerConnectSucceeded() after an OK TCP connect but
752 // we call peerConnectFailed() if SSL failed afterwards. Is that OK?
753 // It is not clear whether we should call peerConnectSucceeded/Failed()
754 // based on TCP results, SSL results, or both. And the code is probably not
755 // consistent in this aspect across tunnelling and forwarding modules.
756 if (CachePeer *p = serverConnection()->getPeer())
757 peerConnectFailed(p);
758 return;
759 }
760
761 const int fd = serverConnection()->fd;
762 SSL *ssl = fd_table[fd].ssl;
763 if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
764 if (serverConnection()->getPeer()->sslSession)
765 SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
766
767 serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
768 }
769}
770
96993ee0 771Security::ContextPtr
1b091aec
CT
772Ssl::PeekingPeerConnector::getSslContext()
773{
774 // XXX: locate a per-server context in Security:: instead
775 return ::Config.ssl_client.sslContext;
776}
777
778SSL *
779Ssl::PeekingPeerConnector::initializeSsl()
780{
781 SSL *ssl = Ssl::PeerConnector::initializeSsl();
782 if (!ssl)
783 return NULL;
784
785 if (ConnStateData *csd = request->clientConnectionManager.valid()) {
786
787 // client connection is required in the case we need to splice
788 // or terminate client and server connections
789 assert(clientConn != NULL);
790 SBuf *hostName = NULL;
791 Ssl::ClientBio *cltBio = NULL;
792
793 //Enable Status_request tls extension, required to bump some clients
794 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
795
796 // In server-first bumping mode, clientSsl is NULL.
797 if (SSL *clientSsl = fd_table[clientConn->fd].ssl) {
798 BIO *b = SSL_get_rbio(clientSsl);
799 cltBio = static_cast<Ssl::ClientBio *>(b->ptr);
800 const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
801 if (!features.serverName.isEmpty())
802 hostName = new SBuf(features.serverName);
803 }
804
805 if (!hostName) {
806 // While we are peeking at the certificate, we may not know the server
807 // name that the client will request (after interception or CONNECT)
808 // unless it was the CONNECT request with a user-typed address.
809 const bool isConnectRequest = !csd->port->flags.isIntercepted();
810 if (!request->flags.sslPeek || isConnectRequest)
5c51bffb 811 hostName = new SBuf(request->url.host());
1b091aec
CT
812 }
813
814 if (hostName)
815 SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
816
817 Must(!csd->serverBump() || csd->serverBump()->step <= Ssl::bumpStep2);
818 if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
819 assert(cltBio);
820 const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
821 if (features.sslVersion != -1) {
822 features.applyToSSL(ssl, csd->sslBumpMode);
823 // Should we allow it for all protocols?
824 if (features.sslVersion >= 3) {
825 BIO *b = SSL_get_rbio(ssl);
826 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
827 // Inherite client features, like SSL version, SNI and other
828 srvBio->setClientFeatures(features);
ffbfd5be 829 srvBio->recordInput(true);
1b091aec
CT
830 srvBio->mode(csd->sslBumpMode);
831 }
832 }
833 } else {
834 // Set client SSL options
835 SSL_set_options(ssl, ::Security::ProxyOutgoingConfig.parsedOptions);
836
837 // Use SNI TLS extension only when we connect directly
838 // to the origin server and we know the server host name.
c52a4693
AW
839 const char *sniServer = NULL;
840 const bool redirected = request->flags.redirected && ::Config.onoff.redir_rewrites_host;
841 if (!hostName || redirected)
842 sniServer = !request->url.hostIsNumeric() ? request->url.host() : NULL;
843 else
844 sniServer = hostName->c_str();
845
1b091aec
CT
846 if (sniServer)
847 Ssl::setClientSNI(ssl, sniServer);
848 }
849
850 // store peeked cert to check SQUID_X509_V_ERR_CERT_CHANGE
851 X509 *peeked_cert;
852 if (csd->serverBump() &&
853 (peeked_cert = csd->serverBump()->serverCert.get())) {
854 CRYPTO_add(&(peeked_cert->references),1,CRYPTO_LOCK_X509);
855 SSL_set_ex_data(ssl, ssl_ex_index_ssl_peeked_cert, peeked_cert);
856 }
857 }
858
859 return ssl;
860}
861
862void
863Ssl::PeekingPeerConnector::noteNegotiationDone(ErrorState *error)
864{
865 SSL *ssl = fd_table[serverConnection()->fd].ssl;
866
867 // Check the list error with
868 if (!request->clientConnectionManager.valid() || ! ssl)
869 return;
870
871 // remember the server certificate from the ErrorDetail object
872 if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
873 // remember validation errors, if any
874 if (certErrors) {
875 if (serverBump->sslErrors)
876 cbdataReferenceDone(serverBump->sslErrors);
877 serverBump->sslErrors = cbdataReference(certErrors);
878 }
879
880 if (!serverBump->serverCert.get()) {
881 // remember the server certificate from the ErrorDetail object
882 if (error && error->detail && error->detail->peerCert())
883 serverBump->serverCert.resetAndLock(error->detail->peerCert());
884 else {
885 handleServerCertificate();
886 }
887 }
888
889 if (error) {
890 // For intercepted connections, set the host name to the server
891 // certificate CN. Otherwise, we just hope that CONNECT is using
892 // a user-entered address (a host name or a user-entered IP).
893 const bool isConnectRequest = !request->clientConnectionManager->port->flags.isIntercepted();
894 if (request->flags.sslPeek && !isConnectRequest) {
895 if (X509 *srvX509 = serverBump->serverCert.get()) {
896 if (const char *name = Ssl::CommonHostName(srvX509)) {
851feda6 897 request->url.host(name);
1b091aec
CT
898 debugs(83, 3, "reset request host: " << name);
899 }
900 }
901 }
902 }
903 }
904
ce74a2eb
CT
905 if (!error) {
906 serverCertificateVerified();
907 if (splice)
908 switchToTunnel(request.getRaw(), clientConn, serverConn);
909 }
1b091aec
CT
910}
911
912void
913Ssl::PeekingPeerConnector::noteWantWrite()
914{
915 const int fd = serverConnection()->fd;
916 SSL *ssl = fd_table[fd].ssl;
917 BIO *b = SSL_get_rbio(ssl);
918 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
919
920 if ((srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) {
921 debugs(81, DBG_IMPORTANT, "hold write on SSL connection on FD " << fd);
922 checkForPeekAndSplice();
923 return;
924 }
925
926 Ssl::PeerConnector::noteWantWrite();
927}
928
929void
930Ssl::PeekingPeerConnector::noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error)
931{
932 const int fd = serverConnection()->fd;
933 SSL *ssl = fd_table[fd].ssl;
934 BIO *b = SSL_get_rbio(ssl);
935 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
936
937 // In Peek mode, the ClientHello message sent to the server. If the
938 // server resuming a previous (spliced) SSL session with the client,
939 // then probably we are here because local SSL object does not know
940 // anything about the session being resumed.
941 //
942 if (srvBio->bumpMode() == Ssl::bumpPeek && (resumingSession = srvBio->resumingSession())) {
943 // we currently splice all resumed sessions unconditionally
944 if (const bool spliceResumed = true) {
945 bypassCertValidator();
566f8310 946 checkForPeekAndSpliceMatched(Ssl::bumpSplice);
1b091aec
CT
947 return;
948 } // else fall through to find a matching ssl_bump action (with limited info)
949 }
950
951 // If we are in peek-and-splice mode and still we did not write to
952 // server yet, try to see if we should splice.
953 // In this case the connection can be saved.
954 // If the checklist decision is do not splice a new error will
955 // occur in the next SSL_connect call, and we will fail again.
956 // Abort on certificate validation errors to avoid splicing and
957 // thus hiding them.
958 // Abort if no certificate found probably because of malformed or
959 // unsupported server Hello message (TODO: make configurable).
960 if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) &&
961 (srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) {
f97700a0 962 Security::CertPointer serverCert(SSL_get_peer_certificate(ssl));
1b091aec
CT
963 if (serverCert.get()) {
964 debugs(81, 3, "Error (" << ERR_error_string(ssl_lib_error, NULL) << ") but, hold write on SSL connection on FD " << fd);
965 checkForPeekAndSplice();
966 return;
967 }
968 }
969
970 // else call parent noteNegotiationError to produce an error page
971 Ssl::PeerConnector::noteSslNegotiationError(result, ssl_error, ssl_lib_error);
972}
973
974void
975Ssl::PeekingPeerConnector::handleServerCertificate()
976{
977 if (serverCertificateHandled)
978 return;
979
980 if (ConnStateData *csd = request->clientConnectionManager.valid()) {
981 const int fd = serverConnection()->fd;
982 SSL *ssl = fd_table[fd].ssl;
f97700a0 983 Security::CertPointer serverCert(SSL_get_peer_certificate(ssl));
1b091aec
CT
984 if (!serverCert.get())
985 return;
986
987 serverCertificateHandled = true;
988
1b091aec
CT
989 // remember the server certificate for later use
990 if (Ssl::ServerBump *serverBump = csd->serverBump()) {
991 serverBump->serverCert.reset(serverCert.release());
992 }
993 }
994}
7fe542fe 995
ce74a2eb
CT
996void
997Ssl::PeekingPeerConnector::serverCertificateVerified()
998{
999 if (ConnStateData *csd = request->clientConnectionManager.valid()) {
f97700a0 1000 Security::CertPointer serverCert;
ce74a2eb
CT
1001 if(Ssl::ServerBump *serverBump = csd->serverBump())
1002 serverCert.resetAndLock(serverBump->serverCert.get());
1003 else {
1004 const int fd = serverConnection()->fd;
1005 SSL *ssl = fd_table[fd].ssl;
1006 serverCert.reset(SSL_get_peer_certificate(ssl));
1007 }
1008 if (serverCert.get()) {
1009 csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get()));
1010 debugs(83, 5, "HTTPS server CN: " << csd->sslCommonName() <<
1011 " bumped: " << *serverConnection());
1012 }
1013 }
1014}
1015