Been digging around in library guts and yes you were right Alex - for
OpenSSL and the very old ones based on SSL protocol. Just not for the
other N libraries based on TLS design which I/we hope to support. There
is structural difference between the two protocols layering and activities.
I'm labeling the patch revert, but it is not a true revert as that would
unwind much other progress and bug fixes. It is more a rename of most
'session' to 'connection' for the Pointer type and text surrounding the
changed variables. With a split of the session and connection API
functionality into separate files along the lines of how Session and
Context are currently split.
NP: passes 'make check', and some few basic https:// fetches (to server
only) respond okay.
I did track down why the previous patch code was broken. It turns out my
available OpenSSL libraries (both 1.0 and 1.1) require the hacks (#if
case for 1.0, or the #elif case for 1.1) - the broken #else case code
never compiles here.
Amos
=== modified file 'src/adaptation/icap/Xaction.cc'
--- src/adaptation/icap/Xaction.cc 2017-02-16 11:51:56 +0000
+++ src/adaptation/icap/Xaction.cc 2017-04-25 16:59:06 +0000
@@ -43,41 +43,41 @@
/* Security::PeerConnector::CbDialer API */
virtual Security::EncryptorAnswer &answer() { return arg1; }
};
namespace Ssl
{
/// A simple PeerConnector for Secure ICAP services. No SslBump capabilities.
class IcapPeerConnector: public Security::PeerConnector {
CBDATA_CLASS(IcapPeerConnector);
public:
IcapPeerConnector(
Adaptation::Icap::ServiceRep::Pointer &service,
const Comm::ConnectionPointer &aServerConn,
AsyncCall::Pointer &aCallback,
AccessLogEntry::Pointer const &alp,
const time_t timeout = 0):
AsyncJob("Ssl::IcapPeerConnector"),
Security::PeerConnector(aServerConn, aCallback, alp, timeout), icapService(service) {}
/* Security::PeerConnector API */
- virtual bool initialize(Security::SessionPointer &);
+ virtual bool initialize(Security::ConnectionPointer &);
virtual void noteNegotiationDone(ErrorState *error);
virtual Security::ContextPointer getTlsContext() {
return icapService->sslContext;
}
private:
Adaptation::Icap::ServiceRep::Pointer icapService;
};
} // namespace Ssl
CBDATA_NAMESPACED_CLASS_INIT(Ssl, IcapPeerConnector);
Adaptation::Icap::Xaction::Xaction(const char *aTypeName, Adaptation::Icap::ServiceRep::Pointer &aService):
AsyncJob(aTypeName),
Adaptation::Initiate(aTypeName),
icapRequest(NULL),
icapReply(NULL),
attempts(0),
connection(NULL),
theService(aService),
@@ -689,41 +689,41 @@
buf.append(";", 1);
}
}
void Adaptation::Icap::Xaction::fillDoneStatus(MemBuf &buf) const
{
if (haveConnection() && commEof)
buf.appendf("Comm(%d)", connection->fd);
if (stopReason != NULL)
buf.append("Stopped", 7);
}
bool Adaptation::Icap::Xaction::fillVirginHttpHeader(MemBuf &) const
{
return false;
}
bool
-Ssl::IcapPeerConnector::initialize(Security::SessionPointer &serverSession)
+Ssl::IcapPeerConnector::initialize(Security::ConnectionPointer &serverSession)
{
if (!Security::PeerConnector::initialize(serverSession))
return false;
assert(!icapService->cfg().secure.sslDomain.isEmpty());
#if USE_OPENSSL
SBuf *host = new SBuf(icapService->cfg().secure.sslDomain);
SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, host);
ACLFilledChecklist *check = static_cast<ACLFilledChecklist *>(SSL_get_ex_data(serverSession.get(), ssl_ex_index_cert_error_check));
if (check)
check->dst_peer_name = *host;
#endif
Security::SetSessionResumeData(serverSession, icapService->sslSession);
return true;
}
void
Ssl::IcapPeerConnector::noteNegotiationDone(ErrorState *error)
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2017-04-14 09:27:23 +0000
+++ src/client_side.cc 2017-04-25 17:07:50 +0000
@@ -2548,41 +2548,41 @@
}
debugs(33, 4, params.conn << ": accepted");
fd_note(params.conn->fd, "client http connect");
if (s->tcp_keepalive.enabled)
commSetTcpKeepalive(params.conn->fd, s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
++incoming_sockets_accepted;
// Socket is ready, setup the connection manager to start using it
auto *srv = Http::NewServer(xact);
AsyncJob::Start(srv); // usually async-calls readSomeData()
}
#if USE_OPENSSL
/// Create TLS connection structure and update fd_table
static bool
httpsCreate(const Comm::ConnectionPointer &conn, const Security::ContextPointer &ctx)
{
- if (Security::CreateServerSession(ctx, conn, "client https start")) {
+ if (Security::CreateServer(ctx, conn, "client https start")) {
debugs(33, 5, "will negotiate TLS on " << conn);
return true;
}
conn->close();
return false;
}
/**
*
* \retval 1 on success
* \retval 0 when needs more data
* \retval -1 on error
*/
static int
Squid_SSL_accept(ConnStateData *conn, PF *callback)
{
int fd = conn->clientConnection->fd;
auto ssl = fd_table[fd].ssl.get();
int ret;
@@ -2622,90 +2622,90 @@
return -1;
}
/* NOTREACHED */
}
return 1;
}
/** negotiate an SSL connection */
static void
clientNegotiateSSL(int fd, void *data)
{
ConnStateData *conn = (ConnStateData *)data;
int ret;
if ((ret = Squid_SSL_accept(conn, clientNegotiateSSL)) <= 0) {
if (ret < 0) // An error
conn->clientConnection->close();
return;
}
- Security::SessionPointer session(fd_table[fd].ssl);
- if (Security::SessionIsResumed(session)) {
- debugs(83, 2, "Session " << SSL_get_session(session.get()) <<
+ Security::ConnectionPointer theAnSsl(fd_table[fd].ssl);
+ if (Security::SessionIsResumed(theAnSsl)) {
+ debugs(83, 2, "Session " << SSL_get_session(theAnSsl.get()) <<
" reused on FD " << fd << " (" << fd_table[fd].ipaddr <<
":" << (int)fd_table[fd].remote_port << ")");
} else {
if (Debug::Enabled(83, 4)) {
/* Write out the SSL session details.. actually the call below, but
* OpenSSL headers do strange typecasts confusing GCC.. */
/* PEM_write_SSL_SESSION(debug_log, SSL_get_session(ssl)); */
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x00908000L
PEM_ASN1_write(reinterpret_cast<i2d_of_void *>(i2d_SSL_SESSION),
PEM_STRING_SSL_SESSION, debug_log,
- reinterpret_cast<char *>(SSL_get_session(session.get())),
+ reinterpret_cast<char *>(SSL_get_session(theAnSsl.get())),
nullptr, nullptr, 0, nullptr, nullptr);
#elif (ALLOW_ALWAYS_SSL_SESSION_DETAIL == 1)
/* When using gcc 3.3.x and OpenSSL 0.9.7x sometimes a compile error can occur here.
* This is caused by an unpredicatble gcc behaviour on a cast of the first argument
* of PEM_ASN1_write(). For this reason this code section is disabled. To enable it,
* define ALLOW_ALWAYS_SSL_SESSION_DETAIL=1.
* Because there are two possible usable cast, if you get an error here, try the other
* commented line. */
PEM_ASN1_write((int(*)())i2d_SSL_SESSION, PEM_STRING_SSL_SESSION,
debug_log,
- reinterpret_cast<char *>(SSL_get_session(session.get())),
+ reinterpret_cast<char *>(SSL_get_session(theAnSsl.get())),
nullptr, nullptr, 0, nullptr, nullptr);
/* PEM_ASN1_write((int(*)(...))i2d_SSL_SESSION, PEM_STRING_SSL_SESSION,
debug_log,
- reinterpret_cast<char *>(SSL_get_session(session.get())),
+ reinterpret_cast<char *>(SSL_get_session(theAnSsl.get())),
nullptr, nullptr, 0, nullptr, nullptr);
*/
#else
debugs(83, 4, "With " OPENSSL_VERSION_TEXT ", session details are available only defining ALLOW_ALWAYS_SSL_SESSION_DETAIL=1 in the source.");
#endif
/* Note: This does not automatically fflush the log file.. */
}
- debugs(83, 2, "New session " << SSL_get_session(session.get()) <<
+ debugs(83, 2, "New session " << SSL_get_session(theAnSsl.get()) <<
" on FD " << fd << " (" << fd_table[fd].ipaddr << ":" <<
fd_table[fd].remote_port << ")");
}
// Connection established. Retrieve TLS connection parameters for logging.
- conn->clientConnection->tlsNegotiations()->retrieveNegotiatedInfo(session);
+ conn->clientConnection->tlsNegotiations()->retrieveNegotiatedInfo(theAnSsl);
- X509 *client_cert = SSL_get_peer_certificate(session.get());
+ X509 *client_cert = SSL_get_peer_certificate(theAnSsl.get());
if (client_cert) {
debugs(83, 3, "FD " << fd << " client certificate: subject: " <<
X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0));
debugs(83, 3, "FD " << fd << " client certificate: issuer: " <<
X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0));
X509_free(client_cert);
} else {
debugs(83, 5, "FD " << fd << " has no certificate.");
}
conn->readSomeData();
}
/**
* If Security::ContextPointer is given, starts reading the TLS handshake.
* Otherwise, calls switchToHttps to generate a dynamic Security::ContextPointer.
*/
=== modified file 'src/comm.cc'
--- src/comm.cc 2017-02-19 17:13:27 +0000
+++ src/comm.cc 2017-04-24 03:32:58 +0000
@@ -742,41 +742,41 @@
if (n < 0) {
int xerrno = errno;
debugs(5, 3, "FD " << fd << " read: " << xstrerr(xerrno));
}
comm_close(fd);
}
static void
commLingerTimeout(const FdeCbParams ¶ms)
{
debugs(5, 3, "commLingerTimeout: FD " << params.fd);
comm_close(params.fd);
}
/*
* Inspired by apache
*/
void
comm_lingering_close(int fd)
{
- Security::SessionSendGoodbye(fd_table[fd].ssl);
+ Security::SendGoodbye(fd_table[fd].ssl);
if (shutdown(fd, 1) < 0) {
comm_close(fd);
return;
}
fd_note(fd, "lingering close");
AsyncCall::Pointer call = commCbCall(5,4, "commLingerTimeout", FdeCbPtrFun(commLingerTimeout, NULL));
debugs(5, 3, HERE << "FD " << fd << " timeout " << timeout);
assert(fd_table[fd].flags.open);
if (callback != NULL) {
typedef FdeCbParams Params;
Params ¶ms = GetCommParams<Params>(callback);
params.fd = fd;
fd_table[fd].timeoutHandler = callback;
fd_table[fd].timeout = squid_curtime + static_cast<time_t>(10);
}
Comm::SetSelect(fd, COMM_SELECT_READ, commLingerClose, NULL, 0);
@@ -803,41 +803,41 @@
}
// Legacy close function.
void
old_comm_reset_close(int fd)
{
struct linger L;
L.l_onoff = 1;
L.l_linger = 0;
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0) {
int xerrno = errno;
debugs(50, DBG_CRITICAL, "ERROR: Closing FD " << fd << " with TCP RST: " << xstrerr(xerrno));
}
comm_close(fd);
}
void
commStartTlsClose(const FdeCbParams ¶ms)
{
- Security::SessionSendGoodbye(fd_table[params.fd].ssl);
+ Security::SendGoodbye(fd_table[params.fd].ssl);
}
void
comm_close_complete(const FdeCbParams ¶ms)
{
fde *F = &fd_table[params.fd];
F->ssl.reset();
F->dynamicTlsContext.reset();
fd_close(params.fd); /* update fdstat */
close(params.fd);
++ statCounter.syscalls.sock.closes;
/* When one connection closes, give accept() a chance, if need be */
Comm::AcceptLimiter::Instance().kick();
}
/*
* Close the socket fd.
*
=== modified file 'src/fde.h'
--- src/fde.h 2017-02-19 17:13:27 +0000
+++ src/fde.h 2017-04-25 16:59:06 +0000
@@ -118,41 +118,41 @@
#if USE_DELAY_POOLS
/// pointer to client info used in client write limiter or nullptr if not present
ClientInfo * clientInfo = nullptr;
MessageBucket::Pointer writeQuotaHandler; ///< response write limiter, if configured
#endif
unsigned epoll_state = 0;
_fde_disk disk;
PF *read_handler;
void *read_data = nullptr;
PF *write_handler;
void *write_data = nullptr;
AsyncCall::Pointer timeoutHandler;
time_t timeout = 0;
time_t writeStart = 0;
void *lifetime_data = nullptr;
AsyncCall::Pointer closeHandler;
AsyncCall::Pointer halfClosedReader; /// read handler for half-closed fds
READ_HANDLER *read_method;
WRITE_HANDLER *write_method;
- Security::SessionPointer ssl;
+ Security::ConnectionPointer ssl;
Security::ContextPointer dynamicTlsContext; ///< cached and then freed when fd is closed
#if _SQUID_WINDOWS_
struct {
long handle = (long)nullptr;
} win32;
#endif
tos_t tosFromServer = '\0'; /**< Stores the TOS flags of the packets from the remote server.
See FwdState::dispatch(). Note that this differs to
tosToServer in that this is the value we *receive* from the,
connection, whereas tosToServer is the value to set on packets
*leaving* Squid. */
unsigned int nfmarkFromServer = 0; /**< Stores the Netfilter mark value of the connection from the remote
server. See FwdState::dispatch(). Note that this differs to
nfmarkToServer in that this is the value we *receive* from the,
connection, whereas nfmarkToServer is the value to set on packets
*leaving* Squid. */
};
#define fd_table fde::Table
=== modified file 'src/security/BlindPeerConnector.cc'
--- src/security/BlindPeerConnector.cc 2017-01-12 13:26:45 +0000
+++ src/security/BlindPeerConnector.cc 2017-04-25 16:59:06 +0000
@@ -13,41 +13,41 @@
#include "fde.h"
#include "HttpRequest.h"
#include "neighbors.h"
#include "security/BlindPeerConnector.h"
#include "security/NegotiationHistory.h"
#include "SquidConfig.h"
CBDATA_NAMESPACED_CLASS_INIT(Security, BlindPeerConnector);
Security::ContextPointer
Security::BlindPeerConnector::getTlsContext()
{
if (const CachePeer *peer = serverConnection()->getPeer()) {
assert(peer->secure.encryptTransport);
return peer->sslContext;
}
return ::Config.ssl_client.sslContext;
}
bool
-Security::BlindPeerConnector::initialize(Security::SessionPointer &serverSession)
+Security::BlindPeerConnector::initialize(Security::ConnectionPointer &serverSession)
{
if (!Security::PeerConnector::initialize(serverSession)) {
debugs(83, 5, "Security::PeerConnector::initialize failed");
return false;
}
if (const CachePeer *peer = serverConnection()->getPeer()) {
assert(peer);
// NP: domain may be a raw-IP but it is now always set
assert(!peer->secure.sslDomain.isEmpty());
#if USE_OPENSSL
// const loss is okay here, ssl_ex_index_server is only read and not assigned a destructor
SBuf *host = new SBuf(peer->secure.sslDomain);
SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, host);
Security::SetSessionResumeData(serverSession, peer->sslSession);
} else {
SBuf *hostName = new SBuf(request->url.host());
=== modified file 'src/security/BlindPeerConnector.h'
--- src/security/BlindPeerConnector.h 2017-01-01 00:12:22 +0000
+++ src/security/BlindPeerConnector.h 2017-04-25 16:59:06 +0000
@@ -20,34 +20,34 @@
class BlindPeerConnector: public Security::PeerConnector {
CBDATA_CLASS(BlindPeerConnector);
public:
BlindPeerConnector(HttpRequestPointer &aRequest,
const Comm::ConnectionPointer &aServerConn,
AsyncCall::Pointer &aCallback,
const AccessLogEntryPointer &alp,
const time_t timeout = 0) :
AsyncJob("Security::BlindPeerConnector"),
Security::PeerConnector(aServerConn, aCallback, alp, timeout)
{
request = aRequest;
}
/* Security::PeerConnector API */
/// Calls parent initialize(), configures the created TLS session object
/// to try and reuse a TLS session and sets the hostname to use for
/// certificate validation
/// \returns true on successful initialization
- virtual bool initialize(Security::SessionPointer &);
+ virtual bool initialize(Security::ConnectionPointer &);
/// Return the configured TLS context object
virtual Security::ContextPointer getTlsContext();
/// On error calls peerConnectFailed().
/// On success store the used TLS session for later use.
virtual void noteNegotiationDone(ErrorState *);
};
} // namespace Security
#endif /* SQUID_SRC_SECURITY_BLINDPEERCONNECTOR_H */
=== added file 'src/security/Connection.cc'
--- src/security/Connection.cc 1970-01-01 00:00:00 +0000
+++ src/security/Connection.cc 2017-04-25 17:41:39 +0000
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "anyp/PortCfg.h"
+#include "base/RunnersRegistry.h"
+#include "CachePeer.h"
+#include "Debug.h"
+#include "fd.h"
+#include "fde.h"
+#include "ipc/MemMap.h"
+#include "security/Connection.h"
+#include "SquidConfig.h"
+#include "ssl/bio.h"
+
+#define SSL_SESSION_ID_SIZE 32
+#define SSL_SESSION_MAX_SIZE 10*1024
+
+#if USE_OPENSSL || USE_GNUTLS
+static int
+tls_read_method(int fd, char *buf, int len)
+{
+ auto handle = fd_table[fd].ssl.get();
+ debugs(83, 3, "started for handle=" << (void*)handle);
+
+#if DONT_DO_THIS && USE_OPENSSL
+ if (!SSL_is_init_finished(handle)) {
+ errno = ENOTCONN;
+ return -1;
+ }
+#endif
+
+#if USE_OPENSSL
+ int i = SSL_read(handle, buf, len);
+#elif USE_GNUTLS
+ int i = gnutls_record_recv(handle, buf, len);
+#endif
+
+ if (i > 0) {
+ debugs(83, 8, "TLS FD " << fd << " handle=" << (void*)handle << " " << i << " bytes");
+ (void)VALGRIND_MAKE_MEM_DEFINED(buf, i);
+ }
+
+#if USE_OPENSSL
+ if (i > 0 && SSL_pending(handle) > 0) {
+#elif USE_GNUTLS
+ if (i > 0 && gnutls_record_check_pending(handle) > 0) {
+#endif
+ debugs(83, 2, "TLS FD " << fd << " is pending");
+ fd_table[fd].flags.read_pending = true;
+ } else
+ fd_table[fd].flags.read_pending = false;
+
+ return i;
+}
+
+static int
+tls_write_method(int fd, const char *buf, int len)
+{
+ auto handle = fd_table[fd].ssl.get();
+ debugs(83, 3, "started for handle=" << (void*)handle);
+
+#if USE_OPENSSL
+ if (!SSL_is_init_finished(handle)) {
+ errno = ENOTCONN;
+ return -1;
+ }
+#endif
+
+#if USE_OPENSSL
+ int i = SSL_write(handle, buf, len);
+#elif USE_GNUTLS
+ int i = gnutls_record_send(handle, buf, len);
+#endif
+
+ if (i > 0) {
+ debugs(83, 8, "TLS FD " << fd << " handle=" << (void*)handle << " " << i << " bytes");
+ }
+ return i;
+}
+#endif
+
+#if USE_OPENSSL
+Security::ConnectionPointer
+Security::NewSslObject(const Security::ContextPointer &ctx)
+{
+ Security::ConnectionPointer handle(SSL_new(ctx.get()), [](SSL *p) {
+ debugs(83, 5, "SSL_free handle=" << (void*)p);
+ SSL_free(p);
+ });
+ debugs(83, 5, "SSL_new handle=" << (void*)handle.get());
+ return handle;
+}
+#endif
+
+static bool
+CreateMagic(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Security::Io::Type type, const char *squidCtx)
+{
+ if (!Comm::IsConnOpen(conn)) {
+ debugs(83, DBG_IMPORTANT, "Gone connection");
+ return false;
+ }
+
+#if USE_OPENSSL || USE_GNUTLS
+
+ const char *errAction = "with no TLS/SSL library";
+ int errCode = 0;
+#if USE_OPENSSL
+ Security::ConnectionPointer handle(Security::NewSslObject(ctx));
+ if (!handle) {
+ errCode = ERR_get_error();
+ errAction = "failed to allocate handle";
+ }
+#elif USE_GNUTLS
+ gnutls_session_t tmp;
+ errCode = gnutls_init(&tmp, static_cast<unsigned int>(type) | GNUTLS_NONBLOCK);
+ Security::ConnectionPointer handle(tmp, [](gnutls_session_t p) {
+ debugs(83, 5, "gnutls_deinit handle=" << (void*)p);
+ gnutls_deinit(p);
+ });
+ debugs(83, 5, "gnutls_init " << (type == Security::Io::BIO_TO_SERVER ? "client" : "server" )<< " handle=" << (void*)handle.get());
+ if (errCode != GNUTLS_E_SUCCESS) {
+ handle.reset();
+ errAction = "failed to initialize session";
+ }
+#endif
+
+ if (handle) {
+ const int fd = conn->fd;
+
+#if USE_OPENSSL
+ // without BIO, we would call SSL_set_fd(ssl.get(), fd) instead
+ if (BIO *bio = Ssl::Bio::Create(fd, type)) {
+ Ssl::Bio::Link(handle.get(), bio); // cannot fail
+#elif USE_GNUTLS
+ errCode = gnutls_credentials_set(handle.get(), GNUTLS_CRD_CERTIFICATE, ctx.get());
+ if (errCode == GNUTLS_E_SUCCESS) {
+
+ if (auto *peer = conn->getPeer())
+ peer->secure.updateSessionOptions(handle);
+ else
+ Security::ProxyOutgoingConfig.updateSessionOptions(handle);
+
+ // NP: GnuTLS does not yet support the BIO operations
+ // this does the equivalent of SSL_set_fd() for now.
+ gnutls_transport_set_int(handle.get(), fd);
+ gnutls_handshake_set_timeout(handle.get(), GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
+#endif
+
+ debugs(83, 5, "link FD " << fd << " to TLS handle=" << (void*)handle.get());
+ fd_table[fd].ssl = handle;
+ fd_table[fd].read_method = &tls_read_method;
+ fd_table[fd].write_method = &tls_write_method;
+ fd_note(fd, squidCtx);
+ return true;
+ }
+
+#if USE_OPENSSL
+ errCode = ERR_get_error();
+ errAction = "failed to initialize I/O";
+#elif USE_GNUTLS
+ errAction = "failed to assign credentials";
+#endif
+ }
+
+ debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
+ ": " << (errCode != 0 ? Security::ErrorString(errCode) : ""));
+#endif
+ return false;
+}
+
+bool
+Security::CreateClient(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
+{
+ return CreateMagic(ctx, c, Security::Io::BIO_TO_SERVER, squidCtx);
+}
+
+bool
+Security::CreateServer(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
+{
+ return CreateMagic(ctx, c, Security::Io::BIO_TO_CLIENT, squidCtx);
+}
+
+void
+Security::SendGoodbye(const Security::ConnectionPointer &s)
+{
+ debugs(83, 5, "handle=" << (void*)s.get());
+ if (s) {
+#if USE_OPENSSL
+ SSL_shutdown(s.get());
+#elif USE_GNUTLS
+ gnutls_bye(s.get(), GNUTLS_SHUT_RDWR);
+#endif
+ }
+}
=== added file 'src/security/Connection.h'
--- src/security/Connection.h 1970-01-01 00:00:00 +0000
+++ src/security/Connection.h 2017-04-25 17:42:00 +0000
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_SECURITY_CONNECTION_H
+#define SQUID_SRC_SECURITY_CONNECTION_H
+
+#if USE_GNUTLS && HAVE_GNUTLS_GNUTLS_H
+#include <gnutls/gnutls.h>
+#endif
+#include <memory>
+#if USE_OPENSSL && HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#endif
+
+namespace Security {
+
+// When Squid is built with GnuTLS this is a handle used to reference the TLS session.
+// When Squid is built against OpenSSL this is a pointer to a TLS connection,
+// ... which gets indirectly de-referenced to manage the TLS session state.
+#if USE_OPENSSL
+typedef std::shared_ptr<SSL> ConnectionPointer;
+#elif USE_GNUTLS
+typedef std::shared_ptr<struct gnutls_session_int> ConnectionPointer;
+#else
+typedef std::shared_ptr<void> ConnectionPointer;
+#endif
+
+/**
+ * Initializes the data structures for a TLS session with a remote server/peer
+ * and associates them with the given transport connection.
+ *
+ * \note 1. The transport connection must be opened before this function is called.
+ * \note 2. The 'TLS connection' is not 'open' until TLS handshake occurs.
+ * This function does not initialte that handshake.
+ *
+ * On errors, emits DBG_IMPORTANT with details and returns false.
+ */
+bool CreateClient(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx);
+
+/**
+ * Initializes the data structures for a TLS session with a remote client
+ * and associates them with the given transport connection.
+ *
+ * \note 1. The transport connection must be opened before this function is called.
+ * \note 2. The 'TLS connection' is not 'open' until TLS handshake occurs.
+ * This function does not initialte that handshake.
+ *
+ * On errors, emits DBG_IMPORTANT with details and returns false.
+ */
+bool CreateServer(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx);
+
+/// 'Close' a given TLS connection (if any) by sending the shutdown/bye notice.
+/// \note This does not close the underlying transport connection, and may
+/// not terminate the TLS session this connection was associated with.
+void SendGoodbye(const Security::ConnectionPointer &);
+
+#if USE_OPENSSL
+/// Helper function to retrieve a (non-locked) ContextPointer from a ConnectionPointer
+inline Security::ContextPointer
+GetFrom(Security::ConnectionPointer &p)
+{
+ auto *ctx = SSL_get_SSL_CTX(p.get());
+ return Security::ContextPointer(ctx, [](SSL_CTX *) {/* nothing to unlock/free */});
+}
+
+/// \deprecated use the PeerOptions/ServerOptions API methods instead.
+/// Wraps ConnectionPointer value creation to reduce risk of
+/// a nasty hack in ssl/support.cc.
+Security::ConnectionPointer NewSslObject(const Security::ContextPointer &);
+#endif
+
+} // namespace Security
+
+#endif /* SQUID_SRC_SECURITY_CONNECTION_H */
+
=== modified file 'src/security/Makefile.am'
--- src/security/Makefile.am 2017-01-01 00:12:22 +0000
+++ src/security/Makefile.am 2017-04-25 17:29:33 +0000
@@ -1,36 +1,38 @@
## 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.
## Please see the COPYING and CONTRIBUTORS files for details.
##
include $(top_srcdir)/src/Common.am
include $(top_srcdir)/src/TestHeaders.am
SUBDIRS= cert_generators cert_validators
noinst_LTLIBRARIES = libsecurity.la
libsecurity_la_SOURCES= \
BlindPeerConnector.cc \
BlindPeerConnector.h \
+ Connection.cc \
+ Connection.h \
CertError.h \
Context.h \
EncryptorAnswer.cc \
EncryptorAnswer.h \
Handshake.cc \
Handshake.h \
forward.h \
KeyData.h \
LockingPointer.h \
NegotiationHistory.cc \
NegotiationHistory.h \
PeerConnector.cc \
PeerConnector.h \
PeerOptions.cc \
PeerOptions.h \
ServerOptions.cc \
ServerOptions.h \
Session.cc \
Session.h
=== modified file 'src/security/NegotiationHistory.cc'
--- src/security/NegotiationHistory.cc 2017-01-01 00:12:22 +0000
+++ src/security/NegotiationHistory.cc 2017-04-25 16:59:06 +0000
@@ -48,41 +48,41 @@
#endif
#if defined(TLS1_VERSION)
case TLS1_VERSION:
return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 0);
#endif
#if defined(SSL3_VERSION)
case SSL3_VERSION:
return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0);
#endif
#if defined(SSL2_VERSION)
case SSL2_VERSION:
return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
#endif
default:
return AnyP::ProtocolVersion();
}
}
#endif
void
-Security::NegotiationHistory::retrieveNegotiatedInfo(const Security::SessionPointer &session)
+Security::NegotiationHistory::retrieveNegotiatedInfo(const Security::ConnectionPointer &session)
{
#if USE_OPENSSL
if ((cipher = SSL_get_current_cipher(session.get()))) {
// Set the negotiated version only if the cipher negotiated
// else probably the negotiation is not completed and version
// is not the final negotiated version
version_ = toProtocolVersion(SSL_version(session.get()));
}
if (Debug::Enabled(83, 5)) {
BIO *b = SSL_get_rbio(session.get());
Ssl::Bio *bio = static_cast<Ssl::Bio *>(BIO_get_data(b));
debugs(83, 5, "SSL connection info on FD " << bio->fd() <<
" SSL version " << version_ <<
" negotiated cipher " << cipherName());
}
#endif
}
void
=== modified file 'src/security/NegotiationHistory.h'
--- src/security/NegotiationHistory.h 2017-01-01 00:12:22 +0000
+++ src/security/NegotiationHistory.h 2017-04-25 16:59:06 +0000
@@ -4,41 +4,41 @@
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#ifndef SQUID_SRC_SECURITY_NEGOTIATIONHISTORY_H
#define SQUID_SRC_SECURITY_NEGOTIATIONHISTORY_H
#include "anyp/ProtocolVersion.h"
#include "security/Handshake.h"
#include "security/Session.h"
namespace Security {
class NegotiationHistory
{
public:
NegotiationHistory();
/// Extract negotiation information from TLS object
- void retrieveNegotiatedInfo(const Security::SessionPointer &);
+ void retrieveNegotiatedInfo(const Security::ConnectionPointer &);
/// Extract information from parser stored in TlsDetails object
void retrieveParsedInfo(Security::TlsDetails::Pointer const &details);
const char *cipherName() const; ///< The name of negotiated cipher
/// String representation of TLS negotiated version
const char *negotiatedVersion() const {return printTlsVersion(version_);}
/// String representation of the received TLS hello message version.
const char *helloVersion() const {return printTlsVersion(helloVersion_);}
/// String representation of the maximum supported TLS version
/// by remote peer
const char *supportedVersion() const {return printTlsVersion(supportedVersion_);}
private:
/// String representation of the TLS version 'v'
const char *printTlsVersion(AnyP::ProtocolVersion const &v) const;
AnyP::ProtocolVersion helloVersion_; ///< The TLS version of the hello message
AnyP::ProtocolVersion supportedVersion_; ///< The maximum supported TLS version
AnyP::ProtocolVersion version_; ///< The negotiated TLS version
#if USE_OPENSSL
const SSL_CIPHER *cipher; ///< The negotiated cipher
=== modified file 'src/security/PeerConnector.cc'
--- src/security/PeerConnector.cc 2017-02-15 03:10:55 +0000
+++ src/security/PeerConnector.cc 2017-04-25 23:07:56 +0000
@@ -43,266 +43,266 @@
Must(dynamic_cast<CbDialer*>(callback->getDialer()));
}
Security::PeerConnector::~PeerConnector()
{
debugs(83, 5, "Security::PeerConnector destructed, this=" << (void*)this);
}
bool Security::PeerConnector::doneAll() const
{
return (!callback || callback->canceled()) && AsyncJob::doneAll();
}
/// Preps connection and SSL state. Calls negotiate().
void
Security::PeerConnector::start()
{
AsyncJob::start();
debugs(83, 5, "this=" << (void*)this);
- Security::SessionPointer tmp;
+ Security::ConnectionPointer tmp;
if (prepareSocket() && initialize(tmp))
negotiate();
else
mustStop("Security::PeerConnector TLS socket initialize failed");
}
void
Security::PeerConnector::commCloseHandler(const CommCloseCbParams ¶ms)
{
debugs(83, 5, "FD " << params.fd << ", Security::PeerConnector=" << params.data);
connectionClosed("Security::PeerConnector::commCloseHandler");
}
void
Security::PeerConnector::connectionClosed(const char *reason)
{
debugs(83, 5, reason << " socket closed/closing. this=" << (void*)this);
mustStop(reason);
callback = NULL;
}
bool
Security::PeerConnector::prepareSocket()
{
debugs(83, 5, serverConnection() << ", this=" << (void*)this);
if (!Comm::IsConnOpen(serverConnection()) || fd_table[serverConnection()->fd].closing()) {
connectionClosed("Security::PeerConnector::prepareSocket");
return false;
}
debugs(83, 5, serverConnection());
// watch for external connection closures
typedef CommCbMemFunT<Security::PeerConnector, CommCloseCbParams> Dialer;
closeHandler = JobCallback(9, 5, Dialer, this, Security::PeerConnector::commCloseHandler);
comm_add_close_handler(serverConnection()->fd, closeHandler);
return true;
}
bool
-Security::PeerConnector::initialize(Security::SessionPointer &serverSession)
+Security::PeerConnector::initialize(Security::ConnectionPointer &server)
{
Security::ContextPointer ctx(getTlsContext());
debugs(83, 5, serverConnection() << ", ctx=" << (void*)ctx.get());
- if (!ctx || !Security::CreateClientSession(ctx, serverConnection(), "server https start")) {
+ if (!ctx || !Security::CreateClient(ctx, serverConnection(), "server https start")) {
const auto xerrno = errno;
if (!ctx) {
debugs(83, DBG_IMPORTANT, "Error initializing TLS connection: No security context.");
- } // else CreateClientSession() did the appropriate debugs() already
+ } // else CreateClient() did the appropriate debugs() already
ErrorState *anErr = new ErrorState(ERR_SOCKET_FAILURE, Http::scInternalServerError, request.getRaw());
anErr->xerrno = xerrno;
noteNegotiationDone(anErr);
bail(anErr);
return false;
}
- // A TLS/SSL session has now been created for the connection and stored in fd_table
- serverSession = fd_table[serverConnection()->fd].ssl;
- debugs(83, 5, serverConnection() << ", session=" << (void*)serverSession.get());
+ // A TLS connection has now been created for the connection and stored in fd_table
+ server = fd_table[serverConnection()->fd].ssl;
+ debugs(83, 5, serverConnection() << ", server=" << (void*)server.get());
#if USE_OPENSSL
// If CertValidation Helper used do not lookup checklist for errors,
// but keep a list of errors to send it to CertValidator
if (!Ssl::TheConfig.ssl_crt_validator) {
// Create the ACL check list now, while we have access to more info.
// The list is used in ssl_verify_cb() and is freed in ssl_free().
if (acl_access *acl = ::Config.ssl_client.cert_error) {
ACLFilledChecklist *check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
check->al = al;
// check->fd(fd); XXX: need client FD here
- SSL_set_ex_data(serverSession.get(), ssl_ex_index_cert_error_check, check);
+ SSL_set_ex_data(server.get(), ssl_ex_index_cert_error_check, check);
}
}
#endif
return true;
}
void
Security::PeerConnector::setReadTimeout()
{
int timeToRead;
if (negotiationTimeout) {
const int timeUsed = squid_curtime - startTime;
const int timeLeft = max(0, static_cast<int>(negotiationTimeout - timeUsed));
timeToRead = min(static_cast<int>(::Config.Timeout.read), timeLeft);
} else
timeToRead = ::Config.Timeout.read;
AsyncCall::Pointer nil;
commSetConnTimeout(serverConnection(), timeToRead, nil);
}
void
Security::PeerConnector::recordNegotiationDetails()
{
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
+ Security::ConnectionPointer server(fd_table[fd].ssl);
// retrieve TLS server negotiated information if any
- serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(session);
+ serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(server);
#if USE_OPENSSL
// retrieve TLS parsed extra info
- BIO *b = SSL_get_rbio(session.get());
+ BIO *b = SSL_get_rbio(server.get());
Ssl::ServerBio *bio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails())
serverConnection()->tlsNegotiations()->retrieveParsedInfo(details);
#endif
}
void
Security::PeerConnector::negotiate()
{
if (!Comm::IsConnOpen(serverConnection()))
return;
const int fd = serverConnection()->fd;
if (fd_table[fd].closing())
return;
#if USE_OPENSSL
- auto session = fd_table[fd].ssl.get();
- debugs(83, 5, "SSL_connect session=" << (void*)session);
- const int result = SSL_connect(session);
+ auto theAnSsl = fd_table[fd].ssl.get();
+ debugs(83, 5, "SSL_connect handle=" << (void*)theAnSsl);
+ const int result = SSL_connect(theAnSsl);
if (result <= 0) {
#elif USE_GNUTLS
auto session = fd_table[fd].ssl.get();
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) {
// 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
handleNegotiateError(result);
return; // we might be gone by now
}
recordNegotiationDetails();
if (!sslFinalized())
return;
callBack();
}
bool
Security::PeerConnector::sslFinalized()
{
#if USE_OPENSSL
if (Ssl::TheConfig.ssl_crt_validator && useCertValidator_) {
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
+ Security::ConnectionPointer handle(fd_table[fd].ssl);
Ssl::CertValidationRequest validationRequest;
// WARNING: Currently we do not use any locking for 'errors' member
// of the Ssl::CertValidationRequest class. In this code the
// Ssl::CertValidationRequest object used only to pass data to
// Ssl::CertValidationHelper::submit method.
- validationRequest.ssl = session;
- if (SBuf *dName = (SBuf *)SSL_get_ex_data(session.get(), ssl_ex_index_server))
+ validationRequest.ssl = handle;
+ if (SBuf *dName = (SBuf *)SSL_get_ex_data(handle.get(), ssl_ex_index_server))
validationRequest.domainName = dName->c_str();
- if (Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_errors)))
+ if (Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(handle.get(), ssl_ex_index_ssl_errors)))
// validationRequest disappears on return so no need to cbdataReference
validationRequest.errors = errs;
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);
return false;
} catch (const std::exception &e) {
debugs(83, DBG_IMPORTANT, "ERROR: Failed to compose ssl_crtvd " <<
"request for " << validationRequest.domainName <<
" certificate: " << e.what() << "; will now block to " <<
"validate that certificate.");
// fall through to do blocking in-process generation.
ErrorState *anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
noteNegotiationDone(anErr);
bail(anErr);
serverConn->close();
return true;
}
}
#endif
noteNegotiationDone(NULL);
return true;
}
#if USE_OPENSSL
void
Security::PeerConnector::sslCrtvdHandleReply(Ssl::CertValidationResponse::Pointer validationResponse)
{
Must(validationResponse != NULL);
Ssl::ErrorDetail *errDetails = NULL;
bool validatorFailed = false;
if (!Comm::IsConnOpen(serverConnection())) {
return;
}
if (Debug::Enabled(83, 5)) {
- Security::SessionPointer ssl(fd_table[serverConnection()->fd].ssl);
+ Security::ConnectionPointer ssl(fd_table[serverConnection()->fd].ssl);
SBuf *server = static_cast<SBuf *>(SSL_get_ex_data(ssl.get(), ssl_ex_index_server));
debugs(83,5, RawPointer("host", server) << " cert validation result: " << validationResponse->resultCode);
}
if (validationResponse->resultCode == ::Helper::Error) {
if (Security::CertErrors *errs = sslCrtvdCheckForErrors(*validationResponse, errDetails)) {
- Security::SessionPointer session(fd_table[serverConnection()->fd].ssl);
- Security::CertErrors *oldErrs = static_cast<Security::CertErrors*>(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_errors));
- SSL_set_ex_data(session.get(), ssl_ex_index_ssl_errors, (void *)errs);
+ Security::ConnectionPointer handle(fd_table[serverConnection()->fd].ssl);
+ Security::CertErrors *oldErrs = static_cast<Security::CertErrors*>(SSL_get_ex_data(handle.get(), ssl_ex_index_ssl_errors));
+ SSL_set_ex_data(handle.get(), ssl_ex_index_ssl_errors, (void *)errs);
delete oldErrs;
}
} else if (validationResponse->resultCode != ::Helper::Okay)
validatorFailed = true;
if (!errDetails && !validatorFailed) {
noteNegotiationDone(NULL);
callBack();
return;
}
ErrorState *anErr = NULL;
if (validatorFailed) {
anErr = new ErrorState(ERR_GATEWAY_FAILURE, Http::scInternalServerError, request.getRaw());
} else {
anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, request.getRaw());
anErr->detail = errDetails;
/*anErr->xerrno= Should preserved*/
}
@@ -310,165 +310,165 @@
bail(anErr);
serverConn->close();
return;
}
#endif
#if USE_OPENSSL
/// Checks errors in the cert. validator response against sslproxy_cert_error.
/// The first honored error, if any, is returned via errDetails parameter.
/// The method returns all seen errors except SSL_ERROR_NONE as Security::CertErrors.
Security::CertErrors *
Security::PeerConnector::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &resp, Ssl::ErrorDetail *& errDetails)
{
ACLFilledChecklist *check = NULL;
if (acl_access *acl = ::Config.ssl_client.cert_error) {
check = new ACLFilledChecklist(acl, request.getRaw(), dash_str);
check->al = al;
}
Security::CertErrors *errs = nullptr;
- Security::SessionPointer session(fd_table[serverConnection()->fd].ssl);
+ Security::ConnectionPointer handle(fd_table[serverConnection()->fd].ssl);
typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) {
debugs(83, 7, "Error item: " << i->error_no << " " << i->error_reason);
assert(i->error_no != SSL_ERROR_NONE);
if (!errDetails) {
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)
allowed = true;
}
// else the Config.ssl_client.cert_error access list is not defined
// and the first error will cause the error page
if (allowed) {
debugs(83, 3, "bypassing SSL error " << i->error_no << " in " << "buffer");
} else {
debugs(83, 5, "confirming SSL error " << i->error_no);
X509 *brokenCert = i->cert.get();
- Security::CertPointer peerCert(SSL_get_peer_certificate(session.get()));
+ Security::CertPointer peerCert(SSL_get_peer_certificate(handle.get()));
const char *aReason = i->error_reason.empty() ? NULL : i->error_reason.c_str();
errDetails = new Ssl::ErrorDetail(i->error_no, peerCert.get(), brokenCert, aReason);
}
if (check) {
delete check->sslErrors;
check->sslErrors = NULL;
}
}
if (!errs)
errs = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth));
else
errs->push_back_unique(Security::CertError(i->error_no, i->cert, i->error_depth));
}
if (check)
delete check;
return errs;
}
#endif
/// A wrapper for Comm::SetSelect() notifications.
void
Security::PeerConnector::NegotiateSsl(int, void *data)
{
PeerConnector *pc = static_cast<Security::PeerConnector *>(data);
// Use job calls to add done() checks and other job logic/protections.
CallJobHere(83, 7, pc, Security::PeerConnector, negotiate);
}
void
Security::PeerConnector::handleNegotiateError(const int ret)
{
const int fd = serverConnection()->fd;
- const Security::SessionPointer session(fd_table[fd].ssl);
+ const Security::ConnectionPointer handle(fd_table[fd].ssl);
unsigned long ssl_lib_error = ret;
#if USE_OPENSSL
- const int ssl_error = SSL_get_error(session.get(), ret);
+ const int ssl_error = SSL_get_error(handle.get(), ret);
switch (ssl_error) {
case SSL_ERROR_WANT_READ:
noteWantRead();
return;
case SSL_ERROR_WANT_WRITE:
noteWantWrite();
return;
case SSL_ERROR_SSL:
case SSL_ERROR_SYSCALL:
ssl_lib_error = ERR_get_error();
// proceed to the general error handling code
break;
default:
// no special error handling for all other errors
ssl_lib_error = SSL_ERROR_NONE;
break;
}
#elif USE_GNUTLS
const int ssl_error = ret;
switch (ret) {
case GNUTLS_E_WARNING_ALERT_RECEIVED: {
- auto alert = gnutls_alert_get(session.get());
+ auto alert = gnutls_alert_get(handle.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)
+ if (gnutls_record_get_direction(handle.get()) == 0)
noteWantRead();
else
noteWantWrite();
return;
default:
// no special error handling for all other errors
break;
}
#else
// this avoids unused variable compiler warnings.
- Must(!session);
+ Must(!handle);
const int ssl_error = ret;
#endif
// Log connection details, if any
recordNegotiationDetails();
noteNegotiationError(ret, ssl_error, ssl_lib_error);
}
void
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());
+ Security::ConnectionPointer handle(fd_table[fd].ssl);
+ BIO *b = SSL_get_rbio(handle.get());
Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
if (srvBio->holdRead()) {
if (srvBio->gotHello()) {
if (checkForMissingCertificates())
return; // Wait to download certificates before proceed.
srvBio->holdRead(false);
// schedule a negotiateSSl to allow openSSL parse received data
Security::PeerConnector::NegotiateSsl(fd, this);
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);
return;
}
}
#endif
setReadTimeout();
@@ -492,50 +492,50 @@
#else
int sysErrNo = EACCES;
#endif
#if USE_OPENSSL
// store/report errno when ssl_error is SSL_ERROR_SYSCALL, ssl_lib_error is 0, and ret is -1
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 << "/" << xerr << ")");
ErrorState *anErr = ErrorState::NewForwarding(ERR_SECURE_CONNECT_FAIL, request);
anErr->xerrno = sysErrNo;
#if USE_OPENSSL
- Security::SessionPointer session(fd_table[fd].ssl);
- Ssl::ErrorDetail *errFromFailure = static_cast<Ssl::ErrorDetail *>(SSL_get_ex_data(session.get(), ssl_ex_index_ssl_error_detail));
+ Security::ConnectionPointer handle(fd_table[fd].ssl);
+ Ssl::ErrorDetail *errFromFailure = static_cast<Ssl::ErrorDetail *>(SSL_get_ex_data(handle.get(), ssl_ex_index_ssl_error_detail));
if (errFromFailure != NULL) {
// The errFromFailure is attached to the ssl object
// and will be released when ssl object destroyed.
// Copy errFromFailure to a new Ssl::ErrorDetail object
anErr->detail = new Ssl::ErrorDetail(*errFromFailure);
} else {
// server_cert can be NULL here
- X509 *server_cert = SSL_get_peer_certificate(session.get());
+ X509 *server_cert = SSL_get_peer_certificate(handle.get());
anErr->detail = new Ssl::ErrorDetail(SQUID_ERR_SSL_HANDSHAKE, server_cert, NULL);
X509_free(server_cert);
}
if (ssl_lib_error != SSL_ERROR_NONE)
anErr->detail->setLibError(ssl_lib_error);
#endif
noteNegotiationDone(anErr);
bail(anErr);
}
void
Security::PeerConnector::bail(ErrorState *error)
{
Must(error); // or the recepient will not know there was a problem
Must(callback != NULL);
CbDialer *dialer = dynamic_cast<CbDialer*>(callback->getDialer());
Must(dialer);
dialer->answer().error = error;
@@ -624,85 +624,85 @@
void
Security::PeerConnector::startCertDownloading(SBuf &url)
{
AsyncCall::Pointer certCallback = asyncCall(81, 4,
"Security::PeerConnector::certDownloadingDone",
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);
AsyncJob::Start(dl);
}
void
Security::PeerConnector::certDownloadingDone(SBuf &obj, int downloadStatus)
{
++certsDownloads;
debugs(81, 5, "Certificate downloading status: " << downloadStatus << " certificate size: " << obj.length());
// get ServerBio from SSL object
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
- BIO *b = SSL_get_rbio(session.get());
+ Security::ConnectionPointer handle(fd_table[fd].ssl);
+ BIO *b = SSL_get_rbio(handle.get());
Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
// Parse Certificate. Assume that it is in DER format.
// According to RFC 4325:
// The server must provide a DER encoded certificate or a collection
// collection of certificates in a "certs-only" CMS message.
// The applications MUST accept DER encoded certificates and SHOULD
// be able to accept collection of certificates.
// TODO: support collection of certificates
const unsigned char *raw = (const unsigned char*)obj.rawContent();
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));
const Security::CertList &certsList = srvBio->serverCertificatesIfAny();
if (const char *issuerUri = Ssl::uriOfIssuerIfMissing(cert, certsList)) {
urlsOfMissingCerts.push(SBuf(issuerUri));
}
- Ssl::SSL_add_untrusted_cert(session.get(), cert);
+ Ssl::SSL_add_untrusted_cert(handle.get(), cert);
}
// Check if there are URIs to download from and if yes start downloading
// the first in queue.
if (urlsOfMissingCerts.size() && certsDownloads <= MaxCertsDownloads) {
startCertDownloading(urlsOfMissingCerts.front());
urlsOfMissingCerts.pop();
return;
}
srvBio->holdRead(false);
Security::PeerConnector::NegotiateSsl(serverConnection()->fd, this);
}
bool
Security::PeerConnector::checkForMissingCertificates()
{
// Check for nested SSL certificates downloads. For example when the
// certificate located in an SSL site which requires to download a
// a missing certificate (... from an SSL site which requires to ...).
const Downloader *csd = (request ? request->downloader.get() : nullptr);
if (csd && csd->nestedLevel() >= MaxNestedDownloads)
return false;
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
- BIO *b = SSL_get_rbio(session.get());
+ Security::ConnectionPointer handle(fd_table[fd].ssl);
+ BIO *b = SSL_get_rbio(handle.get());
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);
if (urlsOfMissingCerts.size()) {
startCertDownloading(urlsOfMissingCerts.front());
urlsOfMissingCerts.pop();
return true;
}
}
return false;
}
#endif //USE_OPENSSL
=== modified file 'src/security/PeerConnector.h'
--- src/security/PeerConnector.h 2017-01-01 00:12:22 +0000
+++ src/security/PeerConnector.h 2017-04-25 16:59:06 +0000
@@ -87,41 +87,41 @@
virtual bool doneAll() const;
virtual void swanSong();
virtual const char *status() const;
/// The comm_close callback handler.
void commCloseHandler(const CommCloseCbParams ¶ms);
/// Inform us that the connection is closed. Does the required clean-up.
void connectionClosed(const char *reason);
/// Sets up TCP socket-related notification callbacks if things go wrong.
/// If socket already closed return false, else install the comm_close
/// handler to monitor the socket.
bool prepareSocket();
/// Sets the read timeout to avoid getting stuck while reading from a
/// silent server
void setReadTimeout();
/// \returns true on successful TLS session initialization
- virtual bool initialize(Security::SessionPointer &);
+ virtual bool initialize(Security::ConnectionPointer &);
/// Performs a single secure connection negotiation step.
/// It is called multiple times untill the negotiation finishes or aborts.
void negotiate();
/// Called after negotiation has finished. Cleans up TLS/SSL state.
/// Returns false if we are now waiting for the certs validation job.
/// Otherwise, returns true, regardless of negotiation success/failure.
bool sslFinalized();
/// Called when the negotiation step aborted because data needs to
/// be transferred to/from server or on error. In the first case
/// setups the appropriate Comm::SetSelect handler. In second case
/// fill an error and report to the PeerConnector caller.
void handleNegotiateError(const int result);
/// Called when the openSSL SSL_connect fnction request more data from
/// the remote SSL server. Sets the read timeout and sets the
/// Squid COMM_SELECT_READ handler.
void noteWantRead();
=== modified file 'src/security/PeerOptions.cc'
--- src/security/PeerOptions.cc 2017-02-14 09:56:34 +0000
+++ src/security/PeerOptions.cc 2017-04-25 16:59:06 +0000
@@ -676,41 +676,41 @@
if (parsedCrl.size()) {
for (auto &i : parsedCrl) {
if (!X509_STORE_add_crl(st, i.get()))
debugs(83, 2, "WARNING: Failed to add CRL");
else
verifyCrl = true;
}
}
#if X509_V_FLAG_CRL_CHECK
if ((parsedFlags & SSL_FLAG_VERIFY_CRL_ALL))
X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
else if (verifyCrl || (parsedFlags & SSL_FLAG_VERIFY_CRL))
X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK);
#endif
#endif /* USE_OPENSSL */
}
void
-Security::PeerOptions::updateSessionOptions(Security::SessionPointer &s)
+Security::PeerOptions::updateSessionOptions(Security::ConnectionPointer &s)
{
#if USE_OPENSSL
// 'options=' value being set to session is a GnuTLS specific thing.
#elif USE_GNUTLS
int x;
SBuf errMsg;
if (!parsedOptions) {
debugs(83, 5, "set GnuTLS default priority/options for session=" << s);
x = gnutls_set_default_priority(s.get());
static const SBuf defaults("default");
errMsg = defaults;
} else {
debugs(83, 5, "set GnuTLS options '" << sslOptions << "' for session=" << s);
x = gnutls_priority_set(s.get(), parsedOptions.get());
errMsg = sslOptions;
}
if (x != GNUTLS_E_SUCCESS) {
debugs(83, DBG_IMPORTANT, "ERROR: Failed to set TLS options (" << errMsg << "). error: " << Security::ErrorString(x));
}
=== modified file 'src/security/PeerOptions.h'
--- src/security/PeerOptions.h 2017-03-11 16:33:07 +0000
+++ src/security/PeerOptions.h 2017-04-25 16:59:06 +0000
@@ -37,41 +37,41 @@
/// generate an unset security context object
virtual Security::ContextPointer createBlankContext() const;
/// generate a security client-context from these configured options
Security::ContextPointer createClientContext(bool setOptions);
/// sync the context options with tls-min-version=N configuration
void updateTlsVersionLimits();
/// setup the NPN extension details for the given context
void updateContextNpn(Security::ContextPointer &);
/// setup the CA details for the given context
void updateContextCa(Security::ContextPointer &);
/// setup the CRL details for the given context
void updateContextCrl(Security::ContextPointer &);
/// setup any library-specific options that can be set for the given session
- void updateSessionOptions(Security::SessionPointer &);
+ void updateSessionOptions(Security::ConnectionPointer &);
/// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
virtual void dumpCfg(Packable *, const char *pfx) const;
private:
void parseOptions(); ///< parsed value of sslOptions
long parseFlags();
void loadCrlFile();
public:
SBuf sslOptions; ///< library-specific options string
SBuf caDir; ///< path of directory containing a set of trusted Certificate Authorities
SBuf crlFile; ///< path of file containing Certificate Revoke List
SBuf sslCipher;
SBuf sslFlags; ///< flags defining what TLS operations Squid performs
SBuf sslDomain;
SBuf tlsMinVersion; ///< version label for minimum TLS version to permit
=== modified file 'src/security/Session.cc'
--- src/security/Session.cc 2017-02-05 06:12:19 +0000
+++ src/security/Session.cc 2017-04-26 12:21:33 +0000
@@ -6,275 +6,97 @@
* Please see the COPYING and CONTRIBUTORS files for details.
*/
/* DEBUG: section 83 TLS session management */
#include "squid.h"
#include "anyp/PortCfg.h"
#include "base/RunnersRegistry.h"
#include "CachePeer.h"
#include "Debug.h"
#include "fd.h"
#include "fde.h"
#include "ipc/MemMap.h"
#include "security/Session.h"
#include "SquidConfig.h"
#include "ssl/bio.h"
#define SSL_SESSION_ID_SIZE 32
#define SSL_SESSION_MAX_SIZE 10*1024
-#if USE_OPENSSL || USE_GNUTLS
-static int
-tls_read_method(int fd, char *buf, int len)
-{
- auto session = fd_table[fd].ssl.get();
- debugs(83, 3, "started for session=" << (void*)session);
-
-#if DONT_DO_THIS && USE_OPENSSL
- if (!SSL_is_init_finished(session)) {
- errno = ENOTCONN;
- return -1;
- }
-#endif
-
-#if USE_OPENSSL
- int i = SSL_read(session, buf, len);
-#elif USE_GNUTLS
- int i = gnutls_record_recv(session, buf, len);
-#endif
-
- if (i > 0) {
- debugs(83, 8, "TLS FD " << fd << " session=" << (void*)session << " " << i << " bytes");
- (void)VALGRIND_MAKE_MEM_DEFINED(buf, i);
- }
-
-#if USE_OPENSSL
- if (i > 0 && SSL_pending(session) > 0) {
-#elif USE_GNUTLS
- if (i > 0 && gnutls_record_check_pending(session) > 0) {
-#endif
- debugs(83, 2, "TLS FD " << fd << " is pending");
- fd_table[fd].flags.read_pending = true;
- } else
- fd_table[fd].flags.read_pending = false;
-
- return i;
-}
-
-static int
-tls_write_method(int fd, const char *buf, int len)
-{
- auto session = fd_table[fd].ssl.get();
- debugs(83, 3, "started for session=" << (void*)session);
-
-#if USE_OPENSSL
- if (!SSL_is_init_finished(session)) {
- errno = ENOTCONN;
- return -1;
- }
-#endif
-
-#if USE_OPENSSL
- int i = SSL_write(session, buf, len);
-#elif USE_GNUTLS
- int i = gnutls_record_send(session, buf, len);
-#endif
-
- if (i > 0) {
- debugs(83, 8, "TLS FD " << fd << " session=" << (void*)session << " " << i << " bytes");
- }
- return i;
-}
-#endif
-
-#if USE_OPENSSL
-Security::SessionPointer
-Security::NewSessionObject(const Security::ContextPointer &ctx)
-{
- Security::SessionPointer session(SSL_new(ctx.get()), [](SSL *p) {
- debugs(83, 5, "SSL_free session=" << (void*)p);
- SSL_free(p);
- });
- debugs(83, 5, "SSL_new session=" << (void*)session.get());
- return session;
-}
-#endif
-
-static bool
-CreateSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Security::Io::Type type, const char *squidCtx)
-{
- if (!Comm::IsConnOpen(conn)) {
- debugs(83, DBG_IMPORTANT, "Gone connection");
- return false;
- }
-
-#if USE_OPENSSL || USE_GNUTLS
-
- const char *errAction = "with no TLS/SSL library";
- int errCode = 0;
-#if USE_OPENSSL
- Security::SessionPointer session(Security::NewSessionObject(ctx));
- if (!session) {
- errCode = ERR_get_error();
- errAction = "failed to allocate handle";
- }
-#elif USE_GNUTLS
- gnutls_session_t tmp;
- errCode = gnutls_init(&tmp, static_cast<unsigned int>(type) | GNUTLS_NONBLOCK);
- Security::SessionPointer session(tmp, [](gnutls_session_t p) {
- debugs(83, 5, "gnutls_deinit session=" << (void*)p);
- gnutls_deinit(p);
- });
- debugs(83, 5, "gnutls_init " << (type == Security::Io::BIO_TO_SERVER ? "client" : "server" )<< " session=" << (void*)session.get());
- if (errCode != GNUTLS_E_SUCCESS) {
- session.reset();
- errAction = "failed to initialize session";
- }
-#endif
-
- if (session) {
- const int fd = conn->fd;
-
-#if USE_OPENSSL
- // without BIO, we would call SSL_set_fd(ssl.get(), fd) instead
- if (BIO *bio = Ssl::Bio::Create(fd, type)) {
- Ssl::Bio::Link(session.get(), bio); // cannot fail
-#elif USE_GNUTLS
- errCode = gnutls_credentials_set(session.get(), GNUTLS_CRD_CERTIFICATE, ctx.get());
- if (errCode == GNUTLS_E_SUCCESS) {
-
- if (auto *peer = conn->getPeer())
- peer->secure.updateSessionOptions(session);
- else
- Security::ProxyOutgoingConfig.updateSessionOptions(session);
-
- // NP: GnuTLS does not yet support the BIO operations
- // this does the equivalent of SSL_set_fd() for now.
- gnutls_transport_set_int(session.get(), fd);
- gnutls_handshake_set_timeout(session.get(), GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
-#endif
-
- debugs(83, 5, "link FD " << fd << " to TLS session=" << (void*)session.get());
- fd_table[fd].ssl = session;
- fd_table[fd].read_method = &tls_read_method;
- fd_table[fd].write_method = &tls_write_method;
- fd_note(fd, squidCtx);
- return true;
- }
-
-#if USE_OPENSSL
- errCode = ERR_get_error();
- errAction = "failed to initialize I/O";
-#elif USE_GNUTLS
- errAction = "failed to assign credentials";
-#endif
- }
-
- debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
- ": " << (errCode != 0 ? Security::ErrorString(errCode) : ""));
-#endif
- return false;
-}
-
-bool
-Security::CreateClientSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
-{
- return CreateSession(ctx, c, Security::Io::BIO_TO_SERVER, squidCtx);
-}
-
-bool
-Security::CreateServerSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
-{
- return CreateSession(ctx, c, Security::Io::BIO_TO_CLIENT, squidCtx);
-}
-
-void
-Security::SessionSendGoodbye(const Security::SessionPointer &s)
-{
- debugs(83, 5, "session=" << (void*)s.get());
- if (s) {
-#if USE_OPENSSL
- SSL_shutdown(s.get());
-#elif USE_GNUTLS
- gnutls_bye(s.get(), GNUTLS_SHUT_RDWR);
-#endif
- }
-}
-
bool
-Security::SessionIsResumed(const Security::SessionPointer &s)
+Security::SessionIsResumed(const Security::ConnectionPointer &s)
{
bool result = false;
#if USE_OPENSSL
result = SSL_session_reused(s.get()) == 1;
#elif USE_GNUTLS
result = gnutls_session_is_resumed(s.get()) != 0;
#endif
debugs(83, 7, "session=" << (void*)s.get() << ", query? answer: " << (result ? 'T' : 'F') );
return result;
}
void
-Security::MaybeGetSessionResumeData(const Security::SessionPointer &s, Security::SessionStatePointer &data)
+Security::MaybeGetSessionResumeData(const Security::ConnectionPointer &s, Security::SessionStatePointer &data)
{
if (!SessionIsResumed(s)) {
#if USE_OPENSSL
// nil is valid for SSL_get1_session(), it cannot fail.
data.reset(SSL_get1_session(s.get()));
#elif USE_GNUTLS
gnutls_datum_t *tmp = nullptr;
const auto x = gnutls_session_get_data2(s.get(), tmp);
if (x != GNUTLS_E_SUCCESS) {
debugs(83, 3, "session=" << (void*)s.get() << " error: " << Security::ErrorString(x));
}
data.reset(tmp);
#endif
debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get());
} else {
debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get() << ", do nothing.");
}
}
void
-Security::SetSessionResumeData(const Security::SessionPointer &s, const Security::SessionStatePointer &data)
+Security::SetSessionResumeData(const Security::ConnectionPointer &s, const Security::SessionStatePointer &data)
{
if (data) {
#if USE_OPENSSL
if (!SSL_set_session(s.get(), data.get())) {
const auto ssl_error = ERR_get_error();
- debugs(83, 3, "session=" << (void*)s.get() << " data=" << (void*)data.get() <<
+ debugs(83, 3, "handle=" << (void*)s.get() << " data=" << (void*)data.get() <<
" resume error: " << Security::ErrorString(ssl_error));
}
#elif USE_GNUTLS
const auto x = gnutls_session_set_data(s.get(), data->data, data->size);
if (x != GNUTLS_E_SUCCESS) {
- debugs(83, 3, "session=" << (void*)s.get() << " data=" << (void*)data.get() <<
+ debugs(83, 3, "handle=" << (void*)s.get() << " data=" << (void*)data.get() <<
" resume error: " << Security::ErrorString(x));
}
#else
// critical because, how did it get here?
- debugs(83, DBG_CRITICAL, "no TLS library. session=" << (void*)s.get() << " data=" << (void*)data.get());
+ debugs(83, DBG_CRITICAL, "no TLS library. handle=" << (void*)s.get() << " data=" << (void*)data.get());
#endif
- debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get());
+ debugs(83, 5, "handle=" << (void*)s.get() << " data=" << (void*)data.get());
} else {
- debugs(83, 5, "session=" << (void*)s.get() << " no resume data");
+ debugs(83, 5, "handle=" << (void*)s.get() << " no resume data");
}
}
static bool
isTlsServer()
{
for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) {
if (s->secure.encryptTransport)
return true;
if (s->flags.tunnelSslBumping)
return true;
}
return false;
}
void
initializeSessionCache()
{
#if USE_OPENSSL
=== modified file 'src/security/Session.h'
--- src/security/Session.h 2017-02-10 13:35:05 +0000
+++ src/security/Session.h 2017-04-26 12:21:33 +0000
@@ -1,98 +1,51 @@
/*
* 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.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#ifndef SQUID_SRC_SECURITY_SESSION_H
#define SQUID_SRC_SECURITY_SESSION_H
#include "base/HardFun.h"
#include "comm/forward.h"
-#include "security/LockingPointer.h"
-
-#include <memory>
-
-#if USE_OPENSSL
-#if HAVE_OPENSSL_SSL_H
-#include <openssl/ssl.h>
-#endif
-#endif
-
-#if USE_GNUTLS
-#if HAVE_GNUTLS_GNUTLS_H
-#include <gnutls/gnutls.h>
-#endif
-#endif
+#include "security/Connection.h"
namespace Security {
-/// Creates TLS Client connection structure (aka 'session' state) and initializes TLS/SSL I/O (Comm and BIO).
-/// On errors, emits DBG_IMPORTANT with details and returns false.
-bool CreateClientSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx);
-
-/// Creates TLS Server connection structure (aka 'session' state) and initializes TLS/SSL I/O (Comm and BIO).
-/// On errors, emits DBG_IMPORTANT with details and returns false.
-bool CreateServerSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx);
-
#if USE_OPENSSL
-typedef std::shared_ptr<SSL> SessionPointer;
-
typedef std::unique_ptr<SSL_SESSION, HardFun<void, SSL_SESSION*, &SSL_SESSION_free>> SessionStatePointer;
#elif USE_GNUTLS
-typedef std::shared_ptr<struct gnutls_session_int> SessionPointer;
-
// wrapper function to get around gnutls_free being a typedef
inline void squid_gnutls_free(void *d) {gnutls_free(d);}
typedef std::unique_ptr<gnutls_datum_t, HardFun<void, void*, &Security::squid_gnutls_free>> SessionStatePointer;
#else
-typedef std::shared_ptr<void> SessionPointer;
-
typedef std::unique_ptr<int> SessionStatePointer;
-
#endif
-/// send the shutdown/bye notice for an active TLS session.
-void SessionSendGoodbye(const Security::SessionPointer &);
-
/// whether the session is a resumed one
-bool SessionIsResumed(const Security::SessionPointer &);
+bool SessionIsResumed(const Security::ConnectionPointer &);
/**
* When the session is not a resumed session, retrieve the details needed to
* resume a later connection and store them in 'data'. This may result in 'data'
* becoming a nil Pointer if no details exist or an error occurs.
*
* When the session is already a resumed session, do nothing and leave 'data'
* unhanged.
* XXX: is this latter behaviour always correct?
*/
-void MaybeGetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &data);
+void MaybeGetSessionResumeData(const Security::ConnectionPointer &, Security::SessionStatePointer &data);
/// Set the data for resuming a previous session.
-/// Needs to be done before using the SessionPointer for a handshake.
-void SetSessionResumeData(const Security::SessionPointer &, const Security::SessionStatePointer &);
-
-#if USE_OPENSSL
-/// Helper function to retrieve a (non-locked) ContextPointer from a SessionPointer
-inline Security::ContextPointer
-GetFrom(Security::SessionPointer &s)
-{
- auto *ctx = SSL_get_SSL_CTX(s.get());
- return Security::ContextPointer(ctx, [](SSL_CTX *) {/* nothing to unlock/free */});
-}
-
-/// \deprecated use the PeerOptions/ServerOptions API methods instead.
-/// Wraps SessionPointer value creation to reduce risk of
-/// a nasty hack in ssl/support.cc.
-Security::SessionPointer NewSessionObject(const Security::ContextPointer &);
-#endif
+/// Needs to be done before using the ConnectionPointer for a handshake.
+void SetSessionResumeData(const Security::ConnectionPointer &, const Security::SessionStatePointer &);
} // namespace Security
#endif /* SQUID_SRC_SECURITY_SESSION_H */
=== modified file 'src/security/forward.h'
--- src/security/forward.h 2017-02-05 06:12:19 +0000
+++ src/security/forward.h 2017-04-25 17:38:50 +0000
@@ -1,33 +1,34 @@
/*
* 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.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#ifndef SQUID_SRC_SECURITY_FORWARD_H
#define SQUID_SRC_SECURITY_FORWARD_H
#include "base/CbDataList.h"
#include "security/Context.h"
+#include "security/LockingPointer.h"
#include "security/Session.h"
#if USE_GNUTLS && HAVE_GNUTLS_X509_H
#include <gnutls/x509.h>
#endif
#include <list>
#if USE_OPENSSL && HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
#include <unordered_set>
#if USE_OPENSSL
// Macro to be used to define the C++ wrapper functor of the sk_*_pop_free
// OpenSSL family of functions. The C++ functor is suffixed with the _free_wrapper
// extension
#define sk_dtor_wrapper(sk_object, argument_type, freefunction) \
struct sk_object ## _free_wrapper { \
void operator()(argument_type a) { sk_object ## _pop_free(a, freefunction); } \
}
#endif /* USE_OPENSSL */
=== modified file 'src/ssl/PeekingPeerConnector.cc'
--- src/ssl/PeekingPeerConnector.cc 2017-02-05 05:57:32 +0000
+++ src/ssl/PeekingPeerConnector.cc 2017-04-25 16:59:06 +0000
@@ -46,54 +46,54 @@
Ssl::PeekingPeerConnector::checkForPeekAndSplice()
{
// Mark Step3 of bumping
if (request->clientConnectionManager.valid()) {
if (Ssl::ServerBump *serverBump = request->clientConnectionManager->serverBump()) {
serverBump->step = Ssl::bumpStep3;
}
}
handleServerCertificate();
ACLFilledChecklist *acl_checklist = new ACLFilledChecklist(
::Config.accessList.ssl_bump,
request.getRaw(), NULL);
acl_checklist->al = al;
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpNone));
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpPeek));
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpStare));
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpClientFirst));
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpServerFirst));
- Security::SessionPointer session(fd_table[serverConn->fd].ssl);
+ Security::ConnectionPointer session(fd_table[serverConn->fd].ssl);
BIO *b = SSL_get_rbio(session.get());
Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
if (!srvBio->canSplice())
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpSplice));
if (!srvBio->canBump())
acl_checklist->banAction(allow_t(ACCESS_ALLOWED, Ssl::bumpBump));
acl_checklist->nonBlockingCheck(Ssl::PeekingPeerConnector::cbCheckForPeekAndSpliceDone, this);
}
void
Ssl::PeekingPeerConnector::checkForPeekAndSpliceMatched(const Ssl::BumpMode action)
{
- Security::SessionPointer session(fd_table[serverConn->fd].ssl);
+ Security::ConnectionPointer session(fd_table[serverConn->fd].ssl);
BIO *b = SSL_get_rbio(session.get());
Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
debugs(83,5, "Will check for peek and splice on FD " << serverConn->fd);
Ssl::BumpMode finalAction = action;
Must(finalAction == Ssl::bumpSplice || finalAction == Ssl::bumpBump || finalAction == Ssl::bumpTerminate);
// Record final decision
if (request->clientConnectionManager.valid()) {
request->clientConnectionManager->sslBumpMode = finalAction;
request->clientConnectionManager->serverBump()->act.step3 = finalAction;
}
if (finalAction == Ssl::bumpTerminate) {
serverConn->close();
clientConn->close();
} else if (finalAction != Ssl::bumpSplice) {
//Allow write, proceed with the connection
srvBio->holdWrite(false);
srvBio->recordInput(false);
debugs(83,5, "Retry the fwdNegotiateSSL on FD " << serverConn->fd);
@@ -116,41 +116,41 @@
const Ssl::BumpMode currentMode = csd->sslBumpMode;
if (currentMode == Ssl::bumpStare) {
debugs(83,5, "default to bumping after staring");
return Ssl::bumpBump;
}
debugs(83,5, "default to splicing after " << currentMode);
} else {
debugs(83,3, "default to splicing due to missing info");
}
return Ssl::bumpSplice;
}
Security::ContextPointer
Ssl::PeekingPeerConnector::getTlsContext()
{
return ::Config.ssl_client.sslContext;
}
bool
-Ssl::PeekingPeerConnector::initialize(Security::SessionPointer &serverSession)
+Ssl::PeekingPeerConnector::initialize(Security::ConnectionPointer &serverSession)
{
if (!Security::PeerConnector::initialize(serverSession))
return false;
if (ConnStateData *csd = request->clientConnectionManager.valid()) {
// client connection is required in the case we need to splice
// or terminate client and server connections
assert(clientConn != NULL);
SBuf *hostName = NULL;
//Enable Status_request TLS extension, required to bump some clients
SSL_set_tlsext_status_type(serverSession.get(), TLSEXT_STATUSTYPE_ocsp);
const Security::TlsDetails::Pointer details = csd->tlsParser.details;
if (details && !details->serverName.isEmpty())
hostName = new SBuf(details->serverName);
if (!hostName) {
// While we are peeking at the certificate, we may not know the server
@@ -241,58 +241,58 @@
debugs(83, 3, "reset request host: " << name);
}
}
}
}
}
if (!error) {
serverCertificateVerified();
if (splice) {
switchToTunnel(request.getRaw(), clientConn, serverConn);
tunnelInsteadOfNegotiating();
}
}
}
void
Ssl::PeekingPeerConnector::noteWantWrite()
{
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
+ Security::ConnectionPointer session(fd_table[fd].ssl);
BIO *b = SSL_get_rbio(session.get());
Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
if ((srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) {
debugs(81, 3, "hold write on SSL connection on FD " << fd);
checkForPeekAndSplice();
return;
}
Security::PeerConnector::noteWantWrite();
}
void
Ssl::PeekingPeerConnector::noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error)
{
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
+ Security::ConnectionPointer session(fd_table[fd].ssl);
BIO *b = SSL_get_rbio(session.get());
Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
// In Peek mode, the ClientHello message sent to the server. If the
// server resuming a previous (spliced) SSL session with the client,
// then probably we are here because local SSL object does not know
// anything about the session being resumed.
//
if (srvBio->bumpMode() == Ssl::bumpPeek && (resumingSession = srvBio->resumingSession())) {
// we currently splice all resumed sessions unconditionally
if (const bool spliceResumed = true) {
bypassCertValidator();
checkForPeekAndSpliceMatched(Ssl::bumpSplice);
return;
} // else fall through to find a matching ssl_bump action (with limited info)
}
// If we are in peek-and-splice mode and still we did not write to
// server yet, try to see if we should splice.
// In this case the connection can be saved.
@@ -307,64 +307,64 @@
Security::CertPointer serverCert(SSL_get_peer_certificate(session.get()));
if (serverCert) {
debugs(81, 3, "Error (" << Security::ErrorString(ssl_lib_error) << ") but, hold write on SSL connection on FD " << fd);
checkForPeekAndSplice();
return;
}
}
// else call parent noteNegotiationError to produce an error page
Security::PeerConnector::noteNegotiationError(result, ssl_error, ssl_lib_error);
}
void
Ssl::PeekingPeerConnector::handleServerCertificate()
{
if (serverCertificateHandled)
return;
if (ConnStateData *csd = request->clientConnectionManager.valid()) {
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
+ Security::ConnectionPointer session(fd_table[fd].ssl);
Security::CertPointer serverCert(SSL_get_peer_certificate(session.get()));
if (!serverCert)
return;
serverCertificateHandled = true;
// remember the server certificate for later use
if (Ssl::ServerBump *serverBump = csd->serverBump()) {
serverBump->serverCert = std::move(serverCert);
}
}
}
void
Ssl::PeekingPeerConnector::serverCertificateVerified()
{
if (ConnStateData *csd = request->clientConnectionManager.valid()) {
Security::CertPointer serverCert;
if(Ssl::ServerBump *serverBump = csd->serverBump())
serverCert.resetAndLock(serverBump->serverCert.get());
else {
const int fd = serverConnection()->fd;
- Security::SessionPointer session(fd_table[fd].ssl);
+ Security::ConnectionPointer session(fd_table[fd].ssl);
serverCert.resetWithoutLocking(SSL_get_peer_certificate(session.get()));
}
if (serverCert) {
csd->resetSslCommonName(Ssl::CommonHostName(serverCert.get()));
debugs(83, 5, "HTTPS server CN: " << csd->sslCommonName() <<
" bumped: " << *serverConnection());
}
}
}
void
Ssl::PeekingPeerConnector::tunnelInsteadOfNegotiating()
{
Must(callback != NULL);
CbDialer *dialer = dynamic_cast<CbDialer*>(callback->getDialer());
Must(dialer);
dialer->answer().tunneled = true;
debugs(83, 5, "The SSL negotiation with server aborted");
}
=== modified file 'src/ssl/PeekingPeerConnector.h'
--- src/ssl/PeekingPeerConnector.h 2017-01-01 00:12:22 +0000
+++ src/ssl/PeekingPeerConnector.h 2017-04-25 16:59:06 +0000
@@ -20,41 +20,41 @@
class PeekingPeerConnector: public Security::PeerConnector {
CBDATA_CLASS(PeekingPeerConnector);
public:
PeekingPeerConnector(HttpRequestPointer &aRequest,
const Comm::ConnectionPointer &aServerConn,
const Comm::ConnectionPointer &aClientConn,
AsyncCall::Pointer &aCallback,
const AccessLogEntryPointer &alp,
const time_t timeout = 0) :
AsyncJob("Ssl::PeekingPeerConnector"),
Security::PeerConnector(aServerConn, aCallback, alp, timeout),
clientConn(aClientConn),
splice(false),
resumingSession(false),
serverCertificateHandled(false)
{
request = aRequest;
}
/* Security::PeerConnector API */
- virtual bool initialize(Security::SessionPointer &);
+ virtual bool initialize(Security::ConnectionPointer &);
virtual Security::ContextPointer getTlsContext();
virtual void noteWantWrite();
virtual void noteNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
virtual void noteNegotiationDone(ErrorState *error);
/// Updates associated client connection manager members
/// if the server certificate was received from the server.
void handleServerCertificate();
/// Initiates the ssl_bump acl check in step3 SSL bump step to decide
/// about bumping, splicing or terminating the connection.
void checkForPeekAndSplice();
/// Callback function for ssl_bump acl check in step3 SSL bump step.
void checkForPeekAndSpliceDone(allow_t answer);
/// Handles the final bumping decision.
void checkForPeekAndSpliceMatched(const Ssl::BumpMode finalMode);
/// Guesses the final bumping decision when no ssl_bump rules match.
=== modified file 'src/ssl/ServerBump.cc'
--- src/ssl/ServerBump.cc 2017-01-12 13:26:45 +0000
+++ src/ssl/ServerBump.cc 2017-04-25 16:59:06 +0000
@@ -36,38 +36,38 @@
SBuf uriBuf(request->effectiveRequestUri());
const char *uri = uriBuf.c_str();
entry = storeCreateEntry(uri, uri, request->flags, request->method);
}
// We do not need to be a client because the error contents will be used
// later, but an entry without any client will trim all its contents away.
sc = storeClientListAdd(entry, this);
}
Ssl::ServerBump::~ServerBump()
{
debugs(33, 4, HERE << "destroying");
if (entry) {
debugs(33, 4, HERE << *entry);
storeUnregister(sc, entry, this);
entry->unlock("Ssl::ServerBump");
}
}
void
-Ssl::ServerBump::attachServerSession(const Security::SessionPointer &s)
+Ssl::ServerBump::attachServerSession(const Security::ConnectionPointer &s)
{
if (serverSession)
return;
serverSession = s;
}
const Security::CertErrors *
Ssl::ServerBump::sslErrors() const
{
if (!serverSession)
return NULL;
const Security::CertErrors *errs = static_cast<const Security::CertErrors*>(SSL_get_ex_data(serverSession.get(), ssl_ex_index_ssl_errors));
return errs;
}
=== modified file 'src/ssl/ServerBump.h'
--- src/ssl/ServerBump.h 2017-01-12 13:26:45 +0000
+++ src/ssl/ServerBump.h 2017-04-25 16:59:06 +0000
@@ -15,46 +15,46 @@
#include "HttpRequest.h"
#include "ip/Address.h"
#include "security/forward.h"
class ConnStateData;
class store_client;
namespace Ssl
{
/**
* Maintains bump-server-first related information.
*/
class ServerBump
{
CBDATA_CLASS(ServerBump);
public:
explicit ServerBump(HttpRequest *fakeRequest, StoreEntry *e = NULL, Ssl::BumpMode mode = Ssl::bumpServerFirst);
~ServerBump();
- void attachServerSession(const Security::SessionPointer &); ///< Sets the server TLS session object
+ void attachServerSession(const Security::ConnectionPointer &); ///< Sets the server TLS session object
const Security::CertErrors *sslErrors() const; ///< SSL [certificate validation] errors
/// faked, minimal request; required by Client API
HttpRequest::Pointer request;
StoreEntry *entry; ///< for receiving Squid-generated error messages
/// HTTPS server certificate. Maybe it is different than the one
/// it is stored in serverSession object (error SQUID_X509_V_ERR_CERT_CHANGE)
Security::CertPointer serverCert;
struct {
Ssl::BumpMode step1; ///< The SSL bump mode at step1
Ssl::BumpMode step2; ///< The SSL bump mode at step2
Ssl::BumpMode step3; ///< The SSL bump mode at step3
} act; ///< bumping actions at various bumping steps
Ssl::BumpStep step; ///< The SSL bumping step
SBuf clientSni; ///< the SSL client SNI name
private:
- Security::SessionPointer serverSession; ///< The TLS session object on server side.
+ Security::ConnectionPointer serverSession; ///< The TLS session object on server side.
store_client *sc; ///< dummy client to prevent entry trimming
};
} // namespace Ssl
#endif
=== modified file 'src/ssl/cert_validate_message.h'
--- src/ssl/cert_validate_message.h 2017-01-12 13:26:45 +0000
+++ src/ssl/cert_validate_message.h 2017-04-25 16:59:06 +0000
@@ -9,41 +9,41 @@
#ifndef SQUID_SSL_CERT_VALIDATE_MESSAGE_H
#define SQUID_SSL_CERT_VALIDATE_MESSAGE_H
#include "base/RefCount.h"
#include "helper/ResultCode.h"
#include "ssl/crtd_message.h"
#include "ssl/support.h"
#include <vector>
namespace Ssl
{
/**
* This class is used to hold the required informations to build
* a request message for the certificate validator helper
*/
class CertValidationRequest
{
public:
- Security::SessionPointer ssl;
+ Security::ConnectionPointer ssl;
Security::CertErrors *errors = nullptr; ///< The list of errors detected
std::string domainName; ///< The server name
};
/**
* This class is used to store informations found in certificate validation
* response messages read from certificate validator helper
*/
class CertValidationResponse: public RefCountable
{
public:
typedef RefCount<CertValidationResponse> Pointer;
/**
* This class used to hold error informations returned from
* cert validator helper.
*/
class RecvdError
{
public:
=== modified file 'src/ssl/helper.cc'
--- src/ssl/helper.cc 2017-01-12 13:26:45 +0000
+++ src/ssl/helper.cc 2017-04-25 16:59:06 +0000
@@ -164,41 +164,41 @@
return;
helperShutdown(ssl_crt_validator);
wordlistDestroy(&ssl_crt_validator->cmdline);
delete ssl_crt_validator;
ssl_crt_validator = NULL;
// CertValidationHelper::HelperCache is a static member, it is not good policy to
// reset it here. Will work because the current Ssl::CertValidationHelper is
// always the same static object.
delete HelperCache;
HelperCache = NULL;
}
class submitData
{
CBDATA_CLASS(submitData);
public:
std::string query;
AsyncCall::Pointer callback;
- Security::SessionPointer ssl;
+ Security::ConnectionPointer ssl;
};
CBDATA_CLASS_INIT(submitData);
static void
sslCrtvdHandleReplyWrapper(void *data, const ::Helper::Reply &reply)
{
Ssl::CertValidationMsg replyMsg(Ssl::CrtdMessage::REPLY);
Ssl::CertValidationResponse::Pointer validationResponse = new Ssl::CertValidationResponse;
std::string error;
submitData *crtdvdData = static_cast<submitData *>(data);
STACK_OF(X509) *peerCerts = SSL_get_peer_cert_chain(crtdvdData->ssl.get());
if (reply.result == ::Helper::BrokenHelper) {
debugs(83, DBG_IMPORTANT, "\"ssl_crtvd\" helper error response: " << reply.other().content());
validationResponse->resultCode = ::Helper::BrokenHelper;
} else if (!reply.other().hasContent()) {
debugs(83, DBG_IMPORTANT, "\"ssl_crtvd\" helper returned NULL response");
validationResponse->resultCode = ::Helper::BrokenHelper;
} else if (replyMsg.parse(reply.other().content(), reply.other().contentSize()) != Ssl::CrtdMessage::OK ||
!replyMsg.parseResponse(*validationResponse, peerCerts, error) ) {
=== modified file 'src/ssl/support.cc'
--- src/ssl/support.cc 2017-02-05 05:57:32 +0000
+++ src/ssl/support.cc 2017-04-26 12:21:33 +0000
@@ -979,41 +979,41 @@
if (!SSL_use_PrivateKey(ssl, pkey.get()))
return false;
return true;
}
bool
Ssl::verifySslCertificate(Security::ContextPointer &ctx, CertificateProperties const &properties)
{
// SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
// Try to retrieve certificate directly from Security::ContextPointer object
#if SQUID_USE_SSLGETCERTIFICATE_HACK
X509 ***pCert = (X509 ***)ctx->cert;
X509 * cert = pCert && *pCert ? **pCert : NULL;
#elif SQUID_SSLGETCERTIFICATE_BUGGY
X509 * cert = NULL;
assert(0);
#else
// Temporary ssl for getting X509 certificate from SSL_CTX.
- Security::SessionPointer ssl(Security::NewSessionObject(ctx));
+ Security::ConnectionPointer ssl(Security::NewSslObject(ctx));
X509 * cert = SSL_get_certificate(ssl.get());
#endif
if (!cert)
return false;
ASN1_TIME * time_notBefore = X509_get_notBefore(cert);
ASN1_TIME * time_notAfter = X509_get_notAfter(cert);
bool ret = (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
if (!ret)
return false;
return certificateMatchesProperties(cert, properties);
}
bool
Ssl::setClientSNI(SSL *ssl, const char *fqdn)
{
//The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
// if the TLS servername extension (SNI) is enabled in openssl library.
#if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
if (!SSL_set_tlsext_host_name(ssl, fqdn)) {
=== modified file 'src/tests/stub_libsecurity.cc'
--- src/tests/stub_libsecurity.cc 2017-02-05 06:12:19 +0000
+++ src/tests/stub_libsecurity.cc 2017-04-26 12:21:33 +0000
@@ -1,108 +1,111 @@
/*
* 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.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
#include "squid.h"
#include "AccessLogEntry.h"
#include "comm/Connection.h"
#include "HttpRequest.h"
#define STUB_API "security/libsecurity.la"
#include "tests/STUB.h"
#include "security/BlindPeerConnector.h"
CBDATA_NAMESPACED_CLASS_INIT(Security, BlindPeerConnector);
namespace Security
{
-bool BlindPeerConnector::initialize(Security::SessionPointer &) STUB_RETVAL(false)
+bool BlindPeerConnector::initialize(Security::ConnectionPointer &) STUB_RETVAL(false)
Security::ContextPointer BlindPeerConnector::getTlsContext() STUB_RETVAL(Security::ContextPointer())
void BlindPeerConnector::noteNegotiationDone(ErrorState *) STUB
}
#include "security/EncryptorAnswer.h"
Security::EncryptorAnswer::~EncryptorAnswer() {}
std::ostream &Security::operator <<(std::ostream &os, const Security::EncryptorAnswer &) STUB_RETVAL(os)
#include "security/Handshake.h"
Security::HandshakeParser::HandshakeParser() STUB
bool Security::HandshakeParser::parseHello(const SBuf &) STUB_RETVAL(false)
#include "security/NegotiationHistory.h"
Security::NegotiationHistory::NegotiationHistory() STUB
-void Security::NegotiationHistory::retrieveNegotiatedInfo(const Security::SessionPointer &) STUB
+void Security::NegotiationHistory::retrieveNegotiatedInfo(const Security::ConnectionPointer &) STUB
void Security::NegotiationHistory::retrieveParsedInfo(Security::TlsDetails::Pointer const &) STUB
const char *Security::NegotiationHistory::cipherName() const STUB
const char *Security::NegotiationHistory::printTlsVersion(AnyP::ProtocolVersion const &v) const STUB
#include "security/PeerConnector.h"
CBDATA_NAMESPACED_CLASS_INIT(Security, PeerConnector);
namespace Security
{
PeerConnector::PeerConnector(const Comm::ConnectionPointer &, AsyncCall::Pointer &, const AccessLogEntryPointer &, const time_t) :
AsyncJob("Security::PeerConnector") {STUB}
PeerConnector::~PeerConnector() {STUB}
void PeerConnector::start() STUB
bool PeerConnector::doneAll() const STUB_RETVAL(true)
void PeerConnector::swanSong() STUB
const char *PeerConnector::status() const STUB_RETVAL("")
void PeerConnector::commCloseHandler(const CommCloseCbParams &) STUB
void PeerConnector::connectionClosed(const char *) STUB
bool PeerConnector::prepareSocket() STUB_RETVAL(false)
void PeerConnector::setReadTimeout() STUB
-bool PeerConnector::initialize(Security::SessionPointer &) STUB_RETVAL(false)
+bool PeerConnector::initialize(Security::ConnectionPointer &) STUB_RETVAL(false)
void PeerConnector::negotiate() STUB
bool PeerConnector::sslFinalized() STUB_RETVAL(false)
void PeerConnector::handleNegotiateError(const int) STUB
void PeerConnector::noteWantRead() STUB
void PeerConnector::noteWantWrite() STUB
void PeerConnector::noteNegotiationError(const int, const int, const int) STUB
// virtual Security::ContextPointer getTlsContext() = 0;
void PeerConnector::bail(ErrorState *) STUB
void PeerConnector::callBack() STUB
void PeerConnector::recordNegotiationDetails() STUB
}
#include "security/PeerOptions.h"
Security::PeerOptions Security::ProxyOutgoingConfig;
Security::PeerOptions::PeerOptions() {
#if USE_OPENSSL
parsedOptions = 0;
#endif
STUB_NOP
}
void Security::PeerOptions::parse(char const*) STUB
Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(Security::ContextPointer())
void Security::PeerOptions::updateTlsVersionLimits() STUB
Security::ContextPointer Security::PeerOptions::createBlankContext() const STUB_RETVAL(Security::ContextPointer())
void Security::PeerOptions::updateContextCa(Security::ContextPointer &) STUB
void Security::PeerOptions::updateContextCrl(Security::ContextPointer &) STUB
-void Security::PeerOptions::updateSessionOptions(Security::SessionPointer &) STUB
+void Security::PeerOptions::updateSessionOptions(Security::ConnectionPointer &) STUB
void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB
void Security::PeerOptions::parseOptions() STUB
void parse_securePeerOptions(Security::PeerOptions *) STUB
#include "security/ServerOptions.h"
//Security::ServerOptions::ServerOptions(const Security::ServerOptions &) STUB
void Security::ServerOptions::parse(const char *) STUB
void Security::ServerOptions::dumpCfg(Packable *, const char *) const STUB
Security::ContextPointer Security::ServerOptions::createBlankContext() const STUB_RETVAL(Security::ContextPointer())
bool Security::ServerOptions::createStaticServerContext(AnyP::PortCfg &) STUB_RETVAL(false)
void Security::ServerOptions::updateContextEecdh(Security::ContextPointer &) STUB
#include "security/Session.h"
namespace Security {
-bool CreateClientSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *) STUB_RETVAL(false)
-bool CreateServerSession(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *) STUB_RETVAL(false)
-void SessionSendGoodbye(const Security::SessionPointer &) STUB
-bool SessionIsResumed(const Security::SessionPointer &) STUB_RETVAL(false)
-void MaybeGetSessionResumeData(const Security::SessionPointer &, Security::SessionStatePointer &) STUB
-void SetSessionResumeData(const Security::SessionPointer &, const Security::SessionStatePointer &) STUB
+bool SessionIsResumed(const Security::ConnectionPointer &) STUB_RETVAL(false)
+void MaybeGetSessionResumeData(const Security::ConnectionPointer &, Security::SessionStatePointer &) STUB
+void SetSessionResumeData(const Security::ConnectionPointer &, const Security::SessionStatePointer &) STUB
+} // namespace Security
+
+#include "security/Connection.h"
+namespace Security {
+bool CreateClient(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *) STUB_RETVAL(false)
+bool CreateServer(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *) STUB_RETVAL(false)
+void SendGoodbye(const Security::ConnectionPointer &) STUB
#if USE_OPENSSL
-Security::SessionPointer NewSessionObject(const Security::ContextPointer &) STUB_RETVAL(nullptr)
+Security::ConnectionPointer NewSslObject(const Security::ContextPointer &) STUB_RETVAL(nullptr)
#endif
} // namespace Security
-
_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev