1use std::num::NonZeroU16;
6
7use super::NewPolicy;
8use super::constraints::{Constraint, ConstraintTerm};
9use super::error::{ParseError, SerializeError, ValidateError};
10use super::id_type::IdType;
11use super::indexed::IdAndNameIndexed;
12use super::parser::{Array, PolicyCursor};
13use super::permissions::Permission;
14use super::traits::{Parse, PolicyId, Serialize, Validate};
15
16use selinux_policy_derive::{HasName, HasPolicyId, Parse, Serialize, Validate};
17
18#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
20pub struct ClassTag;
21
22pub type ClassId = IdType<NonZeroU16, ClassTag>;
24
25#[derive(Parse, Serialize)]
26struct BinaryClassMetadata {
27 key_length: u32,
28 common_key_length: u32,
29 id: u32,
30 permission_primary_names_count: u32,
32 permission_count: u32,
33 constraint_count: u32,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Parse, Serialize, Validate)]
38#[policy(wire_type = u32)]
39pub enum ClassDefault {
40 Unspecified = 0,
41 Source = 1,
42 Target = 2,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Parse, Serialize, Validate)]
47#[policy(wire_type = u32)]
48pub enum ClassDefaultRange {
49 Unspecified = 0,
50 SourceLow = 1,
51 SourceHigh = 2,
52 SourceLowHigh = 3,
53 TargetLow = 4,
54 TargetHigh = 5,
55 TargetLowHigh = 6,
56 UnknownUsedValue = 7,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Parse, Serialize, Validate)]
61pub struct ClassDefaults {
62 default_user: ClassDefault,
63 default_role: ClassDefault,
64 default_range: ClassDefaultRange,
65 default_type: ClassDefault,
66}
67
68impl ClassDefaults {
69 pub fn user(&self) -> ClassDefault {
70 self.default_user
71 }
72
73 pub fn role(&self) -> ClassDefault {
74 self.default_role
75 }
76
77 pub fn range(&self) -> ClassDefaultRange {
78 self.default_range
79 }
80
81 pub fn type_(&self) -> ClassDefault {
82 self.default_type
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, HasName, HasPolicyId)]
88pub struct Class {
89 id: ClassId,
90 name: Box<[u8]>,
91 common_name: Box<[u8]>,
92 permission_primary_names_count: u32,
94 permissions: IdAndNameIndexed<Box<[Permission]>>,
95 constraints: Box<[Constraint]>,
96 validate_transitions: Array<ConstraintTerm>,
97 defaults: ClassDefaults,
98}
99
100impl Class {
101 pub fn common_name(&self) -> &[u8] {
107 &self.common_name
108 }
109
110 pub fn permissions(&self) -> &IdAndNameIndexed<Box<[Permission]>> {
111 &self.permissions
112 }
113
114 pub fn constraints(&self) -> &[Constraint] {
115 &self.constraints
116 }
117
118 pub fn validate_transitions(&self) -> &[ConstraintTerm] {
119 &self.validate_transitions
120 }
121
122 pub fn defaults(&self) -> &ClassDefaults {
123 &self.defaults
124 }
125}
126
127impl Parse for Class {
128 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
129 let metadata = BinaryClassMetadata::parse(cursor)?;
130
131 let id_val = metadata.id;
132 let id = ClassId::from_u32(id_val).ok_or(ParseError::InvalidId { value: id_val })?;
133
134 let name_len = metadata.key_length as usize;
135 let name = Box::from(cursor.read_bytes(name_len)?);
136
137 let common_name_len = metadata.common_key_length as usize;
138 let common_name = Box::from(cursor.read_bytes(common_name_len)?);
139
140 let permissions_count = metadata.permission_count as usize;
141 let mut permissions = Vec::with_capacity(permissions_count);
142 for _ in 0..permissions_count {
143 permissions.push(Permission::parse(cursor)?);
144 }
145 let permissions = IdAndNameIndexed::new(permissions.into_boxed_slice());
146
147 let constraint_count = metadata.constraint_count as usize;
148 let mut constraints = Vec::with_capacity(constraint_count);
149 for _ in 0..constraint_count {
150 constraints.push(Constraint::parse(cursor)?);
151 }
152 let constraints = constraints.into_boxed_slice();
153
154 let validate_transitions = Array::<ConstraintTerm>::parse(cursor)?;
155 let defaults = ClassDefaults::parse(cursor)?;
156
157 Ok(Self {
158 id,
159 name,
160 common_name,
161 permission_primary_names_count: metadata.permission_primary_names_count,
162 permissions,
163 constraints,
164 validate_transitions,
165 defaults,
166 })
167 }
168}
169
170impl Serialize for Class {
171 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
172 let metadata = BinaryClassMetadata {
173 key_length: self.name.len() as u32,
174 common_key_length: self.common_name.len() as u32,
175 id: self.id.as_u32(),
176 permission_primary_names_count: self.permission_primary_names_count,
177 permission_count: self.permissions.len() as u32,
178 constraint_count: self.constraints.len() as u32,
179 };
180 metadata.serialize(writer)?;
181
182 writer.extend_from_slice(&self.name);
183 writer.extend_from_slice(&self.common_name);
184
185 for permission in self.permissions.iter() {
186 permission.serialize(writer)?;
187 }
188
189 for constraint in self.constraints.iter() {
190 constraint.serialize(writer)?;
191 }
192
193 self.validate_transitions.serialize(writer)?;
194 self.defaults.serialize(writer)?;
195 Ok(())
196 }
197}
198
199impl Validate for Class {
200 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
201 self.permissions.validate(policy)?;
202 for constraint in self.constraints.iter() {
203 constraint.validate(policy)?;
204 }
205 self.validate_transitions.validate(policy)?;
206 self.defaults.validate(policy)?;
207
208 let mut common_permissions_count = 0;
209 if !self.common_name.is_empty() {
210 let common_symbol =
211 policy.common_symbols().get_by_name(&self.common_name).ok_or_else(|| {
212 ValidateError::UndefinedCommonSymbol { name: self.common_name.to_vec() }
213 })?;
214 common_permissions_count = common_symbol.permissions().len();
215 }
216
217 let expected_at_most = self.permissions.len() + common_permissions_count;
218 if self.permission_primary_names_count > expected_at_most as u32 {
219 return Err(ValidateError::InvalidPrimaryNamesCount {
220 expected_at_most: expected_at_most as u32,
221 found: self.permission_primary_names_count,
222 });
223 }
224
225 Ok(())
226 }
227}
228
229#[cfg(test)]
230mod tests {
231 use super::super::traits::{HasName, HasPolicyId};
232 use super::{PolicyCursor, *};
233
234 #[test]
235 fn test_class_defaults_parse_and_serialize() {
236 let data = [
237 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, ];
242 let mut cursor = PolicyCursor::new(&data);
243 let defaults = ClassDefaults::parse(&mut cursor).unwrap();
244 assert_eq!(defaults.user(), ClassDefault::Source);
245 assert_eq!(defaults.role(), ClassDefault::Target);
246 assert_eq!(defaults.range(), ClassDefaultRange::TargetLowHigh);
247 assert_eq!(defaults.type_(), ClassDefault::Source);
248
249 let mut writer = Vec::new();
250 defaults.serialize(&mut writer).unwrap();
251 assert_eq!(writer, data);
252 }
253
254 #[test]
255 fn test_minimal_class_parse_and_serialize() {
256 let data = [
257 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268 ];
269 let mut cursor = PolicyCursor::new(&data);
270 let class = Class::parse(&mut cursor).unwrap();
271 assert_eq!(class.id(), ClassId::from_u32(1).unwrap());
272 assert_eq!(class.name(), b"test");
273 assert!(class.common_name().is_empty());
274 assert!(class.permissions().is_empty());
275 assert!(class.constraints().is_empty());
276 assert!(class.validate_transitions().is_empty());
277
278 let mut writer = Vec::new();
279 class.serialize(&mut writer).unwrap();
280 assert_eq!(writer, data);
281 }
282}