/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
if (acl_access *acl = ::Config.ssl_client.cert_error) {
ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
check->al = al;
+ check->syncAle(request.getRaw(), nullptr);
// check->fd(fd); XXX: need client FD here
SSL_set_ex_data(serverSession.get(), ssl_ex_index_cert_error_check, check);
}
#if USE_OPENSSL
// retrieve TLS parsed extra info
BIO *b = SSL_get_rbio(session.get());
- Ssl::ServerBio *bio = static_cast<Ssl::ServerBio *>(b->ptr);
+ Ssl::ServerBio *bio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails())
serverConnection()->tlsNegotiations()->retrieveParsedInfo(details);
#endif
if (result <= 0) {
#elif USE_GNUTLS
auto session = fd_table[fd].ssl.get();
- debugs(83, 5, "gnutls_handshake session=" << (void*)session);
const int result = gnutls_handshake(session);
+ debugs(83, 5, "gnutls_handshake session=" << (void*)session << ", result=" << result);
+
+ if (result == GNUTLS_E_SUCCESS) {
+ char *desc = gnutls_session_get_desc(session);
+ debugs(83, 2, serverConnection() << " TLS Session info: " << desc);
+ gnutls_free(desc);
+ }
+
if (result != GNUTLS_E_SUCCESS) {
- debugs(83, 5, "gnutls_handshake session=" << (void*)session << ", result=" << result);
+ // debug the TLS session state so far
+ auto descIn = gnutls_handshake_get_last_in(session);
+ debugs(83, 2, "handshake IN: " << gnutls_handshake_description_get_name(descIn));
+ auto descOut = gnutls_handshake_get_last_out(session);
+ debugs(83, 2, "handshake OUT: " << gnutls_handshake_description_get_name(descOut));
#else
if (const int result = -1) {
#endif
try {
debugs(83, 5, "Sending SSL certificate for validation to ssl_crtvd.");
AsyncCall::Pointer call = asyncCall(83,5, "Security::PeerConnector::sslCrtvdHandleReply", Ssl::CertValidationHelper::CbDialer(this, &Security::PeerConnector::sslCrtvdHandleReply, nullptr));
- Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, call);
+ Ssl::CertValidationHelper::Submit(validationRequest, call);
return false;
} catch (const std::exception &e) {
debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
if (acl_access *acl = ::Config.ssl_client.cert_error) {
check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
check->al = al;
+ check->syncAle(request.getRaw(), nullptr);
}
Security::CertErrors *errs = nullptr;
bool allowed = false;
if (check) {
check->sslErrors = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth));
- if (check->fastCheck() == ACCESS_ALLOWED)
+ if (check->fastCheck().allowed())
allowed = true;
}
// else the Config.ssl_client.cert_error access list is not defined
void
Security::PeerConnector::NegotiateSsl(int, void *data)
{
- PeerConnector *pc = static_cast<Security::PeerConnector *>(data);
+ const auto pc = static_cast<PeerConnector::Pointer*>(data);
+ if (pc->valid())
+ (*pc)->negotiateSsl();
+ delete pc;
+}
+
+/// Comm::SetSelect() callback. Direct calls tickle/resume negotiations.
+void
+Security::PeerConnector::negotiateSsl()
+{
// Use job calls to add done() checks and other job logic/protections.
- CallJobHere(83, 7, pc, Security::PeerConnector, negotiate);
+ CallJobHere(83, 7, this, Security::PeerConnector, negotiate);
}
void
switch (ret) {
case GNUTLS_E_WARNING_ALERT_RECEIVED: {
- auto alert = gnutls_alert_get(session.get());
- debugs(83, DBG_IMPORTANT, "TLS ALERT: " << gnutls_alert_get_name(alert));
- }
- // drop through to next case
+ auto alert = gnutls_alert_get(session.get());
+ debugs(83, DBG_IMPORTANT, "TLS ALERT: " << gnutls_alert_get_name(alert));
+ }
+ // drop through to next case
case GNUTLS_E_AGAIN:
case GNUTLS_E_INTERRUPTED:
if (gnutls_record_get_direction(session.get()) == 0)
- noteWantWrite();
- else
noteWantRead();
+ else
+ noteWantWrite();
return;
default:
Security::PeerConnector::noteWantRead()
{
const int fd = serverConnection()->fd;
+ debugs(83, 5, serverConnection());
#if USE_OPENSSL
Security::SessionPointer session(fd_table[fd].ssl);
BIO *b = SSL_get_rbio(session.get());
- Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+ Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
if (srvBio->holdRead()) {
if (srvBio->gotHello()) {
if (checkForMissingCertificates())
srvBio->holdRead(false);
// schedule a negotiateSSl to allow openSSL parse received data
- Security::PeerConnector::NegotiateSsl(fd, this);
+ negotiateSsl();
return;
} else if (srvBio->gotHelloFailed()) {
srvBio->holdRead(false);
debugs(83, DBG_IMPORTANT, "Error parsing SSL Server Hello Message on FD " << fd);
// schedule a negotiateSSl to allow openSSL parse received data
- Security::PeerConnector::NegotiateSsl(fd, this);
+ negotiateSsl();
return;
}
}
#endif
setReadTimeout();
- Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, this, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, &NegotiateSsl, new Pointer(this), 0);
}
void
Security::PeerConnector::noteWantWrite()
{
const int fd = serverConnection()->fd;
- Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
+ debugs(83, 5, serverConnection());
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, new Pointer(this), 0);
return;
}
if (ssl_error == SSL_ERROR_SYSCALL && ret == -1 && ssl_lib_error == 0)
sysErrNo = errno;
#endif
+ int xerr = errno;
const int fd = serverConnection()->fd;
debugs(83, DBG_IMPORTANT, "ERROR: negotiating TLS on FD " << fd <<
": " << Security::ErrorString(ssl_lib_error) << " (" <<
- ssl_error << "/" << ret << "/" << errno << ")");
+ ssl_error << "/" << ret << "/" << xerr << ")");
- ErrorState *anErr = NULL;
- if (request != NULL)
- anErr = ErrorState::NewForwarding(ERR_SECURE_CONNECT_FAIL, request.getRaw());
- else
- anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, NULL);
+ ErrorState *anErr = ErrorState::NewForwarding(ERR_SECURE_CONNECT_FAIL, request);
anErr->xerrno = sysErrNo;
#if USE_OPENSSL
// the recepient before the fd-closure notification), but we would rather
// minimize the number of fd-closure notifications and let the recepient
// manage the TCP state of the connection.
-
-#if USE_GNUTLS
- // but we do need to release the bad TLS related details in fd_table
- // ... or GnuTLS will SEGFAULT.
- const int fd = serverConnection()->fd;
- Security::SessionClose(fd_table[fd].ssl, fd);
-#endif
}
void
PeerConnectorCertDownloaderDialer(&Security::PeerConnector::certDownloadingDone, this));
const Downloader *csd = (request ? dynamic_cast<const Downloader*>(request->downloader.valid()) : nullptr);
- Downloader *dl = new Downloader(url, certCallback, csd ? csd->nestedLevel() + 1 : 1);
+ Downloader *dl = new Downloader(url, certCallback, XactionInitiator::initCertFetcher, csd ? csd->nestedLevel() + 1 : 1);
AsyncJob::Start(dl);
}
const int fd = serverConnection()->fd;
Security::SessionPointer session(fd_table[fd].ssl);
BIO *b = SSL_get_rbio(session.get());
- Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+ Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
// Parse Certificate. Assume that it is in DER format.
// According to RFC 4325:
if (X509 *cert = d2i_X509(NULL, &raw, obj.length())) {
char buffer[1024];
debugs(81, 5, "Retrieved certificate: " << X509_NAME_oneline(X509_get_subject_name(cert), buffer, 1024));
+ ContextPointer ctx(getTlsContext());
const Security::CertList &certsList = srvBio->serverCertificatesIfAny();
- if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList)) {
+ if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList, ctx)) {
urlsOfMissingCerts.push(SBuf(issuerUri));
}
Ssl::SSL_add_untrusted_cert(session.get(), cert);
}
srvBio->holdRead(false);
- Security::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
+ negotiateSsl();
}
bool
const int fd = serverConnection()->fd;
Security::SessionPointer session(fd_table[fd].ssl);
BIO *b = SSL_get_rbio(session.get());
- Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+ Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
const Security::CertList &certs = srvBio->serverCertificatesIfAny();
if (certs.size()) {
debugs(83, 5, "SSL server sent " << certs.size() << " certificates");
- Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs);
+ ContextPointer ctx(getTlsContext());
+ Ssl::missingChainCertificatesUrls(urlsOfMissingCerts, certs, ctx);
if (urlsOfMissingCerts.size()) {
startCertDownloading(urlsOfMissingCerts.front());
urlsOfMissingCerts.pop();