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