Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions biscuit-auth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,18 @@ pem = ["ed25519-dalek/pem", "ed25519-dalek/pkcs8"]

[dependencies]
rand_core = "^0.6"
sha2 = "^0.9"
prost = "0.10"
prost-types = "0.10"
prost = "0.14.3"
prost-types = "0.14.3"
regex = { version = "1.5", default-features = false, features = ["std"] }
nom = { version = "7", default-features = false, features = ["std"] }
nom = { version = "8.0.0", default-features = false, features = ["std"] }
hex = "0.4"
zeroize = { version = "1.5", default-features = false }
thiserror = "1"
thiserror = "2.0.18"
rand = { version = "0.8" }
wasm-bindgen = { version = "0.2", optional = true }
base64 = "0.13.0"
base64 = "0.22.1"
ed25519-dalek = { version = "2.0.0", features = ["rand_core", "zeroize"] }
serde = { version = "1.0.132", optional = true, features = ["derive"] }
getrandom = { version = "0.2.15" }
time = { version = "0.3.7", features = ["formatting", "parsing"] }
uuid = { version = "1", optional = true }
biscuit-parser = { version = "0.2.0", path = "../biscuit-parser" }
Expand All @@ -51,15 +49,14 @@ chrono = { version = "0.4.26", optional = true, default-features = false, featur
serde_json = "1.0.117"
ecdsa = { version = "0.16.9", features = ["signing", "verifying", "pem", "alloc", "pkcs8", "serde"] }
p256 = "0.13.2"
pkcs8 = "0.9.0"
elliptic-curve = { version = "0.13.8", features = ["pkcs8"] }

[dev-dependencies]
bencher = "0.1.5"
rand = "0.8"
chrono = { version = "0.4.26", features = ["serde", "clock"] }
colored-diff = "0.2.3"
prost-build = "0.10"
prost-build = "0.14.3"
serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.67"
codspeed-bencher-compat = "2.6.0"
Expand Down
4 changes: 1 addition & 3 deletions biscuit-auth/examples/testcases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,9 +821,7 @@ fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult {
let token = print_blocks(&biscuit3);

let mut serialized = biscuit3.container().clone();
let mut blocks = vec![];
blocks.push(serialized.blocks[1].clone());
blocks.push(serialized.blocks[0].clone());
let blocks = vec![serialized.blocks[1].clone(), serialized.blocks[0].clone()];
serialized.blocks = blocks;

let data = if test {
Expand Down
15 changes: 10 additions & 5 deletions biscuit-auth/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ impl From<base64::DecodeError> for Token {
base64::DecodeError::InvalidByte(offset, byte) => {
Base64Error::InvalidByte(offset, byte)
}
base64::DecodeError::InvalidLength => Base64Error::InvalidLength,
base64::DecodeError::InvalidLength(len) => Base64Error::InvalidLength(len),
base64::DecodeError::InvalidLastSymbol(offset, byte) => {
Base64Error::InvalidLastSymbol(offset, byte)
}
base64::DecodeError::InvalidPadding => Base64Error::InvalidPadding,
};

Token::Base64(err)
Expand All @@ -90,8 +91,9 @@ impl From<Execution> for Token {
#[cfg_attr(feature = "serde-error", derive(serde::Serialize, serde::Deserialize))]
pub enum Base64Error {
InvalidByte(usize, u8),
InvalidLength,
InvalidLength(usize),
InvalidLastSymbol(usize, u8),
InvalidPadding,
Comment on lines -93 to +96
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change

}

impl std::fmt::Display for Base64Error {
Expand All @@ -100,10 +102,13 @@ impl std::fmt::Display for Base64Error {
Base64Error::InvalidByte(index, byte) => {
write!(f, "Invalid byte {byte}, offset {index}.")
}
Base64Error::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
Base64Error::InvalidLength(len) => {
write!(f, "Invalid input length: {len}.")
}
Base64Error::InvalidLastSymbol(index, byte) => {
write!(f, "Invalid last symbol {byte}, offset {index}.")
}
Base64Error::InvalidPadding => write!(f, "Invalid padding"),
}
}
}
Expand Down Expand Up @@ -315,8 +320,8 @@ mod tests {
);

assert_eq!(
format!("{}", Token::Base64(Base64Error::InvalidLength)),
"Cannot decode base64 token: Encoded text cannot have a 6-bit remainder."
format!("{}", Token::Base64(Base64Error::InvalidLength(6))),
"Cannot decode base64 token: Invalid input length: 6."
);

assert_eq!(
Expand Down
102 changes: 53 additions & 49 deletions biscuit-auth/src/format/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/
//! helper functions for conversion between internal structures and Protobuf

use prost::UnknownEnumValue;

use super::schema;
use crate::builder::Convert;
use crate::crypto::PublicKey;
Expand All @@ -18,6 +20,7 @@ use crate::token::{DATALOG_3_1, DATALOG_3_2, DATALOG_3_3, MAX_SCHEMA_VERSION, MI

use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::convert::TryFrom;

pub fn token_block_to_proto_block(input: &Block) -> schema::Block {
schema::Block {
Expand Down Expand Up @@ -380,12 +383,13 @@ pub fn proto_policy_to_policy(
queries.push(c);
}

let kind = if let Some(i) = Kind::from_i32(input.kind) {
i
} else {
return Err(error::Format::DeserializationError(
"deserialization error: invalid policy kind".to_string(),
));
let kind = match Kind::try_from(input.kind) {
Ok(i) => i,
Err(UnknownEnumValue(i)) => {
return Err(error::Format::DeserializationError(format!(
"deserialization error: invalid policy kind `{i}`"
)));
}
};

let kind = match kind {
Expand Down Expand Up @@ -710,78 +714,78 @@ fn proto_op_to_token_op(op: &schema::Op) -> Result<Op, error::Format> {
Ok(match op.content.as_ref() {
Some(op::Content::Value(id)) => Op::Value(proto_id_to_token_term(id)?),
Some(op::Content::Unary(u)) => {
match (op_unary::Kind::from_i32(u.kind), u.ffi_name.as_ref()) {
(Some(op_unary::Kind::Negate), None) => Op::Unary(Unary::Negate),
(Some(op_unary::Kind::Parens), None) => Op::Unary(Unary::Parens),
(Some(op_unary::Kind::Length), None) => Op::Unary(Unary::Length),
(Some(op_unary::Kind::TypeOf), None) => Op::Unary(Unary::TypeOf),
(Some(op_unary::Kind::Ffi), Some(n)) => Op::Unary(Unary::Ffi(*n)),
(Some(op_unary::Kind::Ffi), None) => {
match (op_unary::Kind::try_from(u.kind), u.ffi_name.as_ref()) {
(Ok(op_unary::Kind::Negate), None) => Op::Unary(Unary::Negate),
(Ok(op_unary::Kind::Parens), None) => Op::Unary(Unary::Parens),
(Ok(op_unary::Kind::Length), None) => Op::Unary(Unary::Length),
(Ok(op_unary::Kind::TypeOf), None) => Op::Unary(Unary::TypeOf),
(Ok(op_unary::Kind::Ffi), Some(n)) => Op::Unary(Unary::Ffi(*n)),
(Ok(op_unary::Kind::Ffi), None) => {
return Err(error::Format::DeserializationError(
"deserialization error: missing ffi name".to_string(),
))
}
(Some(_), Some(_)) => {
(Ok(_), Some(_)) => {
return Err(error::Format::DeserializationError(
"deserialization error: ffi name set on a regular unary operation"
.to_string(),
))
}
(None, _) => {
(Err(_), _) => {
return Err(error::Format::DeserializationError(
"deserialization error: unary operation is empty".to_string(),
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about that error message

))
}
}
}
Some(op::Content::Binary(b)) => {
match (op_binary::Kind::from_i32(b.kind), b.ffi_name.as_ref()) {
(Some(op_binary::Kind::LessThan), None) => Op::Binary(Binary::LessThan),
(Some(op_binary::Kind::GreaterThan), None) => Op::Binary(Binary::GreaterThan),
(Some(op_binary::Kind::LessOrEqual), None) => Op::Binary(Binary::LessOrEqual),
(Some(op_binary::Kind::GreaterOrEqual), None) => Op::Binary(Binary::GreaterOrEqual),
(Some(op_binary::Kind::Equal), None) => Op::Binary(Binary::Equal),
(Some(op_binary::Kind::Contains), None) => Op::Binary(Binary::Contains),
(Some(op_binary::Kind::Prefix), None) => Op::Binary(Binary::Prefix),
(Some(op_binary::Kind::Suffix), None) => Op::Binary(Binary::Suffix),
(Some(op_binary::Kind::Regex), None) => Op::Binary(Binary::Regex),
(Some(op_binary::Kind::Add), None) => Op::Binary(Binary::Add),
(Some(op_binary::Kind::Sub), None) => Op::Binary(Binary::Sub),
(Some(op_binary::Kind::Mul), None) => Op::Binary(Binary::Mul),
(Some(op_binary::Kind::Div), None) => Op::Binary(Binary::Div),
(Some(op_binary::Kind::And), None) => Op::Binary(Binary::And),
(Some(op_binary::Kind::Or), None) => Op::Binary(Binary::Or),
(Some(op_binary::Kind::Intersection), None) => Op::Binary(Binary::Intersection),
(Some(op_binary::Kind::Union), None) => Op::Binary(Binary::Union),
(Some(op_binary::Kind::BitwiseAnd), None) => Op::Binary(Binary::BitwiseAnd),
(Some(op_binary::Kind::BitwiseOr), None) => Op::Binary(Binary::BitwiseOr),
(Some(op_binary::Kind::BitwiseXor), None) => Op::Binary(Binary::BitwiseXor),
(Some(op_binary::Kind::NotEqual), None) => Op::Binary(Binary::NotEqual),
(Some(op_binary::Kind::HeterogeneousEqual), None) => {
match (op_binary::Kind::try_from(b.kind), b.ffi_name.as_ref()) {
(Ok(op_binary::Kind::LessThan), None) => Op::Binary(Binary::LessThan),
(Ok(op_binary::Kind::GreaterThan), None) => Op::Binary(Binary::GreaterThan),
(Ok(op_binary::Kind::LessOrEqual), None) => Op::Binary(Binary::LessOrEqual),
(Ok(op_binary::Kind::GreaterOrEqual), None) => Op::Binary(Binary::GreaterOrEqual),
(Ok(op_binary::Kind::Equal), None) => Op::Binary(Binary::Equal),
(Ok(op_binary::Kind::Contains), None) => Op::Binary(Binary::Contains),
(Ok(op_binary::Kind::Prefix), None) => Op::Binary(Binary::Prefix),
(Ok(op_binary::Kind::Suffix), None) => Op::Binary(Binary::Suffix),
(Ok(op_binary::Kind::Regex), None) => Op::Binary(Binary::Regex),
(Ok(op_binary::Kind::Add), None) => Op::Binary(Binary::Add),
(Ok(op_binary::Kind::Sub), None) => Op::Binary(Binary::Sub),
(Ok(op_binary::Kind::Mul), None) => Op::Binary(Binary::Mul),
(Ok(op_binary::Kind::Div), None) => Op::Binary(Binary::Div),
(Ok(op_binary::Kind::And), None) => Op::Binary(Binary::And),
(Ok(op_binary::Kind::Or), None) => Op::Binary(Binary::Or),
(Ok(op_binary::Kind::Intersection), None) => Op::Binary(Binary::Intersection),
(Ok(op_binary::Kind::Union), None) => Op::Binary(Binary::Union),
(Ok(op_binary::Kind::BitwiseAnd), None) => Op::Binary(Binary::BitwiseAnd),
(Ok(op_binary::Kind::BitwiseOr), None) => Op::Binary(Binary::BitwiseOr),
(Ok(op_binary::Kind::BitwiseXor), None) => Op::Binary(Binary::BitwiseXor),
(Ok(op_binary::Kind::NotEqual), None) => Op::Binary(Binary::NotEqual),
(Ok(op_binary::Kind::HeterogeneousEqual), None) => {
Op::Binary(Binary::HeterogeneousEqual)
}
(Some(op_binary::Kind::HeterogeneousNotEqual), None) => {
(Ok(op_binary::Kind::HeterogeneousNotEqual), None) => {
Op::Binary(Binary::HeterogeneousNotEqual)
}
(Some(op_binary::Kind::LazyAnd), None) => Op::Binary(Binary::LazyAnd),
(Some(op_binary::Kind::LazyOr), None) => Op::Binary(Binary::LazyOr),
(Some(op_binary::Kind::All), None) => Op::Binary(Binary::All),
(Some(op_binary::Kind::Any), None) => Op::Binary(Binary::Any),
(Some(op_binary::Kind::Get), None) => Op::Binary(Binary::Get),
(Some(op_binary::Kind::Ffi), Some(n)) => Op::Binary(Binary::Ffi(*n)),
(Some(op_binary::Kind::Ffi), None) => {
(Ok(op_binary::Kind::LazyAnd), None) => Op::Binary(Binary::LazyAnd),
(Ok(op_binary::Kind::LazyOr), None) => Op::Binary(Binary::LazyOr),
(Ok(op_binary::Kind::All), None) => Op::Binary(Binary::All),
(Ok(op_binary::Kind::Any), None) => Op::Binary(Binary::Any),
(Ok(op_binary::Kind::Get), None) => Op::Binary(Binary::Get),
(Ok(op_binary::Kind::Ffi), Some(n)) => Op::Binary(Binary::Ffi(*n)),
(Ok(op_binary::Kind::Ffi), None) => {
return Err(error::Format::DeserializationError(
"deserialization error: missing ffi name".to_string(),
))
}
(Some(_), Some(_)) => {
(Ok(_), Some(_)) => {
return Err(error::Format::DeserializationError(
"deserialization error: ffi name set on a regular binary operation"
.to_string(),
))
}
(Some(op_binary::Kind::TryOr), None) => Op::Binary(Binary::TryOr),
(None, _) => {
(Ok(op_binary::Kind::TryOr), None) => Op::Binary(Binary::TryOr),
(Err(_), _) => {
return Err(error::Format::DeserializationError(
"deserialization error: binary operation is empty".to_string(),
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

))
Expand Down
5 changes: 3 additions & 2 deletions biscuit-auth/src/token/authorizer/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright (c) 2019 Geoffroy Couprie <contact@geoffroycouprie.com> and Contributors to the Eclipse Foundation.
* SPDX-License-Identifier: Apache-2.0
*/
use base64::prelude::*;
use prost::Message;
use std::{collections::HashMap, time::Duration};

Expand Down Expand Up @@ -180,7 +181,7 @@ impl super::Authorizer {
}

pub fn from_base64_snapshot(input: &str) -> Result<Self, error::Token> {
let bytes = base64::decode_config(input, base64::URL_SAFE)?;
let bytes = BASE64_URL_SAFE.decode(input)?;
Self::from_raw_snapshot(&bytes)
}

Expand Down Expand Up @@ -270,7 +271,7 @@ impl super::Authorizer {

pub fn to_base64_snapshot(&self) -> Result<String, error::Format> {
let snapshot_bytes = self.to_raw_snapshot()?;
Ok(base64::encode_config(snapshot_bytes, base64::URL_SAFE))
Ok(BASE64_URL_SAFE.encode(snapshot_bytes))
}
}

Expand Down
5 changes: 3 additions & 2 deletions biscuit-auth/src/token/builder/authorizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{
time::{Duration, SystemTime},
};

use base64::prelude::*;
use biscuit_parser::parser::parse_source;
use prost::Message;

Expand Down Expand Up @@ -635,7 +636,7 @@ impl AuthorizerBuilder {
}

pub fn from_base64_snapshot(input: &str) -> Result<Self, error::Token> {
let bytes = base64::decode_config(input, base64::URL_SAFE)?;
let bytes = BASE64_URL_SAFE.decode(input)?;
Self::from_raw_snapshot(&bytes)
}

Expand Down Expand Up @@ -696,6 +697,6 @@ impl AuthorizerBuilder {

pub fn to_base64_snapshot(&self) -> Result<String, error::Format> {
let snapshot_bytes = self.to_raw_snapshot()?;
Ok(base64::encode_config(snapshot_bytes, base64::URL_SAFE))
Ok(BASE64_URL_SAFE.encode(snapshot_bytes))
}
}
5 changes: 3 additions & 2 deletions biscuit-auth/src/token/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use std::fmt::Display;
use std::iter::once;

use base64::prelude::*;
use builder::{BiscuitBuilder, BlockBuilder};
use prost::Message;
use rand_core::{CryptoRng, RngCore};
Expand Down Expand Up @@ -142,7 +143,7 @@ impl Biscuit {
self.container
.to_vec()
.map_err(error::Token::Format)
.map(|v| base64::encode_config(v, base64::URL_SAFE))
.map(|v| BASE64_URL_SAFE.encode(v))
}

/// serializes the token
Expand Down Expand Up @@ -346,7 +347,7 @@ impl Biscuit {
T: AsRef<[u8]>,
KP: RootKeyProvider,
{
let decoded = base64::decode_config(slice, base64::URL_SAFE)?;
let decoded = BASE64_URL_SAFE.decode(slice)?;
Biscuit::from_with_symbols(&decoded, key_provider, symbols)
}

Expand Down
7 changes: 4 additions & 3 deletions biscuit-auth/src/token/third_party.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
use std::cmp::max;

use base64::prelude::*;
use prost::Message;

use crate::{
Expand Down Expand Up @@ -59,7 +60,7 @@ impl ThirdPartyRequest {
}

pub fn serialize_base64(&self) -> Result<String, error::Token> {
Ok(base64::encode_config(self.serialize()?, base64::URL_SAFE))
Ok(BASE64_URL_SAFE.encode(self.serialize()?))
}

pub fn deserialize(slice: &[u8]) -> Result<Self, error::Token> {
Expand Down Expand Up @@ -88,7 +89,7 @@ impl ThirdPartyRequest {
where
T: AsRef<[u8]>,
{
let decoded = base64::decode_config(slice, base64::URL_SAFE)?;
let decoded = BASE64_URL_SAFE.decode(slice)?;
Self::deserialize(&decoded)
}

Expand Down Expand Up @@ -149,7 +150,7 @@ impl ThirdPartyBlock {
}

pub fn serialize_base64(&self) -> Result<String, error::Token> {
Ok(base64::encode_config(self.serialize()?, base64::URL_SAFE))
Ok(BASE64_URL_SAFE.encode(self.serialize()?))
}
}

Expand Down
Loading