PeerConnector.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 /* DEBUG: section 83 TLS Server/Peer negotiation */
10 
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "comm/Loops.h"
14 #include "Downloader.h"
15 #include "errorpage.h"
16 #include "fde.h"
17 #include "http/Stream.h"
18 #include "HttpRequest.h"
20 #include "security/PeerConnector.h"
21 #include "SquidConfig.h"
22 #if USE_OPENSSL
23 #include "ssl/bio.h"
25 #include "ssl/Config.h"
26 #include "ssl/helper.h"
27 #endif
28 
29 CBDATA_NAMESPACED_CLASS_INIT(Security, PeerConnector);
30 
31 Security::PeerConnector::PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const AccessLogEntryPointer &alp, const time_t timeout) :
32  AsyncJob("Security::PeerConnector"),
33  serverConn(aServerConn),
34  al(alp),
35  callback(aCallback),
36  negotiationTimeout(timeout),
37  startTime(squid_curtime),
38  useCertValidator_(true),
39  certsDownloads(0)
40 {
41  debugs(83, 5, "Security::PeerConnector constructed, this=" << (void*)this);
42  // if this throws, the caller's cb dialer is not our CbDialer
43  Must(dynamic_cast<CbDialer*>(callback->getDialer()));
44 }
45 
47 {
48  debugs(83, 5, "Security::PeerConnector destructed, this=" << (void*)this);
49 }
50 
52 {
53  return (!callback || callback->canceled()) && AsyncJob::doneAll();
54 }
55 
57 void
59 {
61  debugs(83, 5, "this=" << (void*)this);
62 
64  if (prepareSocket() && initialize(tmp))
65  negotiate();
66  else
67  mustStop("Security::PeerConnector TLS socket initialize failed");
68 }
69 
70 void
72 {
73  debugs(83, 5, "FD " << params.fd << ", Security::PeerConnector=" << params.data);
74  connectionClosed("Security::PeerConnector::commCloseHandler");
75 }
76 
77 void
79 {
80  debugs(83, 5, reason << " socket closed/closing. this=" << (void*)this);
81  mustStop(reason);
82  callback = NULL;
83 }
84 
85 bool
87 {
88  debugs(83, 5, serverConnection() << ", this=" << (void*)this);
89  if (!Comm::IsConnOpen(serverConnection()) || fd_table[serverConnection()->fd].closing()) {
90  connectionClosed("Security::PeerConnector::prepareSocket");
91  return false;
92  }
93 
94  debugs(83, 5, serverConnection());
95 
96  // watch for external connection closures
98  closeHandler = JobCallback(9, 5, Dialer, this, Security::PeerConnector::commCloseHandler);
99  comm_add_close_handler(serverConnection()->fd, closeHandler);
100  return true;
101 }
102 
103 bool
105 {
106  Security::ContextPointer ctx(getTlsContext());
107  debugs(83, 5, serverConnection() << ", ctx=" << (void*)ctx.get());
108 
109  if (!ctx || !Security::CreateClientSession(ctx, serverConnection(), "server https start")) {
110  const auto xerrno = errno;
111  if (!ctx) {
112  debugs(83, DBG_IMPORTANT, "Error initializing TLS connection: No security context.");
113  } // else CreateClientSession() did the appropriate debugs() already
115  anErr->xerrno = xerrno;
116  noteNegotiationDone(anErr);
117  bail(anErr);
118  return false;
119  }
120 
121  // A TLS/SSL session has now been created for the connection and stored in fd_table
122  serverSession = fd_table[serverConnection()->fd].ssl;
123  debugs(83, 5, serverConnection() << ", session=" << (void*)serverSession.get());
124 
125 #if USE_OPENSSL
126  // If CertValidation Helper used do not lookup checklist for errors,
127  // but keep a list of errors to send it to CertValidator
128  if (!Ssl::TheConfig.ssl_crt_validator) {
129  // Create the ACL check list now, while we have access to more info.
130  // The list is used in ssl_verify_cb() and is freed in ssl_free().
131  if (acl_access *acl = ::Config.ssl_client.cert_error) {
132  ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
133  check->al = al;
134  // check->fd(fd); XXX: need client FD here
135  SSL_set_ex_data(serverSession.get(), ssl_ex_index_cert_error_check, check);
136  }
137  }
138 #endif
139 
140  return true;
141 }
142 
143 void
145 {
146  int timeToRead;
147  if (negotiationTimeout) {
148  const int timeUsed = squid_curtime - startTime;
149  const int timeLeft = max(0, static_cast<int>(negotiationTimeout - timeUsed));
150  timeToRead = min(static_cast<int>(::Config.Timeout.read), timeLeft);
151  } else
152  timeToRead = ::Config.Timeout.read;
153  AsyncCall::Pointer nil;
154  commSetConnTimeout(serverConnection(), timeToRead, nil);
155 }
156 
157 void
159 {
160  const int fd = serverConnection()->fd;
161  Security::SessionPointer session(fd_table[fd].ssl);
162 
163  // retrieve TLS server negotiated information if any
164  serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(session);
165 
166 #if USE_OPENSSL
167  // retrieve TLS parsed extra info
168  BIO *b = SSL_get_rbio(session.get());
169  Ssl::ServerBio *bio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
170  if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails())
171  serverConnection()->tlsNegotiations()->retrieveParsedInfo(details);
172 #endif
173 }
174 
175 void
177 {
178  if (!Comm::IsConnOpen(serverConnection()))
179  return;
180 
181  const int fd = serverConnection()->fd;
182  if (fd_table[fd].closing())
183  return;
184 
185 #if USE_OPENSSL
186  auto session = fd_table[fd].ssl.get();
187  debugs(83, 5, "SSL_connect session=" << (void*)session);
188  const int result = SSL_connect(session);
189  if (result <= 0) {
190 #elif USE_GNUTLS
191  auto session = fd_table[fd].ssl.get();
192  const int result = gnutls_handshake(session);
193  debugs(83, 5, "gnutls_handshake session=" << (void*)session << ", result=" << result);
194 
195  if (result == GNUTLS_E_SUCCESS) {
196  char *desc = gnutls_session_get_desc(session);
197  debugs(83, 2, serverConnection() << " TLS Session info: " << desc);
198  gnutls_free(desc);
199  }
200 
201  if (result != GNUTLS_E_SUCCESS) {
202  // debug the TLS session state so far
203  auto descIn = gnutls_handshake_get_last_in(session);
204  debugs(83, 2, "handshake IN: " << gnutls_handshake_description_get_name(descIn));
205  auto descOut = gnutls_handshake_get_last_out(session);
206  debugs(83, 2, "handshake OUT: " << gnutls_handshake_description_get_name(descOut));
207 #else
208  if (const int result = -1) {
209 #endif
210  handleNegotiateError(result);
211  return; // we might be gone by now
212  }
213 
214  recordNegotiationDetails();
215 
216  if (!sslFinalized())
217  return;
218 
219  callBack();
220 }
221 
222 bool
224 {
225 #if USE_OPENSSL
226  if (Ssl::TheConfig.ssl_crt_validator && useCertValidator_) {
227  const int fd = serverConnection()->fd;
228  Security::SessionPointer session(fd_table[fd].ssl);
229 
230  Ssl::CertValidationRequest validationRequest;
231  // WARNING: Currently we do not use any locking for 'errors' member
232  // of the Ssl::CertValidationRequest class. In this code the
233  // Ssl::CertValidationRequest object used only to pass data to
234  // Ssl::CertValidationHelper::submit method.
235  validationRequest.ssl = session;
236  if (SBuf *dName = (SBuf *)SSL_get_ex_data(session.get(), ssl_ex_index_server))
237  validationRequest.domainName = dName->c_str();
238  if (Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_errors)))
239  // validationRequest disappears on return so no need to cbdataReference
240  validationRequest.errors = errs;
241  try {
242  debugs(83, 5, "Sending SSL certificate for validation to ssl_crtvd.");
243  AsyncCall::Pointer call = asyncCall(83,5, "Security::PeerConnector::sslCrtvdHandleReply", Ssl::CertValidationHelper::CbDialer(this, &Security::PeerConnector::sslCrtvdHandleReply, nullptr));
244  Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, call);
245  return false;
246  } catch (const std::exception &e) {
247  debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
248  "request for " << validationRequest.domainName <<
249  " certificate: " << e.what() << "; will now block to " <<
250  "validate that certificate.");
251  // fall through to do blocking in-process generation.
253 
254  noteNegotiationDone(anErr);
255  bail(anErr);
256  serverConn->close();
257  return true;
258  }
259  }
260 #endif
261 
262  noteNegotiationDone(NULL);
263  return true;
264 }
265 
266 #if USE_OPENSSL
267 void
269 {
270  Must(validationResponse != NULL);
271 
272  Ssl::ErrorDetail *errDetails = NULL;
273  bool validatorFailed = false;
274  if (!Comm::IsConnOpen(serverConnection())) {
275  return;
276  }
277 
278  if (Debug::Enabled(83, 5)) {
279  Security::SessionPointer ssl(fd_table[serverConnection()->fd].ssl);
280  SBuf *server = static_cast<SBuf *>(SSL_get_ex_data(ssl.get(), ssl_ex_index_server));
281  debugs(83,5, RawPointer("host", server) << " cert validation result: " << validationResponse->resultCode);
282  }
283 
284  if (validationResponse->resultCode == ::Helper::Error) {
285  if (Security::CertErrors *errs = sslCrtvdCheckForErrors(*validationResponse, errDetails)) {
286  Security::SessionPointer session(fd_table[serverConnection()->fd].ssl);
287  Security::CertErrors *oldErrs = static_cast<Security::CertErrors*>(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_errors));
288  SSL_set_ex_data(session.get(), ssl_ex_index_ssl_errors, (void *)errs);
289  delete oldErrs;
290  }
291  } else if (validationResponse->resultCode != ::Helper::Okay)
292  validatorFailed = true;
293 
294  if (!errDetails && !validatorFailed) {
295  noteNegotiationDone(NULL);
296  callBack();
297  return;
298  }
299 
300  ErrorState *anErr = NULL;
301  if (validatorFailed) {
303  } else {
305  anErr->detail = errDetails;
306  /*anErr->xerrno= Should preserved*/
307  }
308 
309  noteNegotiationDone(anErr);
310  bail(anErr);
311  serverConn->close();
312  return;
313 }
314 #endif
315 
316 #if USE_OPENSSL
322 {
323  ACLFilledChecklist *check = NULL;
324  if (acl_access *acl = ::Config.ssl_client.cert_error) {
325  check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
326  check->al = al;
327  }
328 
329  Security::CertErrors *errs = nullptr;
330  Security::SessionPointer session(fd_table[serverConnection()->fd].ssl);
331  typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
332  for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) {
333  debugs(83, 7, "Error item: " << i->error_no << " " << i->error_reason);
334 
335  assert(i->error_no != SSL_ERROR_NONE);
336 
337  if (!errDetails) {
338  bool allowed = false;
339  if (check) {
340  check->sslErrors = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth));
341  if (check->fastCheck().allowed())
342  allowed = true;
343  }
344  // else the Config.ssl_client.cert_error access list is not defined
345  // and the first error will cause the error page
346 
347  if (allowed) {
348  debugs(83, 3, "bypassing SSL error " << i->error_no << " in " << "buffer");
349  } else {
350  debugs(83, 5, "confirming SSL error " << i->error_no);
351  X509 *brokenCert = i->cert.get();
352  Security::CertPointer peerCert(SSL_get_peer_certificate(session.get()));
353  const char *aReason = i->error_reason.empty() ? NULL : i->error_reason.c_str();
354  errDetails = new Ssl::ErrorDetail(i->error_no, peerCert.get(), brokenCert, aReason);
355  }
356  if (check) {
357  delete check->sslErrors;
358  check->sslErrors = NULL;
359  }
360  }
361 
362  if (!errs)
363  errs = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth));
364  else
365  errs->push_back_unique(Security::CertError(i->error_no, i->cert, i->error_depth));
366  }
367  if (check)
368  delete check;
369 
370  return errs;
371 }
372 #endif
373 
375 void
377 {
378  PeerConnector *pc = static_cast<Security::PeerConnector *>(data);
379  // Use job calls to add done() checks and other job logic/protections.
380  CallJobHere(83, 7, pc, Security::PeerConnector, negotiate);
381 }
382 
383 void
385 {
386  const int fd = serverConnection()->fd;
387  const Security::SessionPointer session(fd_table[fd].ssl);
388  unsigned long ssl_lib_error = ret;
389 
390 #if USE_OPENSSL
391  const int ssl_error = SSL_get_error(session.get(), ret);
392 
393  switch (ssl_error) {
394  case SSL_ERROR_WANT_READ:
395  noteWantRead();
396  return;
397 
398  case SSL_ERROR_WANT_WRITE:
399  noteWantWrite();
400  return;
401 
402  case SSL_ERROR_SSL:
403  case SSL_ERROR_SYSCALL:
404  ssl_lib_error = ERR_get_error();
405  // proceed to the general error handling code
406  break;
407  default:
408  // no special error handling for all other errors
409  ssl_lib_error = SSL_ERROR_NONE;
410  break;
411  }
412 
413 #elif USE_GNUTLS
414  const int ssl_error = ret;
415 
416  switch (ret) {
417  case GNUTLS_E_WARNING_ALERT_RECEIVED: {
418  auto alert = gnutls_alert_get(session.get());
419  debugs(83, DBG_IMPORTANT, "TLS ALERT: " << gnutls_alert_get_name(alert));
420  }
421  // drop through to next case
422 
423  case GNUTLS_E_AGAIN:
424  case GNUTLS_E_INTERRUPTED:
425  if (gnutls_record_get_direction(session.get()) == 0)
426  noteWantRead();
427  else
428  noteWantWrite();
429  return;
430 
431  default:
432  // no special error handling for all other errors
433  break;
434  }
435 
436 #else
437  // this avoids unused variable compiler warnings.
438  Must(!session);
439  const int ssl_error = ret;
440 #endif
441 
442  // Log connection details, if any
443  recordNegotiationDetails();
444  noteNegotiationError(ret, ssl_error, ssl_lib_error);
445 }
446 
447 void
449 {
450  const int fd = serverConnection()->fd;
451  debugs(83, 5, serverConnection());
452 #if USE_OPENSSL
453  Security::SessionPointer session(fd_table[fd].ssl);
454  BIO *b = SSL_get_rbio(session.get());
455  Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
456  if (srvBio->holdRead()) {
457  if (srvBio->gotHello()) {
458  if (checkForMissingCertificates())
459  return; // Wait to download certificates before proceed.
460 
461  srvBio->holdRead(false);
462  // schedule a negotiateSSl to allow openSSL parse received data
464  return;
465  } else if (srvBio->gotHelloFailed()) {
466  srvBio->holdRead(false);
467  debugs(83, DBG_IMPORTANT, "Error parsing SSL Server Hello Message on FD " << fd);
468  // schedule a negotiateSSl to allow openSSL parse received data
470  return;
471  }
472  }
473 #endif
474  setReadTimeout();
475  Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, this, 0);
476 }
477 
478 void
480 {
481  const int fd = serverConnection()->fd;
482  debugs(83, 5, serverConnection());
483  Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
484  return;
485 }
486 
487 void
488 Security::PeerConnector::noteNegotiationError(const int ret, const int ssl_error, const int ssl_lib_error)
489 {
490 #if defined(EPROTO)
491  int sysErrNo = EPROTO;
492 #else
493  int sysErrNo = EACCES;
494 #endif
495 
496 #if USE_OPENSSL
497  // store/report errno when ssl_error is SSL_ERROR_SYSCALL, ssl_lib_error is 0, and ret is -1
498  if (ssl_error == SSL_ERROR_SYSCALL && ret == -1 && ssl_lib_error == 0)
499  sysErrNo = errno;
500 #endif
501  int xerr = errno;
502 
503  const int fd = serverConnection()->fd;
504  debugs(83, DBG_IMPORTANT, "ERROR: negotiating TLS on FD " << fd <<
505  ": " << Security::ErrorString(ssl_lib_error) << " (" <<
506  ssl_error << "/" << ret << "/" << xerr << ")");
507 
509  anErr->xerrno = sysErrNo;
510 
511 #if USE_OPENSSL
512  Security::SessionPointer session(fd_table[fd].ssl);
513  Ssl::ErrorDetail *errFromFailure = static_cast<Ssl::ErrorDetail *>(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_error_detail));
514  if (errFromFailure != NULL) {
515  // The errFromFailure is attached to the ssl object
516  // and will be released when ssl object destroyed.
517  // Copy errFromFailure to a new Ssl::ErrorDetail object
518  anErr->detail = new Ssl::ErrorDetail(*errFromFailure);
519  } else {
520  // server_cert can be NULL here
521  X509 *server_cert = SSL_get_peer_certificate(session.get());
522  anErr->detail = new Ssl::ErrorDetail(SQUID_ERR_SSL_HANDSHAKE, server_cert, NULL);
523  X509_free(server_cert);
524  }
525 
526  if (ssl_lib_error != SSL_ERROR_NONE)
527  anErr->detail->setLibError(ssl_lib_error);
528 #endif
529 
530  noteNegotiationDone(anErr);
531  bail(anErr);
532 }
533 
534 void
536 {
537  Must(error); // or the recepient will not know there was a problem
538  Must(callback != NULL);
539  CbDialer *dialer = dynamic_cast<CbDialer*>(callback->getDialer());
540  Must(dialer);
541  dialer->answer().error = error;
542 
543  callBack();
544  // Our job is done. The callabck recepient will probably close the failed
545  // peer connection and try another peer or go direct (if possible). We
546  // can close the connection ourselves (our error notification would reach
547  // the recepient before the fd-closure notification), but we would rather
548  // minimize the number of fd-closure notifications and let the recepient
549  // manage the TCP state of the connection.
550 }
551 
552 void
554 {
555  debugs(83, 5, "TLS setup ended for " << serverConnection());
556 
558  // Do this now so that if we throw below, swanSong() assert that we _tried_
559  // to call back holds.
560  callback = NULL; // this should make done() true
561 
562  // remove close handler
563  comm_remove_close_handler(serverConnection()->fd, closeHandler);
564 
565  CbDialer *dialer = dynamic_cast<CbDialer*>(cb->getDialer());
566  Must(dialer);
567  dialer->answer().conn = serverConnection();
568  ScheduleCallHere(cb);
569 }
570 
571 void
573 {
574  // XXX: unregister fd-closure monitoring and CommSetSelect interest, if any
576  if (callback != NULL) { // paranoid: we have left the caller waiting
577  debugs(83, DBG_IMPORTANT, "BUG: Unexpected state while connecting to a cache_peer or origin server");
579  bail(anErr);
580  assert(!callback);
581  return;
582  }
583 }
584 
585 const char *
587 {
588  static MemBuf buf;
589  buf.reset();
590 
591  // TODO: redesign AsyncJob::status() API to avoid this
592  // id and stop reason reporting duplication.
593  buf.append(" [", 2);
594  if (stopReason != NULL) {
595  buf.append("Stopped, reason:", 16);
596  buf.appendf("%s",stopReason);
597  }
598  if (serverConn != NULL)
599  buf.appendf(" FD %d", serverConn->fd);
600  buf.appendf(" %s%u]", id.prefix(), id.value);
601  buf.terminate();
602 
603  return buf.content();
604 }
605 
606 #if USE_OPENSSL
609 {
610 public:
611  typedef void (Security::PeerConnector::*Method)(SBuf &object, int status);
612 
614  method_(method),
615  peerConnector_(pc) {}
616 
617  /* CallDialer API */
618  virtual bool canDial(AsyncCall &call) { return peerConnector_.valid(); }
619  virtual void dial(AsyncCall &call) { ((&(*peerConnector_))->*method_)(object, status); }
622 };
623 
624 void
626 {
627  AsyncCall::Pointer certCallback = asyncCall(81, 4,
628  "Security::PeerConnector::certDownloadingDone",
630 
631  const Downloader *csd = (request ? dynamic_cast<const Downloader*>(request->downloader.valid()) : nullptr);
632  Downloader *dl = new Downloader(url, certCallback, XactionInitiator::initCertFetcher, csd ? csd->nestedLevel() + 1 : 1);
633  AsyncJob::Start(dl);
634 }
635 
636 void
638 {
639  ++certsDownloads;
640  debugs(81, 5, "Certificate downloading status: " << downloadStatus << " certificate size: " << obj.length());
641 
642  // get ServerBio from SSL object
643  const int fd = serverConnection()->fd;
644  Security::SessionPointer session(fd_table[fd].ssl);
645  BIO *b = SSL_get_rbio(session.get());
646  Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
647 
648  // Parse Certificate. Assume that it is in DER format.
649  // According to RFC 4325:
650  // The server must provide a DER encoded certificate or a collection
651  // collection of certificates in a "certs-only" CMS message.
652  // The applications MUST accept DER encoded certificates and SHOULD
653  // be able to accept collection of certificates.
654  // TODO: support collection of certificates
655  const unsigned char *raw = (const unsigned char*)obj.rawContent();
656  if (X509 *cert = d2i_X509(NULL, &raw, obj.length())) {
657  char buffer[1024];
658  debugs(81, 5, "Retrieved certificate: " << X509_NAME_oneline(X509_get_subject_name(cert), buffer, 1024));
659  ContextPointer ctx(getTlsContext());
660  const Security::CertList &certsList = srvBio->serverCertificatesIfAny();
661  if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList, ctx)) {
662  urlsOfMissingCerts.push(SBuf(issuerUri));
663  }
664  Ssl::SSL_add_untrusted_cert(session.get(), cert);
665  }
666 
667  // Check if there are URIs to download from and if yes start downloading
668  // the first in queue.
669  if (urlsOfMissingCerts.size() && certsDownloads <= MaxCertsDownloads) {
670  startCertDownloading(urlsOfMissingCerts.front());
671  urlsOfMissingCerts.pop();
672  return;
673  }
674 
675  srvBio->holdRead(false);
676  Security::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
677 }
678 
679 bool
681 {
682  // Check for nested SSL certificates downloads. For example when the
683  // certificate located in an SSL site which requires to download a
684  // a missing certificate (... from an SSL site which requires to ...).
685 
686  const Downloader *csd = (request ? request->downloader.get() : nullptr);
687  if (csd && csd->nestedLevel() >= MaxNestedDownloads)
688  return false;
689 
690  const int fd = serverConnection()->fd;
691  Security::SessionPointer session(fd_table[fd].ssl);
692  BIO *b = SSL_get_rbio(session.get());
693  Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
694  const Security::CertList &certs = srvBio->serverCertificatesIfAny();
695 
696  if (certs.size()) {
697  debugs(83, 5, "SSL server sent " << certs.size() << " certificates");
698  ContextPointer ctx(getTlsContext());
699  Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs, ctx);
700  if (urlsOfMissingCerts.size()) {
701  startCertDownloading(urlsOfMissingCerts.front());
702  urlsOfMissingCerts.pop();
703  return true;
704  }
705  }
706 
707  return false;
708 }
709 #endif //USE_OPENSSL
710 
virtual bool doneAll() const
whether positive goal has been reached
Definition: AsyncJob.cc:96
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
Definition: AsyncJobCalls.h:68
#define fd_table
Definition: fde.h:157
#define COMM_SELECT_READ
Definition: defines.h:36
#define assert(EX)
Definition: assert.h:17
void const char HLPCB * callback
Definition: stub_helper.cc:16
RecvdErrors errors
The list of parsed errors.
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:57
void connectionClosed(const char *reason)
Inform us that the connection is closed. Does the required clean-up.
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:225
int ssl_ex_index_server
virtual const char * status() const
internal cleanup; do not call directly
CbcPointer< ErrorState > error
problem details (nil on success)
Definition: SBuf.h:87
void startCertDownloading(SBuf &url)
Start downloading procedure for the given URL.
PeerConnector(const Comm::ConnectionPointer &aServerConn, AsyncCall::Pointer &aCallback, const AccessLogEntryPointer &alp, const time_t timeout=0)
static CertValidationHelper * GetInstance()
Instance class.
Definition: helper.cc:171
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void error(char *format,...)
int i
Definition: membanger.c:49
CbcPointer< Security::PeerConnector > peerConnector_
The Security::PeerConnector object.
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
Missing intermediate certificates fetching code.
int ssl_ex_index_cert_error_check
CallDialer to allow use Downloader objects within PeerConnector class.
AsyncCall::Pointer callback
we call this with the results
A const & max(A const &lhs, A const &rhs)
CtoCpp1(X509_free, X509 *) typedef Security CtoCpp1(X509_CRL_free, X509_CRL *) typedef Security typedef std::list< Security::CertPointer CertList)
Definition: forward.h:96
struct SquidConfig::@123 ssl_client
time_t squid_curtime
Definition: stub_time.cc:17
bool holdRead() const
The read hold state.
Definition: bio.h:148
virtual void noteWantWrite()
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void commCloseHandler(const CommCloseCbParams &params)
The comm_close callback handler.
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
void sslSubmit(Ssl::CertValidationRequest const &request, AsyncCall::Pointer &)
Submit crtd request message to external crtd server.
Definition: helper.cc:301
void const char HLPCB void * data
Definition: stub_helper.cc:16
CbDataList< Security::CertError > CertErrors
Holds a list of X.509 certificate errors.
Definition: forward.h:81
virtual CallDialer * getDialer()=0
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:405
Security::SessionPointer ssl
int fd
FD which the call was about. Set by the async call creator.
Definition: CommCalls.h:90
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define true
Definition: GnuRegex.c:234
#define DBG_IMPORTANT
Definition: Debug.h:45
bool CreateClientSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx)
Definition: Session.cc:185
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:225
int ssl_ex_index_ssl_error_detail
bool push_back_unique(C const &element)
Definition: CbDataList.h:87
virtual void swanSong()
Definition: AsyncJob.h:55
void reset()
Definition: MemBuf.cc:141
void missingChainCertificatesUrls(std::queue< SBuf > &URIs, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
Definition: support.cc:1100
#define COMM_SELECT_WRITE
Definition: defines.h:37
static void NegotiateSsl(int fd, void *data)
A wrapper function for negotiateSsl for use with Comm::SetSelect.
virtual bool doneAll() const
whether positive goal has been reached
std::shared_ptr< SSL_CTX > ContextPointer
Definition: Context.h:28
bool allowed() const
Definition: Acl.h:141
virtual Security::EncryptorAnswer & answer()=0
gives PeerConnector access to the in-dialer answer
void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer)
Process response from cert validator helper.
void handleNegotiateError(const int result)
void SSL_add_untrusted_cert(SSL *ssl, X509 *cert)
Definition: support.cc:1112
int ssl_ex_index_ssl_errors
virtual void start()
Preps connection and SSL state. Calls negotiate().
char * content()
start of the added data
Definition: MemBuf.h:41
void const char * buf
Definition: stub_helper.cc:16
acl_access * cert_error
Definition: SquidConfig.h:512
unsigned int nestedLevel() const
The nested level of Downloader object (downloads inside downloads).
Definition: Downloader.h:57
const char * uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
Definition: support.cc:1079
#define Must(cond)
Definition: TextException.h:89
virtual void dial(AsyncCall &call)
#define SQUID_ERR_SSL_HANDSHAKE
Definition: support.h:42
Security::CertErrors * errors
The list of errors detected.
static ErrorState * NewForwarding(err_type, HttpRequestPointer &)
Creates a general request forwarding error with the right http_status.
Definition: errorpage.cc:553
std::string domainName
The server name.
allow_t const & fastCheck()
Definition: Checklist.cc:336
virtual bool canDial(AsyncCall &call)
#define ScheduleCallHere(call)
Definition: AsyncCall.h:166
static char server[MAXLINE]
void certDownloadingDone(SBuf &object, int status)
Called by Downloader after a certificate object downloaded.
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:69
Callback data to use with Downloader callbacks.
Definition: Downloader.h:35
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:126
Method method_
The Security::PeerConnector method to dial.
PeerConnectorCertDownloaderDialer(Method method, Security::PeerConnector *pc)
Definition: MemBuf.h:23
const Security::CertErrors * sslErrors
SSL [certificate validation] errors, in undefined order.
Comm::ConnectionPointer conn
peer connection (secured on success)
struct SquidConfig::@98 Timeout
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:961
virtual bool initialize(Security::SessionPointer &)
void * BIO_get_data(BIO *table)
Definition: bio.h:207
int xerrno
Definition: errorpage.h:148
CBDATA_NAMESPACED_CLASS_INIT(Security, PeerConnector)
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:43
#define acl_access
Definition: forward.h:44
void comm_remove_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:988
static bool Enabled(const int section, const int level)
whether debugging the given section and the given level produces output
Definition: Debug.h:73
virtual void noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error)
const char * rawContent() const
Definition: SBuf.cc:539
Ssl::ErrorDetail * detail
Definition: errorpage.h:170
void setLibError(unsigned long lib_err_no)
Sets the low-level error returned by OpenSSL ERR_get_error()
Definition: ErrorDetail.h:55
Security::CertErrors * sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&)
Check SSL errors returned from cert validator against sslproxy_cert_error access list.
RawPointerT< Pointer > RawPointer(const char *label, const Pointer &ptr)
convenience wrapper for creating RawPointerT<> objects
Definition: Debug.h:232
Config TheConfig
Definition: Config.cc:12
const char * ErrorString(const ErrorCode code)
Definition: forward.h:121
int commSetConnTimeout(const Comm::ConnectionPointer &conn, int timeout, AsyncCall::Pointer &callback)
Definition: comm.cc:552
void bail(ErrorState *error)
Return an error to the PeerConnector caller.
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
A const & min(A const &lhs, A const &rhs)
time_t read
Definition: SquidConfig.h:102
const char * dash_str
std::shared_ptr< SSL > SessionPointer
Definition: Session.h:41
void terminate()
Definition: MemBuf.cc:259

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors