1use std::num::NonZeroU16;
6
7use selinux_policy_derive::{HasName, HasPolicyId, Parse, Serialize, Validate};
8
9use super::NewPolicy;
10use super::constraints::{Constraint, ConstraintTerm};
11use super::error::{ParseError, SerializeError, ValidateError};
12use super::id_type::IdType;
13use super::indexed::IdAndNameIndexed;
14use super::parser::{Array, PolicyCursor, PolicyWriter};
15use super::permissions::Permission;
16use super::traits::{Parse, PolicyId, Serialize, Validate};
17
18#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
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, 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, 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 #[cfg(test)]
119 pub fn validate_transitions(&self) -> &[ConstraintTerm] {
120 &self.validate_transitions
121 }
122
123 pub fn defaults(&self) -> &ClassDefaults {
124 &self.defaults
125 }
126}
127
128impl Parse for Class {
129 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
130 let metadata = BinaryClassMetadata::parse(cursor)?;
131
132 let id_val = metadata.id;
133 let id = ClassId::from_u32(id_val).ok_or(ParseError::InvalidId { value: id_val })?;
134
135 let name_len = metadata.key_length as usize;
136 let name = Box::from(cursor.read_bytes(name_len)?);
137
138 let common_name_len = metadata.common_key_length as usize;
139 let common_name = Box::from(cursor.read_bytes(common_name_len)?);
140
141 let permissions_count = metadata.permission_count as usize;
142 let mut permissions = Vec::with_capacity(permissions_count);
143 for _ in 0..permissions_count {
144 permissions.push(Permission::parse(cursor)?);
145 }
146 let permissions = IdAndNameIndexed::new(permissions.into_boxed_slice())?;
147
148 let constraint_count = metadata.constraint_count as usize;
149 let mut constraints = Vec::with_capacity(constraint_count);
150 for _ in 0..constraint_count {
151 constraints.push(Constraint::parse(cursor)?);
152 }
153 let constraints = constraints.into_boxed_slice();
154
155 let validate_transitions = Array::<ConstraintTerm>::parse(cursor)?;
156 let defaults = ClassDefaults::parse(cursor)?;
157
158 Ok(Self {
159 id,
160 name,
161 common_name,
162 permission_primary_names_count: metadata.permission_primary_names_count,
163 permissions,
164 constraints,
165 validate_transitions,
166 defaults,
167 })
168 }
169}
170
171impl Serialize for Class {
172 fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
173 let metadata = BinaryClassMetadata {
174 key_length: self.name.len() as u32,
175 common_key_length: self.common_name.len() as u32,
176 id: self.id.as_u32(),
177 permission_primary_names_count: self.permission_primary_names_count,
178 permission_count: self.permissions.len() as u32,
179 constraint_count: self.constraints.len() as u32,
180 };
181 metadata.serialize(writer)?;
182
183 writer.write_bytes(&self.name);
184 writer.write_bytes(&self.common_name);
185
186 self.permissions.serialize(writer)?;
187 self.constraints.serialize(writer)?;
188 self.validate_transitions.serialize(writer)?;
189 self.defaults.serialize(writer)?;
190 Ok(())
191 }
192}
193
194impl Validate for Class {
195 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
196 self.permissions.validate(policy)?;
197 self.constraints.validate(policy)?;
198 self.validate_transitions.validate(policy)?;
199 self.defaults.validate(policy)?;
200
201 let mut common_permissions_count = 0;
202 if !self.common_name.is_empty() {
203 let common_symbol =
204 policy.common_symbols().get_by_name(&self.common_name).ok_or_else(|| {
205 ValidateError::UndefinedCommonSymbol { name: self.common_name.as_ref().into() }
206 })?;
207 common_permissions_count = common_symbol.permissions().len();
208 }
209
210 let expected_at_most = self.permissions.len() + common_permissions_count;
211 if self.permission_primary_names_count > expected_at_most as u32 {
212 return Err(ValidateError::InvalidPrimaryNamesCount {
213 expected_at_most: expected_at_most as u32,
214 found: self.permission_primary_names_count,
215 });
216 }
217
218 Ok(())
219 }
220}
221
222impl Validate for ClassId {
223 fn validate(&self, policy: &NewPolicy) -> Result<(), ValidateError> {
224 policy
225 .classes()
226 .get_by_id(*self)
227 .map(|_| ())
228 .ok_or_else(|| ValidateError::UnknownId { kind: "class", id: self.as_u32() })
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::{PolicyCursor, *};
235 use crate::new_policy::metadata::PolicyVersion;
236 use crate::new_policy::parser::PolicyWriter;
237 use crate::new_policy::traits::{HasName, HasPolicyId};
238
239 #[test]
240 fn test_class_defaults_parse_and_serialize() {
241 let data = [
242 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, ];
247 let mut cursor = PolicyCursor::new(&data);
248 let defaults = ClassDefaults::parse(&mut cursor).unwrap();
249 assert_eq!(defaults.user(), ClassDefault::Source);
250 assert_eq!(defaults.role(), ClassDefault::Target);
251 assert_eq!(defaults.range(), ClassDefaultRange::TargetLowHigh);
252 assert_eq!(defaults.type_(), ClassDefault::Source);
253
254 let mut writer = Vec::new();
255 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
256 defaults.serialize(&mut policy_writer).unwrap();
257 assert_eq!(writer, data);
258 }
259
260 #[test]
261 fn test_minimal_class_parse_and_serialize() {
262 let data = [
263 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,
274 ];
275 let mut cursor = PolicyCursor::new(&data);
276 let class = Class::parse(&mut cursor).unwrap();
277 assert_eq!(class.id(), ClassId::from_u32(1).unwrap());
278 assert_eq!(class.name(), b"test");
279 assert!(class.common_name().is_empty());
280 assert!(class.permissions().is_empty());
281 assert!(class.constraints().is_empty());
282 assert!(class.validate_transitions().is_empty());
283
284 let mut writer = Vec::new();
285 let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
286 class.serialize(&mut policy_writer).unwrap();
287 assert_eq!(writer, data);
288 }
289}