T *get() const { return raw; }
/// Reset raw pointer - delete last one and save new one.
- void reset(T *t) {
+ virtual void reset(T *t) {
deletePointer();
raw = t;
}
return ret;
}
/// Deallocate raw pointer.
- ~TidyPointer() {
+ virtual ~TidyPointer() {
deletePointer();
}
private:
// fake certificate adaptation requires bump-server-first mode
if (!sslServerBump) {
assert(port->signingCert.get());
- certProperties.signWithX509.resetAndLock(port->signingCert.get());
+ certProperties.signWithX509.reset(port->signingCert.get());
if (port->signPkey.get())
- certProperties.signWithPkey.resetAndLock(port->signPkey.get());
+ certProperties.signWithPkey.reset(port->signPkey.get());
certProperties.signAlgorithm = Ssl::algSignTrusted;
return;
}
assert(sslServerBump->entry);
if (sslServerBump->entry->isEmpty()) {
if (X509 *mimicCert = sslServerBump->serverCert.get())
- certProperties.mimicCert.resetAndLock(mimicCert);
+ certProperties.mimicCert.reset(mimicCert);
ACLFilledChecklist checklist(NULL, sslServerBump->request.getRaw(),
clientConnection != NULL ? clientConnection->rfc931 : dash_str);
if (certProperties.signAlgorithm == Ssl::algSignUntrusted) {
assert(port->untrustedSigningCert.get());
- certProperties.signWithX509.resetAndLock(port->untrustedSigningCert.get());
- certProperties.signWithPkey.resetAndLock(port->untrustedSignPkey.get());
+ certProperties.signWithX509.reset(port->untrustedSigningCert.get());
+ certProperties.signWithPkey.reset(port->untrustedSignPkey.get());
} else {
assert(port->signingCert.get());
- certProperties.signWithX509.resetAndLock(port->signingCert.get());
+ certProperties.signWithX509.reset(port->signingCert.get());
if (port->signPkey.get())
- certProperties.signWithPkey.resetAndLock(port->signPkey.get());
+ certProperties.signWithPkey.reset(port->signPkey.get());
}
signAlgorithm = certProperties.signAlgorithm;
#include "base/TidyPointer.h"
#if USE_OPENSSL
+
#if HAVE_OPENSSL_CRYPTO_H
#include <openssl/crypto.h>
#endif
sk_object ## _pop_free(a, freefunction); \
}
+#else // !USE_OPENSSL
+
+#include "base/Lock.h"
+#include <unordered_map>
+
#endif
// Macro to be used to define the C++ equivalent function of an extern "C"
typedef TidyPointer<T, DeAllocator> Parent;
typedef LockingPointer<T, DeAllocator, lock> SelfType;
- explicit LockingPointer(T *t = nullptr): Parent(t) {}
+ explicit LockingPointer(T *t = nullptr): Parent() {reset(t);}
+
+ virtual ~LockingPointer() { Parent::reset(nullptr); }
explicit LockingPointer(const SelfType &o): Parent() {
- resetAndLock(o.get());
+ reset(o.get());
}
SelfType &operator =(const SelfType & o) {
- resetAndLock(o.get());
+ reset(o.get());
return *this;
}
-#if __cplusplus >= 201103L
- explicit LockingPointer(LockingPointer<T, DeAllocator, lock> &&o): Parent(o.release()) {
- }
+ explicit LockingPointer(LockingPointer<T, DeAllocator, lock> &&o): Parent(o.release()) {}
LockingPointer<T, DeAllocator, lock> &operator =(LockingPointer<T, DeAllocator, lock> &&o) {
if (o.get() != this->get())
this->reset(o.release());
return *this;
}
+
+ virtual void reset(T *t) {
+ if (t == this->get())
+ return;
+
+#if !USE_OPENSSL
+ // OpenSSL maintains the reference locks through calls to Deallocator
+ // our manual locking does not have that luxury
+ if (this->get()) {
+ if (SelfType::Locks().at(this->get()).unlock())
+ SelfType::Locks().erase(this->get());
+ }
#endif
+ Parent::reset(t);
- void resetAndLock(T *t) {
- if (t != this->get()) {
- this->reset(t);
+ if (t) {
#if USE_OPENSSL
- if (t)
- CRYPTO_add(&t->references, 1, lock);
-#elif USE_GNUTLS
- // XXX: GnuTLS does not provide locking ?
+ CRYPTO_add(&t->references, 1, lock);
#else
- assert(false);
+ SelfType::Locks()[t].lock(); // find/create and lock
#endif
}
}
+
+private:
+#if !USE_OPENSSL
+ // since we can never be sure if a raw-* passed to us is already being
+ // lock counted by another LockingPointer<> and the types pointed to are
+ // defined by third-party libraries we have to maintain the locks in a
+ // type-specific static external to both the Pointer and base classes.
+ static std::unordered_map<T*, Lock> & Locks() {
+ static std::unordered_map<T*, Lock> Instance;
+ return Instance;
+ }
+#endif
};
} // namespace Security
ServerOptions.cc \
ServerOptions.h \
Session.cc \
- Session.h
+ Session.h \
+ support.cc
CtoCpp1(gnutls_x509_crt_deinit, gnutls_x509_crt_t)
typedef Security::LockingPointer<struct gnutls_x509_crt_int, gnutls_x509_crt_deinit, -1> CertPointer;
#else
-typedef void * CertPointer;
+typedef Security::LockingPointer<void, nullptr, -1> CertPointer;
#endif
#if USE_OPENSSL
CtoCpp1(gnutls_x509_crl_deinit, gnutls_x509_crl_t)
typedef Security::LockingPointer<struct gnutls_x509_crl_int, gnutls_x509_crl_deinit, -1> CrlPointer;
#else
-typedef void *CrlPointer;
+typedef Security::LockingPointer<void, nullptr, -1> CrlPointer;
#endif
typedef std::list<Security::CrlPointer> CertRevokeList;
CtoCpp1(DH_free, DH *);
typedef Security::LockingPointer<DH, DH_free_cpp, CRYPTO_LOCK_DH> DhePointer;
#else
-typedef void *DhePointer;
+typedef Security::LockingPointer<void, nullptr, -1> DhePointer;
#endif
class KeyData;
--- /dev/null
+/*
+ * Copyright (C) 1996-2016 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 "security/forward.h"
+
+#if !USE_OPENSSL
+
+namespace Security
+{
+
+#if USE_GNUTLS
+template std::unordered_map<Security::ContextPtr, Lock> & ContextPointer::Locks();
+
+template std::unordered_map<gnutls_x509_crt_t, Lock> & CertPointer::Locks();
+
+template std::unordered_map<gnutls_x509_crl_t, Lock> & CrlPointer::Locks();
+#endif
+
+template std::unordered_map<void*, Lock> & DhePointer::Locks();
+
+} // namespace Security
+
+#endif /* !USE_OPENSSL */
+
Ssl::ErrorDetail::ErrorDetail( Ssl::ssl_error_t err_no, X509 *cert, X509 *broken, const char *aReason): error_no (err_no), lib_error_no(SSL_ERROR_NONE), errReason(aReason)
{
if (cert)
- peer_cert.resetAndLock(cert);
+ peer_cert.reset(cert);
if (broken)
- broken_cert.resetAndLock(broken);
+ broken_cert.reset(broken);
else
- broken_cert.resetAndLock(cert);
+ broken_cert.reset(cert);
detailEntry.error_no = SSL_ERROR_NONE;
}
request = anErrDetail.request;
if (anErrDetail.peer_cert.get()) {
- peer_cert.resetAndLock(anErrDetail.peer_cert.get());
+ peer_cert.reset(anErrDetail.peer_cert.get());
}
if (anErrDetail.broken_cert.get()) {
- broken_cert.resetAndLock(anErrDetail.broken_cert.get());
+ broken_cert.reset(anErrDetail.broken_cert.get());
}
detailEntry = anErrDetail.detailEntry;
if (!serverBump->serverCert.get()) {
// remember the server certificate from the ErrorDetail object
if (error && error->detail && error->detail->peerCert())
- serverBump->serverCert.resetAndLock(error->detail->peerCert());
+ serverBump->serverCert.reset(error->detail->peerCert());
else {
handleServerCertificate();
}
if (ConnStateData *csd = request->clientConnectionManager.valid()) {
Security::CertPointer serverCert;
if(Ssl::ServerBump *serverBump = csd->serverBump())
- serverCert.resetAndLock(serverBump->serverCert.get());
+ serverCert.reset(serverBump->serverCert.get());
else {
const int fd = serverConnection()->fd;
Security::SessionPtr ssl = fd_table[fd].ssl.get();
if (serverSSL.get())
return;
- serverSSL.resetAndLock(ssl);
+ serverSSL.reset(ssl);
}
const Ssl::CertErrors *
void
Ssl::CertValidationResponse::RecvdError::setCert(X509 *aCert)
{
- cert.resetAndLock(aCert);
+ cert.reset(aCert);
}
Ssl::CertValidationMsg::CertItem::CertItem(const CertItem &old)
void
Ssl::CertValidationMsg::CertItem::setCert(X509 *aCert)
{
- cert.resetAndLock(aCert);
+ cert.reset(aCert);
}
const std::string Ssl::CertValidationMsg::code_cert_validate("cert_validate");
Ssl::EVP_PKEY_Pointer pkey;
// Use signing certificates private key as generated certificate private key
if (properties.signWithPkey.get())
- pkey.resetAndLock(properties.signWithPkey.get());
+ pkey.reset(properties.signWithPkey.get());
else // if not exist generate one
pkey.reset(Ssl::createSslPrivateKey());
ACLFilledChecklist *filledCheck = Filled(check);
assert(!filledCheck->sslErrors);
filledCheck->sslErrors = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert));
- filledCheck->serverCert.resetAndLock(peer_cert);
+ filledCheck->serverCert.reset(peer_cert);
if (check->fastCheck() == ACCESS_ALLOWED) {
debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
ok = 1;
// O, OU, and other CA subject fields will be mimicked
// Expiration date and other common properties will be mimicked
certProperties.signAlgorithm = Ssl::algSignSelf;
- certProperties.signWithPkey.resetAndLock(pkey.get());
- certProperties.mimicCert.resetAndLock(cert.get());
+ certProperties.signWithPkey.reset(pkey.get());
+ certProperties.mimicCert.reset(cert.get());
return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
}
Ssl::CertError::CertError(ssl_error_t anErr, X509 *aCert, int aDepth): code(anErr), depth(aDepth)
{
- cert.resetAndLock(aCert);
+ cert.reset(aCert);
}
Ssl::CertError::CertError(CertError const &err): code(err.code), depth(err.depth)
{
- cert.resetAndLock(err.cert.get());
+ cert.reset(err.cert.get());
}
Ssl::CertError &
Ssl::CertError::operator = (const CertError &old)
{
code = old.code;
- cert.resetAndLock(old.cert.get());
+ cert.reset(old.cert.get());
return *this;
}