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::{NewPolicy, TypeSet};
11
12use selinux_policy_derive::{HasName, HasPolicyId, Parse, Serialize, Validate};
13
14#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
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#[cfg(test)]
95mod tests {
96 use super::*;
97 use crate::new_policy::traits::{HasName, HasPolicyId};
98
99 #[test]
100 fn test_role_parse_and_serialize() {
101 let data = [
102 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, ];
116 let mut cursor = PolicyCursor::new(&data);
117 let role = Role::parse(&mut cursor).unwrap();
118 assert_eq!(role.id(), RoleId::from_u32(1).unwrap());
119 assert_eq!(role.name(), b"test");
120 assert!(role.bounds().is_none());
121 let mut writer = Vec::new();
124 role.serialize(&mut writer).unwrap();
125 assert_eq!(writer, data);
126 }
127}