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}