clientConn(aClientConn),
callback(aCallback),
negotiationTimeout(timeout),
- startTime(squid_curtime)
+ startTime(squid_curtime),
+ splice(false)
{
// if this throws, the caller's cb dialer is not our CbDialer
Must(dynamic_cast<CbDialer*>(callback->getDialer()));
return; // we might be gone by now
}
+ if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
+ if (serverConnection()->getPeer()->sslSession)
+ SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
+
+ serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
+ }
+
+ if (!sslFinalized())
+ return;
+
+ callBack();
+}
+
+bool
+Ssl::PeerConnector::sslFinalized()
+{
+ const int fd = serverConnection()->fd;
+ SSL *ssl = fd_table[fd].ssl;
+
if (request->clientConnectionManager.valid()) {
// remember the server certificate from the ErrorDetail object
if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
}
}
- if (serverConnection()->getPeer() && !SSL_session_reused(ssl)) {
- if (serverConnection()->getPeer()->sslSession)
- SSL_SESSION_free(serverConnection()->getPeer()->sslSession);
-
- serverConnection()->getPeer()->sslSession = SSL_get1_session(ssl);
- }
-
if (Ssl::TheConfig.ssl_crt_validator) {
Ssl::CertValidationRequest validationRequest;
// WARNING: Currently we do not use any locking for any of the
try {
debugs(83, 5, "Sending SSL certificate for validation to ssl_crtvd.");
Ssl::CertValidationHelper::GetInstance()->sslSubmit(validationRequest, sslCrtvdHandleReplyWrapper, this);
- return;
+ return false;
} catch (const std::exception &e) {
debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
"request for " << validationRequest.domainName <<
peerConnectFailed(serverConnection()->getPeer());
}
serverConn->close();
- return;
+ return true;
}
}
-
- callBack();
+ return true;
}
-void switchToTunnel(HttpRequest *request, int *status_ptr, Comm::ConnectionPointer & clientConn, Comm::ConnectionPointer &srvConn);
+void switchToTunnel(HttpRequest *request, Comm::ConnectionPointer & clientConn, Comm::ConnectionPointer &srvConn);
void
Ssl::PeerConnector::cbCheckForPeekAndSpliceDone(allow_t answer, void *data)
Comm::SetSelect(serverConn->fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
debugs(83,5, "Retry the fwdNegotiateSSL on FD " << serverConn->fd);
} else {
- static int status_code = 0;
- debugs(83,5, "Revert to tunnel FD " << clientConn->fd << " with FD " << serverConn->fd);
- switchToTunnel(request.getRaw(), &status_code, clientConn, serverConn);
+ splice = true;
+ // Ssl Negotiation stops here. Last SSL checks for valid certificates
+ // and if done, switch to tunnel mode
+ if (sslFinalized())
+ switchToTunnel(request.getRaw(), clientConn, serverConn);
+ return false;
}
}
validatorFailed = true;
if (!errDetails && !validatorFailed) {
- callBack();
+ if (splice)
+ switchToTunnel(request.getRaw(), clientConn, serverConn);
+ else
+ callBack();
return;
}
/// It is called multiple times untill the negotiation finish or aborted.
void negotiateSsl();
+ /// Called after SSL negotiations have finished. Cleans up SSL state.
+ /// Returns false if we are now waiting for the certs validation job.
+ /// Otherwise, returns true, regardless of negotiation success/failure.
+ bool sslFinalized();
+
/// Initiates the ssl_bump acl check in step3 SSL bump step to decide
/// about bumping, splicing or terminating the connection.
void checkForPeekAndSplice();
AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
time_t negotiationTimeout; ///< the ssl connection timeout to use
time_t startTime; ///< when the peer connector negotiation started
+ bool splice; ///< Whether we are going to splice or not
CBDATA_CLASS2(PeerConnector);
};
#if USE_OPENSSL
void
-switchToTunnel(HttpRequest *request, int *status_ptr, Comm::ConnectionPointer &clientConn, Comm::ConnectionPointer &srvConn)
+switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::ConnectionPointer &srvConn)
{
- debugs(26, 3, HERE);
+ debugs(26,5, "Revert to tunnel FD " << clientConn->fd << " with FD " << srvConn->fd);
/* Create state structure. */
TunnelStateData *tunnelState = NULL;
const char *url = urlCanonical(request);
tunnelState->url = xstrdup(url);
tunnelState->request = request;
tunnelState->server.size_ptr = NULL; //Set later if ClientSocketContext is available
- tunnelState->status_ptr = status_ptr;
+
+ // Temporary static variable to store the unneeded for our case status code
+ static int status_code = 0;
+ tunnelState->status_ptr = &status_code;
tunnelState->client.conn = clientConn;
ConnStateData *conn;