1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! error types
//!

use std::convert::{From, Infallible};
use thiserror::Error;

/// the global error type for Biscuit
#[derive(Error, Clone, Debug, PartialEq)]
pub enum Token {
    #[error("internal error")]
    InternalError,
    #[error("error deserializing or verifying the token")]
    Format(Format),
    #[error("the authority block must have the index 0")]
    InvalidAuthorityIndex(u32),
    #[error("the block index does not match its position")]
    InvalidBlockIndex(InvalidBlockIndex),
    #[error("multiple blocks declare the same symbols")]
    SymbolTableOverlap,
    #[error(r#"the symbol table is missing either "authority" or "ambient""#)]
    MissingSymbols,
    #[error("tried to append a block to a sealed token")]
    Sealed,
    #[error("check validation failed")]
    FailedLogic(Logic),
    #[error("Datalog parsing error")]
    ParseError,
    #[error("Reached Datalog execution limits")]
    RunLimit(RunLimit),
    #[error("Cannot convert from Term: %s")]
    ConversionError(String),
}

impl From<Infallible> for Token {
    fn from(_: Infallible) -> Self {
        unreachable!()
    }
}

impl From<Format> for Token {
    fn from(e: Format) -> Self {
        Token::Format(e)
    }
}

impl From<Logic> for Token {
    fn from(e: Logic) -> Self {
        Token::FailedLogic(e)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct InvalidBlockIndex {
    pub expected: u32,
    pub found: u32,
}

/// Errors related to the token's serialization format or cryptographic
/// signature
#[derive(Error, Clone, Debug, PartialEq)]
pub enum Format {
    #[error("failed verifying the signature")]
    Signature(Signature),
    #[error("failed verifying the signature of a sealed token")]
    SealedSignature,
    #[error("the token does not provide intermediate public keys")]
    EmptyKeys,
    #[error("the root public key was not recognized")]
    UnknownPublicKey,
    #[error("could not deserialize the wrapper object")]
    DeserializationError(String),
    #[error("could not serialize the wrapper object")]
    SerializationError(String),
    #[error("could not deserialize the block")]
    BlockDeserializationError(String),
    #[error("could not serialize the block")]
    BlockSerializationError(String),
    #[error("Block format version is higher than supported")]
    Version { maximum: u32, actual: u32 },
}

/// Signature errors
#[derive(Error, Clone, Debug, PartialEq)]
pub enum Signature {
    #[error("could not parse the signature elements")]
    InvalidFormat,
    #[error("the signature did not match")]
    InvalidSignature,
}

/// errors in the Datalog evaluation
#[derive(Error, Clone, Debug, PartialEq)]
pub enum Logic {
    #[error("a fact of the authority block did not have the authority tag")]
    InvalidAuthorityFact(String),
    #[error("a fact provided or generated by the verifier did not have the ambient tag")]
    InvalidAmbientFact(String),
    #[error("a fact provided or generated by a block had the authority or ambient tag")]
    InvalidBlockFact(u32, String),
    #[error("a rule provided by a block is generating facts with the authority or ambient tag")]
    InvalidBlockRule(u32, String),
    #[error("list of checks that failed validation")]
    FailedChecks(Vec<FailedCheck>),
    #[error("the verifier already contains a token")]
    VerifierNotEmpty,
    #[error("denied by policy")]
    Deny(usize),
    #[error("no matching policy was found")]
    NoMatchingPolicy,
}

/// check check errors
#[derive(Error, Clone, Debug, PartialEq)]
pub enum FailedCheck {
    #[error("a check failed in a block")]
    Block(FailedBlockCheck),
    #[error("a check provided by the verifier failed")]
    Verifier(FailedVerifierCheck),
}

#[derive(Clone, Debug, PartialEq)]
pub struct FailedBlockCheck {
    pub block_id: u32,
    pub check_id: u32,
    /// pretty print of the rule that failed
    pub rule: String,
}

#[derive(Clone, Debug, PartialEq)]
pub struct FailedVerifierCheck {
    pub check_id: u32,
    /// pretty print of the rule that failed
    pub rule: String,
}

/// runtime limits errors
#[derive(Error, Clone, Debug, PartialEq)]
pub enum RunLimit {
    #[error("too many facts generated")]
    TooManyFacts,
    #[error("too many engine iterations")]
    TooManyIterations,
    #[error("spent too much time verifying")]
    Timeout,
}