/*
- * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
#include "ssl/support.h"
#include "util.h"
+/// Retrieves the certificates chain used to verify the peer.
+/// This is the full chain built by OpenSSL while verifying the server
+/// certificate or, if this is not available, the chain sent by server.
+/// \return the certificates chain or nil
+static STACK_OF(X509) *
+PeerValidationCertificatesChain(const Security::SessionPointer &ssl)
+{
+ assert(ssl);
+ // The full chain built by openSSL while verifying the server cert,
+ // retrieved from verify callback:
+ if (const auto certs = static_cast<STACK_OF(X509) *>(SSL_get_ex_data(ssl.get(), ssl_ex_index_ssl_cert_chain)))
+ return certs;
+
+ /// Last resort: certificates chain sent by server
+ return SSL_get_peer_cert_chain(ssl.get()); // may be nil
+}
+
void
Ssl::CertValidationMsg::composeRequest(CertValidationRequest const &vcert)
{
body.clear();
body += Ssl::CertValidationMsg::param_host + "=" + vcert.domainName;
- 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.get()))
body += "\n" + Ssl::CertValidationMsg::param_proto_version + "=" + sslVersion;
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.get());
-
+ STACK_OF(X509) *peerCerts = PeerValidationCertificatesChain(vcert.ssl);
if (peerCerts) {
Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
for (int i = 0; i < sk_X509_num(peerCerts); ++i) {
const char *e = label + len -1;
while (e != label && xisdigit(*e)) --e;
if (e != label) ++e;
- return strtol(e, 0 , 10);
+ return strtol(e, 0, 10);
}
bool
-Ssl::CertValidationMsg::parseResponse(CertValidationResponse &resp, STACK_OF(X509) *peerCerts, std::string &error)
+Ssl::CertValidationMsg::parseResponse(CertValidationResponse &resp, std::string &error)
{
std::vector<CertItem> certs;
+ const STACK_OF(X509) *peerCerts = PeerValidationCertificatesChain(resp.ssl);
+
const char *param = body.c_str();
while (*param) {
while (xisspace(*param)) param++;
return false;
}
- param = value + value_len +1;
+ param = value + value_len;
}
/*Run through parsed errors to check for errors*/
return NULL;
}
+uint64_t
+Ssl::CertValidationResponse::MemoryUsedByResponse(const CertValidationResponse::Pointer &)
+{
+ // XXX: This math does not account for most of the response size!
+ return sizeof(CertValidationResponse);
+}
+
Ssl::CertValidationResponse::RecvdError &
Ssl::CertValidationResponse::getError(int errorId)
{
return errors.back();
}
-Ssl::CertValidationResponse::RecvdError::RecvdError(const RecvdError &old)
-{
- id = old.id;
- error_no = old.error_no;
- error_reason = old.error_reason;
- error_depth = old.error_depth;
- setCert(old.cert.get());
-}
-
-Ssl::CertValidationResponse::RecvdError & Ssl::CertValidationResponse::RecvdError::operator = (const RecvdError &old)
-{
- id = old.id;
- error_no = old.error_no;
- error_reason = old.error_reason;
- error_depth = old.error_depth;
- setCert(old.cert.get());
- return *this;
-}
-
void
Ssl::CertValidationResponse::RecvdError::setCert(X509 *aCert)
{
cert.resetAndLock(aCert);
}
-Ssl::CertValidationMsg::CertItem::CertItem(const CertItem &old)
-{
- name = old.name;
- setCert(old.cert.get());
-}
-
-Ssl::CertValidationMsg::CertItem & Ssl::CertValidationMsg::CertItem::operator = (const CertItem &old)
-{
- name = old.name;
- setCert(old.cert.get());
- return *this;
-}
-
void
Ssl::CertValidationMsg::CertItem::setCert(X509 *aCert)
{