| OLD | NEW |
| 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 // ---------------------------- | 5 // ---------------------------- |
| 6 // Overview of error design | 6 // Overview of error design |
| 7 // ---------------------------- | 7 // ---------------------------- |
| 8 // | 8 // |
| 9 // Certificate path validation may emit a sequence of errors/warnings. These | 9 // Certificate path validation/parsing may emit a sequence of |
| 10 // are represented by |CertErrors|. | 10 // errors/warnings/context. These are represented by a tree of CertErrorNodes. |
| 11 // Each node is comprised of: |
| 11 // | 12 // |
| 12 // |CertErrors| is basically just a sequence of errors. The order of the errors | 13 // * A unique identifier. |
| 13 // reflects when they were added. | |
| 14 // | 14 // |
| 15 // Each |CertError| has three parts: | 15 // This serves similarly to an error code, and is useful for querying if a |
| 16 // particular error occurred. |
| 16 // | 17 // |
| 17 // * A unique identifier for the error/warning | 18 // * [optional] A parameters object. |
| 18 // - essentially an error code | |
| 19 // | 19 // |
| 20 // * Optional parameters specific to this error type | 20 // Nodes may attach a heap-allocated subclass of CertErrorParams, to carry |
| 21 // - May identify relevant DER or OIDs in the certificate | 21 // extra information that is useful when reporting the error. For instance |
| 22 // a parsing error may want to describe where in the DER the failure |
| 23 // happened, or what the unexpected value was. |
| 22 // | 24 // |
| 23 // * Optional context that describes where the error happened | 25 // * [optional] Child nodes. |
| 24 // - Which certificate or trust anchor were we processing when the error | |
| 25 // was encountered? | |
| 26 // | 26 // |
| 27 // Error nodes are arranged in a tree. The parent/child hiearchy is used to |
| 28 // group errors that share some common state. |
| 29 // For instance during path processing it is useful to group the |
| 30 // errors/warnings that happened while processing certificate "i" as |
| 31 // children of a shared "context" node. The context node in this case |
| 32 // doesn't describe a particular error, but rather some shared event and |
| 33 // its parameters. |
| 34 // |
| 35 // ---------------------------- |
| 36 // Using errors in other APIs |
| 37 // ---------------------------- |
| 38 // |
| 39 // The top level object used in APIs is CertErrors. A pointer to a CertErrors |
| 40 // object is typically given as an out-parameter for code that may generate |
| 41 // errors. |
| 42 // |
| 43 // Note that CertErrors gives a non-hiearhical interface for emitting errors. |
| 44 // In other words, it doesn't let you create parent/child relationships |
| 45 // directly. |
| 46 // |
| 47 // To change the parent node for subsequently emitted errors in the CertErrors |
| 48 // object, one constructs a CertErrorScoper on the stack. |
| 49 // |
| 50 // ---------------------------- |
| 51 // Defining new errors |
| 52 // ---------------------------- |
| 53 // |
| 54 // The error IDs are extensible and do not need to be centrally defined. |
| 55 // |
| 56 // To define a new error use the macro DEFINE_CERT_ERROR_ID() in a .cc file. |
| 57 // If consumers are to be able to query for this error then the symbol should |
| 58 // also be exposed in a header file. |
| 59 // |
| 60 // Error IDs are in truth string literals, whose pointer value will be unique |
| 61 // per process. |
| 27 | 62 |
| 28 #ifndef NET_CERT_INTERNAL_CERT_ERRORS_H_ | 63 #ifndef NET_CERT_INTERNAL_CERT_ERRORS_H_ |
| 29 #define NET_CERT_INTERNAL_CERT_ERRORS_H_ | 64 #define NET_CERT_INTERNAL_CERT_ERRORS_H_ |
| 30 | 65 |
| 31 #include <memory> | 66 #include <memory> |
| 32 #include <vector> | 67 #include <vector> |
| 33 | 68 |
| 34 #include "base/compiler_specific.h" | 69 #include "base/compiler_specific.h" |
| 35 #include "base/memory/ref_counted.h" | 70 #include "base/macros.h" |
| 36 #include "net/base/net_export.h" | 71 #include "net/base/net_export.h" |
| 37 #include "net/der/input.h" | 72 #include "net/cert/internal/cert_error_id.h" |
| 38 | |
| 39 namespace base { | |
| 40 class Value; | |
| 41 } | |
| 42 | 73 |
| 43 namespace net { | 74 namespace net { |
| 44 | 75 |
| 76 class CertErrorParams; |
| 77 class CertErrorScoper; |
| 45 class ParsedCertificate; | 78 class ParsedCertificate; |
| 46 class TrustAnchor; | |
| 47 | 79 |
| 48 // Certificate error types are identified by null-terminated C-strings, with | 80 // The type of a particular CertErrorNode. |
| 49 // unique pointer values. | 81 enum class CertErrorNodeType { |
| 50 // | 82 // Note the TYPE_ prefix is to avoid compile errors. Because ERROR() is a |
| 51 // Equality of CertErrorType is done using (pointer) equality and not string | 83 // commonly used macro name. |
| 52 // comparison. | |
| 53 // | |
| 54 // To ensure uniqueness define errors using the macro DEFINE_CERT_ERROR_TYPE(). | |
| 55 using CertErrorType = const char*; | |
| 56 | 84 |
| 57 // TODO(crbug.com/634443): Implement this -- add magic to ensure that storage | 85 // Node that represents a single error. |
| 58 // of identical strings isn't pool. | 86 TYPE_ERROR, |
| 59 #define DEFINE_CERT_ERROR_TYPE(name, c_str_literal) \ | |
| 60 CertErrorType name = c_str_literal | |
| 61 | 87 |
| 62 // CertErrorParams is a base class for describing parameters for a particular | 88 // Node that represents a single non-fatal error. |
| 63 // CertErrorType. | 89 TYPE_WARNING, |
| 64 // | |
| 65 // Parameters may be used to associate extra information with an error. An | |
| 66 // example use for parameters is to identify the OID for an unconsumed critical | |
| 67 // extension. | |
| 68 class NET_EXPORT CertErrorParams { | |
| 69 public: | |
| 70 CertErrorParams(); | |
| 71 virtual ~CertErrorParams(); | |
| 72 | 90 |
| 73 // Creates a representation of this parameter as a base::Value, which may be | 91 // Parent node for other errors/warnings. |
| 74 // used for pretty printing the error. | 92 TYPE_CONTEXT, |
| 75 virtual std::unique_ptr<base::Value> ToValue() const = 0; | |
| 76 | |
| 77 // TODO(crbug.com/634443): Add methods access the underlying structure. | |
| 78 // ToValue() alone is not a great way to get at the data. | |
| 79 | |
| 80 private: | |
| 81 DISALLOW_COPY_AND_ASSIGN(CertErrorParams); | |
| 82 }; | 93 }; |
| 83 | 94 |
| 84 // CertError represents a single error during path validation. | 95 struct CertErrorNode; |
| 85 struct NET_EXPORT CertError { | 96 using CertErrorNodes = std::vector<std::unique_ptr<CertErrorNode>>; |
| 86 CertError(); | |
| 87 CertError(CertError&& other); | |
| 88 ~CertError(); | |
| 89 | 97 |
| 90 // The "type" of the error. This describes the error class -- what is | 98 // CertErrorNode represents a node in the error tree. This could be an error, |
| 91 // typically done using an integer error code. | 99 // warning, or simply contextual parent node. See the error design overview for |
| 92 CertErrorType type = nullptr; | 100 // a better description of how this is used. |
| 101 struct NET_EXPORT CertErrorNode { |
| 102 CertErrorNode(CertErrorNodeType node_type, |
| 103 CertErrorId id, |
| 104 std::unique_ptr<CertErrorParams> params); |
| 105 ~CertErrorNode(); |
| 93 | 106 |
| 94 // This describes any parameter relevant to the error. | 107 void AddChild(std::unique_ptr<CertErrorNode> child); |
| 108 |
| 109 CertErrorNodeType node_type; |
| 110 CertErrorId id; |
| 95 std::unique_ptr<CertErrorParams> params; | 111 std::unique_ptr<CertErrorParams> params; |
| 96 | 112 CertErrorNodes children; |
| 97 // TODO(crbug.com/634443): Add context (i.e. associated certificate/trust | |
| 98 // anchor). | |
| 99 }; | 113 }; |
| 100 | 114 |
| 115 // CertErrors is the main object for emitting errors and internally builds up |
| 116 // the error tree. |
| 101 class NET_EXPORT CertErrors { | 117 class NET_EXPORT CertErrors { |
| 102 public: | 118 public: |
| 103 CertErrors(); | 119 CertErrors(); |
| 104 ~CertErrors(); | 120 ~CertErrors(); |
| 105 | 121 |
| 106 void Add(CertErrorType type); | 122 // Adds a node to the current insertion point in the error tree. |params| may |
| 123 // be null. |
| 124 void Add(CertErrorNodeType node_type, |
| 125 CertErrorId id, |
| 126 std::unique_ptr<CertErrorParams> params); |
| 107 | 127 |
| 108 void AddWithParam(CertErrorType type, | 128 // TODO(crbug.com/634443): Eliminate this and use AddError() instead (which |
| 109 std::unique_ptr<CertErrorParams> params); | 129 // is less ambiguous). |
| 130 void Add(CertErrorId id); |
| 110 | 131 |
| 111 void AddWith1DerParam(CertErrorType type, const der::Input& der1); | 132 void AddError(CertErrorId id, std::unique_ptr<CertErrorParams> params); |
| 112 void AddWith2DerParams(CertErrorType type, | 133 void AddError(CertErrorId id); |
| 113 const der::Input& der1, | |
| 114 const der::Input& der2); | |
| 115 | 134 |
| 116 const std::vector<CertError>& errors() const { return errors_; } | 135 void AddWarning(CertErrorId id, std::unique_ptr<CertErrorParams> params); |
| 136 void AddWarning(CertErrorId id); |
| 137 |
| 138 // Returns true if the tree is empty. Note that emptiness of the error tree |
| 139 // is NOT equivalent to success for some call, and vice versa. (For instance |
| 140 // consumers may forget to emit errors on failures, or some errors may be |
| 141 // non-fatal warnings). |
| 142 bool empty() const; |
| 117 | 143 |
| 118 // Dumps a textual representation of the errors for debugging purposes. | 144 // Dumps a textual representation of the errors for debugging purposes. |
| 119 std::string ToDebugString() const; | 145 std::string ToDebugString() const; |
| 120 | 146 |
| 121 private: | 147 private: |
| 122 std::vector<CertError> errors_; | 148 // CertErrorScoper manipulates the CertErrors object. |
| 149 friend class CertErrorScoper; |
| 150 |
| 151 void AddNode(std::unique_ptr<CertErrorNode> node); |
| 152 |
| 153 // Used by CertErrorScoper to register itself as the top-level scoper. |
| 154 // Returns the previously set scoper, or nullptr if there was none. |
| 155 CertErrorScoper* SetScoper(CertErrorScoper* scoper); |
| 156 |
| 157 CertErrorNodes nodes_; |
| 158 |
| 159 // The top-most CertErrorScoper that is currently in scope (and which affects |
| 160 // the parent node for newly added errors). |
| 161 CertErrorScoper* current_scoper_ = nullptr; |
| 123 | 162 |
| 124 DISALLOW_COPY_AND_ASSIGN(CertErrors); | 163 DISALLOW_COPY_AND_ASSIGN(CertErrors); |
| 125 }; | 164 }; |
| 126 | 165 |
| 127 // -------------------------- | |
| 128 // Context scopers | |
| 129 // -------------------------- | |
| 130 | |
| 131 // TODO(crbug.com/634443): Implement. | |
| 132 class NET_EXPORT ScopedCertErrorsCertContext { | |
| 133 public: | |
| 134 ScopedCertErrorsCertContext(CertErrors* parent, | |
| 135 const ParsedCertificate* cert, | |
| 136 size_t i); | |
| 137 ~ScopedCertErrorsCertContext(); | |
| 138 | |
| 139 private: | |
| 140 DISALLOW_COPY_AND_ASSIGN(ScopedCertErrorsCertContext); | |
| 141 }; | |
| 142 | |
| 143 // TODO(crbug.com/634443): Implement. | |
| 144 class NET_EXPORT ScopedCertErrorsTrustAnchorContext { | |
| 145 public: | |
| 146 ScopedCertErrorsTrustAnchorContext(CertErrors* parent, | |
| 147 const TrustAnchor* trust_anchor); | |
| 148 ~ScopedCertErrorsTrustAnchorContext(); | |
| 149 | |
| 150 private: | |
| 151 DISALLOW_COPY_AND_ASSIGN(ScopedCertErrorsTrustAnchorContext); | |
| 152 }; | |
| 153 | |
| 154 // -------------------------- | |
| 155 // Error parameters | |
| 156 // -------------------------- | |
| 157 | |
| 158 class NET_EXPORT CertErrorParamsDer1 : public CertErrorParams { | |
| 159 public: | |
| 160 explicit CertErrorParamsDer1(const der::Input& der1); | |
| 161 | |
| 162 std::unique_ptr<base::Value> ToValue() const override; | |
| 163 | |
| 164 private: | |
| 165 const std::string der1_; | |
| 166 | |
| 167 DISALLOW_COPY_AND_ASSIGN(CertErrorParamsDer1); | |
| 168 }; | |
| 169 | |
| 170 class NET_EXPORT CertErrorParamsDer2 : public CertErrorParams { | |
| 171 public: | |
| 172 CertErrorParamsDer2(const der::Input& der1, const der::Input& der2); | |
| 173 | |
| 174 std::unique_ptr<base::Value> ToValue() const override; | |
| 175 | |
| 176 private: | |
| 177 const std::string der1_; | |
| 178 const std::string der2_; | |
| 179 | |
| 180 DISALLOW_COPY_AND_ASSIGN(CertErrorParamsDer2); | |
| 181 }; | |
| 182 | |
| 183 } // namespace net | 166 } // namespace net |
| 184 | 167 |
| 185 #endif // NET_CERT_INTERNAL_CERT_ERRORS_H_ | 168 #endif // NET_CERT_INTERNAL_CERT_ERRORS_H_ |
| OLD | NEW |