selinux/new_policy/
context.rs1use std::cmp::Ordering;
6
7pub use selinux_policy_derive::{Parse, Serialize, Validate};
8
9use super::error::{ParseError, SerializeError, ValidateError};
10use super::parser::PolicyCursor;
11use super::traits::{Parse, Serialize, Validate};
12use super::{CategoryId, CategorySet, RoleId, SensitivityId, TypeId, UserId};
13
14#[derive(Debug, Clone, PartialEq, Eq, Parse, Serialize, Validate)]
16pub struct MlsLevel {
17 sensitivity: SensitivityId,
18 categories: CategorySet,
19}
20
21impl MlsLevel {
22 pub fn new(sensitivity: SensitivityId, categories: CategorySet) -> Self {
24 Self { sensitivity, categories }
25 }
26
27 pub fn sensitivity(&self) -> SensitivityId {
29 self.sensitivity
30 }
31
32 pub fn categories(&self) -> &CategorySet {
34 &self.categories
35 }
36
37 pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_> {
39 self.categories.iter()
40 }
41
42 pub fn compare(&self, other: &Self) -> Option<Ordering> {
44 let s_order = self.sensitivity().cmp(&other.sensitivity());
45 let c_order = self.categories().compare(other.categories())?;
46 if s_order == c_order {
47 return Some(s_order);
48 } else if c_order == Ordering::Equal {
49 return Some(s_order);
50 } else if s_order == Ordering::Equal {
51 return Some(c_order);
52 }
53 None
54 }
55
56 pub fn dominates(&self, other: &Self) -> bool {
58 self.sensitivity() >= other.sensitivity()
59 && self.categories().is_superset(other.categories())
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct MlsRange {
66 low: MlsLevel,
67 high: Option<MlsLevel>,
68}
69
70impl Parse for MlsRange {
71 fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
72 let levels_count = u32::parse(cursor)?;
73 let sensitivity_low = SensitivityId::parse(cursor)?;
74
75 if levels_count > 1 {
77 let sensitivity_high = SensitivityId::parse(cursor)?;
78 let low_categories = CategorySet::parse(cursor)?;
79 let high_categories = CategorySet::parse(cursor)?;
80
81 Ok(Self {
82 low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
83 high: Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
84 })
85 } else {
86 let low_categories = CategorySet::parse(cursor)?;
87 Ok(Self {
88 low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
89 high: None,
90 })
91 }
92 }
93}
94
95impl Serialize for MlsRange {
96 fn serialize(&self, writer: &mut Vec<u8>) -> Result<(), SerializeError> {
97 if let Some(ref high) = self.high {
98 2u32.serialize(writer)?;
99 self.low.sensitivity.serialize(writer)?;
100 high.sensitivity.serialize(writer)?;
101 self.low.categories.serialize(writer)?;
102 high.categories.serialize(writer)?;
103 } else {
104 1u32.serialize(writer)?;
105 self.low.sensitivity.serialize(writer)?;
106 self.low.categories.serialize(writer)?;
107 }
108 Ok(())
109 }
110}
111
112impl Validate for MlsRange {
113 fn validate(&self, policy: &super::NewPolicy) -> Result<(), ValidateError> {
114 self.low.validate(policy)?;
115 if let Some(ref high) = self.high {
116 high.validate(policy)?;
117 if !high.dominates(&self.low) {
118 return Err(ValidateError::InvalidMlsRange);
119 }
120 }
121 Ok(())
122 }
123}
124
125impl MlsRange {
126 pub fn new(low: MlsLevel, high: Option<MlsLevel>) -> Self {
128 Self { low, high }
129 }
130
131 pub fn low(&self) -> &MlsLevel {
133 &self.low
134 }
135
136 pub fn high(&self) -> &Option<MlsLevel> {
138 &self.high
139 }
140}
141
142#[derive(Debug, Clone, PartialEq, Eq, Parse, Serialize, Validate)]
144pub struct Context {
145 user: UserId,
146 role: RoleId,
147 context_type: TypeId,
148 mls_range: MlsRange,
149}
150
151impl Context {
152 pub fn new(user: UserId, role: RoleId, context_type: TypeId, mls_range: MlsRange) -> Self {
154 Self { user, role, context_type, mls_range }
155 }
156
157 pub fn user_id(&self) -> UserId {
159 self.user
160 }
161
162 pub fn role_id(&self) -> RoleId {
164 self.role
165 }
166
167 pub fn type_id(&self) -> TypeId {
169 self.context_type
170 }
171
172 pub fn low_level(&self) -> &MlsLevel {
174 &self.mls_range.low
175 }
176
177 pub fn high_level(&self) -> &Option<MlsLevel> {
179 &self.mls_range.high
180 }
181}