tor_netdoc/parse2/error.rs
1//! Parsing errors
2//!
3//! # Error philosophy
4//!
5//! We don't spend a huge amount of effort producing precise and informative errors.
6//!
7//! We report:
8//!
9//! * A line number in the document where the error occurred.
10//! For a problem with an item keyword line, that line is reported.
11//! For an Object, a line somewhere in or just after the object is reported.
12//!
13//! * The expected keyword of a missing item.
14//!
15//! * The struct field name of a missing or invalid argument.
16//!
17//! * The file name (might be a nominal file name)
18//!
19//! * What kind of document we were trying to parse.
20//!
21//! We do not report:
22//!
23//! * Column numbers or byte offsets.
24//!
25//! * Any more details of the error for syntactically invalid arguments,
26//! bad base64 or bad binary data, etc. (eg we discard the `FromStr::Err`)
27//!
28//! This saves a good deal of work.
29
30use super::*;
31
32/// Error encountered when parsing a document, including its location
33#[derive(Error, Clone, Debug, Eq, PartialEq)]
34#[error("failed to parse network document, type {doctype}: {file}:{lno}: {problem}")]
35#[non_exhaustive]
36pub struct ParseError {
37 /// What the problem was
38 #[source]
39 pub problem: ErrorProblem,
40 /// The document type, from `NetdocParseable::doctype_for_error`
41 pub doctype: &'static str,
42 /// Where the document came from, in human-readable form, filename or `<...>`
43 pub file: String,
44 /// Line number
45 pub lno: usize,
46}
47
48/// Problem found when parsing a document
49///
50/// Just the nature of the problem, including possibly which field or argument
51/// if that's necessary to disambiguate, but not including location in the document.
52///
53/// We are quite minimal:
54/// we do not report the `Display` of argument parse errors, for example.
55#[derive(Error, Copy, Clone, Debug, Eq, PartialEq)]
56#[non_exhaustive]
57pub enum ErrorProblem {
58 /// Empty document
59 #[error("empty document")]
60 EmptyDocument,
61 /// Wrong document type
62 #[error("wrong document type")]
63 WrongDocumentType,
64 /// Multiple top-level documents
65 #[error("multiple top-level documents")]
66 MultipleDocuments,
67 /// Item missing required base64-encoded Object
68 #[error("item missing required base64-encoded Object")]
69 MissingObject,
70 /// Item repeated when not allowed
71 #[error("item repeated when not allowed")]
72 ItemRepeated,
73 /// Item forbidden (in this kind of document or location)
74 #[error("item forbidden (in this kind of document or location)")]
75 ItemForbidden,
76 /// Item repeated when not allowed
77 #[error("item repeated when not allowed")]
78 ItemMisplacedAfterSignature,
79 /// Document contains nul byte
80 #[error("document contains nul byte")]
81 NulByte,
82 /// Item keyword line starts with whitespace
83 #[error("item keyword line starts with whitespace")]
84 KeywordLineStartsWithWhitespace,
85 /// No keyword when item keyword line expected
86 #[error("no keyword when item keyword line expected")]
87 MissingKeyword,
88 /// No keyword when item keyword line expected
89 #[error("no keyword when item keyword line expected")]
90 InvalidKeyword(#[from] keyword::InvalidKeyword),
91 /// Missing item {keyword}
92 #[error("missing item {keyword}")]
93 MissingItem {
94 /// Keyword for item that was missing
95 keyword: &'static str,
96 },
97 /// Missing argument {field}
98 #[error("missing argument {field}")]
99 MissingArgument {
100 /// Field name for argument that was missing
101 field: &'static str,
102 },
103 /// Invalid value for argument {field}
104 #[error("invalid value for argument {field}")]
105 InvalidArgument {
106 /// Field name for argument that had invalid value
107 field: &'static str,
108 },
109 /// Unexpected additional argument(s)
110 #[error("too many arguments")]
111 UnexpectedArgument,
112 /// Base64-encoded Object footer not found
113 #[error("base64-encoded Object footer not found")]
114 ObjectMissingFooter,
115 /// Base64-encoded Object END label does not match BEGIN
116 #[error("base64-encoded Object END label does not match BEGIN")]
117 ObjectMismatchedLabels,
118 /// Base64-encoded Object END label does not match BEGIN
119 #[error("base64-encoded Object label is not as expected")]
120 ObjectIncorrectLabel,
121 /// Base64-encoded Object has incorrectly formatted delimiter lines
122 #[error("base64-encoded Object has incorrectly formatted delimiter lines")]
123 InvalidObjectDelimiters,
124 /// Base64-encoded Object found where none expected
125 #[error("base64-encoded Object found where none expected")]
126 ObjectUnexpected,
127 /// Base64-encoded Object contains invalid base64
128 #[error("base64-encoded Object contains invalid base64")]
129 ObjectInvalidBase64,
130 /// Base64-encoded Object contains valid base64 specifying invalid data
131 #[error("base64-encoded Object contains invalid data")]
132 ObjectInvalidData,
133 /// Other parsing proble
134 #[error("other problem: {0}")]
135 Other(&'static str),
136}
137
138/// Error from signature verification (and timeliness check)
139#[derive(Error, Debug, Clone, Copy)]
140#[non_exhaustive]
141pub enum VerifyFailed {
142 /// Signature verification failed
143 #[error("netdoc signature verification failed")]
144 VerifyFailed,
145 /// Document is too new - clock skew?
146 #[error("document is too new - clock skew?")]
147 TooNew,
148 /// Document is too old
149 #[error("document is too old")]
150 TooOld,
151 /// Document not signed by the right testator (or too few known testators)
152 #[error("document not signed by the right testator (or too few known testators)")]
153 InsufficientTrustedSigners,
154 /// document has inconsistent content
155 #[error("document has inconsistent content")]
156 Inconsistent,
157 /// Something else is wrong
158 #[error("document has uncategorised problem found during verification")]
159 Other,
160}
161
162impl From<signature::Error> for VerifyFailed {
163 fn from(_: signature::Error) -> VerifyFailed {
164 VerifyFailed::VerifyFailed
165 }
166}