//! The ledger raises a session's state by the stricter of the grant's label and the result's own //! (M5a spec, section 8). `memoryd` can make a `recall` result untrusted; if the session did not //! follow, a clean session could recall a tainted note and then write it into `memory.md`. Do not //! edit. #[path = "support/build.rs"] mod build; #[path = "support/rig.rs"] mod rig; #[path = "support/sink.rs"] mod sink; #[path = "support/tmp.rs"] mod tmp; use brokerd::ledger::Call; use brokerd::policy::{Label, SessionState}; use build::now; use bxcore::{AuditEvent, CallId, DataClass, SessionId, ToolResponse}; use rig::Rig; fn label(class: DataClass, untrusted: bool) -> Label { Label { class, untrusted } } fn call(label: Label) -> Call { Call { session: SessionId::new("s1").unwrap(), call: CallId(1), decision: 0, label, } } fn result(label: Label) -> ToolResponse { ToolResponse::Result { content: "[1] memory-tainted ยท note".to_string(), class: label.class, untrusted: label.untrusted, truncated: false, } } fn state(rig: &Rig) -> SessionState { rig.state().read(&SessionId::new("s1").unwrap()).unwrap() } /// The one result record's (class, untrusted, taint_after). fn recorded(rig: &Rig) -> (DataClass, bool, DataClass) { match rig.events().as_slice() { [ AuditEvent::Result { class, untrusted, taint_after, .. }, ] => (*class, *untrusted, *taint_after), other => panic!("{other:?}"), } } #[test] fn a_recall_of_a_tainted_note_makes_a_clean_session_untrusted() { let rig = Rig::new("label-recall"); let ledger = rig.ledger(); // `recall`'s built-in grant labels its results private and trusted; `memoryd` found a // `memory-tainted` hit and said untrusted. let found = label(DataClass::Private, true); let answer = ledger.finish( &call(label(DataClass::Private, false)), result(found), now(), ); assert_eq!(answer, result(found), "passed on unchanged"); assert_eq!( state(&rig), SessionState { taint: DataClass::Private, untrusted: true } ); assert_eq!( recorded(&rig), (DataClass::Private, true, DataClass::Private) ); } #[test] fn a_result_of_a_higher_class_than_its_grant_raises_the_taint() { let rig = Rig::new("label-class"); let ledger = rig.ledger(); let found = label(DataClass::Secret, false); ledger.finish(&call(label(DataClass::Public, false)), result(found), now()); assert_eq!( state(&rig), SessionState { taint: DataClass::Secret, untrusted: false } ); assert_eq!( recorded(&rig), (DataClass::Secret, false, DataClass::Secret) ); } #[test] fn a_result_laxer_than_its_grant_still_raises_the_state_by_the_grant() { let rig = Rig::new("label-laxer"); let ledger = rig.ledger(); ledger.finish( &call(label(DataClass::Secret, true)), result(label(DataClass::Public, false)), now(), ); assert_eq!( state(&rig), SessionState { taint: DataClass::Secret, untrusted: true } ); }