1use super::bitmap::IdSet;
6use super::error::{ParseError, SerializeError, ValidateError};
7use super::id_type::IdType;
8use super::parser::PolicyCursor;
9use super::traits::{Parse, PolicyId, Serialize, Validate};
10use super::{ClassId, NewPolicy, TypeId, TypeSet};
11
12use selinux_policy_derive::{HasName, HasPolicyId, Parse, Serialize, Validate};
13
14#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
16pub struct RoleTag;
17
18pub type RoleId = IdType<std::num::NonZeroU16, RoleTag>;
20
21pub type RoleSet = IdSet<RoleId>;
23
24#[derive(Parse, Serialize)]
25struct BinaryRoleMetadata {
26 key_length: u32,
27 id: u32,
28 bounds: u32,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Validate, HasName, HasPolicyId)]
33pub struct Role {
34 id: RoleId,
35 name: Box<[u8]>,
36 bounds: Option<RoleId>,
37 dominates: RoleSet,
38 types: TypeSet,
39}
40
41impl Role {
42 pub fn bounds(&self) -> Option<RoleId> {
43 self.bounds
44 }
45
46 pub fn dominates(&self) -> &RoleSet {
47 &self.dominates
48 }
49
50 pub fn types(&self) -> &TypeSet {
51 &self.types
52 }
53}
54
55impl Parse for Role {
56 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
57 let metadata = BinaryRoleMetadata::parse(cursor)?;
58 let name = Box::from(cursor.read_bytes(metadata.key_length as usize)?);
59 let dominates = RoleSet::parse(cursor)?;
60 let types = TypeSet::parse(cursor)?;
61
62 let bounds = RoleId::from_u32(metadata.bounds);
63 let id =
64 RoleId::from_u32(metadata.id).ok_or(ParseError::InvalidId { value: metadata.id })?;
65
66 Ok(Self { id, name, bounds, dominates, types })
67 }
68}
69
70impl Serialize for Role {
71 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
72 let metadata = BinaryRoleMetadata {
73 key_length: self.name.len() as u32,
74 id: self.id.as_u32(),
75 bounds: self.bounds.map_or(0, |id| id.as_u32()),
76 };
77 metadata.serialize(writer)?;
78 writer.extend_from_slice(&self.name);
79 self.dominates.serialize(writer)?;
80 self.types.serialize(writer)?;
81 Ok(())
82 }
83}
84impl Validate for RoleId {
85 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
86 policy
87 .roles()
88 .get_by_id(*self)
89 .map(|_| ())
90 .ok_or_else(|| ValidateError::UnknownId { kind: "role", id: self.as_u32() })
91 }
92}
93
94#[derive(Clone, Debug, PartialEq, Eq, Parse, Serialize, Validate)]
96pub struct RoleTransition {
97 current_role: RoleId,
98 type_: TypeId,
99 new_role: RoleId,
100 class: ClassId,
101}
102
103impl RoleTransition {
104 pub fn current_role(&self) -> RoleId {
105 self.current_role
106 }
107
108 pub fn type_(&self) -> TypeId {
109 self.type_
110 }
111
112 pub fn new_role(&self) -> RoleId {
113 self.new_role
114 }
115
116 pub fn class(&self) -> ClassId {
117 self.class
118 }
119}
120
121#[derive(Clone, Debug, PartialEq, Eq, Parse, Serialize, Validate)]
123pub struct RoleAllow {
124 source_role: RoleId,
125 new_role: RoleId,
126}
127
128impl RoleAllow {
129 pub fn source_role(&self) -> RoleId {
130 self.source_role
131 }
132
133 pub fn new_role(&self) -> RoleId {
134 self.new_role
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use crate::new_policy::traits::{HasName, HasPolicyId, PolicyId};
142
143 #[test]
144 fn test_role_parse_and_serialize() {
145 let data = [
146 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, b't', b'e', b's', b't', 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];
160 let mut cursor = PolicyCursor::new(&data);
161 let role = Role::parse(&mut cursor).unwrap();
162 assert_eq!(role.id(), RoleId::from_u32(1).unwrap());
163 assert_eq!(role.name(), b"test");
164 assert!(role.bounds().is_none());
165 let mut writer = Vec::new();
168 role.serialize(&mut writer).unwrap();
169 assert_eq!(writer, data);
170 }
171
172 #[test]
173 fn test_role_transition_parse_and_serialize() {
174 let data = [
175 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, ];
180 let mut cursor = PolicyCursor::new(&data);
181 let trans = RoleTransition::parse(&mut cursor).unwrap();
182 assert_eq!(trans.current_role(), RoleId::from_u32(1).unwrap());
183 assert_eq!(trans.type_(), TypeId::from_u32(2).unwrap());
184 assert_eq!(trans.new_role(), RoleId::from_u32(3).unwrap());
185 assert_eq!(trans.class(), ClassId::from_u32(4).unwrap());
186
187 let mut writer = Vec::new();
188 trans.serialize(&mut writer).unwrap();
189 assert_eq!(writer, data);
190 }
191
192 #[test]
193 fn test_role_allow_parse_and_serialize() {
194 let data = [
195 1, 0, 0, 0, 2, 0, 0, 0, ];
198 let mut cursor = PolicyCursor::new(&data);
199 let allow = RoleAllow::parse(&mut cursor).unwrap();
200 assert_eq!(allow.source_role(), RoleId::from_u32(1).unwrap());
201 assert_eq!(allow.new_role(), RoleId::from_u32(2).unwrap());
202
203 let mut writer = Vec::new();
204 allow.serialize(&mut writer).unwrap();
205 assert_eq!(writer, data);
206 }
207
208 #[test]
209 fn test_role_policy_elements() {
210 let policy_bytes =
211 include_bytes!("../../testdata/composite_policies/compiled/role_transition_policy");
212 let new_policy = NewPolicy::parse(policy_bytes).expect("parse role_transition policy");
213 new_policy.validate().expect("validate role_transition policy");
214
215 assert_eq!(new_policy.role_transitions().len(), 2);
216 assert_eq!(new_policy.role_allowlist().len(), 1);
217 }
218}