#if USE_OPENSSL
ACL::Prototype ACLSslError::RegistryProtoype(&ACLSslError::RegistryEntry_, "ssl_error");
-ACLStrategised<const Ssl::CertErrors *> ACLSslError::RegistryEntry_(new ACLSslErrorData, ACLSslErrorStrategy::Instance(), "ssl_error");
+ACLStrategised<const Security::CertErrors *> ACLSslError::RegistryEntry_(new ACLSslErrorData, ACLSslErrorStrategy::Instance(), "ssl_error");
ACL::Prototype ACLCertificate::UserRegistryProtoype(&ACLCertificate::UserRegistryEntry_, "user_cert");
ACLStrategised<X509 *> ACLCertificate::UserRegistryEntry_(new ACLCertificateData (Ssl::GetX509UserAttribute, "*"), ACLCertificateStrategy::Instance(), "user_cert");
ACL::Prototype ACLCertificate::CARegistryProtoype(&ACLCertificate::CARegistryEntry_, "ca_cert");
#if USE_AUTH
#include "auth/UserRequest.h"
#endif
-#if USE_OPENSSL
-#include "ssl/support.h"
-#endif
+#include "security/CertError.h"
class CachePeer;
class ConnStateData;
char *snmp_community;
#endif
-#if USE_OPENSSL
/// SSL [certificate validation] errors, in undefined order
- const Ssl::CertErrors *sslErrors;
+ const Security::CertErrors *sslErrors;
/// The peer certificate
Security::CertPointer serverCert;
-#endif
AccessLogEntry::Pointer al; ///< info for the future access.log, and external ACL
#ifndef SQUID_ACLSSL_ERROR_H
#define SQUID_ACLSSL_ERROR_H
+
#include "acl/Strategised.h"
#include "acl/Strategy.h"
-#include "ssl/support.h"
-class ACLSslErrorStrategy : public ACLStrategy<const Ssl::CertErrors *>
+class ACLSslErrorStrategy : public ACLStrategy<const Security::CertErrors *>
{
public:
private:
static ACL::Prototype RegistryProtoype;
- static ACLStrategised<const Ssl::CertErrors *> RegistryEntry_;
+ static ACLStrategised<const Security::CertErrors *> RegistryEntry_;
};
#endif /* SQUID_ACLSSL_ERROR_H */
#include "acl/Checklist.h"
#include "acl/SslErrorData.h"
#include "ssl/ErrorDetail.h"
+#include "security/CertError.h"
ACLSslErrorData::ACLSslErrorData(ACLSslErrorData const &o) :
values(o.values)
{}
bool
-ACLSslErrorData::match(const Ssl::CertErrors *toFind)
+ACLSslErrorData::match(const Security::CertErrors *toFind)
{
for (const auto *err = toFind; err; err = err->next) {
if (values.count(err->element.code))
#include "acl/Acl.h"
#include "acl/Data.h"
-#include "ssl/support.h"
+#include "security/forward.h"
-class ACLSslErrorData : public ACLData<const Ssl::CertErrors *>
+class ACLSslErrorData : public ACLData<const Security::CertErrors *>
{
MEMPROXY_CLASS(ACLSslErrorData);
ACLSslErrorData(ACLSslErrorData const &);
ACLSslErrorData &operator= (ACLSslErrorData const &);
virtual ~ACLSslErrorData() {}
- bool match(const Ssl::CertErrors *);
+ bool match(const Security::CertErrors *);
virtual SBufList dump() const;
void parse();
bool empty() const { return values.empty(); }
// In bump-server-first mode, we have not necessarily seen the intended
// server name at certificate-peeking time. Check for domain mismatch now,
// when we can extract the intended name from the bumped HTTP request.
- if (X509 *srvCert = sslServerBump->serverCert.get()) {
+ if (const Security::CertPointer &srvCert = sslServerBump->serverCert) {
HttpRequest *request = http->request;
- if (!Ssl::checkX509ServerValidity(srvCert, request->url.host())) {
+ if (!Ssl::checkX509ServerValidity(srvCert.get(), request->url.host())) {
debugs(33, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " <<
"does not match domainname " << request->url.host());
bool allowDomainMismatch = false;
if (Config.ssl_client.cert_error) {
ACLFilledChecklist check(Config.ssl_client.cert_error, request, dash_str);
- check.sslErrors = new Ssl::CertErrors(Ssl::CertError(SQUID_X509_V_ERR_DOMAIN_MISMATCH, srvCert));
+ check.sslErrors = new Security::CertErrors(Security::CertError(SQUID_X509_V_ERR_DOMAIN_MISMATCH, srvCert));
allowDomainMismatch = (check.fastCheck() == ACCESS_ALLOWED);
delete check.sslErrors;
check.sslErrors = NULL;
err->src_addr = clientConnection->remote;
Ssl::ErrorDetail *errDetail = new Ssl::ErrorDetail(
SQUID_X509_V_ERR_DOMAIN_MISMATCH,
- srvCert, NULL);
+ srvCert.get(), nullptr);
err->detail = errDetail;
// Save the original request for logging purposes.
if (!context->http->al->request) {
#include "HttpRequest.h"
#include "MemBuf.h"
#include "rfc1738.h"
+#include "security/CertError.h"
#include "security/NegotiationHistory.h"
#include "SquidTime.h"
#include "Store.h"
if (al->request && al->request->clientConnectionManager.valid()) {
if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
const char *separator = fmt->data.string ? fmt->data.string : ":";
- for (Ssl::CertErrors const *sslError = srvBump->sslErrors(); sslError != NULL; sslError = sslError->next) {
+ for (const Security::CertErrors *sslError = srvBump->sslErrors(); sslError != nullptr; sslError = sslError->next) {
if (sb.size())
sb.append(separator);
if (const char *errorName = Ssl::GetErrorName(sslError->element.code))
--- /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.
+ */
+
+#ifndef SQUID_SRC_SECURITY_CERTERROR_H
+#define SQUID_SRC_SECURITY_CERTERROR_H
+
+#include "security/forward.h"
+
+namespace Security
+{
+
+/// An X.509 certificate-related error.
+/// Pairs an error code with the certificate experiencing the error.
+class CertError
+{
+public:
+ CertError(int anErr, const Security::CertPointer &aCert, int aDepth = -1) :
+ code(anErr), cert(aCert), depth(aDepth)
+ {}
+
+ bool operator == (const CertError &ce) const {
+ // We expect to be used in contexts where identical certificates have
+ // identical pointers.
+ return code == ce.code && depth == ce.depth && cert == ce.cert;
+ }
+
+ bool operator != (const CertError &ce) const {
+ return !(*this == ce);
+ }
+
+public:
+ Security::ErrorCode code; ///< certificate error code
+ Security::CertPointer cert; ///< certificate with the above error code
+
+ /**
+ * Absolute cert position in the final certificate chain that may include
+ * intermediate certificates. Chain positions start with zero and increase
+ * towards the root certificate. Negative if unknown.
+ */
+ int depth;
+};
+
+} // namespace Security
+
+#endif /* SQUID_SRC_SECURITY_CERTERROR_H */
+
bool operator !() const { return !raw; }
explicit operator bool() const { return raw; }
+ bool operator ==(const SelfType &o) const { return (o.get() == raw); }
+ bool operator !=(const SelfType &o) const { return (o.get() != raw); }
/// Returns raw and possibly nullptr pointer
T *get() const { return raw; }
libsecurity_la_SOURCES= \
BlindPeerConnector.cc \
BlindPeerConnector.h \
+ CertError.h \
Context.h \
EncryptorAnswer.cc \
EncryptorAnswer.h \
// Ssl::CertValidationHelper::submit method.
validationRequest.ssl = ssl;
validationRequest.domainName = request->url.host();
- if (Ssl::CertErrors *errs = static_cast<Ssl::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)))
+ if (Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors)))
// validationRequest disappears on return so no need to cbdataReference
validationRequest.errors = errs;
else
debugs(83,5, request->url.host() << " cert validation result: " << validationResponse->resultCode);
if (validationResponse->resultCode == ::Helper::Error) {
- if (Ssl::CertErrors *errs = sslCrtvdCheckForErrors(*validationResponse, errDetails)) {
+ if (Security::CertErrors *errs = sslCrtvdCheckForErrors(*validationResponse, errDetails)) {
Security::SessionPtr ssl = fd_table[serverConnection()->fd].ssl.get();
- Ssl::CertErrors *oldErrs = static_cast<Ssl::CertErrors*>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
+ Security::CertErrors *oldErrs = static_cast<Security::CertErrors*>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs);
delete oldErrs;
}
#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 Ssl::CertErrors.
-Ssl::CertErrors *
+/// 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)
{
- Ssl::CertErrors *errs = NULL;
-
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::SessionPtr ssl = fd_table[serverConnection()->fd].ssl.get();
typedef Ssl::CertValidationResponse::RecvdErrors::const_iterator SVCRECI;
for (SVCRECI i = resp.errors.begin(); i != resp.errors.end(); ++i) {
if (!errDetails) {
bool allowed = false;
if (check) {
- check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
+ check->sslErrors = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth));
if (check->fastCheck() == ACCESS_ALLOWED)
allowed = true;
}
}
if (!errs)
- errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
+ errs = new Security::CertErrors(Security::CertError(i->error_no, i->cert, i->error_depth));
else
- errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
+ errs->push_back_unique(Security::CertError(i->error_no, i->cert, i->error_depth));
}
if (check)
delete check;
void sslCrtvdHandleReply(Ssl::CertValidationResponsePointer);
/// Check SSL errors returned from cert validator against sslproxy_cert_error access list
- Ssl::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&);
+ Security::CertErrors *sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &, Ssl::ErrorDetail *&);
#endif
/// A wrapper function for negotiateSsl for use with Comm::SetSelect
#ifndef SQUID_SRC_SECURITY_FORWARD_H
#define SQUID_SRC_SECURITY_FORWARD_H
+#include "base/CbDataList.h"
#include "security/Context.h"
#include "security/Session.h"
namespace Security
{
+class CertError;
+/// Holds a list of X.509 certificate errors
+typedef CbDataList<Security::CertError> CertErrors;
+
#if USE_OPENSSL
CtoCpp1(X509_free, X509 *)
typedef Security::LockingPointer<X509, X509_free_cpp, CRYPTO_LOCK_X509> CertPointer;
serverSSL.resetAndLock(ssl);
}
-const Ssl::CertErrors *
+const Security::CertErrors *
Ssl::ServerBump::sslErrors() const
{
if (!serverSSL.get())
return NULL;
- const Ssl::CertErrors *errs = static_cast<const Ssl::CertErrors*>(SSL_get_ex_data(serverSSL.get(), ssl_ex_index_ssl_errors));
+ const Security::CertErrors *errs = static_cast<const Security::CertErrors*>(SSL_get_ex_data(serverSSL.get(), ssl_ex_index_ssl_errors));
return errs;
}
explicit ServerBump(HttpRequest *fakeRequest, StoreEntry *e = NULL, Ssl::BumpMode mode = Ssl::bumpServerFirst);
~ServerBump();
void attachServerSSL(SSL *); ///< Sets the server SSL object
- const Ssl::CertErrors *sslErrors() const; ///< SSL [certificate validation] errors
+ const Security::CertErrors *sslErrors() const; ///< SSL [certificate validation] errors
/// faked, minimal request; required by Client API
HttpRequest::Pointer request;
#include "acl/FilledChecklist.h"
#include "globals.h"
#include "helper.h"
+#include "security/CertError.h"
#include "ssl/cert_validate_message.h"
#include "ssl/ErrorDetail.h"
#include "ssl/support.h"
if (vcert.errors) {
int i = 0;
- for (const Ssl::CertErrors *err = vcert.errors; err; err = err->next, ++i) {
+ for (const Security::CertErrors *err = vcert.errors; err; err = err->next, ++i) {
body +="\n";
body = body + param_error_name + xitoa(i) + "=" + GetErrorName(err->element.code) + "\n";
int errorCertPos = -1;
{
public:
SSL *ssl;
- CertErrors *errors; ///< The list of errors detected
+ Security::CertErrors *errors; ///< The list of errors detected
std::string domainName; ///< The server name
CertValidationRequest() : ssl(NULL), errors(NULL) {}
};
#include "fde.h"
#include "globals.h"
#include "ipc/MemMap.h"
+#include "security/CertError.h"
#include "SquidConfig.h"
#include "SquidTime.h"
#include "ssl/bio.h"
void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
X509 *peeked_cert = (X509 *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_peeked_cert);
- X509 *peer_cert = ctx->cert;
+ Security::CertPointer peer_cert;
+ peer_cert.resetAndLock(ctx->cert);
- X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
- sizeof(buffer));
+ X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), buffer, sizeof(buffer));
// detect infinite loops
uint32_t *validationCounter = static_cast<uint32_t *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_validation_counter));
debugs(83, 5, "SSL Certificate signature OK: " << buffer);
// Check for domain mismatch only if the current certificate is the peer certificate.
- if (!dont_verify_domain && server && peer_cert == X509_STORE_CTX_get_current_cert(ctx)) {
- if (!Ssl::checkX509ServerValidity(peer_cert, server->c_str())) {
+ if (!dont_verify_domain && server && peer_cert.get() == X509_STORE_CTX_get_current_cert(ctx)) {
+ if (!Ssl::checkX509ServerValidity(peer_cert.get(), server->c_str())) {
debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
ok = 0;
error_no = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
if (ok && peeked_cert) {
// Check whether the already peeked certificate matches the new one.
- if (X509_cmp(peer_cert, peeked_cert) != 0) {
+ if (X509_cmp(peer_cert.get(), peeked_cert) != 0) {
debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer << " does not match peeked certificate");
ok = 0;
error_no = SQUID_X509_V_ERR_CERT_CHANGE;
}
if (!ok) {
- X509 *broken_cert = X509_STORE_CTX_get_current_cert(ctx);
+ Security::CertPointer broken_cert;
+ broken_cert.resetAndLock(X509_STORE_CTX_get_current_cert(ctx));
if (!broken_cert)
broken_cert = peer_cert;
- Ssl::CertErrors *errs = static_cast<Ssl::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
+ Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
const int depth = X509_STORE_CTX_get_error_depth(ctx);
if (!errs) {
- errs = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert, depth));
+ errs = new Security::CertErrors(Security::CertError(error_no, broken_cert, depth));
if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) {
debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer);
delete errs;
errs = NULL;
}
} else // remember another error number
- errs->push_back_unique(Ssl::CertError(error_no, broken_cert, depth));
+ errs->push_back_unique(Security::CertError(error_no, broken_cert, depth));
if (const char *err_descr = Ssl::GetErrorDescr(error_no))
debugs(83, 5, err_descr << ": " << buffer);
if (check) {
ACLFilledChecklist *filledCheck = Filled(check);
assert(!filledCheck->sslErrors);
- filledCheck->sslErrors = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert));
- filledCheck->serverCert.resetAndLock(peer_cert);
+ filledCheck->sslErrors = new Security::CertErrors(Security::CertError(error_no, broken_cert));
+ filledCheck->serverCert = peer_cert;
if (check->fastCheck() == ACCESS_ALLOWED) {
debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
ok = 1;
if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
// Find the broken certificate. It may be intermediate.
- X509 *broken_cert = peer_cert; // reasonable default if search fails
+ Security::CertPointer broken_cert(peer_cert); // reasonable default if search fails
// Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
- if (X509 *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
- broken_cert = last_used_cert;
+ if (auto *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
+ broken_cert.resetAndLock(last_used_cert);
}
- Ssl::ErrorDetail *errDetail =
- new Ssl::ErrorDetail(error_no, peer_cert, broken_cert);
-
- if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) {
+ auto *errDetail = new Ssl::ErrorDetail(error_no, peer_cert.get(), broken_cert.get());
+ if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) {
debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer);
delete errDetail;
}
ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
int, long, void *)
{
- Ssl::CertErrors *errs = static_cast <Ssl::CertErrors*>(ptr);
+ Security::CertErrors *errs = static_cast <Security::CertErrors*>(ptr);
delete errs;
}
return SslCreate(sslContext, c, Ssl::Bio::BIO_TO_CLIENT, squidCtx);
}
-Ssl::CertError::CertError(Security::ErrorCode anErr, X509 *aCert, int aDepth): code(anErr), depth(aDepth)
-{
- cert.resetAndLock(aCert);
-}
-
static int
store_session_cb(SSL *ssl, SSL_SESSION *session)
{
/// On errors, emits DBG_IMPORTANT with details and returns false.
bool CreateServer(Security::ContextPtr sslContext, const Comm::ConnectionPointer &, const char *squidCtx);
-/// An SSL certificate-related error.
-/// Pairs an error code with the certificate experiencing the error.
-class CertError
-{
-public:
- Security::ErrorCode code; ///< certificate error code
- Security::CertPointer cert; ///< certificate with the above error code
- /**
- * Absolute cert position in the final certificate chain that may include
- * intermediate certificates. Chain positions start with zero and increase
- * towards the root certificate. Negative if unknown.
- */
- int depth;
- CertError(Security::ErrorCode anErr, X509 *aCert, int depth = -1);
- bool operator == (const CertError &ce) const {
- // We expect to be used in contexts where identical certificates have
- // identical pointers.
- return code == ce.code && depth == ce.depth && cert.get() == ce.cert.get();
- }
- bool operator != (const CertError &ce) const {
- return !(*this == ce);
- }
-};
-
-/// Holds a list of certificate SSL errors
-typedef CbDataList<Ssl::CertError> CertErrors;
-
void SetSessionCallbacks(Security::ContextPtr);
extern Ipc::MemMap *SessionCache;
extern const char *SessionCacheName;
#include "ssl/support.h"
namespace Ssl
{
-//CertError::CertError(Security::ErrorCode, X509 *) STUB
bool InitServerContext(const Security::ContextPointer &, AnyP::PortCfg &) STUB_RETVAL(false)
bool InitClientContext(Security::ContextPtr &, Security::PeerOptions &, long, const char *) STUB_RETVAL(false)
} // namespace Ssl