1use crate::policy::arrays::Context;
6use crate::policy::extensible_bitmap::ExtensibleBitmapSpan;
7use crate::policy::index::PolicyIndex;
8use crate::policy::symbols::MlsLevel;
9use crate::policy::{CategoryId, ParsedPolicy, RoleId, SensitivityId, TypeId, UserId};
10
11use crate::NullessByteStr;
12use bstr::BString;
13use std::cell::RefCell;
14use std::cmp::Ordering;
15use std::num::NonZeroU32;
16use std::slice::Iter;
17use thiserror::Error;
18
19#[derive(Clone, Debug, Eq, PartialEq)]
26pub struct SecurityContext {
27 user: UserId,
29 role: RoleId,
31 type_: TypeId,
33 low_level: SecurityLevel,
35 high_level: Option<SecurityLevel>,
37}
38
39impl SecurityContext {
40 pub(crate) fn new(
44 user: UserId,
45 role: RoleId,
46 type_: TypeId,
47 low_level: SecurityLevel,
48 high_level: Option<SecurityLevel>,
49 ) -> Self {
50 Self { user, role, type_, low_level, high_level }
51 }
52
53 pub(super) fn new_from_policy_context(context: &Context) -> SecurityContext {
55 let low_level = SecurityLevel::new_from_mls_level(context.low_level());
56 let high_level =
57 context.high_level().as_ref().map(|x| SecurityLevel::new_from_mls_level(x));
58
59 SecurityContext::new(
60 context.user_id(),
61 context.role_id(),
62 context.type_id(),
63 low_level,
64 high_level,
65 )
66 }
67
68 pub fn user(&self) -> UserId {
70 self.user
71 }
72
73 pub fn role(&self) -> RoleId {
75 self.role
76 }
77
78 pub fn type_(&self) -> TypeId {
80 self.type_
81 }
82
83 pub fn low_level(&self) -> &SecurityLevel {
85 &self.low_level
86 }
87
88 pub fn high_level(&self) -> Option<&SecurityLevel> {
90 self.high_level.as_ref()
91 }
92
93 pub fn effective_high_level(&self) -> &SecurityLevel {
96 self.high_level().map_or(&self.low_level, |x| x)
97 }
98
99 pub(super) fn parse(
128 policy_index: &PolicyIndex,
129 security_context: NullessByteStr<'_>,
130 ) -> Result<Self, SecurityContextError> {
131 let as_str = std::str::from_utf8(security_context.as_bytes())
132 .map_err(|_| SecurityContextError::InvalidSyntax)?;
133
134 let mut items = as_str.splitn(4, ":");
136 let user = items.next().ok_or(SecurityContextError::InvalidSyntax)?;
137 let role = items.next().ok_or(SecurityContextError::InvalidSyntax)?;
138 let type_ = items.next().ok_or(SecurityContextError::InvalidSyntax)?;
139
140 let mut levels = items.next().ok_or(SecurityContextError::InvalidSyntax)?.split("-");
142 let low_level = levels.next().ok_or(SecurityContextError::InvalidSyntax)?;
143 if low_level.is_empty() {
144 return Err(SecurityContextError::InvalidSyntax);
145 }
146 let high_level = levels.next();
147 if let Some(high_level) = high_level {
148 if high_level.is_empty() {
149 return Err(SecurityContextError::InvalidSyntax);
150 }
151 }
152 if levels.next() != None {
153 return Err(SecurityContextError::InvalidSyntax);
154 }
155
156 let user = policy_index
158 .parsed_policy()
159 .user_by_name(user)
160 .ok_or_else(|| SecurityContextError::UnknownUser { name: user.into() })?
161 .id();
162 let role = policy_index
163 .parsed_policy()
164 .role_by_name(role)
165 .ok_or_else(|| SecurityContextError::UnknownRole { name: role.into() })?
166 .id();
167 let type_ = policy_index
168 .parsed_policy()
169 .type_by_name(type_)
170 .ok_or_else(|| SecurityContextError::UnknownType { name: type_.into() })?
171 .id();
172
173 let low_level = SecurityLevel::parse(policy_index, low_level)?;
174 let high_level = high_level.map(|x| SecurityLevel::parse(policy_index, x)).transpose()?;
175
176 Ok(Self::new(user, role, type_, low_level, high_level))
177 }
178
179 pub(super) fn serialize(&self, policy_index: &PolicyIndex) -> Vec<u8> {
181 let mut levels = self.low_level.serialize(policy_index.parsed_policy());
182 if let Some(high_level) = &self.high_level {
183 levels.push(b'-');
184 levels.extend(high_level.serialize(policy_index.parsed_policy()));
185 }
186 let parts: [&[u8]; 4] = [
187 policy_index.parsed_policy().user(self.user).name_bytes(),
188 policy_index.parsed_policy().role(self.role).name_bytes(),
189 policy_index.parsed_policy().type_(self.type_).name_bytes(),
190 levels.as_slice(),
191 ];
192 parts.join(b":".as_ref())
193 }
194
195 pub(super) fn validate(&self, policy_index: &PolicyIndex) -> Result<(), SecurityContextError> {
198 let user = policy_index.parsed_policy().user(self.user);
199
200 if self.role != policy_index.object_role() {
203 if !user.roles().is_set(self.role.0.get() - 1) {
207 return Err(SecurityContextError::InvalidRoleForUser {
208 role: policy_index.parsed_policy().role(self.role).name_bytes().into(),
209 user: user.name_bytes().into(),
210 });
211 }
212
213 let role = policy_index.parsed_policy().role(self.role);
215 if !role.types().is_set(self.type_.0.get() - 1) {
217 return Err(SecurityContextError::InvalidTypeForRole {
218 type_: policy_index.parsed_policy().type_(self.type_).name_bytes().into(),
219 role: role.name_bytes().into(),
220 });
221 }
222 }
223
224 let valid_low = user.mls_range().low();
227 let valid_high = user.mls_range().high().as_ref().unwrap_or(valid_low);
228
229 if !(self.low_level.dominates(valid_low) && valid_high.dominates(&self.low_level)) {
231 return Err(SecurityContextError::InvalidLevelForUser {
232 level: self.low_level.serialize(policy_index.parsed_policy()).into(),
233 user: user.name_bytes().into(),
234 });
235 }
236 if let Some(ref high_level) = self.high_level {
237 if !(valid_high.dominates(high_level) && high_level.dominates(valid_low)) {
239 return Err(SecurityContextError::InvalidLevelForUser {
240 level: high_level.serialize(policy_index.parsed_policy()).into(),
241 user: user.name_bytes().into(),
242 });
243 }
244
245 if !(high_level).dominates(&self.low_level) {
248 return Err(SecurityContextError::InvalidSecurityRange {
249 low: self.low_level.serialize(policy_index.parsed_policy()).into(),
250 high: high_level.serialize(policy_index.parsed_policy()).into(),
251 });
252 }
253 }
254 Ok(())
255 }
256}
257
258#[derive(Clone, Debug, Eq, PartialEq)]
261pub struct SecurityLevel {
262 sensitivity: SensitivityId,
263 categories: Vec<CategorySpan>,
264}
265
266impl SecurityLevel {
267 pub(super) fn new(sensitivity: SensitivityId, categories: Vec<CategorySpan>) -> Self {
268 Self { sensitivity, categories }
269 }
270
271 pub(super) fn new_from_mls_level(level: &MlsLevel) -> SecurityLevel {
274 SecurityLevel::new(
275 level.sensitivity(),
276 level.category_spans().map(|span| span.into()).collect(),
277 )
278 }
279
280 fn parse(policy_index: &PolicyIndex, level: &str) -> Result<Self, SecurityContextError> {
282 if level.is_empty() {
283 return Err(SecurityContextError::InvalidSyntax);
284 }
285
286 let mut items = level.split(":");
288 let sensitivity = items.next().ok_or(SecurityContextError::InvalidSyntax)?;
289 let categories_item = items.next();
290 if items.next() != None {
291 return Err(SecurityContextError::InvalidSyntax);
292 }
293
294 let sensitivity = policy_index
296 .parsed_policy()
297 .sensitivity_by_name(sensitivity)
298 .ok_or_else(|| SecurityContextError::UnknownSensitivity { name: sensitivity.into() })?
299 .id();
300 let mut categories = Vec::new();
301 if let Some(categories_str) = categories_item {
302 for entry in categories_str.split(",") {
303 let category = if let Some((low, high)) = entry.split_once(".") {
304 let low = Self::category_id_by_name(policy_index, low)?;
305 let high = Self::category_id_by_name(policy_index, high)?;
306 if high <= low {
307 return Err(SecurityContextError::InvalidSyntax);
308 }
309 CategorySpan::new(low, high)
310 } else {
311 let id = Self::category_id_by_name(policy_index, entry)?;
312 CategorySpan::new(id, id)
313 };
314 categories.push(category);
315 }
316 }
317 if categories.is_empty() {
318 return Ok(Self { sensitivity, categories });
319 }
320 categories.sort_by(|x, y| (x.low, x.high).cmp(&(y.low, y.high)));
326 let categories = categories.into_iter();
328 let normalized =
329 categories.fold(vec![], |mut normalized: Vec<CategorySpan>, current: CategorySpan| {
330 if let Some(last) = normalized.last_mut() {
331 if current.low <= last.high
332 || (u32::from(current.low.0) - u32::from(last.high.0) == 1)
333 {
334 *last = CategorySpan::new(last.low, current.high)
335 } else {
336 normalized.push(current);
337 }
338 return normalized;
339 }
340 normalized.push(current);
341 normalized
342 });
343
344 Ok(Self { sensitivity, categories: normalized })
345 }
346
347 fn category_id_by_name(
348 policy_index: &PolicyIndex,
349 name: &str,
350 ) -> Result<CategoryId, SecurityContextError> {
351 Ok(policy_index
352 .parsed_policy()
353 .category_by_name(name)
354 .ok_or_else(|| SecurityContextError::UnknownCategory { name: name.into() })?
355 .id())
356 }
357}
358
359pub trait Level<'a, T: Into<CategorySpan> + Clone, IterT: 'a + Iterator<Item = T>> {
362 fn sensitivity(&self) -> SensitivityId;
364
365 fn category_spans(&'a self) -> CategoryIterator<T, IterT>;
367
368 fn serialize(&'a self, parsed_policy: &ParsedPolicy) -> Vec<u8> {
371 let sensitivity = parsed_policy.sensitivity(self.sensitivity()).name_bytes();
372 let categories = self
373 .category_spans()
374 .map(|x| x.serialize(parsed_policy))
375 .collect::<Vec<Vec<u8>>>()
376 .join(b",".as_ref());
377
378 if categories.is_empty() {
379 sensitivity.to_vec()
380 } else {
381 [sensitivity, categories.as_slice()].join(b":".as_ref())
382 }
383 }
384
385 fn compare<U: Into<CategorySpan> + Clone, IterU: 'a + Iterator<Item = U>>(
387 &'a self,
388 other: &'a (impl Level<'a, U, IterU> + 'a),
389 ) -> Option<Ordering> {
390 let s_order = self.sensitivity().cmp(&other.sensitivity());
391 let c_order = self.category_spans().compare(&other.category_spans())?;
392 if s_order == c_order {
393 return Some(s_order);
394 } else if c_order == Ordering::Equal {
395 return Some(s_order);
396 } else if s_order == Ordering::Equal {
397 return Some(c_order);
398 }
399 None
402 }
403
404 fn dominates<U: Into<CategorySpan> + Clone, IterU: 'a + Iterator<Item = U>>(
406 &'a self,
407 other: &'a (impl Level<'a, U, IterU> + 'a),
408 ) -> bool {
409 match self.compare(other) {
410 Some(Ordering::Equal) | Some(Ordering::Greater) => true,
411 _ => false,
412 }
413 }
414}
415
416impl<'a> Level<'a, &'a CategorySpan, Iter<'a, CategorySpan>> for SecurityLevel {
417 fn sensitivity(&self) -> SensitivityId {
418 self.sensitivity
419 }
420 fn category_spans(&'a self) -> CategoryIterator<&'a CategorySpan, Iter<'a, CategorySpan>> {
421 CategoryIterator::<&'a CategorySpan, Iter<'a, CategorySpan>>::new(self.categories.iter())
422 }
423}
424
425pub struct CategoryIterator<T: Into<CategorySpan>, IterT: Iterator<Item = T>>(RefCell<IterT>);
427
428impl<T: Into<CategorySpan> + Clone, IterT: Iterator<Item = T>> CategoryIterator<T, IterT> {
429 pub fn new(iter: IterT) -> Self {
430 Self(RefCell::new(iter))
431 }
432
433 fn next(&self) -> Option<CategorySpan> {
434 self.0.borrow_mut().next().map(|x| x.into())
435 }
436
437 fn compare<'a, U: Into<CategorySpan> + Clone, IterU: 'a + Iterator<Item = U>>(
438 &'a self,
439 other: &'a CategoryIterator<U, IterU>,
440 ) -> Option<Ordering> {
441 let mut self_contains_other = true;
442 let mut other_contains_self = true;
443
444 let mut self_now = self.next();
445 let mut other_now = other.next();
446
447 while let (Some(self_span), Some(other_span)) = (self_now.clone(), other_now.clone()) {
448 if self_span.high < other_span.low {
449 other_contains_self = false;
450 } else if other_span.high < self_span.low {
451 self_contains_other = false;
452 } else {
453 match self_span.compare(&other_span) {
454 None => {
455 return None;
456 }
457 Some(Ordering::Less) => {
458 self_contains_other = false;
459 }
460 Some(Ordering::Greater) => {
461 other_contains_self = false;
462 }
463 Some(Ordering::Equal) => {}
464 }
465 if !self_contains_other && !other_contains_self {
466 return None;
467 }
468 }
469 if self_span.high <= other_span.high {
470 self_now = self.next();
471 }
472 if other_span.high <= self_span.high {
473 other_now = other.next();
474 }
475 }
476 if self_now.is_some() {
477 other_contains_self = false;
478 } else if other_now.is_some() {
479 self_contains_other = false;
480 }
481 match (self_contains_other, other_contains_self) {
482 (true, true) => Some(Ordering::Equal),
483 (true, false) => Some(Ordering::Greater),
484 (false, true) => Some(Ordering::Less),
485 (false, false) => None,
486 }
487 }
488}
489
490impl<T: Into<CategorySpan>, IterT: Iterator<Item = T>> Iterator for CategoryIterator<T, IterT> {
491 type Item = CategorySpan;
492
493 fn next(&mut self) -> Option<Self::Item> {
494 self.0.borrow_mut().next().map(|x| x.into())
495 }
496}
497
498#[derive(Clone, Debug, Eq, PartialEq)]
502pub struct CategorySpan {
503 low: CategoryId,
504 high: CategoryId,
505}
506
507impl CategorySpan {
508 pub(super) fn new(low: CategoryId, high: CategoryId) -> Self {
509 Self { low, high }
510 }
511
512 fn serialize(&self, parsed_policy: &ParsedPolicy) -> Vec<u8> {
514 match self.low == self.high {
515 true => parsed_policy.category(self.low).name_bytes().into(),
516 false => [
517 parsed_policy.category(self.low).name_bytes(),
518 parsed_policy.category(self.high).name_bytes(),
519 ]
520 .join(b".".as_ref()),
521 }
522 }
523
524 fn compare(&self, other: &Self) -> Option<Ordering> {
526 match (self.low.cmp(&other.low), self.high.cmp(&other.high)) {
527 (Ordering::Equal, Ordering::Equal) => Some(Ordering::Equal),
528 (Ordering::Equal, Ordering::Greater)
529 | (Ordering::Less, Ordering::Equal)
530 | (Ordering::Less, Ordering::Greater) => Some(Ordering::Greater),
531 (Ordering::Equal, Ordering::Less)
532 | (Ordering::Greater, Ordering::Equal)
533 | (Ordering::Greater, Ordering::Less) => Some(Ordering::Less),
534 _ => None,
535 }
536 }
537}
538
539impl From<ExtensibleBitmapSpan> for CategorySpan {
540 fn from(value: ExtensibleBitmapSpan) -> CategorySpan {
541 CategorySpan {
542 low: CategoryId(NonZeroU32::new(value.low + 1).unwrap()),
543 high: CategoryId(NonZeroU32::new(value.high + 1).unwrap()),
544 }
545 }
546}
547
548impl From<&CategorySpan> for CategorySpan {
549 fn from(value: &CategorySpan) -> Self {
550 value.clone()
551 }
552}
553
554#[derive(Clone, Debug, Error, Eq, PartialEq)]
556pub enum SecurityContextError {
557 #[error("security context syntax is invalid")]
558 InvalidSyntax,
559 #[error("sensitivity {name:?} not defined by policy")]
560 UnknownSensitivity { name: BString },
561 #[error("category {name:?} not defined by policy")]
562 UnknownCategory { name: BString },
563 #[error("user {name:?} not defined by policy")]
564 UnknownUser { name: BString },
565 #[error("role {name:?} not defined by policy")]
566 UnknownRole { name: BString },
567 #[error("type {name:?} not defined by policy")]
568 UnknownType { name: BString },
569 #[error("role {role:?} not valid for {user:?}")]
570 InvalidRoleForUser { role: BString, user: BString },
571 #[error("type {type_:?} not valid for {role:?}")]
572 InvalidTypeForRole { role: BString, type_: BString },
573 #[error("security level {level:?} not valid for {user:?}")]
574 InvalidLevelForUser { level: BString, user: BString },
575 #[error("high security level {high:?} lower than low level {low:?}")]
576 InvalidSecurityRange { low: BString, high: BString },
577}
578
579#[cfg(test)]
580mod tests {
581 use super::super::{Policy, parse_policy_by_value};
582 use super::*;
583
584 use std::num::NonZeroU32;
585
586 type TestPolicy = Policy;
587 fn test_policy() -> TestPolicy {
588 const TEST_POLICY: &[u8] =
589 include_bytes!("../../testdata/micro_policies/security_context_tests_policy.pp");
590 parse_policy_by_value(TEST_POLICY.to_vec()).unwrap().validate().unwrap()
591 }
592
593 #[derive(Debug, Eq, PartialEq)]
595 struct CategoryItem<'a> {
596 low: &'a str,
597 high: &'a str,
598 }
599
600 fn user_name(policy: &TestPolicy, id: UserId) -> &str {
601 std::str::from_utf8(policy.0.parsed_policy().user(id).name_bytes()).unwrap()
602 }
603
604 fn role_name(policy: &TestPolicy, id: RoleId) -> &str {
605 std::str::from_utf8(policy.0.parsed_policy().role(id).name_bytes()).unwrap()
606 }
607
608 fn type_name(policy: &TestPolicy, id: TypeId) -> &str {
609 std::str::from_utf8(policy.0.parsed_policy().type_(id).name_bytes()).unwrap()
610 }
611
612 fn sensitivity_name(policy: &TestPolicy, id: SensitivityId) -> &str {
613 std::str::from_utf8(policy.0.parsed_policy().sensitivity(id).name_bytes()).unwrap()
614 }
615
616 fn category_name(policy: &TestPolicy, id: CategoryId) -> &str {
617 std::str::from_utf8(policy.0.parsed_policy().category(id).name_bytes()).unwrap()
618 }
619
620 fn category_span<'a>(policy: &'a TestPolicy, category: &CategorySpan) -> CategoryItem<'a> {
621 CategoryItem {
622 low: category_name(policy, category.low),
623 high: category_name(policy, category.high),
624 }
625 }
626
627 fn category_spans<'a>(
628 policy: &'a TestPolicy,
629 categories: &Vec<CategorySpan>,
630 ) -> Vec<CategoryItem<'a>> {
631 categories.iter().map(|x| category_span(policy, x)).collect()
632 }
633
634 fn cat(low: u32, high: u32) -> CategorySpan {
636 CategorySpan {
637 low: CategoryId(NonZeroU32::new(low).expect("category ids are nonzero")),
638 high: CategoryId(NonZeroU32::new(high).expect("category ids are nonzero")),
639 }
640 }
641
642 fn compare(lhs: &[CategorySpan], rhs: &[CategorySpan]) -> Option<Ordering> {
644 CategoryIterator::new(lhs.iter()).compare(&CategoryIterator::new(rhs.iter()))
645 }
646
647 #[test]
648 fn category_compare() {
649 let cat_1 = cat(1, 1);
650 let cat_2 = cat(1, 3);
651 let cat_3 = cat(2, 3);
652 assert_eq!(cat_1.compare(&cat_1), Some(Ordering::Equal));
653 assert_eq!(cat_1.compare(&cat_2), Some(Ordering::Less));
654 assert_eq!(cat_1.compare(&cat_3), None);
655 assert_eq!(cat_2.compare(&cat_1), Some(Ordering::Greater));
656 assert_eq!(cat_2.compare(&cat_3), Some(Ordering::Greater));
657 }
658
659 #[test]
660 fn categories_compare_empty_iter() {
661 let cats_0 = &[];
662 let cats_1 = &[cat(1, 1)];
663 assert_eq!(compare(cats_0, cats_0), Some(Ordering::Equal));
664 assert_eq!(compare(cats_0, cats_1), Some(Ordering::Less));
665 assert_eq!(compare(cats_1, cats_0), Some(Ordering::Greater));
666 }
667
668 #[test]
669 fn categories_compare_same_length() {
670 let cats_1 = &[cat(1, 1), cat(3, 3)];
671 let cats_2 = &[cat(1, 1), cat(4, 4)];
672 let cats_3 = &[cat(1, 2), cat(4, 4)];
673 let cats_4 = &[cat(1, 2), cat(4, 5)];
674
675 assert_eq!(compare(cats_1, cats_1), Some(Ordering::Equal));
676 assert_eq!(compare(cats_1, cats_2), None);
677 assert_eq!(compare(cats_1, cats_3), None);
678 assert_eq!(compare(cats_1, cats_4), None);
679
680 assert_eq!(compare(cats_2, cats_1), None);
681 assert_eq!(compare(cats_2, cats_2), Some(Ordering::Equal));
682 assert_eq!(compare(cats_2, cats_3), Some(Ordering::Less));
683 assert_eq!(compare(cats_2, cats_4), Some(Ordering::Less));
684
685 assert_eq!(compare(cats_3, cats_1), None);
686 assert_eq!(compare(cats_3, cats_2), Some(Ordering::Greater));
687 assert_eq!(compare(cats_3, cats_3), Some(Ordering::Equal));
688 assert_eq!(compare(cats_3, cats_4), Some(Ordering::Less));
689
690 assert_eq!(compare(cats_4, cats_1), None);
691 assert_eq!(compare(cats_4, cats_2), Some(Ordering::Greater));
692 assert_eq!(compare(cats_4, cats_3), Some(Ordering::Greater));
693 assert_eq!(compare(cats_4, cats_4), Some(Ordering::Equal));
694 }
695
696 #[test]
697 fn categories_compare_different_lengths() {
698 let cats_1 = &[cat(1, 1)];
699 let cats_2 = &[cat(1, 4)];
700 let cats_3 = &[cat(1, 1), cat(4, 4)];
701 let cats_4 = &[cat(1, 2), cat(4, 5), cat(7, 7)];
702
703 assert_eq!(compare(cats_1, cats_3), Some(Ordering::Less));
704 assert_eq!(compare(cats_1, cats_4), Some(Ordering::Less));
705
706 assert_eq!(compare(cats_2, cats_3), Some(Ordering::Greater));
707 assert_eq!(compare(cats_2, cats_4), None);
708
709 assert_eq!(compare(cats_3, cats_1), Some(Ordering::Greater));
710 assert_eq!(compare(cats_3, cats_2), Some(Ordering::Less));
711 assert_eq!(compare(cats_3, cats_4), Some(Ordering::Less));
712
713 assert_eq!(compare(cats_4, cats_1), Some(Ordering::Greater));
714 assert_eq!(compare(cats_4, cats_2), None);
715 assert_eq!(compare(cats_4, cats_3), Some(Ordering::Greater));
716 }
717
718 #[test]
719 fn categories_compare_with_gaps() {
722 let cats_1 = &[cat(1, 2), cat(4, 5)];
723 let cats_2 = &[cat(4, 5)];
724 let cats_3 = &[cat(2, 5), cat(10, 11)];
725 let cats_4 = &[cat(2, 5), cat(7, 8), cat(10, 11)];
726
727 assert_eq!(compare(cats_1, cats_2), Some(Ordering::Greater));
728 assert_eq!(compare(cats_1, cats_3), None);
729 assert_eq!(compare(cats_1, cats_4), None);
730
731 assert_eq!(compare(cats_2, cats_1), Some(Ordering::Less));
732 assert_eq!(compare(cats_2, cats_3), Some(Ordering::Less));
733 assert_eq!(compare(cats_2, cats_4), Some(Ordering::Less));
734
735 assert_eq!(compare(cats_3, cats_1), None);
736 assert_eq!(compare(cats_3, cats_2), Some(Ordering::Greater));
737 assert_eq!(compare(cats_3, cats_4), Some(Ordering::Less));
738
739 assert_eq!(compare(cats_4, cats_1), None);
740 assert_eq!(compare(cats_4, cats_2), Some(Ordering::Greater));
741 assert_eq!(compare(cats_4, cats_3), Some(Ordering::Greater));
742 }
743
744 #[test]
745 fn parse_security_context_single_sensitivity() {
746 let policy = test_policy();
747 let security_context = policy
748 .parse_security_context(b"user0:object_r:type0:s0".into())
749 .expect("creating security context should succeed");
750 assert_eq!(user_name(&policy, security_context.user), "user0");
751 assert_eq!(role_name(&policy, security_context.role), "object_r");
752 assert_eq!(type_name(&policy, security_context.type_), "type0");
753 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s0");
754 assert_eq!(security_context.low_level.categories, Vec::new());
755 assert_eq!(security_context.high_level, None);
756 }
757
758 #[test]
759 fn parse_security_context_with_sensitivity_range() {
760 let policy = test_policy();
761 let security_context = policy
762 .parse_security_context(b"user0:object_r:type0:s0-s1".into())
763 .expect("creating security context should succeed");
764 assert_eq!(user_name(&policy, security_context.user), "user0");
765 assert_eq!(role_name(&policy, security_context.role), "object_r");
766 assert_eq!(type_name(&policy, security_context.type_), "type0");
767 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s0");
768 assert_eq!(security_context.low_level.categories, Vec::new());
769 let high_level = security_context.high_level.as_ref().unwrap();
770 assert_eq!(sensitivity_name(&policy, high_level.sensitivity), "s1");
771 assert_eq!(high_level.categories, Vec::new());
772 }
773
774 #[test]
775 fn parse_security_context_with_single_sensitivity_and_categories_interval() {
776 let policy = test_policy();
777 let security_context = policy
778 .parse_security_context(b"user0:object_r:type0:s1:c0.c4".into())
779 .expect("creating security context should succeed");
780 assert_eq!(user_name(&policy, security_context.user), "user0");
781 assert_eq!(role_name(&policy, security_context.role), "object_r");
782 assert_eq!(type_name(&policy, security_context.type_), "type0");
783 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s1");
784 assert_eq!(
785 category_spans(&policy, &security_context.low_level.categories),
786 [CategoryItem { low: "c0", high: "c4" }]
787 );
788 assert_eq!(security_context.high_level, None);
789 }
790
791 #[test]
792 fn parse_security_context_and_normalize_categories() {
793 let policy = &test_policy();
794 let normalize = {
795 |security_context: &str| -> String {
796 String::from_utf8(
797 policy.serialize_security_context(
798 &policy
799 .parse_security_context(security_context.into())
800 .expect("creating security context should succeed"),
801 ),
802 )
803 .unwrap()
804 }
805 };
806 assert_eq!(normalize("user0:object_r:type0:s1:c0.c1,c1"), "user0:object_r:type0:s1:c0.c1");
808 assert_eq!(
809 normalize("user0:object_r:type0:s1:c0.c2,c1.c2"),
810 "user0:object_r:type0:s1:c0.c2"
811 );
812 assert_eq!(
813 normalize("user0:object_r:type0:s1:c0.c2,c1.c3"),
814 "user0:object_r:type0:s1:c0.c3"
815 );
816 assert_eq!(normalize("user0:object_r:type0:s1:c0.c1,c2"), "user0:object_r:type0:s1:c0.c2");
818 assert_eq!(
820 normalize("user0:object_r:type0:s1:c2.c3,c0"),
821 "user0:object_r:type0:s1:c0,c2.c3"
822 );
823 }
824
825 #[test]
826 fn parse_security_context_with_sensitivity_range_and_category_interval() {
827 let policy = test_policy();
828 let security_context = policy
829 .parse_security_context(b"user0:object_r:type0:s0-s1:c0.c4".into())
830 .expect("creating security context should succeed");
831 assert_eq!(user_name(&policy, security_context.user), "user0");
832 assert_eq!(role_name(&policy, security_context.role), "object_r");
833 assert_eq!(type_name(&policy, security_context.type_), "type0");
834 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s0");
835 assert_eq!(security_context.low_level.categories, Vec::new());
836 let high_level = security_context.high_level.as_ref().unwrap();
837 assert_eq!(sensitivity_name(&policy, high_level.sensitivity), "s1");
838 assert_eq!(
839 category_spans(&policy, &high_level.categories),
840 [CategoryItem { low: "c0", high: "c4" }]
841 );
842 }
843
844 #[test]
845 fn parse_security_context_with_sensitivity_range_with_categories() {
846 let policy = test_policy();
847 let security_context = policy
848 .parse_security_context(b"user0:object_r:type0:s0:c0-s1:c0.c4".into())
849 .expect("creating security context should succeed");
850 assert_eq!(user_name(&policy, security_context.user), "user0");
851 assert_eq!(role_name(&policy, security_context.role), "object_r");
852 assert_eq!(type_name(&policy, security_context.type_), "type0");
853 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s0");
854 assert_eq!(
855 category_spans(&policy, &security_context.low_level.categories),
856 [CategoryItem { low: "c0", high: "c0" }]
857 );
858
859 let high_level = security_context.high_level.as_ref().unwrap();
860 assert_eq!(sensitivity_name(&policy, high_level.sensitivity), "s1");
861 assert_eq!(
862 category_spans(&policy, &high_level.categories),
863 [CategoryItem { low: "c0", high: "c4" }]
864 );
865 }
866
867 #[test]
868 fn parse_security_context_with_single_sensitivity_and_category_list() {
869 let policy = test_policy();
870 let security_context = policy
871 .parse_security_context(b"user0:object_r:type0:s1:c0,c4".into())
872 .expect("creating security context should succeed");
873 assert_eq!(user_name(&policy, security_context.user), "user0");
874 assert_eq!(role_name(&policy, security_context.role), "object_r");
875 assert_eq!(type_name(&policy, security_context.type_), "type0");
876 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s1");
877 assert_eq!(
878 category_spans(&policy, &security_context.low_level.categories),
879 [CategoryItem { low: "c0", high: "c0" }, CategoryItem { low: "c4", high: "c4" }]
880 );
881 assert_eq!(security_context.high_level, None);
882 }
883
884 #[test]
885 fn parse_security_context_with_single_sensitivity_and_category_list_and_range() {
886 let policy = test_policy();
887 let security_context = policy
888 .parse_security_context(b"user0:object_r:type0:s1:c0,c3.c4".into())
889 .expect("creating security context should succeed");
890 assert_eq!(user_name(&policy, security_context.user), "user0");
891 assert_eq!(role_name(&policy, security_context.role), "object_r");
892 assert_eq!(type_name(&policy, security_context.type_), "type0");
893 assert_eq!(sensitivity_name(&policy, security_context.low_level.sensitivity), "s1");
894 assert_eq!(
895 category_spans(&policy, &security_context.low_level.categories),
896 [CategoryItem { low: "c0", high: "c0" }, CategoryItem { low: "c3", high: "c4" }]
897 );
898 assert_eq!(security_context.high_level, None);
899 }
900
901 #[test]
902 fn parse_invalid_syntax() {
903 let policy = test_policy();
904 for invalid_label in [
905 "user0",
906 "user0:object_r",
907 "user0:object_r:type0",
908 "user0:object_r:type0:s0-",
909 "user0:object_r:type0:s0:s0:s0",
910 "user0:object_r:type0:s0:c0.c0", "user0:object_r:type0:s0:c1.c0", ] {
913 assert_eq!(
914 policy.parse_security_context(invalid_label.as_bytes().into()),
915 Err(SecurityContextError::InvalidSyntax),
916 "validating {:?}",
917 invalid_label
918 );
919 }
920 }
921
922 #[test]
923 fn parse_invalid_sensitivity() {
924 let policy = test_policy();
925 for invalid_label in ["user0:object_r:type0:s_invalid", "user0:object_r:type0:s0-s_invalid"]
926 {
927 assert_eq!(
928 policy.parse_security_context(invalid_label.as_bytes().into()),
929 Err(SecurityContextError::UnknownSensitivity { name: "s_invalid".into() }),
930 "validating {:?}",
931 invalid_label
932 );
933 }
934 }
935
936 #[test]
937 fn parse_invalid_category() {
938 let policy = test_policy();
939 for invalid_label in
940 ["user0:object_r:type0:s1:c_invalid", "user0:object_r:type0:s1:c0.c_invalid"]
941 {
942 assert_eq!(
943 policy.parse_security_context(invalid_label.as_bytes().into()),
944 Err(SecurityContextError::UnknownCategory { name: "c_invalid".into() }),
945 "validating {:?}",
946 invalid_label
947 );
948 }
949 }
950
951 #[test]
952 fn invalid_security_context_fields() {
953 let policy = test_policy();
954
955 let context = policy
958 .parse_security_context(b"user0:object_r:type0:s1:c0,c3.c4-s1".into())
959 .expect("successfully parsed");
960 assert_eq!(
961 policy.validate_security_context(&context),
962 Err(SecurityContextError::InvalidSecurityRange {
963 low: "s1:c0,c3.c4".into(),
964 high: "s1".into()
965 })
966 );
967
968 let context = policy
971 .parse_security_context(b"user0:object_r:type0:s1:c0-s1:c1".into())
972 .expect("successfully parsed");
973 assert_eq!(
974 policy.validate_security_context(&context),
975 Err(SecurityContextError::InvalidSecurityRange {
976 low: "s1:c0".into(),
977 high: "s1:c1".into()
978 })
979 );
980
981 let context = policy
984 .parse_security_context(b"user0:object_r:type0:s1:c0-s0:c0.c1".into())
985 .expect("successfully parsed");
986 assert_eq!(
987 policy.validate_security_context(&context),
988 Err(SecurityContextError::InvalidSecurityRange {
989 low: "s1:c0".into(),
990 high: "s0:c0.c1".into()
991 })
992 );
993
994 let context = policy
998 .parse_security_context(b"user1:subject_r:type0:s1-s1:c3".into())
999 .expect("successfully parsed");
1000 assert_eq!(
1001 policy.validate_security_context(&context),
1002 Err(SecurityContextError::InvalidLevelForUser {
1003 level: "s1:c3".into(),
1004 user: "user1".into(),
1005 })
1006 );
1007
1008 let context = policy
1012 .parse_security_context(b"user1:object_r:type0:s0".into())
1013 .expect("successfully parsed");
1014 assert_eq!(
1015 policy.validate_security_context(&context),
1016 Err(SecurityContextError::InvalidLevelForUser {
1017 level: "s0".into(),
1018 user: "user1".into(),
1019 })
1020 );
1021
1022 let context = policy
1024 .parse_security_context(b"user1:object_r:type0:s0".into())
1025 .expect("successfully parsed");
1026 assert!(policy.validate_security_context(&context).is_err());
1027
1028 let context = policy
1030 .parse_security_context(b"user0:subject_r:type0:s0".into())
1031 .expect("successfully parsed");
1032 assert!(policy.validate_security_context(&context).is_err());
1033
1034 let context = policy
1036 .parse_security_context(b"user1:subject_r:non_subject_t:s1".into())
1037 .expect("successfully parsed");
1038 assert!(policy.validate_security_context(&context).is_err());
1039
1040 let context = policy
1043 .parse_security_context(b"user1:object_r:type0:s1".into())
1044 .expect("successfully parsed");
1045 assert!(policy.validate_security_context(&context).is_ok());
1046 }
1047
1048 #[test]
1049 fn format_security_contexts() {
1050 let policy = test_policy();
1051 for label in [
1052 "user0:object_r:type0:s0",
1053 "user0:object_r:type0:s0-s1",
1054 "user0:object_r:type0:s1:c0.c4",
1055 "user0:object_r:type0:s0-s1:c0.c4",
1056 "user0:object_r:type0:s1:c0,c3",
1057 "user0:object_r:type0:s0-s1:c0,c2,c4",
1058 "user0:object_r:type0:s1:c0,c3.c4-s1:c0,c2.c4",
1059 ] {
1060 let security_context =
1061 policy.parse_security_context(label.as_bytes().into()).expect("should succeed");
1062 assert_eq!(policy.serialize_security_context(&security_context), label.as_bytes());
1063 }
1064 }
1065}