1use super::constraints::{evaluate_constraint, ConstraintError};
6use super::error::{ParseError, ValidateError};
7use super::extensible_bitmap::{
8 ExtensibleBitmap, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator,
9};
10use super::parser::ParseStrategy;
11use super::security_context::{CategoryIterator, Level, SecurityContext};
12use super::{
13 array_type, array_type_validate_deref_both, array_type_validate_deref_data,
14 array_type_validate_deref_metadata_data_vec, array_type_validate_deref_none_data_vec,
15 AccessVector, Array, CategoryId, ClassId, ClassPermissionId, Counted, Parse, ParseSlice,
16 RoleId, SensitivityId, TypeId, UserId, Validate, ValidateArray,
17};
18
19use anyhow::{anyhow, Context as _};
20use std::fmt::Debug;
21use std::num::NonZeroU32;
22use std::ops::Deref;
23use zerocopy::{little_endian as le, FromBytes, Immutable, KnownLayout, Unaligned};
24
25pub(super) const CONSTRAINT_TERM_TYPE_NOT_OPERATOR: u32 = 1;
30pub(super) const CONSTRAINT_TERM_TYPE_AND_OPERATOR: u32 = 2;
33pub(super) const CONSTRAINT_TERM_TYPE_OR_OPERATOR: u32 = 3;
36pub(super) const CONSTRAINT_TERM_TYPE_EXPR: u32 = 4;
40pub(super) const CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES: u32 = 5;
53
54pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_EQ: u32 = 1;
67pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_NE: u32 = 2;
70pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_DOM: u32 = 3;
73pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY: u32 = 4;
77pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP: u32 = 5;
81
82pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_USER: u32 = 0x1;
108pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_ROLE: u32 = 0x2;
110pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_TYPE: u32 = 0x4;
112pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2: u32 = 0x20;
115pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2: u32 = 0x40;
118pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2: u32 = 0x80;
121pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2: u32 = 0x100;
124pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1: u32 = 0x200;
127pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2: u32 = 0x400;
130
131pub(super) const CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK: u32 = 0x8;
144
145pub(super) const TYPE_PROPERTIES_TYPE: u32 = 1;
147
148pub(super) const TYPE_PROPERTIES_ALIAS: u32 = 0;
150
151pub(super) const TYPE_PROPERTIES_ATTRIBUTE: u32 = 0;
153
154#[derive(Debug, PartialEq)]
157pub(super) struct SymbolList<PS: ParseStrategy, T>(Array<PS, PS::Output<Metadata>, Vec<T>>);
158
159impl<PS: ParseStrategy, T> Deref for SymbolList<PS, T> {
160 type Target = Array<PS, PS::Output<Metadata>, Vec<T>>;
161
162 fn deref(&self) -> &Self::Target {
163 &self.0
164 }
165}
166
167impl<PS: ParseStrategy, T> Parse<PS> for SymbolList<PS, T>
168where
169 Array<PS, PS::Output<Metadata>, Vec<T>>: Parse<PS>,
170{
171 type Error = <Array<PS, PS::Output<Metadata>, Vec<T>> as Parse<PS>>::Error;
172
173 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
174 let (array, tail) = Array::<PS, PS::Output<Metadata>, Vec<T>>::parse(bytes)?;
175 Ok((Self(array), tail))
176 }
177}
178
179impl<PS: ParseStrategy, T> Validate for SymbolList<PS, T>
180where
181 [T]: Validate,
182{
183 type Error = anyhow::Error;
184
185 fn validate(&self) -> Result<(), Self::Error> {
187 PS::deref(&self.metadata).validate().map_err(Into::<anyhow::Error>::into)?;
188 self.data.as_slice().validate().map_err(Into::<anyhow::Error>::into)?;
189
190 Ok(())
191 }
192}
193
194#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
196#[repr(C, packed)]
197pub(super) struct Metadata {
198 primary_names_count: le::U32,
200 count: le::U32,
202}
203
204impl Metadata {
205 pub fn primary_names_count(&self) -> u32 {
206 self.primary_names_count.get()
207 }
208}
209
210impl Counted for Metadata {
211 fn count(&self) -> u32 {
214 self.count.get()
215 }
216}
217
218impl Validate for Metadata {
219 type Error = anyhow::Error;
220
221 fn validate(&self) -> Result<(), Self::Error> {
223 Ok(())
224 }
225}
226
227impl<PS: ParseStrategy> Validate for [CommonSymbol<PS>] {
228 type Error = <CommonSymbol<PS> as Validate>::Error;
229
230 fn validate(&self) -> Result<(), Self::Error> {
233 Ok(())
234 }
235}
236
237array_type!(CommonSymbol, PS, CommonSymbolMetadata<PS>, Permissions<PS>);
238
239array_type_validate_deref_none_data_vec!(CommonSymbol);
240
241impl<PS: ParseStrategy> CommonSymbol<PS> {
242 pub fn permissions(&self) -> &Permissions<PS> {
243 &self.data
244 }
245}
246
247pub(super) type CommonSymbols<PS> = Vec<CommonSymbol<PS>>;
248
249impl<PS: ParseStrategy> CommonSymbol<PS> {
250 pub fn name_bytes(&self) -> &[u8] {
254 PS::deref_slice(&self.metadata.data)
255 }
256}
257
258impl<PS: ParseStrategy> Counted for CommonSymbol<PS>
259where
260 CommonSymbolMetadata<PS>: Parse<PS> + Validate,
261 Array<PS, PS::Output<CommonSymbolStaticMetadata>, PS::Slice<u8>>: Parse<PS>,
262 Array<PS, PS::Output<PermissionMetadata>, PS::Slice<u8>>: Parse<PS>,
263 Array<PS, CommonSymbolMetadata<PS>, Vec<Permission<PS>>>: Parse<PS>,
264 Vec<Permission<PS>>: ParseSlice<PS>,
265{
266 fn count(&self) -> u32 {
269 self.metadata.count()
270 }
271}
272
273impl<PS: ParseStrategy> ValidateArray<CommonSymbolMetadata<PS>, Permission<PS>>
274 for CommonSymbol<PS>
275{
276 type Error = anyhow::Error;
277
278 fn validate_array<'a>(
280 _metadata: &'a CommonSymbolMetadata<PS>,
281 _data: &'a [Permission<PS>],
282 ) -> Result<(), Self::Error> {
283 Ok(())
284 }
285}
286
287array_type!(CommonSymbolMetadata, PS, PS::Output<CommonSymbolStaticMetadata>, PS::Slice<u8>);
288
289array_type_validate_deref_both!(CommonSymbolMetadata);
290
291impl<PS: ParseStrategy> Counted for CommonSymbolMetadata<PS> {
292 fn count(&self) -> u32 {
295 PS::deref(&self.metadata).count.get()
296 }
297}
298
299impl<PS: ParseStrategy> ValidateArray<CommonSymbolStaticMetadata, u8> for CommonSymbolMetadata<PS> {
300 type Error = anyhow::Error;
301
302 fn validate_array<'a>(
304 _metadata: &'a CommonSymbolStaticMetadata,
305 _data: &'a [u8],
306 ) -> Result<(), Self::Error> {
307 Ok(())
308 }
309}
310
311#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
313#[repr(C, packed)]
314pub(super) struct CommonSymbolStaticMetadata {
315 length: le::U32,
317 id: le::U32,
320 primary_names_count: le::U32,
322 count: le::U32,
324}
325
326impl Validate for CommonSymbolStaticMetadata {
327 type Error = anyhow::Error;
328
329 fn validate(&self) -> Result<(), Self::Error> {
331 Ok(())
332 }
333}
334
335impl Counted for CommonSymbolStaticMetadata {
336 fn count(&self) -> u32 {
338 self.length.get()
339 }
340}
341
342pub(super) type Permissions<PS> = Vec<Permission<PS>>;
344
345impl<PS: ParseStrategy> Validate for Permissions<PS> {
346 type Error = anyhow::Error;
347
348 fn validate(&self) -> Result<(), Self::Error> {
351 Ok(())
352 }
353}
354
355array_type!(Permission, PS, PS::Output<PermissionMetadata>, PS::Slice<u8>);
356
357array_type_validate_deref_both!(Permission);
358
359impl<PS: ParseStrategy> Permission<PS> {
360 pub fn name_bytes(&self) -> &[u8] {
364 PS::deref_slice(&self.data)
365 }
366
367 pub fn id(&self) -> ClassPermissionId {
369 ClassPermissionId(NonZeroU32::new(PS::deref(&self.metadata).id.get()).unwrap())
370 }
371}
372
373impl<PS: ParseStrategy> ValidateArray<PermissionMetadata, u8> for Permission<PS> {
374 type Error = anyhow::Error;
375
376 fn validate_array<'a>(
378 _metadata: &'a PermissionMetadata,
379 _data: &'a [u8],
380 ) -> Result<(), Self::Error> {
381 Ok(())
382 }
383}
384
385#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
386#[repr(C, packed)]
387pub(super) struct PermissionMetadata {
388 length: le::U32,
390 id: le::U32,
391}
392
393impl Counted for PermissionMetadata {
394 fn count(&self) -> u32 {
396 self.length.get()
397 }
398}
399
400impl Validate for PermissionMetadata {
401 type Error = anyhow::Error;
402
403 fn validate(&self) -> Result<(), Self::Error> {
405 Ok(())
406 }
407}
408
409pub(super) type Constraints<PS> = Vec<Constraint<PS>>;
411
412impl<PS: ParseStrategy> Validate for Constraints<PS> {
413 type Error = anyhow::Error;
414
415 fn validate(&self) -> Result<(), Self::Error> {
418 Ok(())
419 }
420}
421
422#[derive(Debug, PartialEq)]
426pub(super) struct Constraint<PS: ParseStrategy>
427where
428 ConstraintExpr<PS>: Debug + PartialEq,
429{
430 access_vector: PS::Output<le::U32>,
431 constraint_expr: ConstraintExpr<PS>,
432}
433
434impl<PS: ParseStrategy> Constraint<PS> {
435 pub(super) fn access_vector(&self) -> AccessVector {
436 AccessVector((*PS::deref(&self.access_vector)).get())
437 }
438
439 pub(super) fn constraint_expr(&self) -> &ConstraintExpr<PS> {
440 &self.constraint_expr
441 }
442}
443
444impl<PS: ParseStrategy> Parse<PS> for Constraint<PS>
445where
446 ConstraintExpr<PS>: Debug + PartialEq + Parse<PS>,
447{
448 type Error = anyhow::Error;
449
450 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
451 let tail = bytes;
452
453 let num_bytes = tail.len();
454 let (access_vector, tail) = PS::parse::<le::U32>(tail).ok_or_else(|| {
455 Into::<anyhow::Error>::into(ParseError::MissingData {
456 type_name: "AccessVector",
457 type_size: std::mem::size_of::<le::U32>(),
458 num_bytes,
459 })
460 })?;
461 let (constraint_expr, tail) = ConstraintExpr::parse(tail)
462 .map_err(|error| error.into() as anyhow::Error)
463 .context("parsing constraint expression")?;
464
465 Ok((Self { access_vector, constraint_expr }, tail))
466 }
467}
468
469array_type!(ConstraintExpr, PS, PS::Output<ConstraintTermCount>, ConstraintTerms<PS>);
472
473array_type_validate_deref_metadata_data_vec!(ConstraintExpr);
474
475impl<PS: ParseStrategy> ValidateArray<ConstraintTermCount, ConstraintTerm<PS>>
476 for ConstraintExpr<PS>
477{
478 type Error = anyhow::Error;
479
480 fn validate_array<'a>(
484 _metadata: &'a ConstraintTermCount,
485 _data: &'a [ConstraintTerm<PS>],
486 ) -> Result<(), Self::Error> {
487 Ok(())
488 }
489}
490
491impl<PS: ParseStrategy> ConstraintExpr<PS> {
492 pub(super) fn evaluate(
493 &self,
494 source_context: &SecurityContext,
495 target_context: &SecurityContext,
496 ) -> Result<bool, ConstraintError> {
497 evaluate_constraint(&self, source_context, target_context)
498 }
499
500 pub(super) fn constraint_terms(&self) -> &[ConstraintTerm<PS>] {
501 &self.data
502 }
503}
504
505#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
506#[repr(C, packed)]
507pub(super) struct ConstraintTermCount(le::U32);
508
509impl Counted for ConstraintTermCount {
510 fn count(&self) -> u32 {
511 self.0.get()
512 }
513}
514
515impl Validate for ConstraintTermCount {
516 type Error = anyhow::Error;
517
518 fn validate(&self) -> Result<(), Self::Error> {
519 Ok(())
520 }
521}
522
523impl<PS: ParseStrategy> Validate for ConstraintTerms<PS> {
524 type Error = anyhow::Error;
525
526 fn validate(&self) -> Result<(), Self::Error> {
531 Ok(())
532 }
533}
534
535#[derive(Debug, PartialEq)]
536pub(super) struct ConstraintTerm<PS: ParseStrategy> {
537 metadata: PS::Output<ConstraintTermMetadata>,
538 names: Option<ExtensibleBitmap<PS>>,
539 names_type_set: Option<TypeSet<PS>>,
540}
541
542pub(super) type ConstraintTerms<PS> = Vec<ConstraintTerm<PS>>;
543
544impl<PS: ParseStrategy> Parse<PS> for ConstraintTerm<PS>
545where
546 ExtensibleBitmap<PS>: Parse<PS>,
547{
548 type Error = anyhow::Error;
549
550 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
551 let tail = bytes;
552
553 let (metadata, tail) = PS::parse::<ConstraintTermMetadata>(tail)
554 .context("parsing constraint term metadata")?;
555
556 let (names, names_type_set, tail) = match PS::deref(&metadata).constraint_term_type.get() {
557 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES => {
558 let (names, tail) = ExtensibleBitmap::parse(tail)
559 .map_err(Into::<anyhow::Error>::into)
560 .context("parsing constraint term names")?;
561 let (names_type_set, tail) =
562 TypeSet::parse(tail).context("parsing constraint term names type set")?;
563 (Some(names), Some(names_type_set), tail)
564 }
565 _ => (None, None, tail),
566 };
567
568 Ok((Self { metadata, names, names_type_set }, tail))
569 }
570}
571
572impl<PS: ParseStrategy> ConstraintTerm<PS> {
573 pub(super) fn constraint_term_type(&self) -> u32 {
574 PS::deref(&self.metadata).constraint_term_type.get()
575 }
576
577 pub(super) fn expr_operand_type(&self) -> u32 {
578 PS::deref(&self.metadata).expr_operand_type.get()
579 }
580
581 pub(super) fn expr_operator_type(&self) -> u32 {
582 PS::deref(&self.metadata).expr_operator_type.get()
583 }
584
585 pub(super) fn names(&self) -> Option<&ExtensibleBitmap<PS>> {
586 self.names.as_ref()
587 }
588
589 #[allow(dead_code)]
593 pub(super) fn names_type_set(&self) -> &Option<TypeSet<PS>> {
594 &self.names_type_set
595 }
596}
597
598#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
599#[repr(C, packed)]
600pub(super) struct ConstraintTermMetadata {
601 constraint_term_type: le::U32,
602 expr_operand_type: le::U32,
603 expr_operator_type: le::U32,
604}
605
606impl Validate for ConstraintTermMetadata {
607 type Error = anyhow::Error;
608
609 fn validate(&self) -> Result<(), Self::Error> {
612 if !(self.constraint_term_type > 0
613 && self.constraint_term_type <= CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
614 {
615 return Err(anyhow!("invalid constraint term type"));
616 }
617 if !(self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR
618 || self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
619 {
620 if self.expr_operand_type != 0 {
621 return Err(anyhow!(
622 "invalid operand type {} for constraint term type {}",
623 self.expr_operand_type,
624 self.constraint_term_type
625 ));
626 }
627 if self.expr_operator_type != 0 {
628 return Err(anyhow!(
629 "invalid operator type {} for constraint term type {}",
630 self.expr_operator_type,
631 self.constraint_term_type
632 ));
633 }
634 }
635 Ok(())
638 }
639}
640
641#[derive(Debug, PartialEq)]
642pub(super) struct TypeSet<PS: ParseStrategy> {
643 types: ExtensibleBitmap<PS>,
644 negative_set: ExtensibleBitmap<PS>,
645 flags: PS::Output<le::U32>,
646}
647
648impl<PS: ParseStrategy> Parse<PS> for TypeSet<PS>
649where
650 ExtensibleBitmap<PS>: Parse<PS>,
651{
652 type Error = anyhow::Error;
653
654 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
655 let tail = bytes;
656
657 let (types, tail) = ExtensibleBitmap::parse(tail)
658 .map_err(Into::<anyhow::Error>::into)
659 .context("parsing type set types")?;
660
661 let (negative_set, tail) = ExtensibleBitmap::parse(tail)
662 .map_err(Into::<anyhow::Error>::into)
663 .context("parsing type set negative set")?;
664
665 let num_bytes = tail.len();
666 let (flags, tail) = PS::parse::<le::U32>(tail).ok_or_else(|| {
667 Into::<anyhow::Error>::into(ParseError::MissingData {
668 type_name: "TypeSetFlags",
669 type_size: std::mem::size_of::<le::U32>(),
670 num_bytes,
671 })
672 })?;
673
674 Ok((Self { types, negative_set, flags }, tail))
675 }
676}
677
678pub(super) fn find_class_by_name<'a, PS: ParseStrategy>(
681 classes: &'a Classes<PS>,
682 name: &str,
683) -> Option<&'a Class<PS>> {
684 find_class_by_name_bytes(classes, name.as_bytes())
685}
686
687fn find_class_by_name_bytes<'a, PS: ParseStrategy>(
688 classes: &'a Classes<PS>,
689 name_bytes: &[u8],
690) -> Option<&'a Class<PS>> {
691 for cls in classes.into_iter() {
692 if cls.name_bytes() == name_bytes {
693 return Some(cls);
694 }
695 }
696
697 None
698}
699
700pub(super) fn find_common_symbol_by_name_bytes<'a, PS: ParseStrategy>(
704 common_symbols: &'a CommonSymbols<PS>,
705 name_bytes: &[u8],
706) -> Option<&'a CommonSymbol<PS>> {
707 for common_symbol in common_symbols.into_iter() {
708 if common_symbol.name_bytes() == name_bytes {
709 return Some(common_symbol);
710 }
711 }
712
713 None
714}
715
716impl<PS: ParseStrategy> Validate for [Class<PS>] {
717 type Error = anyhow::Error;
718
719 fn validate(&self) -> Result<(), Self::Error> {
720 for class in self {
722 class.defaults().validate().context("class defaults")?;
724 }
725 Ok(())
726 }
727}
728
729#[derive(Debug, PartialEq)]
730pub(super) struct Class<PS: ParseStrategy> {
731 constraints: ClassConstraints<PS>,
732 validate_transitions: ClassValidateTransitions<PS>,
733 defaults: PS::Output<ClassDefaults>,
734}
735
736pub(super) type Classes<PS> = Vec<Class<PS>>;
737
738impl<PS: ParseStrategy> Class<PS> {
739 pub fn common_name_bytes(&self) -> &[u8] {
746 let class_common_key: &ClassCommonKey<PS> = &self.constraints.metadata.metadata;
751 PS::deref_slice(&class_common_key.data)
752 }
753
754 pub fn name_bytes(&self) -> &[u8] {
756 let class_key: &ClassKey<PS> = &self.constraints.metadata.metadata.metadata;
760 PS::deref_slice(&class_key.data)
761 }
762
763 pub fn id(&self) -> ClassId {
767 let class_metadata: &ClassMetadata =
768 &PS::deref(&self.constraints.metadata.metadata.metadata.metadata);
769 ClassId(NonZeroU32::new(class_metadata.id.get()).unwrap())
770 }
771
772 pub fn permissions(&self) -> &Permissions<PS> {
774 &self.constraints.metadata.data
775 }
776
777 pub fn constraints(&self) -> &Vec<Constraint<PS>> {
785 &self.constraints.data
786 }
787
788 pub fn defaults(&self) -> &ClassDefaults {
789 PS::deref(&self.defaults)
790 }
791}
792
793impl<PS: ParseStrategy> Parse<PS> for Class<PS>
794where
795 ClassConstraints<PS>: Parse<PS>,
796 ClassValidateTransitions<PS>: Parse<PS>,
797{
798 type Error = anyhow::Error;
799
800 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
801 let tail = bytes;
802
803 let (constraints, tail) = ClassConstraints::parse(tail)
804 .map_err(Into::<anyhow::Error>::into)
805 .context("parsing class constraints")?;
806
807 let (validate_transitions, tail) = ClassValidateTransitions::parse(tail)
808 .map_err(Into::<anyhow::Error>::into)
809 .context("parsing class validate transitions")?;
810
811 let (defaults, tail) =
812 PS::parse::<ClassDefaults>(tail).context("parsing class defaults")?;
813
814 Ok((Self { constraints, validate_transitions, defaults }, tail))
815 }
816}
817
818#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
819#[repr(C, packed)]
820pub(super) struct ClassDefaults {
821 default_user: le::U32,
822 default_role: le::U32,
823 default_range: le::U32,
824 default_type: le::U32,
825}
826
827impl ClassDefaults {
828 pub fn user(&self) -> ClassDefault {
829 self.default_user.get().into()
830 }
831
832 pub fn role(&self) -> ClassDefault {
833 self.default_role.get().into()
834 }
835
836 pub fn range(&self) -> ClassDefaultRange {
837 self.default_range.get().into()
838 }
839
840 pub fn type_(&self) -> ClassDefault {
841 self.default_type.get().into()
842 }
843}
844
845impl Validate for ClassDefaults {
846 type Error = anyhow::Error;
847
848 fn validate(&self) -> Result<(), Self::Error> {
849 ClassDefault::validate(self.default_user.get()).context("default user")?;
850 ClassDefault::validate(self.default_role.get()).context("default role")?;
851 ClassDefault::validate(self.default_type.get()).context("default type")?;
852 ClassDefaultRange::validate(self.default_range.get()).context("default range")?;
853 Ok(())
854 }
855}
856
857#[derive(PartialEq)]
858pub(super) enum ClassDefault {
859 Unspecified,
860 Source,
861 Target,
862}
863
864impl ClassDefault {
865 pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
866 pub(super) const DEFAULT_SOURCE: u32 = 1;
867 pub(super) const DEFAULT_TARGET: u32 = 2;
868
869 fn validate(value: u32) -> Result<(), ValidateError> {
870 match value {
871 Self::DEFAULT_UNSPECIFIED | Self::DEFAULT_SOURCE | Self::DEFAULT_TARGET => Ok(()),
872 value => Err(ValidateError::InvalidClassDefault { value }),
873 }
874 }
875}
876
877impl From<u32> for ClassDefault {
878 fn from(value: u32) -> Self {
879 match value {
880 Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
881 Self::DEFAULT_SOURCE => Self::Source,
882 Self::DEFAULT_TARGET => Self::Target,
883 v => panic!(
884 "invalid SELinux class default; expected {}, {}, or {}, but got {}",
885 Self::DEFAULT_UNSPECIFIED,
886 Self::DEFAULT_SOURCE,
887 Self::DEFAULT_TARGET,
888 v
889 ),
890 }
891 }
892}
893
894#[derive(PartialEq)]
895pub(super) enum ClassDefaultRange {
896 Unspecified,
897 SourceLow,
898 SourceHigh,
899 SourceLowHigh,
900 TargetLow,
901 TargetHigh,
902 TargetLowHigh,
903}
904
905impl ClassDefaultRange {
906 pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
907 pub(super) const DEFAULT_SOURCE_LOW: u32 = 1;
908 pub(super) const DEFAULT_SOURCE_HIGH: u32 = 2;
909 pub(super) const DEFAULT_SOURCE_LOW_HIGH: u32 = 3;
910 pub(super) const DEFAULT_TARGET_LOW: u32 = 4;
911 pub(super) const DEFAULT_TARGET_HIGH: u32 = 5;
912 pub(super) const DEFAULT_TARGET_LOW_HIGH: u32 = 6;
913 pub(super) const DEFAULT_UNKNOWN_USED_VALUE: u32 = 7;
915
916 fn validate(value: u32) -> Result<(), ValidateError> {
917 match value {
918 Self::DEFAULT_UNSPECIFIED
919 | Self::DEFAULT_SOURCE_LOW
920 | Self::DEFAULT_SOURCE_HIGH
921 | Self::DEFAULT_SOURCE_LOW_HIGH
922 | Self::DEFAULT_TARGET_LOW
923 | Self::DEFAULT_TARGET_HIGH
924 | Self::DEFAULT_TARGET_LOW_HIGH
925 | Self::DEFAULT_UNKNOWN_USED_VALUE => Ok(()),
926 value => Err(ValidateError::InvalidClassDefaultRange { value }),
927 }
928 }
929}
930
931impl From<u32> for ClassDefaultRange {
932 fn from(value: u32) -> Self {
933 match value {
934 Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
935 Self::DEFAULT_SOURCE_LOW => Self::SourceLow,
936 Self::DEFAULT_SOURCE_HIGH => Self::SourceHigh,
937 Self::DEFAULT_SOURCE_LOW_HIGH => Self::SourceLowHigh,
938 Self::DEFAULT_TARGET_LOW => Self::TargetLow,
939 Self::DEFAULT_TARGET_HIGH => Self::TargetHigh,
940 Self::DEFAULT_TARGET_LOW_HIGH => Self::TargetLowHigh,
941 v => panic!(
942 "invalid SELinux MLS range default; expected one of {:?}, but got {}",
943 [
944 Self::DEFAULT_UNSPECIFIED,
945 Self::DEFAULT_SOURCE_LOW,
946 Self::DEFAULT_SOURCE_HIGH,
947 Self::DEFAULT_SOURCE_LOW_HIGH,
948 Self::DEFAULT_TARGET_LOW,
949 Self::DEFAULT_TARGET_HIGH,
950 Self::DEFAULT_TARGET_LOW_HIGH,
951 ],
952 v
953 ),
954 }
955 }
956}
957
958array_type!(
959 ClassValidateTransitions,
960 PS,
961 PS::Output<ClassValidateTransitionsCount>,
962 ConstraintTerms<PS>
963);
964
965array_type_validate_deref_metadata_data_vec!(ClassValidateTransitions);
966
967impl<PS: ParseStrategy> ValidateArray<ClassValidateTransitionsCount, ConstraintTerm<PS>>
968 for ClassValidateTransitions<PS>
969{
970 type Error = anyhow::Error;
971
972 fn validate_array<'a>(
974 _metadata: &'a ClassValidateTransitionsCount,
975 _data: &'a [ConstraintTerm<PS>],
976 ) -> Result<(), Self::Error> {
977 Ok(())
978 }
979}
980
981#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
982#[repr(C, packed)]
983pub(super) struct ClassValidateTransitionsCount(le::U32);
984
985impl Counted for ClassValidateTransitionsCount {
986 fn count(&self) -> u32 {
987 self.0.get()
988 }
989}
990
991impl Validate for ClassValidateTransitionsCount {
992 type Error = anyhow::Error;
993
994 fn validate(&self) -> Result<(), Self::Error> {
996 Ok(())
997 }
998}
999
1000array_type!(ClassConstraints, PS, ClassPermissions<PS>, Constraints<PS>);
1001
1002array_type_validate_deref_none_data_vec!(ClassConstraints);
1003
1004impl<PS: ParseStrategy> ValidateArray<ClassPermissions<PS>, Constraint<PS>>
1005 for ClassConstraints<PS>
1006{
1007 type Error = anyhow::Error;
1008
1009 fn validate_array<'a>(
1011 _metadata: &'a ClassPermissions<PS>,
1012 _data: &'a [Constraint<PS>],
1013 ) -> Result<(), Self::Error> {
1014 Ok(())
1015 }
1016}
1017
1018array_type!(ClassPermissions, PS, ClassCommonKey<PS>, Permissions<PS>);
1019
1020array_type_validate_deref_none_data_vec!(ClassPermissions);
1021
1022impl<PS: ParseStrategy> ValidateArray<ClassCommonKey<PS>, Permission<PS>> for ClassPermissions<PS> {
1023 type Error = anyhow::Error;
1024
1025 fn validate_array<'a>(
1027 _metadata: &'a ClassCommonKey<PS>,
1028 _data: &'a [Permission<PS>],
1029 ) -> Result<(), Self::Error> {
1030 Ok(())
1031 }
1032}
1033
1034impl<PS: ParseStrategy> Counted for ClassPermissions<PS>
1035where
1036 ClassCommonKey<PS>: Parse<PS>,
1037 Array<PS, ClassKey<PS>, PS::Slice<u8>>: Parse<PS>,
1038 Array<PS, PS::Output<ClassMetadata>, PS::Slice<u8>>: Parse<PS>,
1039 ClassKey<PS>: Parse<PS>,
1040 Vec<Permission<PS>>: ParseSlice<PS>,
1041 Array<PS, PS::Output<PermissionMetadata>, PS::Slice<u8>>: Parse<PS>,
1042 Array<PS, ClassCommonKey<PS>, Vec<Permission<PS>>>: Parse<PS>,
1043{
1044 fn count(&self) -> u32 {
1046 PS::deref(&self.metadata.metadata.metadata).constraint_count.get()
1047 }
1048}
1049
1050array_type!(ClassCommonKey, PS, ClassKey<PS>, PS::Slice<u8>);
1051
1052array_type_validate_deref_data!(ClassCommonKey);
1053
1054impl<PS: ParseStrategy> ValidateArray<ClassKey<PS>, u8> for ClassCommonKey<PS> {
1055 type Error = anyhow::Error;
1056
1057 fn validate_array<'a>(_metadata: &'a ClassKey<PS>, _data: &'a [u8]) -> Result<(), Self::Error> {
1059 Ok(())
1060 }
1061}
1062
1063impl<PS: ParseStrategy> Counted for ClassCommonKey<PS>
1064where
1065 Array<PS, ClassKey<PS>, PS::Slice<u8>>: Parse<PS>,
1066 Array<PS, PS::Output<ClassMetadata>, PS::Slice<u8>>: Parse<PS>,
1067 ClassKey<PS>: Parse<PS>,
1068{
1069 fn count(&self) -> u32 {
1071 PS::deref(&self.metadata.metadata).elements_count.get()
1072 }
1073}
1074
1075array_type!(ClassKey, PS, PS::Output<ClassMetadata>, PS::Slice<u8>);
1076
1077array_type_validate_deref_both!(ClassKey);
1078
1079impl<PS: ParseStrategy> ValidateArray<ClassMetadata, u8> for ClassKey<PS> {
1080 type Error = anyhow::Error;
1081
1082 fn validate_array<'a>(
1084 _metadata: &'a ClassMetadata,
1085 _data: &'a [u8],
1086 ) -> Result<(), Self::Error> {
1087 Ok(())
1088 }
1089}
1090
1091impl<PS: ParseStrategy> Counted for ClassKey<PS>
1092where
1093 Array<PS, PS::Output<ClassMetadata>, PS::Slice<u8>>: Parse<PS>,
1094{
1095 fn count(&self) -> u32 {
1097 PS::deref(&self.metadata).common_key_length.get()
1098 }
1099}
1100
1101#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1102#[repr(C, packed)]
1103pub(super) struct ClassMetadata {
1104 key_length: le::U32,
1105 common_key_length: le::U32,
1106 id: le::U32,
1107 primary_names_count: le::U32,
1108 elements_count: le::U32,
1109 constraint_count: le::U32,
1110}
1111
1112impl Counted for ClassMetadata {
1113 fn count(&self) -> u32 {
1114 self.key_length.get()
1115 }
1116}
1117
1118impl Validate for ClassMetadata {
1119 type Error = anyhow::Error;
1120
1121 fn validate(&self) -> Result<(), Self::Error> {
1123 if self.id.get() == 0 {
1124 return Err(ValidateError::NonOptionalIdIsZero.into());
1125 } else {
1126 Ok(())
1127 }
1128 }
1129}
1130
1131impl<PS: ParseStrategy> Validate for [Role<PS>] {
1132 type Error = anyhow::Error;
1133
1134 fn validate(&self) -> Result<(), Self::Error> {
1136 Ok(())
1137 }
1138}
1139
1140#[derive(Debug, PartialEq)]
1141pub(super) struct Role<PS: ParseStrategy> {
1142 metadata: RoleMetadata<PS>,
1143 role_dominates: ExtensibleBitmap<PS>,
1144 role_types: ExtensibleBitmap<PS>,
1145}
1146
1147impl<PS: ParseStrategy> Role<PS> {
1148 pub(super) fn id(&self) -> RoleId {
1149 RoleId(NonZeroU32::new(PS::deref(&self.metadata.metadata).id.get()).unwrap())
1150 }
1151
1152 pub(super) fn name_bytes(&self) -> &[u8] {
1153 PS::deref_slice(&self.metadata.data)
1154 }
1155
1156 pub(super) fn types(&self) -> &ExtensibleBitmap<PS> {
1157 &self.role_types
1158 }
1159}
1160
1161impl<PS: ParseStrategy> Parse<PS> for Role<PS>
1162where
1163 RoleMetadata<PS>: Parse<PS>,
1164 ExtensibleBitmap<PS>: Parse<PS>,
1165{
1166 type Error = anyhow::Error;
1167
1168 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1169 let tail = bytes;
1170
1171 let (metadata, tail) = RoleMetadata::parse(tail)
1172 .map_err(Into::<anyhow::Error>::into)
1173 .context("parsing role metadata")?;
1174
1175 let (role_dominates, tail) = ExtensibleBitmap::parse(tail)
1176 .map_err(Into::<anyhow::Error>::into)
1177 .context("parsing role dominates")?;
1178
1179 let (role_types, tail) = ExtensibleBitmap::parse(tail)
1180 .map_err(Into::<anyhow::Error>::into)
1181 .context("parsing role types")?;
1182
1183 Ok((Self { metadata, role_dominates, role_types }, tail))
1184 }
1185}
1186
1187array_type!(RoleMetadata, PS, PS::Output<RoleStaticMetadata>, PS::Slice<u8>);
1188
1189array_type_validate_deref_both!(RoleMetadata);
1190
1191impl<PS: ParseStrategy> ValidateArray<RoleStaticMetadata, u8> for RoleMetadata<PS> {
1192 type Error = anyhow::Error;
1193
1194 fn validate_array<'a>(
1196 _metadata: &'a RoleStaticMetadata,
1197 _data: &'a [u8],
1198 ) -> Result<(), Self::Error> {
1199 Ok(())
1200 }
1201}
1202
1203#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1204#[repr(C, packed)]
1205pub(super) struct RoleStaticMetadata {
1206 length: le::U32,
1207 id: le::U32,
1208 bounds: le::U32,
1209}
1210
1211impl Counted for RoleStaticMetadata {
1212 fn count(&self) -> u32 {
1214 self.length.get()
1215 }
1216}
1217
1218impl Validate for RoleStaticMetadata {
1219 type Error = anyhow::Error;
1220
1221 fn validate(&self) -> Result<(), Self::Error> {
1223 Ok(())
1224 }
1225}
1226
1227impl<PS: ParseStrategy> Validate for [Type<PS>] {
1228 type Error = anyhow::Error;
1229
1230 fn validate(&self) -> Result<(), Self::Error> {
1232 Ok(())
1233 }
1234}
1235
1236array_type!(Type, PS, PS::Output<TypeMetadata>, PS::Slice<u8>);
1237
1238array_type_validate_deref_both!(Type);
1239
1240impl<PS: ParseStrategy> Type<PS> {
1241 pub fn name_bytes(&self) -> &[u8] {
1243 PS::deref_slice(&self.data)
1244 }
1245
1246 pub fn id(&self) -> TypeId {
1250 TypeId(NonZeroU32::new(PS::deref(&self.metadata).id.get()).unwrap())
1251 }
1252
1253 pub fn bounded_by(&self) -> Option<TypeId> {
1255 NonZeroU32::new(PS::deref(&self.metadata).bounds.get()).map(|id| TypeId(id))
1256 }
1257
1258 #[allow(dead_code)]
1262 pub fn is_type(&self) -> bool {
1263 PS::deref(&self.metadata).properties.get() == TYPE_PROPERTIES_TYPE
1264 }
1265
1266 #[allow(dead_code)]
1271 pub fn is_alias(&self) -> bool {
1272 PS::deref(&self.metadata).properties.get() == TYPE_PROPERTIES_ALIAS
1273 }
1274
1275 #[allow(dead_code)]
1279 pub fn is_attribute(&self) -> bool {
1280 PS::deref(&self.metadata).properties.get() == TYPE_PROPERTIES_ATTRIBUTE
1281 }
1282}
1283
1284impl<PS: ParseStrategy> ValidateArray<TypeMetadata, u8> for Type<PS> {
1285 type Error = anyhow::Error;
1286
1287 fn validate_array<'a>(_metadata: &'a TypeMetadata, _data: &'a [u8]) -> Result<(), Self::Error> {
1289 Ok(())
1290 }
1291}
1292
1293#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1294#[repr(C, packed)]
1295pub(super) struct TypeMetadata {
1296 length: le::U32,
1297 id: le::U32,
1298 properties: le::U32,
1299 bounds: le::U32,
1300}
1301
1302impl Counted for TypeMetadata {
1303 fn count(&self) -> u32 {
1304 self.length.get()
1305 }
1306}
1307
1308impl Validate for TypeMetadata {
1309 type Error = anyhow::Error;
1310
1311 fn validate(&self) -> Result<(), Self::Error> {
1313 Ok(())
1314 }
1315}
1316
1317impl<PS: ParseStrategy> Validate for [User<PS>] {
1318 type Error = anyhow::Error;
1319
1320 fn validate(&self) -> Result<(), Self::Error> {
1322 Ok(())
1323 }
1324}
1325
1326#[derive(Debug, PartialEq)]
1327pub(super) struct User<PS: ParseStrategy> {
1328 user_data: UserData<PS>,
1329 roles: ExtensibleBitmap<PS>,
1330 expanded_range: MlsRange<PS>,
1331 default_level: MlsLevel<PS>,
1332}
1333
1334impl<PS: ParseStrategy> User<PS> {
1335 pub(super) fn id(&self) -> UserId {
1336 UserId(NonZeroU32::new(PS::deref(&self.user_data.metadata).id.get()).unwrap())
1337 }
1338
1339 pub(super) fn name_bytes(&self) -> &[u8] {
1340 PS::deref_slice(&self.user_data.data)
1341 }
1342
1343 pub(super) fn roles(&self) -> &ExtensibleBitmap<PS> {
1344 &self.roles
1345 }
1346
1347 pub(super) fn mls_range(&self) -> &MlsRange<PS> {
1348 &self.expanded_range
1349 }
1350}
1351
1352impl<PS: ParseStrategy> Parse<PS> for User<PS>
1353where
1354 UserData<PS>: Parse<PS>,
1355 ExtensibleBitmap<PS>: Parse<PS>,
1356{
1357 type Error = anyhow::Error;
1358
1359 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1360 let tail = bytes;
1361
1362 let (user_data, tail) = UserData::parse(tail)
1363 .map_err(Into::<anyhow::Error>::into)
1364 .context("parsing user data")?;
1365
1366 let (roles, tail) = ExtensibleBitmap::parse(tail)
1367 .map_err(Into::<anyhow::Error>::into)
1368 .context("parsing user roles")?;
1369
1370 let (expanded_range, tail) =
1371 MlsRange::parse(tail).context("parsing user expanded range")?;
1372
1373 let (default_level, tail) = MlsLevel::parse(tail).context("parsing user default level")?;
1374
1375 Ok((Self { user_data, roles, expanded_range, default_level }, tail))
1376 }
1377}
1378
1379array_type!(UserData, PS, PS::Output<UserMetadata>, PS::Slice<u8>);
1380
1381array_type_validate_deref_both!(UserData);
1382
1383impl<PS: ParseStrategy> ValidateArray<UserMetadata, u8> for UserData<PS> {
1384 type Error = anyhow::Error;
1385
1386 fn validate_array<'a>(_metadata: &'a UserMetadata, _data: &'a [u8]) -> Result<(), Self::Error> {
1388 Ok(())
1389 }
1390}
1391
1392#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1393#[repr(C, packed)]
1394pub(super) struct UserMetadata {
1395 length: le::U32,
1396 id: le::U32,
1397 bounds: le::U32,
1398}
1399
1400impl Counted for UserMetadata {
1401 fn count(&self) -> u32 {
1402 self.length.get()
1403 }
1404}
1405
1406impl Validate for UserMetadata {
1407 type Error = anyhow::Error;
1408
1409 fn validate(&self) -> Result<(), Self::Error> {
1411 Ok(())
1412 }
1413}
1414
1415#[derive(Debug, PartialEq)]
1416pub(super) struct MlsLevel<PS: ParseStrategy> {
1417 sensitivity: PS::Output<le::U32>,
1418 categories: ExtensibleBitmap<PS>,
1419}
1420
1421impl<PS: ParseStrategy> MlsLevel<PS> {
1422 pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_, PS> {
1423 self.categories.spans().flat_map(|span| {
1424 (span.low..=span.high).map(|i| CategoryId(NonZeroU32::new(i + 1).unwrap()))
1425 })
1426 }
1427}
1428
1429impl<PS: ParseStrategy> Parse<PS> for MlsLevel<PS>
1430where
1431 ExtensibleBitmap<PS>: Parse<PS>,
1432{
1433 type Error = anyhow::Error;
1434
1435 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1436 let tail = bytes;
1437
1438 let num_bytes = tail.len();
1439 let (sensitivity, tail) = PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1440 type_name: "MlsLevelSensitivity",
1441 type_size: std::mem::size_of::<le::U32>(),
1442 num_bytes,
1443 })?;
1444
1445 let (categories, tail) = ExtensibleBitmap::parse(tail)
1446 .map_err(Into::<anyhow::Error>::into)
1447 .context("parsing mls level categories")?;
1448
1449 Ok((Self { sensitivity, categories }, tail))
1450 }
1451}
1452
1453impl<'a, PS: ParseStrategy> Level<'a, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a, PS>>
1454 for MlsLevel<PS>
1455{
1456 fn sensitivity(&self) -> SensitivityId {
1457 SensitivityId(NonZeroU32::new(PS::deref(&self.sensitivity).get()).unwrap())
1458 }
1459
1460 fn category_spans(
1461 &'a self,
1462 ) -> CategoryIterator<ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a, PS>> {
1463 CategoryIterator::new(self.categories.spans())
1464 }
1465}
1466
1467#[derive(Debug, PartialEq)]
1468pub(super) struct MlsRange<PS: ParseStrategy> {
1469 count: PS::Output<le::U32>,
1470 low: MlsLevel<PS>,
1471 high: Option<MlsLevel<PS>>,
1472}
1473
1474impl<PS: ParseStrategy> MlsRange<PS> {
1475 pub fn low(&self) -> &MlsLevel<PS> {
1476 &self.low
1477 }
1478
1479 pub fn high(&self) -> &Option<MlsLevel<PS>> {
1480 &self.high
1481 }
1482}
1483
1484impl<PS: ParseStrategy> Parse<PS> for MlsRange<PS>
1485where
1486 ExtensibleBitmap<PS>: Parse<PS>,
1487{
1488 type Error = anyhow::Error;
1489
1490 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1491 let tail = bytes;
1492
1493 let num_bytes = tail.len();
1494 let (count, tail) = PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1495 type_name: "MlsLevelCount",
1496 type_size: std::mem::size_of::<le::U32>(),
1497 num_bytes,
1498 })?;
1499
1500 let num_bytes = tail.len();
1504 let (sensitivity_low, tail) =
1505 PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1506 type_name: "MlsLevelSensitivityLow",
1507 type_size: std::mem::size_of::<le::U32>(),
1508 num_bytes,
1509 })?;
1510
1511 let (low_categories, high_level, tail) = if PS::deref(&count).get() > 1 {
1512 let num_bytes = tail.len();
1513 let (sensitivity_high, tail) =
1514 PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1515 type_name: "MlsLevelSensitivityHigh",
1516 type_size: std::mem::size_of::<le::U32>(),
1517 num_bytes,
1518 })?;
1519 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1520 .map_err(Into::<anyhow::Error>::into)
1521 .context("parsing mls range low categories")?;
1522 let (high_categories, tail) = ExtensibleBitmap::parse(tail)
1523 .map_err(Into::<anyhow::Error>::into)
1524 .context("parsing mls range high categories")?;
1525
1526 (
1527 low_categories,
1528 Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
1529 tail,
1530 )
1531 } else {
1532 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1533 .map_err(Into::<anyhow::Error>::into)
1534 .context("parsing mls range low categories")?;
1535
1536 (low_categories, None, tail)
1537 };
1538
1539 Ok((
1540 Self {
1541 count,
1542 low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
1543 high: high_level,
1544 },
1545 tail,
1546 ))
1547 }
1548}
1549
1550impl<PS: ParseStrategy> Validate for [ConditionalBoolean<PS>] {
1551 type Error = anyhow::Error;
1552
1553 fn validate(&self) -> Result<(), Self::Error> {
1555 Ok(())
1556 }
1557}
1558
1559array_type!(ConditionalBoolean, PS, PS::Output<ConditionalBooleanMetadata>, PS::Slice<u8>);
1560
1561array_type_validate_deref_both!(ConditionalBoolean);
1562
1563impl<PS: ParseStrategy> ValidateArray<ConditionalBooleanMetadata, u8> for ConditionalBoolean<PS> {
1564 type Error = anyhow::Error;
1565
1566 fn validate_array<'a>(
1568 _metadata: &'a ConditionalBooleanMetadata,
1569 _data: &'a [u8],
1570 ) -> Result<(), Self::Error> {
1571 Ok(())
1572 }
1573}
1574
1575#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1576#[repr(C, packed)]
1577pub(super) struct ConditionalBooleanMetadata {
1578 id: le::U32,
1579 active: le::U32,
1581 length: le::U32,
1582}
1583
1584impl ConditionalBooleanMetadata {
1585 pub(super) fn active(&self) -> bool {
1587 self.active != le::U32::ZERO
1588 }
1589}
1590
1591impl Counted for ConditionalBooleanMetadata {
1592 fn count(&self) -> u32 {
1595 self.length.get()
1596 }
1597}
1598
1599impl Validate for ConditionalBooleanMetadata {
1600 type Error = anyhow::Error;
1601
1602 fn validate(&self) -> Result<(), Self::Error> {
1604 Ok(())
1605 }
1606}
1607
1608impl<PS: ParseStrategy> Validate for [Sensitivity<PS>] {
1609 type Error = anyhow::Error;
1610
1611 fn validate(&self) -> Result<(), Self::Error> {
1613 Ok(())
1614 }
1615}
1616
1617#[derive(Debug, PartialEq)]
1618pub(super) struct Sensitivity<PS: ParseStrategy> {
1619 metadata: SensitivityMetadata<PS>,
1620 level: MlsLevel<PS>,
1621}
1622
1623impl<PS: ParseStrategy> Sensitivity<PS> {
1624 pub fn id(&self) -> SensitivityId {
1625 SensitivityId(NonZeroU32::new(PS::deref(&self.level.sensitivity).get()).unwrap())
1626 }
1627
1628 pub fn name_bytes(&self) -> &[u8] {
1629 PS::deref_slice(&self.metadata.data)
1630 }
1631}
1632
1633impl<PS: ParseStrategy> Parse<PS> for Sensitivity<PS>
1634where
1635 SensitivityMetadata<PS>: Parse<PS>,
1636 MlsLevel<PS>: Parse<PS>,
1637{
1638 type Error = anyhow::Error;
1639
1640 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1641 let tail = bytes;
1642
1643 let (metadata, tail) = SensitivityMetadata::parse(tail)
1644 .map_err(Into::<anyhow::Error>::into)
1645 .context("parsing sensitivity metadata")?;
1646
1647 let (level, tail) = MlsLevel::parse(tail)
1648 .map_err(Into::<anyhow::Error>::into)
1649 .context("parsing sensitivity mls level")?;
1650
1651 Ok((Self { metadata, level }, tail))
1652 }
1653}
1654
1655impl<PS: ParseStrategy> Validate for Sensitivity<PS> {
1656 type Error = anyhow::Error;
1657
1658 fn validate(&self) -> Result<(), Self::Error> {
1660 NonZeroU32::new(PS::deref(&self.level.sensitivity).get())
1661 .ok_or(ValidateError::NonOptionalIdIsZero)?;
1662 Ok(())
1663 }
1664}
1665
1666array_type!(SensitivityMetadata, PS, PS::Output<SensitivityStaticMetadata>, PS::Slice<u8>);
1667
1668array_type_validate_deref_both!(SensitivityMetadata);
1669
1670impl<PS: ParseStrategy> ValidateArray<SensitivityStaticMetadata, u8> for SensitivityMetadata<PS> {
1671 type Error = anyhow::Error;
1672
1673 fn validate_array<'a>(
1675 _metadata: &'a SensitivityStaticMetadata,
1676 _data: &'a [u8],
1677 ) -> Result<(), Self::Error> {
1678 Ok(())
1679 }
1680}
1681
1682#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1683#[repr(C, packed)]
1684pub(super) struct SensitivityStaticMetadata {
1685 length: le::U32,
1686 is_alias: le::U32,
1687}
1688
1689impl Counted for SensitivityStaticMetadata {
1690 fn count(&self) -> u32 {
1693 self.length.get()
1694 }
1695}
1696
1697impl Validate for SensitivityStaticMetadata {
1698 type Error = anyhow::Error;
1699
1700 fn validate(&self) -> Result<(), Self::Error> {
1702 Ok(())
1703 }
1704}
1705
1706impl<PS: ParseStrategy> Validate for [Category<PS>] {
1707 type Error = anyhow::Error;
1708
1709 fn validate(&self) -> Result<(), Self::Error> {
1711 Ok(())
1712 }
1713}
1714
1715array_type!(Category, PS, PS::Output<CategoryMetadata>, PS::Slice<u8>);
1716
1717array_type_validate_deref_both!(Category);
1718
1719impl<PS: ParseStrategy> Category<PS> {
1720 pub fn id(&self) -> CategoryId {
1721 CategoryId(NonZeroU32::new(PS::deref(&self.metadata).id.get()).unwrap())
1722 }
1723
1724 pub fn name_bytes(&self) -> &[u8] {
1725 PS::deref_slice(&self.data)
1726 }
1727}
1728
1729impl<PS: ParseStrategy> ValidateArray<CategoryMetadata, u8> for Category<PS> {
1730 type Error = anyhow::Error;
1731
1732 fn validate_array<'a>(
1734 _metadata: &'a CategoryMetadata,
1735 _data: &'a [u8],
1736 ) -> Result<(), Self::Error> {
1737 Ok(())
1738 }
1739}
1740
1741#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1742#[repr(C, packed)]
1743pub(super) struct CategoryMetadata {
1744 length: le::U32,
1745 id: le::U32,
1746 is_alias: le::U32,
1747}
1748
1749impl Counted for CategoryMetadata {
1750 fn count(&self) -> u32 {
1753 self.length.get()
1754 }
1755}
1756
1757impl Validate for CategoryMetadata {
1758 type Error = anyhow::Error;
1759
1760 fn validate(&self) -> Result<(), Self::Error> {
1762 NonZeroU32::new(self.id.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1763 Ok(())
1764 }
1765}
1766
1767#[cfg(test)]
1768mod tests {
1769 use super::super::security_context::Level;
1770 use super::super::{parse_policy_by_reference, CategoryId, SensitivityId, UserId};
1771 use super::*;
1772
1773 use std::num::NonZeroU32;
1774
1775 #[test]
1776 fn mls_levels_for_user_context() {
1777 const TEST_POLICY: &[u8] = include_bytes! {"../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"};
1778 let policy = parse_policy_by_reference(TEST_POLICY).unwrap().validate().unwrap();
1779 let parsed_policy = policy.0.parsed_policy();
1780
1781 let user = parsed_policy.user(UserId(NonZeroU32::new(1).expect("user with id 1")));
1782 let mls_range = user.mls_range();
1783 let low_level = mls_range.low();
1784 let high_level = mls_range.high().as_ref().expect("user 1 has a high mls level");
1785
1786 assert_eq!(low_level.sensitivity(), SensitivityId(NonZeroU32::new(1).unwrap()));
1787 assert_eq!(
1788 low_level.category_ids().collect::<Vec<_>>(),
1789 vec![CategoryId(NonZeroU32::new(1).unwrap())]
1790 );
1791
1792 assert_eq!(high_level.sensitivity(), SensitivityId(NonZeroU32::new(2).unwrap()));
1793 assert_eq!(
1794 high_level.category_ids().collect::<Vec<_>>(),
1795 vec![
1796 CategoryId(NonZeroU32::new(1).unwrap()),
1797 CategoryId(NonZeroU32::new(2).unwrap()),
1798 CategoryId(NonZeroU32::new(3).unwrap()),
1799 CategoryId(NonZeroU32::new(4).unwrap()),
1800 CategoryId(NonZeroU32::new(5).unwrap()),
1801 ]
1802 );
1803 }
1804
1805 #[test]
1806 fn parse_mls_constrain_statement() {
1807 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1808 let policy = parse_policy_by_reference(policy_bytes.as_slice()).expect("parse policy");
1809 let parsed_policy = &policy.0;
1810 Validate::validate(parsed_policy).expect("validate policy");
1811
1812 let class = find_class_by_name(parsed_policy.classes(), "class_mls_constraints")
1813 .expect("look up class");
1814 let constraints = class.constraints();
1815 assert_eq!(constraints.len(), 6);
1816 let expected = [
1823 (
1824 CONSTRAINT_TERM_TYPE_EXPR,
1825 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1826 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1,
1827 ),
1828 (
1829 CONSTRAINT_TERM_TYPE_EXPR,
1830 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1831 CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2,
1832 ),
1833 (
1834 CONSTRAINT_TERM_TYPE_EXPR,
1835 CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY,
1836 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2,
1837 ),
1838 (
1839 CONSTRAINT_TERM_TYPE_EXPR,
1840 CONSTRAINT_EXPR_OPERATOR_TYPE_DOM,
1841 CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2,
1842 ),
1843 (
1844 CONSTRAINT_TERM_TYPE_EXPR,
1845 CONSTRAINT_EXPR_OPERATOR_TYPE_NE,
1846 CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2,
1847 ),
1848 (
1849 CONSTRAINT_TERM_TYPE_EXPR,
1850 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1851 CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2,
1852 ),
1853 ];
1854 for (i, constraint) in constraints.iter().enumerate() {
1855 assert_eq!(constraint.access_vector(), AccessVector(1), "constraint {}", i);
1856 let terms = constraint.constraint_expr().constraint_terms();
1857 assert_eq!(terms.len(), 1, "constraint {}", i);
1858 let term = &terms[0];
1859 assert_eq!(
1860 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1861 expected[i],
1862 "constraint {}",
1863 i
1864 );
1865 }
1866 }
1867
1868 #[test]
1869 fn parse_constrain_statement() {
1870 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1871 let policy = parse_policy_by_reference(policy_bytes.as_slice()).expect("parse policy");
1872 let parsed_policy = &policy.0;
1873 Validate::validate(parsed_policy).expect("validate policy");
1874
1875 let class = find_class_by_name(parsed_policy.classes(), "class_constraint_nested")
1876 .expect("look up class");
1877 let constraints = class.constraints();
1878 assert_eq!(constraints.len(), 1);
1879 let constraint = &constraints[0];
1880 assert_eq!(constraint.access_vector(), AccessVector(1));
1881 let terms = constraint.constraint_expr().constraint_terms();
1882 assert_eq!(terms.len(), 8);
1883
1884 let expected = [
1890 (
1891 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES,
1892 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1893 CONSTRAINT_EXPR_OPERAND_TYPE_USER
1894 | CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK,
1895 ),
1896 (
1897 CONSTRAINT_TERM_TYPE_EXPR,
1898 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1899 CONSTRAINT_EXPR_OPERAND_TYPE_ROLE,
1900 ),
1901 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1902 (
1903 CONSTRAINT_TERM_TYPE_EXPR,
1904 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1905 CONSTRAINT_EXPR_OPERAND_TYPE_USER,
1906 ),
1907 (
1908 CONSTRAINT_TERM_TYPE_EXPR,
1909 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1910 CONSTRAINT_EXPR_OPERAND_TYPE_TYPE,
1911 ),
1912 (CONSTRAINT_TERM_TYPE_NOT_OPERATOR, 0, 0),
1913 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1914 (CONSTRAINT_TERM_TYPE_OR_OPERATOR, 0, 0),
1915 ];
1916 for (i, term) in terms.iter().enumerate() {
1917 assert_eq!(
1918 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1919 expected[i],
1920 "term {}",
1921 i
1922 );
1923 }
1924 }
1925}