Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: net/cert/internal/cert_errors.cc

Issue 2759023002: Improvements to the net/cert/internal error handling. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/internal/cert_errors.h" 5 #include "net/cert/internal/cert_errors.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/strings/string_split.h" 9 #include "base/strings/string_split.h"
10 #include "base/strings/stringprintf.h"
10 #include "net/cert/internal/cert_error_params.h" 11 #include "net/cert/internal/cert_error_params.h"
11 #include "net/cert/internal/cert_error_scoper.h" 12 #include "net/cert/internal/parse_name.h"
13 #include "net/cert/internal/parsed_certificate.h"
12 14
13 namespace net { 15 namespace net {
14 16
15 namespace { 17 namespace {
16 18
17 // Helpers for pretty-printing CertErrors to a string.
18 void AppendNodeToDebugString(CertErrorNode* node,
19 const std::string& indentation,
20 std::string* out);
21
22 void AppendChildrenToDebugString(const CertErrorNodes& children,
23 const std::string& indentation,
24 std::string* out) {
25 for (const auto& child : children)
26 AppendNodeToDebugString(child.get(), indentation, out);
27 }
28
29 void AppendLinesWithIndentation(const std::string& text, 19 void AppendLinesWithIndentation(const std::string& text,
30 const std::string& indentation, 20 const std::string& indentation,
31 std::string* out) { 21 std::string* out) {
32 std::vector<base::StringPiece> lines = base::SplitStringPieceUsingSubstr( 22 std::vector<base::StringPiece> lines = base::SplitStringPieceUsingSubstr(
33 text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); 23 text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
34 24
35 for (const auto& line : lines) { 25 for (const auto& line : lines) {
36 *out += indentation; 26 *out += indentation;
37 line.AppendToString(out); 27 line.AppendToString(out);
38 *out += "\n"; 28 *out += "\n";
39 } 29 }
40 } 30 }
41 31
42 const char* CertErrorNodeTypeToString(CertErrorNodeType type) {
43 switch (type) {
44 case CertErrorNodeType::TYPE_CONTEXT:
45 return "[Context] ";
46 case CertErrorNodeType::TYPE_WARNING:
47 return "[Warning] ";
48 case CertErrorNodeType::TYPE_ERROR:
49 return "[Error] ";
50 }
51 return nullptr;
52 }
53
54 void AppendNodeToDebugString(CertErrorNode* node,
55 const std::string& indentation,
56 std::string* out) {
57 std::string cur_indentation = indentation;
58
59 *out += cur_indentation;
60 *out += CertErrorNodeTypeToString(node->node_type);
61 *out += CertErrorIdToDebugString(node->id);
62 *out += +"\n";
63
64 if (node->params) {
65 cur_indentation += " ";
66 AppendLinesWithIndentation(node->params->ToDebugString(), cur_indentation,
67 out);
68 }
69
70 cur_indentation += " ";
71
72 AppendChildrenToDebugString(node->children, cur_indentation, out);
73 }
74
75 // Returns true if |children| contains the error |id| anywhere within it or its
76 // children recursively.
77 bool NodesContainError(const CertErrorNodes& children, CertErrorId id) {
78 for (const auto& child : children) {
79 if (child->node_type == CertErrorNodeType::TYPE_ERROR && child->id == id)
80 return true;
81 if (NodesContainError(child->children, id))
82 return true;
83 }
84 return false;
85 }
86
87 } // namespace 32 } // namespace
88 33
89 CertErrorNode::CertErrorNode(CertErrorNodeType node_type, 34 CertError::CertError() = default;
90 CertErrorId id,
91 std::unique_ptr<CertErrorParams> params)
92 : node_type(node_type), id(id), params(std::move(params)) {}
93 35
94 CertErrorNode::~CertErrorNode() = default; 36 CertError::CertError(Severity severity,
37 CertErrorId id,
38 std::unique_ptr<CertErrorParams> params)
39 : severity(severity), id(id), params(std::move(params)) {}
95 40
96 void CertErrorNode::AddChild(std::unique_ptr<CertErrorNode> child) { 41 CertError::CertError(CertError&& other) = default;
97 DCHECK_EQ(CertErrorNodeType::TYPE_CONTEXT, node_type); 42
98 children.push_back(std::move(child)); 43 CertError& CertError::operator=(CertError&&) = default;
44
45 CertError::~CertError() = default;
46
47 std::string CertError::ToDebugString() const {
48 std::string result;
49 switch (severity) {
50 case SEVERITY_WARNING:
51 result += "WARNING: ";
52 break;
53 case SEVERITY_HIGH:
54 result += "ERROR: ";
55 break;
56 }
57 result += CertErrorIdToDebugString(id);
58 result += +"\n";
59
60 if (params)
61 AppendLinesWithIndentation(params->ToDebugString(), " ", &result);
62
63 return result;
99 } 64 }
100 65
101 CertErrors::CertErrors() = default; 66 CertErrors::CertErrors() = default;
102 67 CertErrors::CertErrors(CertErrors&& other) = default;
68 CertErrors& CertErrors::operator=(CertErrors&&) = default;
103 CertErrors::~CertErrors() = default; 69 CertErrors::~CertErrors() = default;
104 70
105 void CertErrors::Add(CertErrorNodeType node_type, 71 void CertErrors::Add(CertError::Severity severity,
106 CertErrorId id, 72 CertErrorId id,
107 std::unique_ptr<CertErrorParams> params) { 73 std::unique_ptr<CertErrorParams> params) {
108 AddNode(base::MakeUnique<CertErrorNode>(node_type, id, std::move(params))); 74 nodes_.push_back(CertError(severity, id, std::move(params)));
109 } 75 }
110 76
111 void CertErrors::AddError(CertErrorId id, 77 void CertErrors::AddError(CertErrorId id,
112 std::unique_ptr<CertErrorParams> params) { 78 std::unique_ptr<CertErrorParams> params) {
113 Add(CertErrorNodeType::TYPE_ERROR, id, std::move(params)); 79 Add(CertError::SEVERITY_HIGH, id, std::move(params));
114 } 80 }
115 81
116 void CertErrors::AddError(CertErrorId id) { 82 void CertErrors::AddError(CertErrorId id) {
117 AddError(id, nullptr); 83 AddError(id, nullptr);
118 } 84 }
119 85
120 void CertErrors::AddWarning(CertErrorId id, 86 void CertErrors::AddWarning(CertErrorId id,
121 std::unique_ptr<CertErrorParams> params) { 87 std::unique_ptr<CertErrorParams> params) {
122 Add(CertErrorNodeType::TYPE_WARNING, id, std::move(params)); 88 Add(CertError::SEVERITY_WARNING, id, std::move(params));
123 } 89 }
124 90
125 void CertErrors::AddWarning(CertErrorId id) { 91 void CertErrors::AddWarning(CertErrorId id) {
126 AddWarning(id, nullptr); 92 AddWarning(id, nullptr);
127 } 93 }
128 94
129 bool CertErrors::empty() const {
130 return nodes_.empty();
131 }
132
133 std::string CertErrors::ToDebugString() const { 95 std::string CertErrors::ToDebugString() const {
134 std::string result; 96 std::string result;
135 AppendChildrenToDebugString(nodes_, std::string(), &result); 97 for (const CertError& node : nodes_)
98 result += node.ToDebugString();
99
136 return result; 100 return result;
137 } 101 }
138 102
139 bool CertErrors::ContainsError(CertErrorId id) const { 103 bool CertErrors::ContainsError(CertErrorId id) const {
140 return NodesContainError(nodes_, id); 104 for (const CertError& node : nodes_) {
105 if (node.id == id)
106 return true;
107 }
108 return false;
141 } 109 }
142 110
143 void CertErrors::AddNode(std::unique_ptr<CertErrorNode> node) { 111 bool CertErrors::HasErrors() const {
144 if (current_scoper_) 112 for (const CertError& node : nodes_) {
145 current_scoper_->LazyGetRootNode()->AddChild(std::move(node)); 113 // Disregard warnings.
146 else 114 if (node.severity == CertError::SEVERITY_HIGH)
mattm 2017/03/23 00:32:05 Maybe use a switch so this is forced to be updated
eroman 2017/03/23 01:32:11 I ended up solving this by changing the signature
147 nodes_.push_back(std::move(node)); 115 return true;
116 }
117 return false;
148 } 118 }
149 119
150 CertErrorScoper* CertErrors::SetScoper(CertErrorScoper* scoper) { 120 CertPathErrors::CertPathErrors() = default;
151 CertErrorScoper* prev = current_scoper_; 121
152 current_scoper_ = scoper; 122 CertPathErrors::CertPathErrors(CertPathErrors&& other) = default;
153 return prev; 123 CertPathErrors& CertPathErrors::operator=(CertPathErrors&&) = default;
124
125 CertPathErrors::~CertPathErrors() = default;
126
127 CertErrors* CertPathErrors::GetErrorsForCert(size_t cert_index) {
128 if (cert_index >= cert_errors_.size())
129 cert_errors_.resize(cert_index + 1);
130 return &cert_errors_[cert_index];
131 }
132
133 CertErrors* CertPathErrors::GetOtherErrors() {
134 return &other_errors_;
135 }
136
137 bool CertPathErrors::ContainsError(CertErrorId id) const {
138 for (const CertErrors& errors : cert_errors_) {
139 if (errors.ContainsError(id))
140 return true;
141 }
142
143 if (other_errors_.ContainsError(id))
144 return true;
145
146 return false;
147 }
148
149 bool CertPathErrors::HasErrors() const {
150 for (const CertErrors& errors : cert_errors_) {
151 if (errors.HasErrors())
152 return true;
153 }
154
155 if (other_errors_.HasErrors())
156 return true;
157
158 return false;
159 }
160
161 std::string CertPathErrors::ToDebugString(
162 const ParsedCertificateList& certs) const {
163 std::string result;
164
165 for (size_t i = 0; i < cert_errors_.size(); ++i) {
166 // Pretty print the current CertErrors. If there were no errors/warnings,
167 // then continue.
168 const CertErrors& errors = cert_errors_[i];
169 std::string cert_errors_string = errors.ToDebugString();
170 if (cert_errors_string.empty())
171 continue;
172
173 // Add a header for the CertErrors that describes which certificate they
174 // apply to.
175 std::string cert_name_debug_str;
176 if (i < certs.size() && certs[i]) {
mattm 2017/03/23 00:32:05 I guess this means the trust anchor errors won't s
eroman 2017/03/23 01:32:11 You are correct, that case is not handled. I have
177 RDNSequence subject;
178 if (ParseNameValue(certs[i]->normalized_subject(), &subject) &&
mattm 2017/03/23 00:32:05 use the original (un-normalized) subject from tbs(
eroman 2017/03/23 01:32:11 Done.
179 ConvertToRFC2253(subject, &cert_name_debug_str)) {
180 cert_name_debug_str = " (" + cert_name_debug_str + ")";
181 }
182 }
183
184 result +=
185 base::StringPrintf("----- Certificate i=%d%s -----\n",
186 static_cast<int>(i), cert_name_debug_str.c_str());
187
188 result += cert_errors_string;
189 result += "\n";
190 }
191
192 // Print any other errors that aren't associated with a particular certificate
193 // in the chain.
194 std::string other_errors = other_errors_.ToDebugString();
195 if (!other_errors.empty()) {
196 result += "----- Other errors (not certificate specific) -----\n";
197 result += other_errors;
198 result += "\n";
199 }
200
201 return result;
154 } 202 }
155 203
156 } // namespace net 204 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698