fapolicy_rules/parser/
rule.rs1use nom::character::complete::space0;
10use nom::character::complete::space1;
11use nom::sequence::terminated;
12
13use crate::parser::parse::{end_of_rule, subject_object_parts, StrTrace, TraceResult};
14use crate::parser::{decision, permission};
15use crate::Rule;
16
17pub fn parse(i: StrTrace) -> TraceResult<Rule> {
18 match nom::combinator::complete(nom::sequence::tuple((
19 terminated(decision::parse, space1),
20 terminated(permission::parse, space0),
21 subject_object_parts,
22 end_of_rule,
23 )))(i)
24 {
25 Ok((remaining_input, (dec, perm, so, _))) => Ok((
26 remaining_input,
27 Rule {
28 subj: so.subject,
29 perm,
30 obj: so.object,
31 dec,
32 },
33 )),
34 Err(e) => Err(e),
35 }
36}
37
38pub fn parse_with_error_message(i: StrTrace) -> Result<Rule, String> {
39 match parse(i) {
40 Ok((_, r)) => Ok(r),
41 Err(nom::Err::Error(e)) => Err(e.to_string()),
42 _ => Err("Unrecognized error".to_string()),
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use crate::{Decision, ObjPart, Object, Permission, Rvalue, SubjPart, Subject};
49
50 use super::*;
51
52 #[test]
54 fn bad_rules() {
55 parse("deny_audit perm=open all : foo".into())
56 .err()
57 .unwrap();
58 parse("deny_audit perm=open all trust=foo : all".into())
59 .err()
60 .unwrap();
61
62 parse("deny_audit perm=open all : all trust=1 foo".into())
63 .err()
64 .unwrap();
65
66 parse("deny_audit perm=open all : all trust=foo".into())
67 .err()
68 .unwrap();
69 }
70
71 #[test]
72 fn parse_rule() {
73 let (rem, r) = parse("deny_audit perm=any pattern=ld_so : all".into())
74 .ok()
75 .unwrap();
76 assert_eq!(Decision::DenyAudit, r.dec);
77 assert_eq!(Permission::Any, r.perm);
78 assert_eq!(Subject::from(SubjPart::Pattern("ld_so".into())), r.subj);
79 assert_eq!(Object::from(ObjPart::All), r.obj);
80 assert!(rem.is_empty());
81
82 let (rem, r) = parse("deny_audit perm=any all : all".into()).ok().unwrap();
83 assert_eq!(Decision::DenyAudit, r.dec);
84 assert_eq!(Permission::Any, r.perm);
85 assert_eq!(Subject::from(SubjPart::All), r.subj);
86 assert_eq!(Object::from(ObjPart::All), r.obj);
87 assert!(rem.is_empty());
88
89 let (rem, r) = parse("deny_audit perm=open all : device=/dev/cdrom".into())
90 .ok()
91 .unwrap();
92 assert_eq!(Decision::DenyAudit, r.dec);
93 assert_eq!(Permission::Open, r.perm);
94 assert_eq!(Subject::from(SubjPart::All), r.subj);
95 assert_eq!(Object::from(ObjPart::Device("/dev/cdrom".into())), r.obj);
96 assert!(rem.is_empty());
97
98 let (rem, r) = parse("deny_audit perm=open exe=/usr/bin/ssh : dir=/opt".into())
99 .ok()
100 .unwrap();
101 assert_eq!(Decision::DenyAudit, r.dec);
102 assert_eq!(Permission::Open, r.perm);
103 assert_eq!(Subject::from(SubjPart::Exe("/usr/bin/ssh".into())), r.subj);
104 assert_eq!(Object::from(ObjPart::Dir("/opt".into())), r.obj);
105 assert!(rem.is_empty());
106
107 let (rem, r) = parse("deny_audit perm=any all : ftype=application/x-bad-elf".into())
108 .ok()
109 .unwrap();
110 assert_eq!(Decision::DenyAudit, r.dec);
111 assert_eq!(Permission::Any, r.perm);
112 assert_eq!(Subject::from(SubjPart::All), r.subj);
113 assert_eq!(
114 Object::from(ObjPart::FileType(Rvalue::Literal(
115 "application/x-bad-elf".into()
116 ))),
117 r.obj
118 );
119 assert!(rem.is_empty());
120 }
121}