33 const time_t timeout):
34 AsyncJob(
"Ssl::PeekingPeerConnector"),
35 Security::PeerConnector(aServerConn, aCallback, alp, timeout),
36 clientConn(aClientConn),
38 serverCertificateHandled(false)
43 const auto serverBump = csd->serverBump();
63 checkForPeekAndSpliceGuess();
64 checkForPeekAndSpliceMatched(finalAction);
70 handleServerCertificate();
73 acl_checklist->al = al;
80 BIO *b = SSL_get_rbio(session.get());
86 acl_checklist->syncAle(request.getRaw(),
nullptr);
94 BIO *b = SSL_get_rbio(session.get());
96 debugs(83,5,
"Will check for peek and splice on FD " << serverConn->fd);
101 if (request->clientConnectionManager.valid()) {
102 request->clientConnectionManager->sslBumpMode = finalAction;
103 request->clientConnectionManager->serverBump()->act.step3 = finalAction;
105 al->ssl.bumpMode = finalAction;
110 clientConn =
nullptr;
115 debugs(83,5,
"Retry the fwdNegotiateSSL on FD " << serverConn->fd);
121 if (sslFinalized() && callback)
129 if (
const ConnStateData *csd = request->clientConnectionManager.valid()) {
132 debugs(83,5,
"default to bumping after staring");
135 debugs(83,5,
"default to splicing after " << currentMode);
137 debugs(83,3,
"default to splicing due to missing info");
146 return ::Config.ssl_client.defaultPeerContext;
160 if (
ConnStateData *csd = request->clientConnectionManager.valid()) {
162 SBuf *hostName =
nullptr;
165 SSL_set_tlsext_status_type(serverSession.get(), TLSEXT_STATUSTYPE_ocsp);
168 if (details && !details->serverName.isEmpty())
169 hostName =
new SBuf(details->serverName);
175 const bool isConnectRequest = !csd->port->flags.isIntercepted();
176 if (!request->flags.sslPeek || isConnectRequest)
177 hostName =
new SBuf(request->url.host());
184 auto clientSession =
fd_table[clientConn->fd].ssl.get();
186 BIO *bc = SSL_get_rbio(clientSession);
192 BIO *b = SSL_get_rbio(serverSession.get());
198 srvBio->
mode(csd->sslBumpMode);
200 const bool redirected = request->flags.redirected && ::Config.onoff.redir_rewrites_host;
201 const char *sniServer = (!hostName || redirected) ?
202 request->url.host() :
209 serverBump->attachServerSession(serverSession);
211 if (X509 *peeked_cert = serverBump->serverCert.get()) {
212 X509_up_ref(peeked_cert);
225 if (!request->clientConnectionManager.valid() || !
fd_table[serverConnection()->fd].ssl)
229 if (
Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
230 if (!serverBump->serverCert.get()) {
233 if (errDetail && errDetail->peerCert())
234 serverBump->serverCert.resetAndLock(errDetail->peerCert());
236 handleServerCertificate();
244 const bool isConnectRequest = !request->clientConnectionManager->port->flags.isIntercepted();
245 if (request->flags.sslPeek && !isConnectRequest) {
246 if (X509 *srvX509 = serverBump->serverCert.get()) {
248 request->url.host(name);
249 debugs(83, 3,
"reset request host: " << name);
257 serverCertificateVerified();
272 fd_table[serverConn->fd].useDefaultIo();
274 fd_table[clientConn->fd].useDefaultIo();
277 const auto session =
fd_table[serverConn->fd].ssl;
278 auto b = SSL_get_rbio(session.get());
281 debugs(83, 5,
"will tunnel instead of negotiating TLS");
282 switchToTunnel(request.getRaw(), clientConn, serverConn, srvBio->rBufData());
283 answer().tunneled =
true;
291 const int fd = serverConnection()->fd;
293 BIO *b = SSL_get_rbio(session.get());
297 debugs(81, 3,
"hold write on SSL connection on FD " << fd);
298 checkForPeekAndSplice();
308 const int fd = serverConnection()->fd;
310 BIO *b = SSL_get_rbio(session.get());
314 auto bypassValidator =
false;
320 bypassValidator =
true;
330 bypassValidator =
true;
334 if (bypassValidator) {
335 bypassCertValidator();
357 debugs(81, 3,
"hold TLS write on FD " << fd <<
" despite " << errorDetail);
358 checkForPeekAndSplice();
370 if (serverCertificateHandled)
373 if (
ConnStateData *csd = request->clientConnectionManager.valid()) {
374 const int fd = serverConnection()->fd;
380 serverCertificateHandled =
true;
384 serverBump->serverCert = std::move(serverCert);
392 if (
ConnStateData *csd = request->clientConnectionManager.valid()) {
397 const int fd = serverConnection()->fd;
403 debugs(83, 5,
"HTTPS server CN: " << csd->sslCommonName() <<
404 " bumped: " << *serverConnection());
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
#define Here()
source code location of the caller
void error(char *format,...)
void applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
static MakingPointer Make(const acl_access *a, HttpRequest *r)
static void NonBlockingCheck(MakingPointer &&p, ACLCB *cb, void *data)
int kind
the matched custom access list verb (or zero)
a smart AsyncCall pointer for delivery of future results
Cbc * valid() const
was set and is valid
CbcPointer< ConnStateData > clientConnectionManager
A combination of PeerOptions and the corresponding Context.
void resetWithoutLocking(T *t)
Reset raw pointer - unlock any previous one and save new one without locking.
T * get() const
Returns raw and possibly nullptr pointer.
virtual bool initialize(Security::SessionPointer &)
virtual void noteNegotiationError(const Security::ErrorDetailPointer &)
Called when the SSL_connect function aborts with an SSL negotiation error.
virtual void noteWantWrite()
HttpRequestPointer request
peer connection trigger or cause
const SBuf & rBufData()
The buffered input data.
A PeerConnector for HTTP origin servers. Capable of SslBumping.
bool initialize(Security::SessionPointer &) override
void checkForPeekAndSpliceDone(Acl::Answer)
Callback function for ssl_bump acl check in step3 SSL bump step.
void noteNegotiationError(const Security::ErrorDetailPointer &) override
Called when the SSL_connect function aborts with an SSL negotiation error.
void startTunneling()
Abruptly stops TLS negotiation and starts tunneling.
void checkForPeekAndSpliceMatched(const Ssl::BumpMode finalMode)
Handles the final bumping decision.
void checkForPeekAndSplice()
void noteNegotiationDone(ErrorState *error) override
void handleServerCertificate()
static void cbCheckForPeekAndSpliceDone(Acl::Answer, void *data)
A wrapper function for checkForPeekAndSpliceDone for use with acl.
PeekingPeerConnector(HttpRequestPointer &aRequest, const Comm::ConnectionPointer &aServerConn, const Comm::ConnectionPointer &aClientConn, const AsyncCallback< Security::EncryptorAnswer > &aCallback, const AccessLogEntryPointer &alp, time_t timeout=0)
Security::FuturePeerContext * peerContext() const override
void serverCertificateVerified()
Ssl::BumpMode checkForPeekAndSpliceGuess() const
Guesses the final bumping decision when no ssl_bump rules match.
void noteWantWrite() override
void mode(Ssl::BumpMode m)
The bumping mode.
bool holdWrite() const
The write hold state.
void recordInput(bool r)
Enables or disables the input data recording, for internal analysis.
bool canBump()
Whether we can bump or not the SSL stream.
void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello)
Sets the random number to use in client SSL HELLO message.
bool encryptedCertificates() const
Ssl::BumpMode bumpMode()
return the bumping mode
bool canSplice()
Whether we can splice or not the SSL stream.
an std::runtime_error with thrower location info
#define debugs(SECTION, LEVEL, CONTENT)
@ ERR_SECURE_CONNECT_FAIL
int ssl_ex_index_ssl_peeked_cert
int ssl_ex_index_ssl_error_detail
void setClientSNI(SSL *ssl, const char *fqdn)
const char * CommonHostName(X509 *x509)
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Network/connection security abstraction layer.
std::shared_ptr< SSL > SessionPointer
void * BIO_get_data(BIO *table)
void switchToTunnel(HttpRequest *request, const Comm::ConnectionPointer &clientConn, const Comm::ConnectionPointer &srvConn, const SBuf &preReadServerData)