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
229impl Validate for ClassId {
230 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
231 policy
232 .classes()
233 .get_by_id(*self)
234 .map(|_| ())
235 .ok_or_else(|| ValidateError::UnknownId { kind: "class", id: self.as_u32() })
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::super::traits::{HasName, HasPolicyId};
242 use super::{PolicyCursor, *};
243
244 #[test]
245 fn test_class_defaults_parse_and_serialize() {
246 let data = [
247 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, ];
252 let mut cursor = PolicyCursor::new(&data);
253 let defaults = ClassDefaults::parse(&mut cursor).unwrap();
254 assert_eq!(defaults.user(), ClassDefault::Source);
255 assert_eq!(defaults.role(), ClassDefault::Target);
256 assert_eq!(defaults.range(), ClassDefaultRange::TargetLowHigh);
257 assert_eq!(defaults.type_(), ClassDefault::Source);
258
259 let mut writer = Vec::new();
260 defaults.serialize(&mut writer).unwrap();
261 assert_eq!(writer, data);
262 }
263
264 #[test]
265 fn test_minimal_class_parse_and_serialize() {
266 let data = [
267 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,
278 ];
279 let mut cursor = PolicyCursor::new(&data);
280 let class = Class::parse(&mut cursor).unwrap();
281 assert_eq!(class.id(), ClassId::from_u32(1).unwrap());
282 assert_eq!(class.name(), b"test");
283 assert!(class.common_name().is_empty());
284 assert!(class.permissions().is_empty());
285 assert!(class.constraints().is_empty());
286 assert!(class.validate_transitions().is_empty());
287
288 let mut writer = Vec::new();
289 class.serialize(&mut writer).unwrap();
290 assert_eq!(writer, data);
291 }
292}