1use std::{
9 convert::{From, Infallible},
10 fmt::Display,
11};
12use thiserror::Error;
13
14#[derive(Error, Clone, Debug, PartialEq, Eq)]
16#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
17pub enum Token {
18 #[error("internal error")]
19 InternalError,
20 #[error("error deserializing or verifying the token")]
21 Format(Format),
22 #[error("tried to append a block to a sealed token")]
23 AppendOnSealed,
24 #[error("tried to seal an already sealed token")]
25 AlreadySealed,
26 #[error("authorization failed: {0}")]
27 FailedLogic(Logic),
28 #[error("error generating Datalog: {0}")]
29 Language(biscuit_parser::error::LanguageError),
30 #[error("Reached Datalog execution limits")]
31 RunLimit(RunLimit),
32 #[error("Cannot convert from Term: {0}")]
33 ConversionError(String),
34 #[error("Cannot decode base64 token: {0}")]
35 Base64(Base64Error),
36 #[error("Datalog execution failure: {0}")]
37 Execution(Expression),
38}
39
40impl From<Infallible> for Token {
41 fn from(_: Infallible) -> Self {
42 unreachable!()
43 }
44}
45
46impl From<Format> for Token {
47 fn from(e: Format) -> Self {
48 Token::Format(e)
49 }
50}
51
52impl From<Logic> for Token {
53 fn from(e: Logic) -> Self {
54 Token::FailedLogic(e)
55 }
56}
57
58impl From<biscuit_parser::error::LanguageError> for Token {
59 fn from(e: biscuit_parser::error::LanguageError) -> Self {
60 Token::Language(e)
61 }
62}
63
64impl From<base64::DecodeError> for Token {
65 fn from(e: base64::DecodeError) -> Self {
66 let err = match e {
67 base64::DecodeError::InvalidByte(offset, byte) => {
68 Base64Error::InvalidByte(offset, byte)
69 }
70 base64::DecodeError::InvalidLength => Base64Error::InvalidLength,
71 base64::DecodeError::InvalidLastSymbol(offset, byte) => {
72 Base64Error::InvalidLastSymbol(offset, byte)
73 }
74 };
75
76 Token::Base64(err)
77 }
78}
79
80impl From<Execution> for Token {
81 fn from(e: Execution) -> Self {
82 match e {
83 Execution::RunLimit(limit) => Token::RunLimit(limit),
84 Execution::Expression(e) => Token::Execution(e),
85 }
86 }
87}
88
89#[derive(Clone, Debug, PartialEq, Eq)]
90#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
91pub enum Base64Error {
92 InvalidByte(usize, u8),
93 InvalidLength,
94 InvalidLastSymbol(usize, u8),
95}
96
97impl std::fmt::Display for Base64Error {
98 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
99 match *self {
100 Base64Error::InvalidByte(index, byte) => {
101 write!(f, "Invalid byte {}, offset {}.", byte, index)
102 }
103 Base64Error::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
104 Base64Error::InvalidLastSymbol(index, byte) => {
105 write!(f, "Invalid last symbol {}, offset {}.", byte, index)
106 }
107 }
108 }
109}
110
111#[derive(Error, Clone, Debug, PartialEq, Eq)]
114#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
115pub enum Format {
116 #[error("failed verifying the signature")]
117 Signature(Signature),
118 #[error("failed verifying the signature of a sealed token")]
119 SealedSignature,
120 #[error("the token does not provide intermediate public keys")]
121 EmptyKeys,
122 #[error("the root public key was not recognized")]
123 UnknownPublicKey,
124 #[error("could not deserialize the wrapper object")]
125 DeserializationError(String),
126 #[error("could not serialize the wrapper object")]
127 SerializationError(String),
128 #[error("could not deserialize the block")]
129 BlockDeserializationError(String),
130 #[error("could not serialize the block")]
131 BlockSerializationError(String),
132 #[error("Block format version is higher than supported")]
133 Version {
134 maximum: u32,
135 minimum: u32,
136 actual: u32,
137 },
138 #[error("invalid key size")]
139 InvalidKeySize(usize),
140 #[error("invalid signature size")]
141 InvalidSignatureSize(usize),
142 #[error("invalid key")]
143 InvalidKey(String),
144 #[error("could not deserialize signature")]
145 SignatureDeserializationError(String),
146 #[error("could not deserialize the block signature")]
147 BlockSignatureDeserializationError(String),
148 #[error("invalid block id")]
149 InvalidBlockId(usize),
150 #[error("the public key is already present in previous blocks")]
151 ExistingPublicKey(String),
152 #[error("multiple blocks declare the same symbols")]
153 SymbolTableOverlap,
154 #[error("multiple blocks declare the same public keys")]
155 PublicKeyTableOverlap,
156 #[error("the external public key was not recognized")]
157 UnknownExternalKey,
158 #[error("the symbol id was not in the table")]
159 UnknownSymbol(u64),
160 #[cfg(feature = "pem")]
161 #[error("PKCS8 serialization error")]
162 PKCS8(String),
163}
164
165#[derive(Error, Clone, Debug, PartialEq, Eq)]
167#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
168pub enum Signature {
169 #[error("could not parse the signature elements")]
170 InvalidFormat,
171 #[error("the signature did not match")]
172 InvalidSignature(String),
173 #[error("could not sign")]
174 InvalidSignatureGeneration(String),
175}
176
177#[derive(Error, Clone, Debug, PartialEq, Eq)]
179#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
180pub enum Logic {
181 #[error("a rule provided by a block is producing a fact with unbound variables")]
182 InvalidBlockRule(u32, String),
183 #[error("{policy}, and the following checks failed: {}", display_failed_checks(.checks))]
184 Unauthorized {
185 policy: MatchedPolicy,
187 checks: Vec<FailedCheck>,
189 },
190 #[error("the authorizer already contains a token")]
191 AuthorizerNotEmpty,
192 #[error("no matching policy was found, and the following checks failed: {}", display_failed_checks(.checks))]
193 NoMatchingPolicy {
194 checks: Vec<FailedCheck>,
196 },
197}
198
199#[derive(Error, Clone, Debug, PartialEq, Eq)]
200#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
201pub enum MatchedPolicy {
202 #[error("an allow policy matched (policy index: {0})")]
203 Allow(usize),
204 #[error("a deny policy matched (policy index: {0})")]
205 Deny(usize),
206}
207
208#[derive(Error, Clone, Debug, PartialEq, Eq)]
210#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
211pub enum FailedCheck {
212 #[error("{0}")]
213 Block(FailedBlockCheck),
214 #[error("{0}")]
215 Authorizer(FailedAuthorizerCheck),
216}
217
218fn display_failed_checks(c: &[FailedCheck]) -> String {
219 c.iter()
220 .map(|c| c.to_string())
221 .collect::<Vec<_>>()
222 .join(", ")
223}
224
225#[derive(Clone, Debug, PartialEq, Eq)]
226#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
227pub struct FailedBlockCheck {
228 pub block_id: u32,
229 pub check_id: u32,
230 pub rule: String,
232}
233
234impl Display for FailedBlockCheck {
235 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236 write!(
237 f,
238 "Check n°{} in block n°{}: {}",
239 self.check_id, self.block_id, self.rule
240 )
241 }
242}
243
244#[derive(Clone, Debug, PartialEq, Eq)]
245#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
246pub struct FailedAuthorizerCheck {
247 pub check_id: u32,
248 pub rule: String,
250}
251
252impl Display for FailedAuthorizerCheck {
253 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 write!(f, "Check n°{} in authorizer: {}", self.check_id, self.rule)
255 }
256}
257
258#[derive(Error, Clone, Debug, PartialEq, Eq)]
260#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
261pub enum Execution {
262 #[error("Reached Datalog execution limits")]
263 RunLimit(RunLimit),
264 #[error("Expression execution failure")]
265 Expression(Expression),
266}
267
268#[derive(Error, Clone, Debug, PartialEq, Eq)]
270#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
271pub enum Expression {
272 #[error("Unknown symbol")]
273 UnknownSymbol(u64),
274 #[error("Unknown variable")]
275 UnknownVariable(u32),
276 #[error("Invalid type")]
277 InvalidType,
278 #[error("Overflow")]
279 Overflow,
280 #[error("Division by zero")]
281 DivideByZero,
282 #[error("Wrong number of elements on stack")]
283 InvalidStack,
284 #[error("Shadowed variable")]
285 ShadowedVariable,
286 #[error("Undefined extern func: {0}")]
287 UndefinedExtern(String),
288 #[error("Error while evaluating extern func {0}: {1}")]
289 ExternEvalError(String, String),
290}
291
292#[derive(Error, Clone, Debug, PartialEq, Eq)]
294#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
295pub enum RunLimit {
296 #[error("too many facts generated")]
297 TooManyFacts,
298 #[error("too many engine iterations")]
299 TooManyIterations,
300 #[error("spent too much time verifying")]
301 Timeout,
302 #[error("Unexpected query results, expected {0} got {1}")]
303 UnexpectedQueryResult(usize, usize),
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn error_format_strings() {
312 assert_eq!(
313 format!("{}", Token::ConversionError("test".to_owned())),
314 "Cannot convert from Term: test"
315 );
316
317 assert_eq!(
318 format!("{}", Token::Base64(Base64Error::InvalidLength)),
319 "Cannot decode base64 token: Encoded text cannot have a 6-bit remainder."
320 );
321
322 assert_eq!(
323 format!(
324 "{}",
325 Token::FailedLogic(Logic::Unauthorized {
326 policy: MatchedPolicy::Allow(0),
327 checks: vec![
328 FailedCheck::Authorizer(FailedAuthorizerCheck {
329 check_id: 0,
330 rule: "check if false".to_string()
331 }),
332 FailedCheck::Block(FailedBlockCheck {
333 block_id: 0,
334 check_id: 0,
335 rule: "check if false".to_string()
336 })
337 ]
338 })
339 )
340 .to_string(),
341 "authorization failed: an allow policy matched (policy index: 0), and the following checks failed: Check n°0 in authorizer: check if false, Check n°0 in block n°0: check if false"
342 );
343 }
344}