sb.append(errorName);
else
sb.append(sslErrorName(sslError->element.code, tmp, sizeof(tmp)));
+ if (sslError->element.depth >= 0) {
+ snprintf(tmp, sizeof(tmp), "@depth=%d", sslError->element.depth);
+ sb.append(tmp);
+ }
}
if (sb.size())
out = sb.termedBuf();
if (!errDetails) {
bool allowed = false;
if (check) {
- check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get()));
+ check->sslErrors = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
if (check->fastCheck() == ACCESS_ALLOWED)
allowed = true;
}
}
if (!errs)
- errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get()));
+ errs = new Ssl::CertErrors(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
else
- errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get()));
+ errs->push_back_unique(Ssl::CertError(i->error_no, i->cert.get(), i->error_depth));
}
if (check)
delete check;
//if certId is not correct sk_X509_value returns NULL
currentItem.setCert(sk_X509_value(peerCerts, certId));
}
+ } else if (param_len > param_error_depth.length() &&
+ strncmp(param, param_error_depth.c_str(), param_error_depth.length()) == 0 &&
+ std::all_of(v.begin(), v.end(), isdigit)) {
+ currentItem.error_depth = std::stoi(v);
} else {
debugs(83, DBG_IMPORTANT, "WARNING: cert validator response parse error: Unknown parameter name " << std::string(param, param_len).c_str());
return false;
const std::string Ssl::CertValidationMsg::param_error_name("error_name_");
const std::string Ssl::CertValidationMsg::param_error_reason("error_reason_");
const std::string Ssl::CertValidationMsg::param_error_cert("error_cert_");
+const std::string Ssl::CertValidationMsg::param_error_depth("error_depth_");
const std::string Ssl::CertValidationMsg::param_proto_version("proto_version");
const std::string Ssl::CertValidationMsg::param_cipher("cipher");
class RecvdError
{
public:
- RecvdError(): id(0), error_no(SSL_ERROR_NONE), cert(NULL) {}
+ RecvdError(): id(0), error_no(SSL_ERROR_NONE), cert(NULL), error_depth(-1) {}
RecvdError(const RecvdError &);
RecvdError & operator =(const RecvdError &);
void setCert(X509 *); ///< Sets cert to the given certificate
ssl_error_t error_no; ///< The OpenSSL error code
std::string error_reason; ///< A string describing the error
Security::CertPointer cert; ///< The broken certificate
+ int error_depth; ///< The error depth
};
typedef std::vector<RecvdError> RecvdErrors;
static const std::string param_error_reason;
/// Parameter name for passing the error cert ID
static const std::string param_error_cert;
+ /// Parameter name for passing the error depth
+ static const std::string param_error_depth;
/// Parameter name for SSL version
static const std::string param_proto_version;
/// Parameter name for SSL cipher
Ssl::CertErrors *errs = static_cast<Ssl::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
if (!errs) {
- errs = new Ssl::CertErrors(Ssl::CertError(error_no, broken_cert));
+ const int depth = X509_STORE_CTX_get_error_depth(ctx);
+ errs = new Ssl::CertErrors(Ssl::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;
return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_CLIENT, squidCtx);
}
-Ssl::CertError::CertError(ssl_error_t anErr, X509 *aCert): code(anErr)
+Ssl::CertError::CertError(ssl_error_t anErr, X509 *aCert, int aDepth): code(anErr), depth(aDepth)
{
cert.resetAndLock(aCert);
}
-Ssl::CertError::CertError(CertError const &err): code(err.code)
+Ssl::CertError::CertError(CertError const &err): code(err.code), depth(err.depth)
{
cert.resetAndLock(err.cert.get());
}
public:
ssl_error_t code; ///< certificate error code
Security::CertPointer cert; ///< certificate with the above error code
- CertError(ssl_error_t anErr, X509 *aCert);
+ /**
+ * 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(ssl_error_t anErr, X509 *aCert, int depth = -1);
CertError(CertError const &err);
CertError & operator = (const CertError &old);
bool operator == (const CertError &ce) const;