From 7d1297db03a4de1a8136582d241c7c988f58dc0f Mon Sep 17 00:00:00 2001 From: Clement Delafargue Date: Fri, 25 Oct 2024 15:18:50 +0200 Subject: [PATCH] ensure that FFI function names are only defined on FFI operations --- biscuit-auth/src/capi.rs | 2 - biscuit-auth/src/error.rs | 2 - biscuit-auth/src/format/convert.rs | 132 +++++++++++++++++------------ biscuit-auth/tests/capi.rs | 2 +- 4 files changed, 78 insertions(+), 60 deletions(-) diff --git a/biscuit-auth/src/capi.rs b/biscuit-auth/src/capi.rs index 43b376eb..3a80cbba 100644 --- a/biscuit-auth/src/capi.rs +++ b/biscuit-auth/src/capi.rs @@ -79,7 +79,6 @@ pub enum ErrorKind { FormatPublicKeyTableOverlap, FormatUnknownExternalKey, FormatUnknownSymbol, - FormatMissingFfiName, AppendOnSealed, LogicInvalidBlockRule, LogicUnauthorized, @@ -159,7 +158,6 @@ pub extern "C" fn error_kind() -> ErrorKind { ErrorKind::FormatUnknownExternalKey } Token::Format(Format::UnknownSymbol(_)) => ErrorKind::FormatUnknownSymbol, - Token::Format(Format::MissingFfiName) => ErrorKind::FormatMissingFfiName, Token::AppendOnSealed => ErrorKind::AppendOnSealed, Token::AlreadySealed => ErrorKind::AlreadySealed, Token::Language(_) => ErrorKind::LanguageError, diff --git a/biscuit-auth/src/error.rs b/biscuit-auth/src/error.rs index d5570ca9..5690e3eb 100644 --- a/biscuit-auth/src/error.rs +++ b/biscuit-auth/src/error.rs @@ -150,8 +150,6 @@ pub enum Format { UnknownExternalKey, #[error("the symbol id was not in the table")] UnknownSymbol(u64), - #[error("missing FFI name field")] - MissingFfiName, } /// Signature errors diff --git a/biscuit-auth/src/format/convert.rs b/biscuit-auth/src/format/convert.rs index 096396cc..75cc6087 100644 --- a/biscuit-auth/src/format/convert.rs +++ b/biscuit-auth/src/format/convert.rs @@ -678,63 +678,85 @@ pub mod v2 { use schema::{op, op_binary, op_unary}; 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) { - Some(op_unary::Kind::Negate) => Op::Unary(Unary::Negate), - Some(op_unary::Kind::Parens) => Op::Unary(Unary::Parens), - Some(op_unary::Kind::Length) => Op::Unary(Unary::Length), - Some(op_unary::Kind::TypeOf) => Op::Unary(Unary::TypeOf), - Some(op_unary::Kind::Ffi) => match u.ffi_name.as_ref() { - // todo clementd error if ffi name is defined with another kind - Some(n) => Op::Unary(Unary::Ffi(n.to_owned())), - None => return Err(error::Format::MissingFfiName), - }, - None => { - return Err(error::Format::DeserializationError( - "deserialization error: unary operation is empty".to_string(), - )) - } - }, - Some(op::Content::Binary(b)) => match op_binary::Kind::from_i32(b.kind) { - Some(op_binary::Kind::LessThan) => Op::Binary(Binary::LessThan), - Some(op_binary::Kind::GreaterThan) => Op::Binary(Binary::GreaterThan), - Some(op_binary::Kind::LessOrEqual) => Op::Binary(Binary::LessOrEqual), - Some(op_binary::Kind::GreaterOrEqual) => Op::Binary(Binary::GreaterOrEqual), - Some(op_binary::Kind::Equal) => Op::Binary(Binary::Equal), - Some(op_binary::Kind::Contains) => Op::Binary(Binary::Contains), - Some(op_binary::Kind::Prefix) => Op::Binary(Binary::Prefix), - Some(op_binary::Kind::Suffix) => Op::Binary(Binary::Suffix), - Some(op_binary::Kind::Regex) => Op::Binary(Binary::Regex), - Some(op_binary::Kind::Add) => Op::Binary(Binary::Add), - Some(op_binary::Kind::Sub) => Op::Binary(Binary::Sub), - Some(op_binary::Kind::Mul) => Op::Binary(Binary::Mul), - Some(op_binary::Kind::Div) => Op::Binary(Binary::Div), - Some(op_binary::Kind::And) => Op::Binary(Binary::And), - Some(op_binary::Kind::Or) => Op::Binary(Binary::Or), - Some(op_binary::Kind::Intersection) => Op::Binary(Binary::Intersection), - Some(op_binary::Kind::Union) => Op::Binary(Binary::Union), - Some(op_binary::Kind::BitwiseAnd) => Op::Binary(Binary::BitwiseAnd), - Some(op_binary::Kind::BitwiseOr) => Op::Binary(Binary::BitwiseOr), - Some(op_binary::Kind::BitwiseXor) => Op::Binary(Binary::BitwiseXor), - Some(op_binary::Kind::NotEqual) => Op::Binary(Binary::NotEqual), - Some(op_binary::Kind::HeterogeneousEqual) => Op::Binary(Binary::HeterogeneousEqual), - Some(op_binary::Kind::HeterogeneousNotEqual) => { - Op::Binary(Binary::HeterogeneousNotEqual) + 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.to_owned())), + (Some(op_unary::Kind::Ffi), None) => { + return Err(error::Format::DeserializationError( + "deserialization error: missing ffi name".to_string(), + )) + } + (Some(_), Some(_)) => { + return Err(error::Format::DeserializationError( + "deserialization error: ffi name set on a regular unary operation" + .to_string(), + )) + } + (None, _) => { + return Err(error::Format::DeserializationError( + "deserialization error: unary operation is empty".to_string(), + )) + } } - Some(op_binary::Kind::LazyAnd) => Op::Binary(Binary::LazyAnd), - Some(op_binary::Kind::LazyOr) => Op::Binary(Binary::LazyOr), - Some(op_binary::Kind::All) => Op::Binary(Binary::All), - Some(op_binary::Kind::Any) => Op::Binary(Binary::Any), - Some(op_binary::Kind::Ffi) => match b.ffi_name.as_ref() { - // todo clementd error if ffi name is defined with another kind - Some(n) => Op::Binary(Binary::Ffi(n.to_owned())), - None => return Err(error::Format::MissingFfiName), - }, - None => { - return Err(error::Format::DeserializationError( - "deserialization error: binary operation is empty".to_string(), - )) + } + 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) => { + Op::Binary(Binary::HeterogeneousEqual) + } + (Some(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::Ffi), Some(n)) => Op::Binary(Binary::Ffi(n.to_owned())), + (Some(op_binary::Kind::Ffi), None) => { + return Err(error::Format::DeserializationError( + "deserialization error: missing ffi name".to_string(), + )) + } + (Some(_), Some(_)) => { + return Err(error::Format::DeserializationError( + "deserialization error: ffi name set on a regular binary operation" + .to_string(), + )) + } + (None, _) => { + return Err(error::Format::DeserializationError( + "deserialization error: binary operation is empty".to_string(), + )) + } } - }, + } Some(op::Content::Closure(op_closure)) => Op::Closure( op_closure.params.clone(), op_closure diff --git a/biscuit-auth/tests/capi.rs b/biscuit-auth/tests/capi.rs index bad297da..9d0a1c61 100644 --- a/biscuit-auth/tests/capi.rs +++ b/biscuit-auth/tests/capi.rs @@ -104,7 +104,7 @@ biscuit append error? (null) authorizer creation error? (null) authorizer add check error? (null) authorizer add policy error? (null) -authorizer error(code = 22): authorization failed +authorizer error(code = 21): authorization failed failed checks (2): Authorizer check 0: check if right("efgh") Block 1, check 0: check if operation("read")