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 pub(super) fn types(&self) -> &ExtensibleBitmap<PS> {
1160 &self.role_types
1161 }
1162}
1163
1164impl<PS: ParseStrategy> Parse<PS> for Role<PS>
1165where
1166 RoleMetadata<PS>: Parse<PS>,
1167 ExtensibleBitmap<PS>: Parse<PS>,
1168{
1169 type Error = anyhow::Error;
1170
1171 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1172 let tail = bytes;
1173
1174 let (metadata, tail) = RoleMetadata::parse(tail)
1175 .map_err(Into::<anyhow::Error>::into)
1176 .context("parsing role metadata")?;
1177
1178 let (role_dominates, tail) = ExtensibleBitmap::parse(tail)
1179 .map_err(Into::<anyhow::Error>::into)
1180 .context("parsing role dominates")?;
1181
1182 let (role_types, tail) = ExtensibleBitmap::parse(tail)
1183 .map_err(Into::<anyhow::Error>::into)
1184 .context("parsing role types")?;
1185
1186 Ok((Self { metadata, role_dominates, role_types }, tail))
1187 }
1188}
1189
1190array_type!(RoleMetadata, PS, PS::Output<RoleStaticMetadata>, PS::Slice<u8>);
1191
1192array_type_validate_deref_both!(RoleMetadata);
1193
1194impl<PS: ParseStrategy> ValidateArray<RoleStaticMetadata, u8> for RoleMetadata<PS> {
1195 type Error = anyhow::Error;
1196
1197 fn validate_array<'a>(
1199 _metadata: &'a RoleStaticMetadata,
1200 _data: &'a [u8],
1201 ) -> Result<(), Self::Error> {
1202 Ok(())
1203 }
1204}
1205
1206#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1207#[repr(C, packed)]
1208pub(super) struct RoleStaticMetadata {
1209 length: le::U32,
1210 id: le::U32,
1211 bounds: le::U32,
1212}
1213
1214impl Counted for RoleStaticMetadata {
1215 fn count(&self) -> u32 {
1217 self.length.get()
1218 }
1219}
1220
1221impl Validate for RoleStaticMetadata {
1222 type Error = anyhow::Error;
1223
1224 fn validate(&self) -> Result<(), Self::Error> {
1226 Ok(())
1227 }
1228}
1229
1230#[allow(dead_code)]
1236pub(super) fn type_has_attribute<'a, PS: ParseStrategy>(
1237 ty: &'a Type<PS>,
1238 attr: &'a Type<PS>,
1239 attribute_maps: &Vec<ExtensibleBitmap<PS>>,
1240) -> bool {
1241 let type_id = PS::deref(&ty.metadata).id.get();
1242 let type_index = type_id - 1;
1243
1244 let attribute_id = PS::deref(&attr.metadata).id.get();
1245 let attribute_index = attribute_id - 1;
1246
1247 attribute_maps[type_index as usize].is_set(attribute_index)
1248}
1249
1250impl<PS: ParseStrategy> Validate for [Type<PS>] {
1251 type Error = anyhow::Error;
1252
1253 fn validate(&self) -> Result<(), Self::Error> {
1255 Ok(())
1256 }
1257}
1258
1259array_type!(Type, PS, PS::Output<TypeMetadata>, PS::Slice<u8>);
1260
1261array_type_validate_deref_both!(Type);
1262
1263impl<PS: ParseStrategy> Type<PS> {
1264 pub fn name_bytes(&self) -> &[u8] {
1266 PS::deref_slice(&self.data)
1267 }
1268
1269 pub fn id(&self) -> TypeId {
1273 TypeId(NonZeroU32::new(PS::deref(&self.metadata).id.get()).unwrap())
1274 }
1275
1276 pub fn bounded_by(&self) -> Option<TypeId> {
1278 NonZeroU32::new(PS::deref(&self.metadata).bounds.get()).map(|id| TypeId(id))
1279 }
1280
1281 #[allow(dead_code)]
1285 pub fn is_type(&self) -> bool {
1286 PS::deref(&self.metadata).properties.get() == TYPE_PROPERTIES_TYPE
1287 }
1288
1289 #[allow(dead_code)]
1294 pub fn is_alias(&self) -> bool {
1295 PS::deref(&self.metadata).properties.get() == TYPE_PROPERTIES_ALIAS
1296 }
1297
1298 #[allow(dead_code)]
1302 pub fn is_attribute(&self) -> bool {
1303 PS::deref(&self.metadata).properties.get() == TYPE_PROPERTIES_ATTRIBUTE
1304 }
1305}
1306
1307impl<PS: ParseStrategy> ValidateArray<TypeMetadata, u8> for Type<PS> {
1308 type Error = anyhow::Error;
1309
1310 fn validate_array<'a>(_metadata: &'a TypeMetadata, _data: &'a [u8]) -> Result<(), Self::Error> {
1312 Ok(())
1313 }
1314}
1315
1316#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1317#[repr(C, packed)]
1318pub(super) struct TypeMetadata {
1319 length: le::U32,
1320 id: le::U32,
1321 properties: le::U32,
1322 bounds: le::U32,
1323}
1324
1325impl Counted for TypeMetadata {
1326 fn count(&self) -> u32 {
1327 self.length.get()
1328 }
1329}
1330
1331impl Validate for TypeMetadata {
1332 type Error = anyhow::Error;
1333
1334 fn validate(&self) -> Result<(), Self::Error> {
1336 Ok(())
1337 }
1338}
1339
1340impl<PS: ParseStrategy> Validate for [User<PS>] {
1341 type Error = anyhow::Error;
1342
1343 fn validate(&self) -> Result<(), Self::Error> {
1345 Ok(())
1346 }
1347}
1348
1349#[derive(Debug, PartialEq)]
1350pub(super) struct User<PS: ParseStrategy> {
1351 user_data: UserData<PS>,
1352 roles: ExtensibleBitmap<PS>,
1353 expanded_range: MlsRange<PS>,
1354 default_level: MlsLevel<PS>,
1355}
1356
1357impl<PS: ParseStrategy> User<PS> {
1358 pub(super) fn id(&self) -> UserId {
1359 UserId(NonZeroU32::new(PS::deref(&self.user_data.metadata).id.get()).unwrap())
1360 }
1361
1362 pub(super) fn name_bytes(&self) -> &[u8] {
1363 PS::deref_slice(&self.user_data.data)
1364 }
1365
1366 pub(super) fn roles(&self) -> &ExtensibleBitmap<PS> {
1367 &self.roles
1368 }
1369
1370 pub(super) fn mls_range(&self) -> &MlsRange<PS> {
1371 &self.expanded_range
1372 }
1373}
1374
1375impl<PS: ParseStrategy> Parse<PS> for User<PS>
1376where
1377 UserData<PS>: Parse<PS>,
1378 ExtensibleBitmap<PS>: Parse<PS>,
1379{
1380 type Error = anyhow::Error;
1381
1382 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1383 let tail = bytes;
1384
1385 let (user_data, tail) = UserData::parse(tail)
1386 .map_err(Into::<anyhow::Error>::into)
1387 .context("parsing user data")?;
1388
1389 let (roles, tail) = ExtensibleBitmap::parse(tail)
1390 .map_err(Into::<anyhow::Error>::into)
1391 .context("parsing user roles")?;
1392
1393 let (expanded_range, tail) =
1394 MlsRange::parse(tail).context("parsing user expanded range")?;
1395
1396 let (default_level, tail) = MlsLevel::parse(tail).context("parsing user default level")?;
1397
1398 Ok((Self { user_data, roles, expanded_range, default_level }, tail))
1399 }
1400}
1401
1402array_type!(UserData, PS, PS::Output<UserMetadata>, PS::Slice<u8>);
1403
1404array_type_validate_deref_both!(UserData);
1405
1406impl<PS: ParseStrategy> ValidateArray<UserMetadata, u8> for UserData<PS> {
1407 type Error = anyhow::Error;
1408
1409 fn validate_array<'a>(_metadata: &'a UserMetadata, _data: &'a [u8]) -> Result<(), Self::Error> {
1411 Ok(())
1412 }
1413}
1414
1415#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1416#[repr(C, packed)]
1417pub(super) struct UserMetadata {
1418 length: le::U32,
1419 id: le::U32,
1420 bounds: le::U32,
1421}
1422
1423impl Counted for UserMetadata {
1424 fn count(&self) -> u32 {
1425 self.length.get()
1426 }
1427}
1428
1429impl Validate for UserMetadata {
1430 type Error = anyhow::Error;
1431
1432 fn validate(&self) -> Result<(), Self::Error> {
1434 Ok(())
1435 }
1436}
1437
1438#[derive(Debug, PartialEq)]
1439pub(super) struct MlsLevel<PS: ParseStrategy> {
1440 sensitivity: PS::Output<le::U32>,
1441 categories: ExtensibleBitmap<PS>,
1442}
1443
1444impl<PS: ParseStrategy> MlsLevel<PS> {
1445 pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_, PS> {
1446 self.categories.spans().flat_map(|span| {
1447 (span.low..=span.high).map(|i| CategoryId(NonZeroU32::new(i + 1).unwrap()))
1448 })
1449 }
1450}
1451
1452impl<PS: ParseStrategy> Parse<PS> for MlsLevel<PS>
1453where
1454 ExtensibleBitmap<PS>: Parse<PS>,
1455{
1456 type Error = anyhow::Error;
1457
1458 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1459 let tail = bytes;
1460
1461 let num_bytes = tail.len();
1462 let (sensitivity, tail) = PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1463 type_name: "MlsLevelSensitivity",
1464 type_size: std::mem::size_of::<le::U32>(),
1465 num_bytes,
1466 })?;
1467
1468 let (categories, tail) = ExtensibleBitmap::parse(tail)
1469 .map_err(Into::<anyhow::Error>::into)
1470 .context("parsing mls level categories")?;
1471
1472 Ok((Self { sensitivity, categories }, tail))
1473 }
1474}
1475
1476impl<'a, PS: ParseStrategy> Level<'a, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a, PS>>
1477 for MlsLevel<PS>
1478{
1479 fn sensitivity(&self) -> SensitivityId {
1480 SensitivityId(NonZeroU32::new(PS::deref(&self.sensitivity).get()).unwrap())
1481 }
1482
1483 fn category_spans(
1484 &'a self,
1485 ) -> CategoryIterator<ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a, PS>> {
1486 CategoryIterator::new(self.categories.spans())
1487 }
1488}
1489
1490#[derive(Debug, PartialEq)]
1491pub(super) struct MlsRange<PS: ParseStrategy> {
1492 count: PS::Output<le::U32>,
1493 low: MlsLevel<PS>,
1494 high: Option<MlsLevel<PS>>,
1495}
1496
1497impl<PS: ParseStrategy> MlsRange<PS> {
1498 pub fn low(&self) -> &MlsLevel<PS> {
1499 &self.low
1500 }
1501
1502 pub fn high(&self) -> &Option<MlsLevel<PS>> {
1503 &self.high
1504 }
1505}
1506
1507impl<PS: ParseStrategy> Parse<PS> for MlsRange<PS>
1508where
1509 ExtensibleBitmap<PS>: Parse<PS>,
1510{
1511 type Error = anyhow::Error;
1512
1513 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1514 let tail = bytes;
1515
1516 let num_bytes = tail.len();
1517 let (count, tail) = PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1518 type_name: "MlsLevelCount",
1519 type_size: std::mem::size_of::<le::U32>(),
1520 num_bytes,
1521 })?;
1522
1523 let num_bytes = tail.len();
1527 let (sensitivity_low, tail) =
1528 PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1529 type_name: "MlsLevelSensitivityLow",
1530 type_size: std::mem::size_of::<le::U32>(),
1531 num_bytes,
1532 })?;
1533
1534 let (low_categories, high_level, tail) = if PS::deref(&count).get() > 1 {
1535 let num_bytes = tail.len();
1536 let (sensitivity_high, tail) =
1537 PS::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1538 type_name: "MlsLevelSensitivityHigh",
1539 type_size: std::mem::size_of::<le::U32>(),
1540 num_bytes,
1541 })?;
1542 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1543 .map_err(Into::<anyhow::Error>::into)
1544 .context("parsing mls range low categories")?;
1545 let (high_categories, tail) = ExtensibleBitmap::parse(tail)
1546 .map_err(Into::<anyhow::Error>::into)
1547 .context("parsing mls range high categories")?;
1548
1549 (
1550 low_categories,
1551 Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
1552 tail,
1553 )
1554 } else {
1555 let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1556 .map_err(Into::<anyhow::Error>::into)
1557 .context("parsing mls range low categories")?;
1558
1559 (low_categories, None, tail)
1560 };
1561
1562 Ok((
1563 Self {
1564 count,
1565 low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
1566 high: high_level,
1567 },
1568 tail,
1569 ))
1570 }
1571}
1572
1573impl<PS: ParseStrategy> Validate for [ConditionalBoolean<PS>] {
1574 type Error = anyhow::Error;
1575
1576 fn validate(&self) -> Result<(), Self::Error> {
1578 Ok(())
1579 }
1580}
1581
1582array_type!(ConditionalBoolean, PS, PS::Output<ConditionalBooleanMetadata>, PS::Slice<u8>);
1583
1584array_type_validate_deref_both!(ConditionalBoolean);
1585
1586impl<PS: ParseStrategy> ValidateArray<ConditionalBooleanMetadata, u8> for ConditionalBoolean<PS> {
1587 type Error = anyhow::Error;
1588
1589 fn validate_array<'a>(
1591 _metadata: &'a ConditionalBooleanMetadata,
1592 _data: &'a [u8],
1593 ) -> Result<(), Self::Error> {
1594 Ok(())
1595 }
1596}
1597
1598#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1599#[repr(C, packed)]
1600pub(super) struct ConditionalBooleanMetadata {
1601 id: le::U32,
1602 active: le::U32,
1604 length: le::U32,
1605}
1606
1607impl ConditionalBooleanMetadata {
1608 pub(super) fn active(&self) -> bool {
1610 self.active != le::U32::ZERO
1611 }
1612}
1613
1614impl Counted for ConditionalBooleanMetadata {
1615 fn count(&self) -> u32 {
1618 self.length.get()
1619 }
1620}
1621
1622impl Validate for ConditionalBooleanMetadata {
1623 type Error = anyhow::Error;
1624
1625 fn validate(&self) -> Result<(), Self::Error> {
1627 Ok(())
1628 }
1629}
1630
1631impl<PS: ParseStrategy> Validate for [Sensitivity<PS>] {
1632 type Error = anyhow::Error;
1633
1634 fn validate(&self) -> Result<(), Self::Error> {
1636 Ok(())
1637 }
1638}
1639
1640#[derive(Debug, PartialEq)]
1641pub(super) struct Sensitivity<PS: ParseStrategy> {
1642 metadata: SensitivityMetadata<PS>,
1643 level: MlsLevel<PS>,
1644}
1645
1646impl<PS: ParseStrategy> Sensitivity<PS> {
1647 pub fn id(&self) -> SensitivityId {
1648 SensitivityId(NonZeroU32::new(PS::deref(&self.level.sensitivity).get()).unwrap())
1649 }
1650
1651 pub fn name_bytes(&self) -> &[u8] {
1652 PS::deref_slice(&self.metadata.data)
1653 }
1654}
1655
1656impl<PS: ParseStrategy> Parse<PS> for Sensitivity<PS>
1657where
1658 SensitivityMetadata<PS>: Parse<PS>,
1659 MlsLevel<PS>: Parse<PS>,
1660{
1661 type Error = anyhow::Error;
1662
1663 fn parse(bytes: PS) -> Result<(Self, PS), Self::Error> {
1664 let tail = bytes;
1665
1666 let (metadata, tail) = SensitivityMetadata::parse(tail)
1667 .map_err(Into::<anyhow::Error>::into)
1668 .context("parsing sensitivity metadata")?;
1669
1670 let (level, tail) = MlsLevel::parse(tail)
1671 .map_err(Into::<anyhow::Error>::into)
1672 .context("parsing sensitivity mls level")?;
1673
1674 Ok((Self { metadata, level }, tail))
1675 }
1676}
1677
1678impl<PS: ParseStrategy> Validate for Sensitivity<PS> {
1679 type Error = anyhow::Error;
1680
1681 fn validate(&self) -> Result<(), Self::Error> {
1683 NonZeroU32::new(PS::deref(&self.level.sensitivity).get())
1684 .ok_or(ValidateError::NonOptionalIdIsZero)?;
1685 Ok(())
1686 }
1687}
1688
1689array_type!(SensitivityMetadata, PS, PS::Output<SensitivityStaticMetadata>, PS::Slice<u8>);
1690
1691array_type_validate_deref_both!(SensitivityMetadata);
1692
1693impl<PS: ParseStrategy> ValidateArray<SensitivityStaticMetadata, u8> for SensitivityMetadata<PS> {
1694 type Error = anyhow::Error;
1695
1696 fn validate_array<'a>(
1698 _metadata: &'a SensitivityStaticMetadata,
1699 _data: &'a [u8],
1700 ) -> Result<(), Self::Error> {
1701 Ok(())
1702 }
1703}
1704
1705#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1706#[repr(C, packed)]
1707pub(super) struct SensitivityStaticMetadata {
1708 length: le::U32,
1709 is_alias: le::U32,
1710}
1711
1712impl Counted for SensitivityStaticMetadata {
1713 fn count(&self) -> u32 {
1716 self.length.get()
1717 }
1718}
1719
1720impl Validate for SensitivityStaticMetadata {
1721 type Error = anyhow::Error;
1722
1723 fn validate(&self) -> Result<(), Self::Error> {
1725 Ok(())
1726 }
1727}
1728
1729impl<PS: ParseStrategy> Validate for [Category<PS>] {
1730 type Error = anyhow::Error;
1731
1732 fn validate(&self) -> Result<(), Self::Error> {
1734 Ok(())
1735 }
1736}
1737
1738array_type!(Category, PS, PS::Output<CategoryMetadata>, PS::Slice<u8>);
1739
1740array_type_validate_deref_both!(Category);
1741
1742impl<PS: ParseStrategy> Category<PS> {
1743 pub fn id(&self) -> CategoryId {
1744 CategoryId(NonZeroU32::new(PS::deref(&self.metadata).id.get()).unwrap())
1745 }
1746
1747 pub fn name_bytes(&self) -> &[u8] {
1748 PS::deref_slice(&self.data)
1749 }
1750}
1751
1752impl<PS: ParseStrategy> ValidateArray<CategoryMetadata, u8> for Category<PS> {
1753 type Error = anyhow::Error;
1754
1755 fn validate_array<'a>(
1757 _metadata: &'a CategoryMetadata,
1758 _data: &'a [u8],
1759 ) -> Result<(), Self::Error> {
1760 Ok(())
1761 }
1762}
1763
1764#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1765#[repr(C, packed)]
1766pub(super) struct CategoryMetadata {
1767 length: le::U32,
1768 id: le::U32,
1769 is_alias: le::U32,
1770}
1771
1772impl Counted for CategoryMetadata {
1773 fn count(&self) -> u32 {
1776 self.length.get()
1777 }
1778}
1779
1780impl Validate for CategoryMetadata {
1781 type Error = anyhow::Error;
1782
1783 fn validate(&self) -> Result<(), Self::Error> {
1785 NonZeroU32::new(self.id.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1786 Ok(())
1787 }
1788}
1789
1790#[cfg(test)]
1791mod tests {
1792 use super::super::security_context::Level;
1793 use super::super::{parse_policy_by_reference, CategoryId, SensitivityId, UserId};
1794 use super::*;
1795
1796 use std::num::NonZeroU32;
1797
1798 #[test]
1799 fn mls_levels_for_user_context() {
1800 const TEST_POLICY: &[u8] = include_bytes! {"../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"};
1801 let policy = parse_policy_by_reference(TEST_POLICY).unwrap().validate().unwrap();
1802 let parsed_policy = policy.0.parsed_policy();
1803
1804 let user = parsed_policy.user(UserId(NonZeroU32::new(1).expect("user with id 1")));
1805 let mls_range = user.mls_range();
1806 let low_level = mls_range.low();
1807 let high_level = mls_range.high().as_ref().expect("user 1 has a high mls level");
1808
1809 assert_eq!(low_level.sensitivity(), SensitivityId(NonZeroU32::new(1).unwrap()));
1810 assert_eq!(
1811 low_level.category_ids().collect::<Vec<_>>(),
1812 vec![CategoryId(NonZeroU32::new(1).unwrap())]
1813 );
1814
1815 assert_eq!(high_level.sensitivity(), SensitivityId(NonZeroU32::new(2).unwrap()));
1816 assert_eq!(
1817 high_level.category_ids().collect::<Vec<_>>(),
1818 vec![
1819 CategoryId(NonZeroU32::new(1).unwrap()),
1820 CategoryId(NonZeroU32::new(2).unwrap()),
1821 CategoryId(NonZeroU32::new(3).unwrap()),
1822 CategoryId(NonZeroU32::new(4).unwrap()),
1823 CategoryId(NonZeroU32::new(5).unwrap()),
1824 ]
1825 );
1826 }
1827
1828 #[test]
1829 fn parse_mls_constrain_statement() {
1830 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1831 let policy = parse_policy_by_reference(policy_bytes.as_slice()).expect("parse policy");
1832 let parsed_policy = &policy.0;
1833 Validate::validate(parsed_policy).expect("validate policy");
1834
1835 let class = find_class_by_name(parsed_policy.classes(), "class_mls_constraints")
1836 .expect("look up class");
1837 let constraints = class.constraints();
1838 assert_eq!(constraints.len(), 6);
1839 let expected = [
1846 (
1847 CONSTRAINT_TERM_TYPE_EXPR,
1848 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1849 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1,
1850 ),
1851 (
1852 CONSTRAINT_TERM_TYPE_EXPR,
1853 CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1854 CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2,
1855 ),
1856 (
1857 CONSTRAINT_TERM_TYPE_EXPR,
1858 CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY,
1859 CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2,
1860 ),
1861 (
1862 CONSTRAINT_TERM_TYPE_EXPR,
1863 CONSTRAINT_EXPR_OPERATOR_TYPE_DOM,
1864 CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2,
1865 ),
1866 (
1867 CONSTRAINT_TERM_TYPE_EXPR,
1868 CONSTRAINT_EXPR_OPERATOR_TYPE_NE,
1869 CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2,
1870 ),
1871 (
1872 CONSTRAINT_TERM_TYPE_EXPR,
1873 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1874 CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2,
1875 ),
1876 ];
1877 for (i, constraint) in constraints.iter().enumerate() {
1878 assert_eq!(constraint.access_vector(), AccessVector(1), "constraint {}", i);
1879 let terms = constraint.constraint_expr().constraint_terms();
1880 assert_eq!(terms.len(), 1, "constraint {}", i);
1881 let term = &terms[0];
1882 assert_eq!(
1883 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1884 expected[i],
1885 "constraint {}",
1886 i
1887 );
1888 }
1889 }
1890
1891 #[test]
1892 fn parse_constrain_statement() {
1893 let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1894 let policy = parse_policy_by_reference(policy_bytes.as_slice()).expect("parse policy");
1895 let parsed_policy = &policy.0;
1896 Validate::validate(parsed_policy).expect("validate policy");
1897
1898 let class = find_class_by_name(parsed_policy.classes(), "class_constraint_nested")
1899 .expect("look up class");
1900 let constraints = class.constraints();
1901 assert_eq!(constraints.len(), 1);
1902 let constraint = &constraints[0];
1903 assert_eq!(constraint.access_vector(), AccessVector(1));
1904 let terms = constraint.constraint_expr().constraint_terms();
1905 assert_eq!(terms.len(), 8);
1906
1907 let expected = [
1913 (
1914 CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES,
1915 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1916 CONSTRAINT_EXPR_OPERAND_TYPE_USER
1917 | CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK,
1918 ),
1919 (
1920 CONSTRAINT_TERM_TYPE_EXPR,
1921 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1922 CONSTRAINT_EXPR_OPERAND_TYPE_ROLE,
1923 ),
1924 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1925 (
1926 CONSTRAINT_TERM_TYPE_EXPR,
1927 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1928 CONSTRAINT_EXPR_OPERAND_TYPE_USER,
1929 ),
1930 (
1931 CONSTRAINT_TERM_TYPE_EXPR,
1932 CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1933 CONSTRAINT_EXPR_OPERAND_TYPE_TYPE,
1934 ),
1935 (CONSTRAINT_TERM_TYPE_NOT_OPERATOR, 0, 0),
1936 (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1937 (CONSTRAINT_TERM_TYPE_OR_OPERATOR, 0, 0),
1938 ];
1939 for (i, term) in terms.iter().enumerate() {
1940 assert_eq!(
1941 (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1942 expected[i],
1943 "term {}",
1944 i
1945 );
1946 }
1947 }
1948}