// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/cert/internal/cert_errors.h" #include "base/logging.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "net/cert/internal/cert_error_params.h" #include "net/cert/internal/parse_name.h" #include "net/cert/internal/parsed_certificate.h" namespace net { namespace { void AppendLinesWithIndentation(const std::string& text, const std::string& indentation, std::string* out) { std::vector lines = base::SplitStringPieceUsingSubstr( text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); for (const auto& line : lines) { *out += indentation; line.AppendToString(out); *out += "\n"; } } } // namespace CertError::CertError() = default; CertError::CertError(Severity severity, CertErrorId id, std::unique_ptr params) : severity(severity), id(id), params(std::move(params)) {} CertError::CertError(CertError&& other) = default; CertError& CertError::operator=(CertError&&) = default; CertError::~CertError() = default; std::string CertError::ToDebugString() const { std::string result; switch (severity) { case SEVERITY_WARNING: result += "WARNING: "; break; case SEVERITY_HIGH: result += "ERROR: "; break; } result += CertErrorIdToDebugString(id); result += +"\n"; if (params) AppendLinesWithIndentation(params->ToDebugString(), " ", &result); return result; } CertErrors::CertErrors() = default; CertErrors::CertErrors(CertErrors&& other) = default; CertErrors& CertErrors::operator=(CertErrors&&) = default; CertErrors::~CertErrors() = default; void CertErrors::Add(CertError::Severity severity, CertErrorId id, std::unique_ptr params) { nodes_.push_back(CertError(severity, id, std::move(params))); } void CertErrors::AddError(CertErrorId id, std::unique_ptr params) { Add(CertError::SEVERITY_HIGH, id, std::move(params)); } void CertErrors::AddError(CertErrorId id) { AddError(id, nullptr); } void CertErrors::AddWarning(CertErrorId id, std::unique_ptr params) { Add(CertError::SEVERITY_WARNING, id, std::move(params)); } void CertErrors::AddWarning(CertErrorId id) { AddWarning(id, nullptr); } std::string CertErrors::ToDebugString() const { std::string result; for (const CertError& node : nodes_) result += node.ToDebugString(); return result; } bool CertErrors::ContainsError(CertErrorId id) const { for (const CertError& node : nodes_) { if (node.id == id) return true; } return false; } bool CertErrors::ContainsAnyErrorWithSeverity( CertError::Severity severity) const { for (const CertError& node : nodes_) { if (node.severity == severity) return true; } return false; } CertPathErrors::CertPathErrors() = default; CertPathErrors::CertPathErrors(CertPathErrors&& other) = default; CertPathErrors& CertPathErrors::operator=(CertPathErrors&&) = default; CertPathErrors::~CertPathErrors() = default; CertErrors* CertPathErrors::GetErrorsForCert(size_t cert_index) { if (cert_index >= cert_errors_.size()) cert_errors_.resize(cert_index + 1); return &cert_errors_[cert_index]; } const CertErrors* CertPathErrors::GetErrorsForCert(size_t cert_index) const { if (cert_index >= cert_errors_.size()) return nullptr; return &cert_errors_[cert_index]; } CertErrors* CertPathErrors::GetOtherErrors() { return &other_errors_; } bool CertPathErrors::ContainsError(CertErrorId id) const { for (const CertErrors& errors : cert_errors_) { if (errors.ContainsError(id)) return true; } if (other_errors_.ContainsError(id)) return true; return false; } bool CertPathErrors::ContainsAnyErrorWithSeverity( CertError::Severity severity) const { for (const CertErrors& errors : cert_errors_) { if (errors.ContainsAnyErrorWithSeverity(severity)) return true; } if (other_errors_.ContainsAnyErrorWithSeverity(severity)) return true; return false; } std::string CertPathErrors::ToDebugString( const ParsedCertificateList& certs) const { std::string result; for (size_t i = 0; i < cert_errors_.size(); ++i) { // Pretty print the current CertErrors. If there were no errors/warnings, // then continue. const CertErrors& errors = cert_errors_[i]; std::string cert_errors_string = errors.ToDebugString(); if (cert_errors_string.empty()) continue; // Add a header that identifies which certificate this CertErrors pertains // to. std::string cert_name_debug_str; if (i < certs.size() && certs[i]) { RDNSequence subject; if (ParseName(certs[i]->tbs().subject_tlv, &subject) && ConvertToRFC2253(subject, &cert_name_debug_str)) { cert_name_debug_str = " (" + cert_name_debug_str + ")"; } } result += base::StringPrintf("----- Certificate i=%d%s -----\n", static_cast(i), cert_name_debug_str.c_str()); result += cert_errors_string; result += "\n"; } // Print any other errors that aren't associated with a particular certificate // in the chain. std::string other_errors = other_errors_.ToDebugString(); if (!other_errors.empty()) { result += "----- Other errors (not certificate specific) -----\n"; result += other_errors; result += "\n"; } return result; } } // namespace net