acl/libacls.la \
DiskIO/libdiskio.la \
acl/libapi.la \
+ anyp/libanyp.la \
$(SSL_LIBS) \
ipc/libipc.la \
comm/libcomm.la \
- anyp/libanyp.la \
dns/libdns.la \
base/libbase.la \
ip/libip.la \
To control SSLv3 use the options= parameter.
Supported Values: 1.0 (default), 1.1, 1.2
- options=... Specify various TLS/SSL implementation options:
+ options=... Specify various TLS/SSL implementation options.
- NO_SSLv3 Disallow the use of SSLv3
-
- NO_TLSv1 Disallow the use of TLSv1.0
-
- NO_TLSv1_1 Disallow the use of TLSv1.1
+ OpenSSL options most important are:
- NO_TLSv1_2 Disallow the use of TLSv1.2
+ NO_SSLv3 Disallow the use of SSLv3
SINGLE_DH_USE
Always create a new key when using
Be warned that this reduces SSL/TLS
strength to some attacks.
- See the OpenSSL SSL_CTX_set_options documentation for a
- more complete list.
+ See the OpenSSL SSL_CTX_set_options documentation
+ for a more complete list.
+
+ GnuTLS options most important are:
+
+ %NO_TICKETS
+ Disable use of RFC5077 session tickets.
+ Some servers may have problems
+ understanding the TLS extension due
+ to ambiguous specification in RFC4507.
+
+ See the GnuTLS Priority Strings documentation
+ for a more complete list.
+ http://www.gnutls.org/manual/gnutls.html#Priority-Strings
+
cafile= PEM file containing CA certificates to use when verifying
the peer certificate. May be repeated to load multiple files.
tls-min-version=1.N
The minimum TLS protocol version to permit. To control
- SSLv3 use the ssloptions= parameter.
+ SSLv3 use the tls-options= parameter.
Supported Values: 1.0 (default), 1.1, 1.2
- ssloptions=... Specify various SSL implementation options:
+ tls-options=... Specify various TLS implementation options.
- NO_SSLv3 Disallow the use of SSLv3
+ OpenSSL options most important are:
- NO_TLSv1 Disallow the use of TLSv1.0
-
- NO_TLSv1_1 Disallow the use of TLSv1.1
-
- NO_TLSv1_2 Disallow the use of TLSv1.2
+ NO_SSLv3 Disallow the use of SSLv3
SINGLE_DH_USE
Always create a new key when using
See the OpenSSL SSL_CTX_set_options documentation for a
more complete list.
-
+
+ GnuTLS options most important are:
+
+ %NO_TICKETS
+ Disable use of RFC5077 session tickets.
+ Some servers may have problems
+ understanding the TLS extension due
+ to ambiguous specification in RFC4507.
+
+ See the GnuTLS Priority Strings documentation
+ for a more complete list.
+ http://www.gnutls.org/manual/gnutls.html#Priority-Strings
+
tls-cafile= PEM file containing CA certificates to use when verifying
the peer certificate. May be repeated to load multiple files.
tls-min-version=1.N
The minimum TLS protocol version to permit. To control
- SSLv3 use the ssloptions= parameter.
+ SSLv3 use the tls-options= parameter.
Supported Values: 1.0 (default), 1.1, 1.2
tls-options=... Specify various OpenSSL library options:
NO_SSLv3 Disallow the use of SSLv3
- NO_TLSv1 Disallow the use of TLSv1.0
- NO_TLSv1_1 Disallow the use of TLSv1.1
- NO_TLSv1_2 Disallow the use of TLSv1.2
-
SINGLE_DH_USE
Always create a new key when using
temporary/ephemeral DH key exchanges
}
#if USE_OPENSSL
-
-/** Create SSL connection structure and update fd_table */
+/// Create TLS connection structure and update fd_table
static bool
httpsCreate(const Comm::ConnectionPointer &conn, const Security::ContextPointer &ctx)
{
- if (Ssl::CreateServer(ctx, conn, "client https start")) {
- debugs(33, 5, "will negotate SSL on " << conn);
+ if (Security::CreateServerSession(ctx, conn, "client https start")) {
+ debugs(33, 5, "will negotiate TLS on " << conn);
return true;
}
if (!ret)
debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode");
- Security::ContextPointer ctx;
- ctx.resetAndLock(SSL_get_SSL_CTX(ssl));
+ Security::ContextPointer ctx(Security::GetFrom(fd_table[clientConnection->fd].ssl));
Ssl::configureUnconfiguredSslContext(ctx, signAlgorithm, *port);
} else {
Security::ContextPointer ctx(Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port));
if (!Ssl::configureSSL(ssl, certProperties, *port))
debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode");
- Security::ContextPointer ctx;
- ctx.resetAndLock(SSL_get_SSL_CTX(ssl));
+ Security::ContextPointer ctx(Security::GetFrom(fd_table[clientConnection->fd].ssl));
Ssl::configureUnconfiguredSslContext(ctx, certProperties.signAlgorithm, *port);
} else {
Security::ContextPointer dynCtx(Ssl::generateSslContext(certProperties, *port));
void
comm_lingering_close(int fd)
{
-#if USE_OPENSSL
- if (fd_table[fd].ssl)
- ssl_shutdown_method(fd_table[fd].ssl);
-#endif
+ Security::SessionSendGoodbye(fd_table[fd].ssl);
if (shutdown(fd, 1) < 0) {
comm_close(fd);
comm_close(fd);
}
-#if USE_OPENSSL
void
-commStartSslClose(const FdeCbParams ¶ms)
+commStartTlsClose(const FdeCbParams ¶ms)
{
- assert(fd_table[params.fd].ssl);
- ssl_shutdown_method(fd_table[params.fd].ssl.get());
+ Security::SessionSendGoodbye(fd_table[params.fd].ssl);
}
-#endif
void
comm_close_complete(const FdeCbParams ¶ms)
F->flags.close_request = true;
-#if USE_OPENSSL
if (F->ssl) {
- AsyncCall::Pointer startCall=commCbCall(5,4, "commStartSslClose",
- FdeCbPtrFun(commStartSslClose, NULL));
+ AsyncCall::Pointer startCall=commCbCall(5,4, "commStartTlsClose",
+ FdeCbPtrFun(commStartTlsClose, nullptr));
FdeCbParams &startParams = GetCommParams<FdeCbParams>(startCall);
startParams.fd = fd;
ScheduleCallHere(startCall);
}
-#endif
// a half-closed fd may lack a reader, so we stop monitoring explicitly
if (commHasHalfClosedMonitor(fd))
bool
Security::BlindPeerConnector::initialize(Security::SessionPointer &serverSession)
{
- if (!Security::PeerConnector::initialize(serverSession))
+ if (!Security::PeerConnector::initialize(serverSession)) {
+ debugs(83, 5, "Security::PeerConnector::initialize failed");
return false;
+ }
if (const CachePeer *peer = serverConnection()->getPeer()) {
assert(peer);
SSL_set_ex_data(serverSession.get(), ssl_ex_index_server, (void*)hostName);
#endif
}
+
+ debugs(83, 5, "success");
return true;
}
Security::BlindPeerConnector::noteNegotiationDone(ErrorState *error)
{
if (error) {
+ debugs(83, 5, "error=" << (void*)error);
// XXX: forward.cc calls peerConnectSucceeded() after an OK TCP connect but
// we call peerConnectFailed() if SSL failed afterwards. Is that OK?
// It is not clear whether we should call peerConnectSucceeded/Failed()
#ifndef SQUID_SRC_SECURITY_CONTEXT_H
#define SQUID_SRC_SECURITY_CONTEXT_H
-#include "security/forward.h"
-#include "security/LockingPointer.h"
+#include <memory>
#if USE_OPENSSL
#if HAVE_OPENSSL_SSL_H
namespace Security {
#if USE_OPENSSL
-CtoCpp1(SSL_CTX_free, SSL_CTX *);
-#if defined(CRYPTO_LOCK_SSL_CTX) // OpenSSL 1.0
-inline int SSL_CTX_up_ref(SSL_CTX *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_SSL_CTX); return 0;}
-#endif
-typedef Security::LockingPointer<SSL_CTX, SSL_CTX_free_cpp, HardFun<int, SSL_CTX *, SSL_CTX_up_ref> > ContextPointer;
+typedef std::shared_ptr<SSL_CTX> ContextPointer;
#elif USE_GNUTLS
-CtoCpp1(gnutls_certificate_free_credentials, gnutls_certificate_credentials_t);
-typedef Security::LockingPointer<struct gnutls_certificate_credentials_st, gnutls_certificate_free_credentials_cpp> ContextPointer;
+typedef std::shared_ptr<struct gnutls_certificate_credentials_st> ContextPointer;
#else
// use void* so we can check against nullptr
-typedef Security::LockingPointer<void, nullptr> ContextPointer;
+typedef std::shared_ptr<void> ContextPointer;
#endif
Security::PeerConnector::start()
{
AsyncJob::start();
+ debugs(83, 5, "this=" << (void*)this);
Security::SessionPointer tmp;
if (prepareSocket() && initialize(tmp))
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()
{
- const int fd = serverConnection()->fd;
- if (!Comm::IsConnOpen(serverConn) || fd_table[serverConn->fd].closing()) {
+ 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(fd, closeHandler);
+ comm_add_close_handler(serverConnection()->fd, closeHandler);
return true;
}
bool
Security::PeerConnector::initialize(Security::SessionPointer &serverSession)
{
-#if USE_OPENSSL
Security::ContextPointer ctx(getTlsContext());
- assert(ctx);
+ debugs(83, 5, serverConnection() << ", ctx=" << (void*)ctx.get());
- if (!Ssl::CreateClient(ctx, serverConnection(), "server https start")) {
+ if (!ctx || !Security::CreateClientSession(ctx, serverConnection(), "server https start")) {
const auto xerrno = errno;
- const auto ssl_error = ERR_get_error();
+ if (!ctx) {
+ debugs(83, DBG_IMPORTANT, "Error initializing TLS connection: No security context.");
+ } // else CreateClientSession() did the appropriate debugs() already
ErrorState *anErr = new ErrorState(ERR_SOCKET_FAILURE, Http::scInternalServerError, request.getRaw());
anErr->xerrno = xerrno;
- debugs(83, DBG_IMPORTANT, "Error allocating TLS handle: " << Security::ErrorString(ssl_error));
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());
+#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) {
SSL_set_ex_data(serverSession.get(), ssl_ex_index_cert_error_check, check);
}
}
+#endif
return true;
-#else
- return false;
-#endif
}
void
return;
#if USE_OPENSSL
- const int result = SSL_connect(fd_table[fd].ssl.get());
+ auto session = fd_table[fd].ssl.get();
+ debugs(83, 5, "SSL_connect session=" << (void*)session);
+ const int result = SSL_connect(session);
+ 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
- const int result = -1;
+ if (const int result = -1) {
#endif
- if (result <= 0) {
handleNegotiateError(result);
return; // we might be gone by now
}
Security::SessionPointer session(fd_table[fd].ssl);
Ssl::CertValidationRequest validationRequest;
- // WARNING: Currently we do not use any locking for any of the
- // members of the Ssl::CertValidationRequest class. In this code the
+ // 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.get();
+ validationRequest.ssl = session;
if (SBuf *dName = (SBuf *)SSL_get_ex_data(session.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)))
void
Security::PeerConnector::handleNegotiateError(const int ret)
{
-#if USE_OPENSSL
const int fd = serverConnection()->fd;
- unsigned long ssl_lib_error = SSL_ERROR_NONE;
- Security::SessionPointer session(fd_table[fd].ssl);
+ const Security::SessionPointer session(fd_table[fd].ssl);
+ unsigned long ssl_lib_error = ret;
+
+#if USE_OPENSSL
const int ssl_error = SSL_get_error(session.get(), ret);
switch (ssl_error) {
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());
+ 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)
+ noteWantRead();
+ else
+ noteWantWrite();
+ return;
+
+ default:
+ // no special error handling for all other errors
+ break;
+ }
+
+#else
+ // this avoids unused variable compiler warnings.
+ Must(!session);
+ const int ssl_error = ret;
+#endif
+
// Log connection details, if any
recordNegotiationDetails();
noteNegotiationError(ret, ssl_error, ssl_lib_error);
-#endif
}
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::PeerConnector::noteWantWrite()
{
const int fd = serverConnection()->fd;
+ debugs(83, 5, serverConnection());
Comm::SetSelect(fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
return;
}
void
Security::PeerConnector::noteNegotiationError(const int ret, const int ssl_error, const int ssl_lib_error)
{
-#if USE_OPENSSL // not used unless OpenSSL enabled.
#if defined(EPROTO)
int sysErrNo = EPROTO;
#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 SSL on FD " << fd <<
+ debugs(83, DBG_IMPORTANT, "ERROR: negotiating TLS on FD " << fd <<
": " << Security::ErrorString(ssl_lib_error) << " (" <<
- ssl_error << "/" << ret << "/" << errno << ")");
+ ssl_error << "/" << ret << "/" << xerr << ")");
ErrorState *anErr = NULL;
if (request != NULL)
anErr = new ErrorState(ERR_SECURE_CONNECT_FAIL, Http::scServiceUnavailable, NULL);
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));
if (errFromFailure != NULL) {
if (ssl_lib_error != SSL_ERROR_NONE)
anErr->detail->setLibError(ssl_lib_error);
+#endif
noteNegotiationDone(anErr);
bail(anErr);
-#endif
}
void
void
Security::PeerConnector::callBack()
{
+ debugs(83, 5, "TLS setup ended for " << serverConnection());
+
AsyncCall::Pointer cb = callback;
// Do this now so that if we throw below, swanSong() assert that we _tried_
// to call back holds.
Security::PeerOptions Security::ProxyOutgoingConfig;
-Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) :
- sslOptions(p.sslOptions),
- caDir(p.caDir),
- crlFile(p.crlFile),
- sslCipher(p.sslCipher),
- sslFlags(p.sslFlags),
- sslDomain(p.sslDomain),
- parsedOptions(p.parsedOptions),
- parsedFlags(p.parsedFlags),
- certs(p.certs),
- caFiles(p.caFiles),
- parsedCrl(p.parsedCrl),
- sslVersion(p.sslVersion),
- encryptTransport(p.encryptTransport)
+Security::PeerOptions::PeerOptions()
{
- memcpy(&flags, &p.flags, sizeof(flags));
+ // init options consistent with an empty sslOptions
+ parseOptions();
}
void
tlsMinVersion = SBuf(token + 12);
} else if (strncmp(token, "options=", 8) == 0) {
sslOptions = SBuf(token + 8);
- parsedOptions = parseOptions();
+ parseOptions();
} else if (strncmp(token, "cipher=", 7) == 0) {
sslCipher = SBuf(token + 7);
} else if (strncmp(token, "cafile=", 7) == 0) {
if (tok.skip('1') && tok.skip('.') && tok.int64(v, 10, false, 1) && v <= 3) {
// only account for TLS here - SSL versions are handled by options= parameter
// avoid affecting options= parameter in cachemgr config report
+#if USE_OPENSSL
#if SSL_OP_NO_TLSv1
if (v > 0)
parsedOptions |= SSL_OP_NO_TLSv1;
parsedOptions |= SSL_OP_NO_TLSv1_2;
#endif
+#elif USE_GNUTLS
+ // XXX: update parsedOptions directly to avoid polluting 'options=' dumps
+ SBuf add;
+ if (v > 0)
+ add.append(":-VERS-TLS1.0");
+ if (v > 1)
+ add.append(":-VERS-TLS1.1");
+ if (v > 2)
+ add.append(":-VERS-TLS1.2");
+
+ if (sslOptions.isEmpty())
+ add.chop(1); // remove the initial ':'
+ sslOptions.append(add);
+#endif
+
} else {
debugs(0, DBG_PARSE_NOTE(1), "WARNING: Unknown TLS minimum version: " << tlsMinVersion);
}
- } else if (sslVersion > 2) {
+ return;
+ }
+
+ if (sslVersion > 2) {
// backward compatibility hack for sslversion= configuration
// only use if tls-min-version=N.N is not present
// values 0-2 for auto and SSLv2 are not supported any longer.
// Do it this way so we DO cause changes to options= in cachemgr config report
- const char *add = NULL;
+ const char *add = nullptr;
switch (sslVersion) {
case 3:
- add = "NO_TLSv1,NO_TLSv1_1,NO_TLSv1_2";
+#if USE_OPENSSL
+ parsedOptions |= (SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
+#elif USE_GNUTLS
+ add = ":-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2";
+#endif
break;
case 4:
- add = "NO_SSLv3,NO_TLSv1_1,NO_TLSv1_2";
+#if USE_OPENSSL
+ parsedOptions |= (SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
+#elif USE_GNUTLS
+ add = ":+VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2";
+#endif
break;
case 5:
- add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_2";
+#if USE_OPENSSL
+ parsedOptions |= (SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_2);
+#elif USE_GNUTLS
+ add = ":-VERS-TLS1.0:+VERS-TLS1.1:-VERS-TLS1.2";
+#endif
break;
case 6:
- add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_1";
+#if USE_OPENSSL
+ parsedOptions |= (SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1);
+#elif USE_GNUTLS
+ add = ":-VERS-TLS1.0:-VERS-TLS1.1";
+#endif
break;
default: // nothing
break;
}
if (add) {
- if (!sslOptions.isEmpty())
- sslOptions.append(",",1);
- sslOptions.append(add, strlen(add));
+#if USE_GNUTLS // dont bother otherwise
+ if (sslOptions.isEmpty())
+ sslOptions.append(add+1, strlen(add+1));
+ else
+ sslOptions.append(add, strlen(add));
+#endif
}
sslVersion = 0; // prevent sslOptions being repeatedly appended
}
const auto x = ERR_get_error();
fatalf("Failed to allocate TLS client context: %s\n", Security::ErrorString(x));
}
- ctx.resetWithoutLocking(t);
+ ctx = convertContextFromRawPtr(t);
#elif USE_GNUTLS
// Initialize for X.509 certificate exchange
if (const int x = gnutls_certificate_allocate_credentials(&t)) {
fatalf("Failed to allocate TLS client context: %s\n", Security::ErrorString(x));
}
- ctx.resetWithoutLocking(t);
+ ctx = convertContextFromRawPtr(t);
#else
debugs(83, 1, "WARNING: Failed to allocate TLS client context: No TLS library");
Security::ContextPointer t(createBlankContext());
if (t) {
#if USE_OPENSSL
+ // NP: GnuTLS uses 'priorities' which are set per-session instead.
+ SSL_CTX_set_options(t.get(), (setOptions ? parsedOptions : 0));
+
// XXX: temporary performance regression. c_str() data copies and prevents this being a const method
- Ssl::InitClientContext(t, *this, (setOptions ? parsedOptions : 0), parsedFlags);
+ Ssl::InitClientContext(t, *this, parsedFlags);
#endif
updateContextNpn(t);
updateContextCa(t);
return t;
}
+#if USE_OPENSSL
/// set of options we can parse and what they map to
static struct ssl_option {
const char *name;
NULL, 0
}
};
+#endif /* USE_OPENSSL */
/**
* Pre-parse TLS options= parameter to be applied when the TLS objects created.
* Options must not used in the case of peek or stare bump mode.
*/
-long
+void
Security::PeerOptions::parseOptions()
{
- long op = 0;
+#if USE_OPENSSL
::Parser::Tokenizer tok(sslOptions);
+ long op = 0;
- do {
+ while (!tok.atEnd()) {
enum {
MODE_ADD, MODE_REMOVE
} mode;
fatalf("Unknown TLS option '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(tok.remaining()));
}
- } while (!tok.atEnd());
+ }
#if SSL_OP_NO_SSLv2
// compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
op = op | SSL_OP_NO_SSLv2;
#endif
- return op;
+ parsedOptions = op;
+
+#elif USE_GNUTLS
+ if (sslOptions.isEmpty()) {
+ parsedOptions.reset();
+ return;
+ }
+
+ const char *err = nullptr;
+ const char *priorities = sslOptions.c_str();
+ gnutls_priority_t op;
+ if (gnutls_priority_init(&op, priorities, &err) != GNUTLS_E_SUCCESS) {
+ fatalf("Unknown TLS option '%s'", err);
+ }
+ parsedOptions = Security::ParsedOptions(op, [](gnutls_priority_t p) {
+ debugs(83, 5, "gnutls_priority_deinit p=" << (void*)p);
+ gnutls_priority_deinit(p);
+ });
+#endif
}
/**
static const char *
loadSystemTrustedCa(Security::ContextPointer &ctx)
{
+ debugs(83, 8, "Setting default system Trusted CA. ctx=" << (void*)ctx.get());
#if USE_OPENSSL
if (SSL_CTX_set_default_verify_paths(ctx.get()) == 0)
return Security::ErrorString(ERR_get_error());
#endif /* USE_OPENSSL */
}
+void
+Security::PeerOptions::updateSessionOptions(Security::SessionPointer &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));
+ }
+#endif
+}
+
void
parse_securePeerOptions(Security::PeerOptions *opt)
{
class PeerOptions
{
public:
- PeerOptions() : parsedOptions(0), parsedFlags(0), sslVersion(0), encryptTransport(false) {}
- PeerOptions(const PeerOptions &);
- virtual ~PeerOptions() = default;
+ PeerOptions();
+ PeerOptions(const PeerOptions &) = default;
+ PeerOptions &operator =(const PeerOptions &) = default;
+ virtual ~PeerOptions() {}
/// parse a TLS squid.conf option
virtual void parse(const char *);
/// 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 &);
+
/// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
virtual void dumpCfg(Packable *, const char *pfx) const;
private:
- long parseOptions();
+ void parseOptions(); ///< parsed value of sslOptions
long parseFlags();
void loadCrlFile();
SBuf tlsMinVersion; ///< version label for minimum TLS version to permit
- long parsedOptions; ///< parsed value of sslOptions
- long parsedFlags; ///< parsed value of sslFlags
+ Security::ParsedOptions parsedOptions; ///< parsed value of sslOptions
+ long parsedFlags = 0; ///< parsed value of sslFlags
std::list<Security::KeyData> certs; ///< details from the cert= and file= config parameters
std::list<SBuf> caFiles; ///< paths of files containing trusted Certificate Authority
Security::CertRevokeList parsedCrl; ///< CRL to use when verifying the remote end certificate
protected:
- int sslVersion;
+ template<typename T>
+ Security::ContextPointer convertContextFromRawPtr(T ctx) const {
+#if USE_OPENSSL
+ return ContextPointer(ctx, [](SSL_CTX *p) {
+ debugs(83, 5, "SSL_free ctx=" << (void*)p);
+ SSL_CTX_free(p);
+ });
+#elif USE_GNUTLS
+ return Security::ContextPointer(ctx, [](gnutls_certificate_credentials_t p) {
+ debugs(83, 5, "gnutls_certificate_free_credentials ctx=" << (void*)p);
+ gnutls_certificate_free_credentials(p);
+ });
+#else
+ assert(!ctx);
+ return Security::ContextPointer();
+#endif
+ }
+
+ int sslVersion = 0;
/// flags governing Squid internal TLS operations
struct flags_ {
flags_() : tlsDefaultCa(true), tlsNpn(true) {}
+ flags_(const flags_ &) = default;
+ flags_ &operator =(const flags_ &) = default;
/// whether to use the system default Trusted CA when verifying the remote end certificate
YesNoNone tlsDefaultCa;
public:
/// whether transport encryption (TLS/SSL) is to be used on connections to the peer
- bool encryptTransport;
+ bool encryptTransport = false;
};
/// configuration options for DIRECT server access
const auto x = ERR_get_error();
debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate TLS server context: " << Security::ErrorString(x));
}
- ctx.resetWithoutLocking(t);
+ ctx = convertContextFromRawPtr(t);
#elif USE_GNUTLS
// Initialize for X.509 certificate exchange
if (const int x = gnutls_certificate_allocate_credentials(&t)) {
debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate TLS server context: " << Security::ErrorString(x));
}
- ctx.resetWithoutLocking(t);
+ ctx = convertContextFromRawPtr(t);
#else
debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate TLS server context: No TLS library");
#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)
{
#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>
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
-CtoCpp1(SSL_free, SSL *);
-#if defined(CRYPTO_LOCK_SSL) // OpenSSL 1.0
-inline int SSL_up_ref(SSL *t) {if (t) CRYPTO_add(&t->references, 1, CRYPTO_LOCK_SSL); return 0;}
-#endif
-typedef Security::LockingPointer<SSL, Security::SSL_free_cpp, HardFun<int, SSL *, SSL_up_ref> > SessionPointer;
+typedef std::shared_ptr<SSL> SessionPointer;
typedef std::unique_ptr<SSL_SESSION, HardFun<void, SSL_SESSION*, &SSL_SESSION_free>> SessionStatePointer;
#elif USE_GNUTLS
-// Locks can be implemented attaching locks counter to gnutls_session_t
-// objects using the gnutls_session_set_ptr()/gnutls_session_get_ptr ()
-// library functions
-CtoCpp1(gnutls_deinit, gnutls_session_t);
-typedef Security::LockingPointer<struct gnutls_session_int, gnutls_deinit_cpp> SessionPointer;
+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
-// use void* so we can check against NULL
-CtoCpp1(xfree, void *);
-typedef Security::LockingPointer<void, xfree_cpp> SessionPointer;
+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 &);
/// 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
+
} // namespace Security
#endif /* SQUID_SRC_SECURITY_SESSION_H */
/// \note using std::unordered_set ensures values are unique, with fast lookup
typedef std::unordered_set<Security::ErrorCode> Errors;
+namespace Io
+{
+enum Type {
+#if USE_OPENSSL
+ BIO_TO_CLIENT = 6000,
+ BIO_TO_SERVER
+#elif USE_GNUTLS
+ // NP: this is odd looking but correct.
+ // 'to-client' means we are a server, and vice versa.
+ BIO_TO_CLIENT = GNUTLS_SERVER,
+ BIO_TO_SERVER = GNUTLS_CLIENT
+#else
+ BIO_TO_CLIENT = 6000,
+ BIO_TO_SERVER
+#endif
+};
+
+} // namespace Io
+
class KeyData;
+
+#if USE_OPENSSL
+typedef long ParsedOptions;
+#elif USE_GNUTLS
+typedef std::shared_ptr<struct gnutls_priority_st> ParsedOptions;
+#else
+class ParsedOptions {}; // we never parse/use TLS options in this case
+#endif
+
class PeerConnector;
class PeerOptions;
class ServerOptions;
#endif
BIO *
-Ssl::Bio::Create(const int fd, Ssl::Bio::Type type)
+Ssl::Bio::Create(const int fd, Security::Io::Type type)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
BIO_METHOD *useMethod = &SquidMethods;
assert(arg2);
const int fd = *static_cast<int*>(arg2);
Ssl::Bio *bio;
- if (arg1 == Ssl::Bio::BIO_TO_SERVER)
+ if (arg1 == Security::Io::BIO_TO_SERVER)
bio = new Ssl::ServerBio(fd);
else
bio = new Ssl::ClientBio(fd);
#ifndef SQUID_SSL_BIO_H
#define SQUID_SSL_BIO_H
+#if USE_OPENSSL
+
#include "FadingCounter.h"
#include "fd.h"
#include "security/Handshake.h"
class Bio
{
public:
- enum Type {
- BIO_TO_CLIENT = 6000,
- BIO_TO_SERVER
- };
-
explicit Bio(const int anFd);
virtual ~Bio();
/// Creates a low-level BIO table, creates a high-level Ssl::Bio object
/// for a given socket, and then links the two together via BIO_C_SET_FD.
- static BIO *Create(const int fd, Type type);
+ static BIO *Create(const int fd, Security::Io::Type type);
/// Tells ssl connection to use BIO and monitor state via stateChanged()
static void Link(SSL *ssl, BIO *bio);
inline void BIO_set_init(BIO *table, int init) { table->init = init; }
#endif
+#endif /* USE_OPENSSL */
#endif /* SQUID_SSL_BIO_H */
{
body.clear();
body += Ssl::CertValidationMsg::param_host + "=" + vcert.domainName;
- STACK_OF(X509) *peerCerts = static_cast<STACK_OF(X509) *>(SSL_get_ex_data(vcert.ssl, ssl_ex_index_ssl_cert_chain));
+ STACK_OF(X509) *peerCerts = static_cast<STACK_OF(X509) *>(SSL_get_ex_data(vcert.ssl.get(), ssl_ex_index_ssl_cert_chain));
- if (const char *sslVersion = SSL_get_version(vcert.ssl))
+ if (const char *sslVersion = SSL_get_version(vcert.ssl.get()))
body += "\n" + Ssl::CertValidationMsg::param_proto_version + "=" + sslVersion;
- if (const char *cipherName = SSL_CIPHER_get_name(SSL_get_current_cipher(vcert.ssl)))
+ if (const char *cipherName = SSL_CIPHER_get_name(SSL_get_current_cipher(vcert.ssl.get())))
body += "\n" + Ssl::CertValidationMsg::param_cipher + "=" + cipherName;
if (!peerCerts)
- peerCerts = SSL_get_peer_cert_chain(vcert.ssl);
+ peerCerts = SSL_get_peer_cert_chain(vcert.ssl.get());
if (peerCerts) {
Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
class CertValidationRequest
{
public:
- SSL *ssl;
- Security::CertErrors *errors; ///< The list of errors detected
+ Security::SessionPointer ssl;
+ Security::CertErrors *errors = nullptr; ///< The list of errors detected
std::string domainName; ///< The server name
- CertValidationRequest() : ssl(NULL), errors(NULL) {}
};
/**
crtdvdData->query = message.compose();
crtdvdData->query += '\n';
crtdvdData->callback = callback;
- crtdvdData->ssl.resetAndLock(request.ssl);
+ crtdvdData->ssl = request.ssl;
Ssl::CertValidationResponse::Pointer const*validationResponse;
if (CertValidationHelper::HelperCache &&
#include "globals.h"
#include "ipc/MemMap.h"
#include "security/CertError.h"
+#include "security/Session.h"
#include "SquidConfig.h"
#include "SquidTime.h"
#include "ssl/bio.h"
}
bool
-Ssl::InitClientContext(Security::ContextPointer &ctx, Security::PeerOptions &peer, long options, long fl)
+Ssl::InitClientContext(Security::ContextPointer &ctx, Security::PeerOptions &peer, long fl)
{
if (!ctx)
return false;
- SSL_CTX_set_options(ctx.get(), options);
-
if (!peer.sslCipher.isEmpty()) {
debugs(83, 5, "Using chiper suite " << peer.sslCipher << ".");
return true;
}
-/// \ingroup ServerProtocolSSLInternal
-int
-ssl_read_method(int fd, char *buf, int len)
-{
- auto ssl = fd_table[fd].ssl.get();
-
-#if DONT_DO_THIS
-
- if (!SSL_is_init_finished(ssl)) {
- errno = ENOTCONN;
- return -1;
- }
-
-#endif
-
- int i = SSL_read(ssl, buf, len);
- if (i > 0) {
- (void)VALGRIND_MAKE_MEM_DEFINED(buf, i);
- }
-
- if (i > 0 && SSL_pending(ssl) > 0) {
- debugs(83, 2, "SSL FD " << fd << " is pending");
- fd_table[fd].flags.read_pending = true;
- } else
- fd_table[fd].flags.read_pending = false;
-
- return i;
-}
-
-/// \ingroup ServerProtocolSSLInternal
-int
-ssl_write_method(int fd, const char *buf, int len)
-{
- auto ssl = fd_table[fd].ssl.get();
- if (!SSL_is_init_finished(ssl)) {
- errno = ENOTCONN;
- return -1;
- }
-
- int i = SSL_write(ssl, buf, len);
- return i;
-}
-
-void
-ssl_shutdown_method(SSL *ssl)
-{
- SSL_shutdown(ssl);
-}
-
/// \ingroup ServerProtocolSSLInternal
static const char *
ssl_get_attribute(X509_NAME * name, const char *attribute_name)
assert(0);
#else
// Temporary ssl for getting X509 certificate from SSL_CTX.
- Security::SessionPointer ssl(SSL_new(ctx.get()));
+ Security::SessionPointer ssl(Security::NewSessionObject(ctx));
X509 * cert = SSL_get_certificate(ssl.get());
#endif
if (!cert)
return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
}
-static bool
-SslCreate(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Ssl::Bio::Type type, const char *squidCtx)
-{
- if (!Comm::IsConnOpen(conn)) {
- debugs(83, DBG_IMPORTANT, "Gone connection");
- return false;
- }
-
- const char *errAction = NULL;
- int errCode = 0;
- if (auto ssl = SSL_new(ctx.get())) {
- const int fd = conn->fd;
- // without BIO, we would call SSL_set_fd(ssl, fd) instead
- if (BIO *bio = Ssl::Bio::Create(fd, type)) {
- Ssl::Bio::Link(ssl, bio); // cannot fail
-
- fd_table[fd].ssl.resetWithoutLocking(ssl);
- fd_table[fd].read_method = &ssl_read_method;
- fd_table[fd].write_method = &ssl_write_method;
- fd_note(fd, squidCtx);
- return true;
- }
- errCode = ERR_get_error();
- errAction = "failed to initialize I/O";
- SSL_free(ssl);
- } else {
- errCode = ERR_get_error();
- errAction = "failed to allocate handle";
- }
-
- debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
- ": " << Security::ErrorString(errCode));
- return false;
-}
-
-bool
-Ssl::CreateClient(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
-{
- return SslCreate(ctx, c, Ssl::Bio::BIO_TO_SERVER, squidCtx);
-}
-
-bool
-Ssl::CreateServer(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
-{
- return SslCreate(ctx, c, Ssl::Bio::BIO_TO_CLIENT, squidCtx);
-}
-
static int
store_session_cb(SSL *ssl, SSL_SESSION *session)
{
class CertValidationResponse;
typedef RefCount<CertValidationResponse> CertValidationResponsePointer;
-/// Creates SSL Client connection structure and initializes SSL I/O (Comm and BIO).
-/// On errors, emits DBG_IMPORTANT with details and returns false.
-bool CreateClient(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx);
-
-/// Creates SSL Server connection structure and initializes SSL I/O (Comm and BIO).
-/// On errors, emits DBG_IMPORTANT with details and returns false.
-bool CreateServer(const Security::ContextPointer &, const Comm::ConnectionPointer &, const char *squidCtx);
-
void SetSessionCallbacks(Security::ContextPointer &);
extern Ipc::MemMap *SessionCache;
extern const char *SessionCacheName;
bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &);
/// initialize a TLS client context with OpenSSL specific settings
-bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long options, long flags);
+bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long flags);
#if defined(CRYPTO_LOCK_X509)
// portability wrapper for OpenSSL 1.0 vs 1.1
} //namespace Ssl
-/// \ingroup ServerProtocolSSLAPI
-int ssl_read_method(int, char *, int);
-
-/// \ingroup ServerProtocolSSLAPI
-int ssl_write_method(int, const char *, int);
-
-/// \ingroup ServerProtocolSSLAPI
-void ssl_shutdown_method(SSL *ssl);
-
/// \ingroup ServerProtocolSSLAPI
const char *sslGetUserEmail(SSL *ssl);
#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::dumpCfg(Packable*, char const*) const STUB
-long Security::PeerOptions::parseOptions() STUB_RETVAL(0)
-long Security::PeerOptions::parseFlags() STUB_RETVAL(0)
+void Security::PeerOptions::parseOptions() STUB
void parse_securePeerOptions(Security::PeerOptions *) STUB
#include "security/ServerOptions.h"
#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
+#if USE_OPENSSL
+Security::SessionPointer NewSessionObject(const Security::ContextPointer &) STUB_RETVAL(nullptr)
+#endif
} // namespace Security
namespace Ssl
{
bool InitServerContext(Security::ContextPointer &, AnyP::PortCfg &) STUB_RETVAL(false)
-bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, long, const char *) STUB_RETVAL(false)
+bool InitClientContext(Security::ContextPointer &, Security::PeerOptions &, const char *) STUB_RETVAL(false)
} // namespace Ssl
-int ssl_read_method(int, char *, int) STUB_RETVAL(0)
-int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
-void ssl_shutdown_method(SSL *ssl) STUB
const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
case AnyP::PROTO_HTTPS:
#if USE_OPENSSL
rc = 1;
+#elif USE_GNUTLS
+ rc = 1;
#else
/*
* Squid can't originate an SSL connection, so it should