/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
#include "base/RunnersRegistry.h"
#include "clientStreamForward.h"
#include "comm.h"
+#include "forward.h"
#include "helper/forward.h"
#include "http/forward.h"
#include "HttpControlMsg.h"
#include "ipc/FdNotes.h"
-#include "SBuf.h"
+#include "sbuf/SBuf.h"
#include "servers/Server.h"
#if USE_AUTH
#include "auth/UserRequest.h"
#endif
#if USE_OPENSSL
+#include "security/Handshake.h"
#include "ssl/support.h"
#endif
+#if USE_DELAY_POOLS
+#include "MessageBucket.h"
+#endif
class ClientHttpRequest;
class HttpHdrRangeSpec;
* managing, or for graceful half-close use the stopReceiving() or
* stopSending() methods.
*/
-class ConnStateData : public Server, public HttpControlMsgSink, public RegisteredRunner
+class ConnStateData : public Server, public HttpControlMsgSink, private IndependentRunner
{
public:
- explicit ConnStateData(const MasterXaction::Pointer &xact);
+ explicit ConnStateData(const MasterXactionPointer &xact);
virtual ~ConnStateData();
/* ::Server API */
/* HttpControlMsgSink API */
virtual void sendControlMsg(HttpControlMsg);
+ virtual void doneWithControlMsg();
/// Traffic parsing
bool clientParseRequests();
/// Initializes and starts a peek-and-splice negotiation with the SSL client
void startPeekAndSplice();
- /// Called when the initialization of peek-and-splice negotiation finidhed
- void startPeekAndSpliceDone();
+
/// Called when a peek-and-splice step finished. For example after
/// server SSL certificates received and fake server SSL certificates
/// generated
void httpsPeeked(Comm::ConnectionPointer serverConnection);
/// Splice a bumped client connection on peek-and-splice mode
- void splice();
-
- /// Check on_unsupported_protocol access list and splice if required
- /// \retval true on splice
- /// \retval false otherwise
- bool spliceOnError(const err_type err);
+ bool splice();
- /// Start to create dynamic Security::ContextPtr for host or uses static port SSL context.
+ /// Start to create dynamic Security::ContextPointer for host or uses static port SSL context.
void getSslContextStart();
/**
* Done create dynamic ssl certificate.
*
* \param[in] isNew if generated certificate is new, so we need to add this certificate to storage.
*/
- void getSslContextDone(Security::ContextPtr sslContext, bool isNew = false);
+ void getSslContextDone(Security::ContextPointer &, bool isNew = false);
/// Callback function. It is called when squid receive message from ssl_crtd.
static void sslCrtdHandleReplyWrapper(void *data, const Helper::Reply &reply);
/// Proccess response from ssl_crtd.
void sslCrtdHandleReply(const Helper::Reply &reply);
void switchToHttps(HttpRequest *request, Ssl::BumpMode bumpServerMode);
+ void parseTlsHandshake();
bool switchedToHttps() const { return switchedToHttps_; }
Ssl::ServerBump *serverBump() {return sslServerBump;}
inline void setServerBump(Ssl::ServerBump *srvBump) {
}
const SBuf &sslCommonName() const {return sslCommonName_;}
void resetSslCommonName(const char *name) {sslCommonName_ = name;}
+ const SBuf &tlsClientSni() const { return tlsClientSni_; }
/// Fill the certAdaptParams with the required data for certificate adaptation
/// and create the key for storing/retrieve the certificate to/from the cache
void buildSslCertGenerationParams(Ssl::CertificateProperties &certProperties);
Ssl::BumpMode sslBumpMode; ///< ssl_bump decision (Ssl::bumpEnd if n/a).
+ /// Tls parser to use for client HELLO messages parsing on bumped
+ /// connections.
+ Security::HandshakeParser tlsParser;
#else
bool switchedToHttps() const { return false; }
#endif
- /* clt_conn_tag=tag annotation access */
- const SBuf &connectionTag() const { return connectionTag_; }
- void connectionTag(const char *aTag) { connectionTag_ = aTag; }
-
/// handle a control message received by context from a peer and call back
- virtual void writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) = 0;
+ virtual bool writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) = 0;
/// ClientStream calls this to supply response header (once) and data
/// for the current Http::Stream.
/// generate a fake CONNECT request with the given payload
/// at the beginning of the client I/O buffer
- void fakeAConnectRequest(const char *reason, const SBuf &payload);
+ bool fakeAConnectRequest(const char *reason, const SBuf &payload);
+
+ /// generates and sends to tunnel.cc a fake request with a given payload
+ bool initiateTunneledRequest(HttpRequest::Pointer const &cause, Http::MethodType const method, const char *reason, const SBuf &payload);
+
+ /// whether tunneling of unsupported protocol is allowed for this connection
+ bool mayTunnelUnsupportedProto();
+
+ /// build a fake http request
+ ClientHttpRequest *buildFakeRequest(Http::MethodType const method, SBuf &useHost, unsigned short usePort, const SBuf &payload);
/// client data which may need to forward as-is to server after an
/// on_unsupported_protocol tunnel decision.
virtual void startShutdown();
virtual void endingShutdown();
+ /// \returns existing non-empty connection annotations,
+ /// creates and returns empty annotations otherwise
+ NotePairs::Pointer notes();
+ bool hasNotes() const { return bool(theNotes) && !theNotes->empty(); }
+
protected:
void startDechunkingRequest();
void finishDechunkingRequest(bool withSuccess);
virtual Http::Stream *parseOneRequest() = 0;
/// start processing a freshly parsed request
- virtual void processParsedRequest(Http::Stream *) = 0;
+ virtual void processParsedRequest(Http::StreamPointer &) = 0;
/// returning N allows a pipeline of 1+N requests (see pipeline_prefetch)
virtual int pipelinePrefetchMax() const;
/// timeout to use when waiting for the next request
virtual time_t idleTimeout() const = 0;
+ /// Perform client data lookups that depend on client src-IP.
+ /// The PROXY protocol may require some data input first.
+ void whenClientIpKnown();
+
BodyPipe::Pointer bodyPipe; ///< set when we are reading request body
private:
/* ::Server API */
virtual bool connFinishedWithConn(int size);
+ virtual void checkLogging();
void clientAfterReadingRequests();
bool concurrentRequestQueueFilled() const;
#if USE_OPENSSL
bool switchedToHttps_;
+ bool parsingTlsHandshake; ///< whether we are getting/parsing TLS Hello bytes
+
/// The SSL server host name appears in CONNECT request or the server ip address for the intercepted requests
String sslConnectHostOrIp; ///< The SSL server host name as passed in the CONNECT request
SBuf sslCommonName_; ///< CN name for SSL certificate generation
+
+ /// TLS client delivered SNI value. Empty string if none has been received.
+ SBuf tlsClientSni_;
String sslBumpCertKey; ///< Key to use to store/retrieve generated certificate
/// HTTPS server cert. fetching state for bump-ssl-server-first
const char *stoppedSending_;
/// the reason why we no longer read the request or nil
const char *stoppedReceiving_;
-
- SBuf connectionTag_; ///< clt_conn_tag=Tag annotation for client connection
+ /// Connection annotations, clt_conn_tag and other tags are stored here.
+ /// If set, are propagated to the current and all future master transactions
+ /// on the connection.
+ NotePairs::Pointer theNotes;
};
void setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl = false);
void clientSetKeepaliveFlag(ClientHttpRequest *http);
/// append a "part" HTTP header (as in a multi-part/range reply) to the buffer
-void clientPackRangeHdr(const HttpReply *, const HttpHdrRangeSpec *, String boundary, MemBuf *);
+void clientPackRangeHdr(const HttpReplyPointer &, const HttpHdrRangeSpec *, String boundary, MemBuf *);
/// put terminating boundary for multiparts to the buffer
void clientPackTermBound(String boundary, MemBuf *);