From: Christos Tsantilas Date: Sun, 13 Dec 2015 17:53:57 +0000 (+0200) Subject: %ssl::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(); diff --git a/src/ssl/PeerConnector.cc b/src/ssl/PeerConnector.cc index 40abcb2357..f2b3ecf44f 100644 --- a/src/ssl/PeerConnector.cc +++ b/src/ssl/PeerConnector.cc @@ -377,7 +377,7 @@ Ssl::PeerConnector::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &re 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; } @@ -400,9 +400,9 @@ Ssl::PeerConnector::sslCrtvdCheckForErrors(Ssl::CertValidationResponse const &re } 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; diff --git a/src/ssl/cert_validate_message.cc b/src/ssl/cert_validate_message.cc index 071795d28a..d3a3130bf0 100644 --- a/src/ssl/cert_validate_message.cc +++ b/src/ssl/cert_validate_message.cc @@ -145,6 +145,10 @@ Ssl::CertValidationMsg::parseResponse(CertValidationResponse &resp, STACK_OF(X50 //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; @@ -238,6 +242,7 @@ const std::string Ssl::CertValidationMsg::param_cert("cert_"); 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"); diff --git a/src/ssl/cert_validate_message.h b/src/ssl/cert_validate_message.h index 2aa4e84d83..59b2a4fb31 100644 --- a/src/ssl/cert_validate_message.h +++ b/src/ssl/cert_validate_message.h @@ -48,7 +48,7 @@ public: 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 @@ -56,6 +56,7 @@ public: 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 RecvdErrors; @@ -116,6 +117,8 @@ public: 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 diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 17bc85459b..429fd81206 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -285,7 +285,8 @@ ssl_verify_cb(int ok, X509_STORE_CTX * ctx) Ssl::CertErrors *errs = static_cast(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; @@ -1351,12 +1352,12 @@ Ssl::CreateServer(Security::ContextPtr sslContext, const int fd, const char *squ 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()); } diff --git a/src/ssl/support.h b/src/ssl/support.h index baf25c8109..86b4931ded 100644 --- a/src/ssl/support.h +++ b/src/ssl/support.h @@ -80,7 +80,13 @@ class CertError 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;