diff --git a/pyproject.toml b/pyproject.toml index a7a28828..08e61a33 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ module = ['networkx.*', ignore_missing_imports = true [[tool.mypy.overrides]] -module = ['tests-gui.*'] +module = ['tests.gui.*'] # PyQt has many Optional[] returns since Qt doesn't throw exceptions. Fixing # this with type narrowing asserts in the code would add no value as the # test case would fail either way. diff --git a/seinfo b/seinfo index 31a78a09..80d308ce 100755 --- a/seinfo +++ b/seinfo @@ -308,7 +308,7 @@ try: components.append(("Validatetrans", vtq, lambda x: x.statement())) - if p.target_platform == "xen": + if p.target_platform == setools.PolicyTarget.xen: if args.ioportconquery or args.all: xiopq = setools.IoportconQuery(p) components.append(("Ioportcon", xiopq, lambda x: x.statement())) diff --git a/setools/constraintquery.py b/setools/constraintquery.py index 1449c80c..21a7fda1 100644 --- a/setools/constraintquery.py +++ b/setools/constraintquery.py @@ -77,7 +77,7 @@ def _match_expr(self, expr: frozenset[policyrep.User] | frozenset[policyrep.Role if indirect: obj = set() for item in expr: - obj.update(item.expand()) # type: ignore[union-attr] + obj.update(item.expand()) else: obj = expr diff --git a/setools/policyrep.pyi b/setools/policyrep.pyi index 5ae40ab9..445a2b4d 100644 --- a/setools/policyrep.pyi +++ b/setools/policyrep.pyi @@ -3,20 +3,16 @@ from collections.abc import Callable, Iterable, Iterator from dataclasses import dataclass -from typing import Any, NamedTuple, NoReturn +from typing import Any, NoReturn import enum import ipaddress -import setools.exception -import weakref AnyConstraint = "Constraint" | "Validatetrans" AnyDefault = "Default" | "DefaultRange" AnyRBACRule = "RoleAllow" | "RoleTransition" AnyTERule = "AVRule" | "AVRuleXperm" | "TERule" | "FileNameTERule" -SELINUX_SIDNAMES: Any TypeOrAttr = "Type" | "TypeAttribute" -XEN_SIDNAMES: Any def lookup_boolean_name_sub(name: str) -> str: ... @@ -26,8 +22,6 @@ def lookup_boolean_name_sub(name: str) -> str: ... class PolicyObject: policy: "SELinuxPolicy" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def statement(self) -> str: ... def __copy__(self) -> "PolicyObject": ... def __deepcopy__(self, memo) -> "PolicyObject": ... @@ -38,46 +32,31 @@ class PolicyObject: def __le__(self, other) -> bool: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class PolicyRule(PolicyObject): conditional: "Conditional" = ... conditional_block: bool = ... extended: bool = ... origin: "PolicyRule" = ... - ruletype: Any = ... + ruletype: "PolicyEnum" = ... source: "PolicySymbol" = ... target: "PolicySymbol" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... + tclass: "ObjClass" = ... + xperm_type: str = ... + perms: frozenset[str] | "IoctlSet" = ... + default: PolicyObject = ... + filename: str = ... def enabled(self, **kwargs) -> bool: ... - def expand(self) -> Any: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... + def expand(self) -> Iterable["PolicyRule"]: ... class PolicySymbol(PolicyObject): name: str = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PolicyIterator: - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __iter__(self) -> Any: ... - def __len__(self) -> int: ... - def __next__(self) -> Any: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... + def __contains__(self, other) -> bool: ... + def expand(self) -> Iterable["PolicySymbol"]: ... class PolicyEnum(enum.Enum): @classmethod def lookup(cls, value) -> Any: ... - def __eq__(self, other) -> bool: ... - def __format__(self, *args, **kwargs) -> Any: ... - def __hash__(self) -> int: ... # # Base classes, in alphabetical order @@ -88,18 +67,10 @@ class BaseConstraint(PolicyObject): perms: frozenset[str] = ... ruletype: "ConstraintRuletype" = ... tclass: "ObjClass" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class BaseMLSLevel(PolicyObject): sensitivity: "Sensitivity" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def categories(self) -> Iterable[Category]: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class BaseTERule(PolicyRule): conditional: "Conditional" = ... @@ -109,300 +80,81 @@ class BaseTERule(PolicyRule): source: TypeOrAttr = ... tclass: "ObjClass" = ... target: TypeOrAttr = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def enabled(self, **kwargs) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class BaseType(PolicySymbol): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def aliases(self) -> Iterable[str]: ... def attributes(self) -> Iterable["BaseType"]: ... def expand(self) -> Iterable["BaseType"]: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class EbitmapIterator(PolicyIterator): - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "PolicyObject": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class HashtabIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> Any: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Ocontext(PolicyObject): context: "Context" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class OcontextIterator(PolicyIterator): - def __init__(self, *args, **kwargs) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "Ocontext": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... # # Concrete classes, in alphabetical order # class AVRule(BaseTERule): default: NoReturn = ... - perms: set[str] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... + perms: frozenset[str] = ... def derive_expanded(self, *args, **kwargs) -> "AVRule": ... def expand(self, *args, **kwargs) -> Iterable["AVRule"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class AVRuleXperm(BaseTERule): default: NoReturn = ... perms: "IoctlSet" = ... xperm_type: str = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self, *args, **kwargs) -> Iterable["AVRuleXperm"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - class Boolean(PolicySymbol): state: bool = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class BooleanHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Boolean: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Bounds(PolicyObject): child: "Type" = ... parent: "Type" = ... ruletype: "BoundsRuletype" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class BoundsRuletype(PolicyEnum): typebounds: int = ... class Category(PolicySymbol): - _value: int = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def aliases(self, *args, **kwargs) -> Iterable[str]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class CategoryEbitmapIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Category: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class CategoryHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> Category: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Common(PolicySymbol): perms: frozenset[str] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __contains__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class CommonHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Common: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Conditional(PolicyObject): booleans: frozenset[Boolean] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def evaluate(self, **kwargs) -> bool: ... def expression(self) -> Iterable["ConditionalOperator" | str]: ... def false_rules(self, *args, **kwargs) -> Iterable[AnyTERule]: ... - def statement(self) -> str: ... def true_rules(self, *args, **kwargs) -> Iterable[AnyTERule]: ... def truth_table(self) -> list["TruthTableRow"]: ... def __contains__(self, other) -> bool: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ConditionalExprIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> ConditionalOperator | Boolean: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ConditionalIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> Conditional: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class ConditionalOperator(PolicyObject): - _cond_expr_val_to_details: Any = ... evaluate: Callable = ... precedence: int = ... unary: bool = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self, *args, **kwargs) -> NoReturn: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ConditionalTERuleIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def ruletype_count(self, *args, **kwargs) -> Any: ... - def __len__(self) -> int: ... - def __next__(self) -> AnyTERule: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Constraint(BaseConstraint): perms: frozenset[str] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ConstraintExprIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "ConstraintExprNode": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class ConstraintExprNode(PolicyObject): - _expr_op_to_text: Any = ... - _expr_type_to_text: Any = ... - _role_syms: Any = ... - _sym_to_text: Any = ... - _type_syms: Any = ... - _user_syms: Any = ... names: frozenset[TypeOrAttr] | frozenset["Role"] | frozenset["User"] = ... symbol_type: int = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> NoReturn: ... def __contains__(self, other) -> bool: ... def __getitem__(self, index) -> frozenset[TypeOrAttr] | frozenset["Role"] | frozenset["User"] | str: ... def __iter__(self) -> Iterable[frozenset[TypeOrAttr] | frozenset["Role"] | frozenset["User"] | str]: ... def __len__(self) -> int: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class ConstraintExpression(PolicyObject): mls: bool = ... roles: frozenset["Role"] = ... types: frozenset["Type"] = ... users: frozenset["User"] = ... - __hash__: Any = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def infix(self, *args, **kwargs) -> frozenset[TypeOrAttr] | frozenset["Role"] | frozenset["User"] | str: ... - def statement(self) -> NoReturn: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> frozenset[TypeOrAttr] | frozenset["Role"] | frozenset["User"] | str: ... - def __gt__(self, other) -> bool: ... def __iter__(self) -> Iterator[frozenset["Role"] | frozenset["Type"] | frozenset["User"] | str]: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ConstraintIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> Constraint: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class ConstraintRuletype(PolicyEnum): constrain: int = ... @@ -410,50 +162,19 @@ class ConstraintRuletype(PolicyEnum): mlsvalidatetrans: int = ... validatetrans: int = ... -class ConstraintUseError(setools.exception.SymbolUseError): ... - class Context(PolicyObject): range_: "Range" = ... role: "Role" = ... type_: "Type" = ... user: "User" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Default(PolicyObject): default: "DefaultValue" = ... ruletype: "DefaultRuletype" = ... tclass: "ObjClass" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class DefaultRange(Default): default_range: "DefaultRangeValue" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class DefaultRangeValue(PolicyEnum): high: int = ... @@ -473,45 +194,14 @@ class DefaultValue(PolicyEnum): source: int = ... target: int = ... @classmethod - def from_default_range(cls, *args, **kwargs) -> Any: ... + def from_default_range(cls, *args, **kwargs) -> "DefaultValue": ... class Devicetreecon(Ocontext): path: str = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class DevicetreeconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Devicetreecon: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class FSUse(Ocontext): fs: str = ... ruletype: "FSUseRuletype" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class FSUseIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> FSUse: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class FSUseRuletype(PolicyEnum): fs_use_task: int = ... @@ -526,67 +216,15 @@ class FileNameTERule(BaseTERule): source: TypeOrAttr = ... tclass: "ObjClass" = ... target: TypeOrAttr = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self, *args, **kwargs) -> Iterable["FileNameTERule"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class FileNameTERuleIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "FileNameTERule": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class GenfsFiletype(int): - _filetype_to_text: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... + +class GenfsFiletype(int): ... class Genfscon(Ocontext): - _sclass_to_stat: Any = ... filetype: "GenfsFiletype" = ... fs: str = ... path: str = ... tclass: "ObjClass" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class GenfsconIterator: - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __iter__(self) -> Iterable["Genfscon"]: ... - def __len__(self) -> int: ... - def __next__(self) -> "Genfscon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class GenfsconOcontextIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Ocontext": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class HandleUnknown(PolicyEnum): allow: int = ... @@ -596,204 +234,43 @@ class HandleUnknown(PolicyEnum): class Ibendportcon(Ocontext): name: str = ... port: int = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class IbendportconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Ibendportcon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Ibpkeycon(Ocontext): pkeys: "IbpkeyconRange" = ... subnet_prefix: ipaddress.IPv6Address = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... -class IbpkeyconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Ibpkeycon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -@dataclass +@dataclass(eq=True, order=True, frozen=True) class IbpkeyconRange: high: int = ... low: int = ... class InitialSID(Ocontext): name: str = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class InitialSIDIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "InitialSID": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class InvalidBoolean(setools.exception.InvalidSymbol): ... - -class InvalidBoundsType(setools.exception.InvalidSymbol): ... - -class InvalidCategory(setools.exception.InvalidSymbol): ... - -class InvalidClass(setools.exception.InvalidSymbol): ... - -class InvalidCommon(setools.exception.InvalidSymbol): ... - -class InvalidConstraintType(setools.exception.InvalidSymbol): ... - -class InvalidDefaultRange(setools.exception.InvalidSymbol): ... - -class InvalidDefaultType(setools.exception.InvalidRuleType): ... - -class InvalidDefaultValue(setools.exception.InvalidSymbol): ... - -class InvalidFSUseType(setools.exception.InvalidRuleType): ... - -class InvalidInitialSid(setools.exception.InvalidSymbol): ... - -class InvalidLevel(setools.exception.InvalidSymbol): ... - -class InvalidLevelDecl(setools.exception.InvalidSymbol): ... - -class InvalidMLSRuleType(setools.exception.InvalidRuleType): ... - -class InvalidPolicy(ValueError, setools.exception.PolicyrepException): ... - -class InvalidRBACRuleType(setools.exception.InvalidRuleType): ... - -class InvalidRange(setools.exception.InvalidSymbol): ... - -class InvalidRole(setools.exception.InvalidSymbol): ... - -class InvalidRuleType(setools.exception.InvalidSymbol): ... - -class InvalidSensitivity(setools.exception.InvalidSymbol): ... - -class InvalidTERuleType(setools.exception.InvalidRuleType): ... - -class InvalidType(setools.exception.InvalidSymbol): ... - -class InvalidUser(setools.exception.InvalidSymbol): ... class IoctlSet(frozenset[int]): - def __init__(self, *args, **kwargs) -> None: ... def ranges(self) -> int: ... - def __format__(self, *args, **kwargs) -> str: ... - def __reduce_cython__(self, *args, **kwargs) -> Any: ... - def __setstate_cython__(self, *args, **kwargs) -> Any: ... class Iomemcon(Ocontext): addr: "IomemconRange" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class IomemconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Iomemcon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... -@dataclass +@dataclass(eq=True, order=True, frozen=True) class IomemconRange: high: int = ... low: int = ... class Ioportcon(Ocontext): ports: "IoportconRange" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class IoportconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Ioportcon: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... -@dataclass +@dataclass(eq=True, order=True, frozen=True) class IoportconRange: high: int = ... low: int = ... class Level(BaseMLSLevel): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> NoReturn: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... def __rxor__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... def __xor__(self, other) -> bool: ... -class LevelDecl(BaseMLSLevel): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class LevelDeclHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "LevelDecl": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class LowLevelPolicyError(ValueError, setools.exception.PolicyrepException): ... - -class MLSDisabled(setools.exception.PolicyrepException): ... +class LevelDecl(BaseMLSLevel): ... class MLSRule(PolicyRule): default: "Range" = ... @@ -802,26 +279,7 @@ class MLSRule(PolicyRule): source: TypeOrAttr = ... tclass: "ObjClass" = ... target: TypeOrAttr = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self) -> Iterable["MLSRule"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class MLSRuleIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "MLSRuletype": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class MLSRuletype(PolicyEnum): range_transition: int = ... @@ -829,138 +287,29 @@ class MLSRuletype(PolicyEnum): class Netifcon(Ocontext): netif: str = ... packet: "Context" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class NetifconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Netifcon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class NoCommon(AttributeError, setools.exception.PolicyrepException): ... - -class NoDefaults(setools.exception.InvalidSymbol): ... - -class NoStatement(setools.exception.SymbolUseError): ... class Nodecon(Ocontext): ip_version: "NodeconIPVersion" = ... network: ipaddress.IPv4Network | ipaddress.IPv6Network = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class NodeconIPVersion(PolicyEnum): ipv4: int = ... ipv6: int = ... -class NodeconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Nodecon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - class ObjClass(PolicySymbol): common: "Common" = ... perms: frozenset[str] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def constraints(self, *args, **kwargs) -> Iterable["Constraint"]: ... def defaults(self, *args, **kwargs) -> Iterable[AnyDefault]: ... - def statement(self) -> str: ... def validatetrans(self, *args, **kwargs) -> Iterable["Validatetrans"]: ... - def __contains__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ObjClassHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "ObjClass": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Pcidevicecon(Ocontext): device: str = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PcideviceconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Pcidevicecon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PermissionVectorIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Pirqcon(Ocontext): irq: int = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PirqconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Pirqcon": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PolicyCapability(PolicySymbol): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... -class PolicyCapabilityIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "PolicyCapability": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... +class PolicyCapability(PolicySymbol): ... class PolicyTarget(PolicyEnum): selinux: int = ... @@ -969,25 +318,6 @@ class PolicyTarget(PolicyEnum): class Portcon(Ocontext): ports: "PortconRange" = ... protocol: "PortconProtocol" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PortconIterator(OcontextIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Portcon: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class PortconProtocol(PolicyEnum): dccp: int = ... @@ -995,7 +325,7 @@ class PortconProtocol(PolicyEnum): tcp: int = ... udp: int = ... -@dataclass +@dataclass(eq=True, order=True, frozen=True) class PortconRange: high: int = ... low: int = ... @@ -1007,29 +337,12 @@ class RBACRuletype(PolicyEnum): class Range(PolicyObject): high: Level = ... low: Level = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... def __contains__(self, other) -> bool: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Role(PolicySymbol): dominated_roles: frozenset["Role"] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self) -> Iterable["Role"]: ... - def statement(self) -> str: ... def types(self) -> Iterable["Type"]: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class RoleAllow(PolicyRule): default: NoReturn = ... @@ -1037,42 +350,7 @@ class RoleAllow(PolicyRule): source: "Role" = ... tclass: NoReturn = ... target: "Role" = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self) -> Iterable["RoleAllow"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class RoleAllowIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "RoleAllow": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class RoleEbitmapIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> Any: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class RoleHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Role": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class RoleTransition(PolicyRule): default: "Role" = ... @@ -1080,32 +358,7 @@ class RoleTransition(PolicyRule): source: "Role" = ... tclass: "ObjClass" = ... target: TypeOrAttr = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self) -> Iterable["RoleTransition"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class RoleTransitionIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "RoleTransition": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class RuleNotConditional(AttributeError, setools.exception.PolicyrepException): ... - -class RuleUseError(setools.exception.SymbolUseError): ... class SELinuxPolicy: allow_count: int = ... @@ -1159,7 +412,6 @@ class SELinuxPolicy: user_count: int = ... validatetrans_count: int = ... version: int = ... - __pyx_vtable__: Any = ... def __init__(self, policyfile: str | None = None) -> None: ... def bools(self) -> Iterable["Boolean"]: ... def bounds(self) -> Iterable["Bounds"]: ... @@ -1207,65 +459,15 @@ class SELinuxPolicy: def users(self) -> Iterable["User"]: ... def __copy__(self) -> "SELinuxPolicy": ... def __deepcopy__(self, memo) -> "SELinuxPolicy": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Sensitivity(PolicySymbol): - _value: int = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def aliases(self, *args, **kwargs) -> Any: ... def level_decl(self, *args, **kwargs) -> Any: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class SensitivityHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "Sensitivity": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class SymbolUseError(AttributeError, setools.exception.PolicyrepException): ... class TERule(BaseTERule): default: "Type" = ... perms: NoReturn = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def expand(self) -> Iterable["TERule"]: ... - def statement(self) -> str: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TERuleIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def ruletype_count(self, *args, **kwargs) -> Any: ... - def __len__(self) -> int: ... - def __next__(self) -> "TERule": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TERuleNoFilename(AttributeError, setools.exception.PolicyrepException): ... class TERuletype(PolicyEnum): allow: int = ... @@ -1287,121 +489,22 @@ class TruthTableRow: class Type(BaseType): ispermissive: bool = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def aliases(self) -> Iterable[str]: ... def attributes(self) -> Iterable["TypeAttribute"]: ... def expand(self) -> Iterable["Type"]: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class TypeAttribute(BaseType): ispermissive: bool = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... def aliases(self) -> Iterable[str]: ... def attributes(self) -> Iterable["TypeAttribute"]: ... def expand(self) -> Iterable["Type"]: ... - def statement(self) -> str: ... - def __contains__(self, other) -> bool: ... def __iter__(self) -> Iterable["TypeAttribute"]: ... def __len__(self) -> int: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TypeAttributeEbitmapIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "TypeAttribute": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TypeAttributeHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "TypeAttribute": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TypeEbitmapIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "Type": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TypeHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "Type": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TypeOrAttributeEbitmapIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> TypeOrAttr: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class TypeboundsIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "Bounds": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class User(PolicySymbol): mls_level: "Level" = ... mls_range: "Range" = ... roles: frozenset["Role"] = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class UserEbitmapIterator(EbitmapIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "User": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class UserHashtabIterator(HashtabIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __next__(self) -> "User": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... class Validatetrans(BaseConstraint): perms: NoReturn = ... - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def statement(self) -> str: ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class ValidatetransIterator(PolicyIterator): - __pyx_vtable__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def reset(self) -> None: ... - def __len__(self) -> int: ... - def __next__(self) -> "Validatetrans": ... - def __reduce__(self) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class WeakKeyDefaultDict(weakref.WeakKeyDictionary): - _abc_impl: Any = ... - __abstractmethods__: Any = ... - def __init__(self, *args, **kwargs) -> None: ... - def __getitem__(self, index) -> Any: ... - def __missing__(self, *args, **kwargs) -> Any: ... diff --git a/setools/policyrep/mls.pxi b/setools/policyrep/mls.pxi index 6083268f..908fd7ae 100644 --- a/setools/policyrep/mls.pxi +++ b/setools/policyrep/mls.pxi @@ -331,9 +331,11 @@ cdef class Level(BaseMLSLevel): # verify level is valid if not l <= l.sensitivity.level_decl(): + invalid_cats = l._categories - set(l.sensitivity.level_decl().categories()) raise InvalidLevel( - f"{name} is not a valid level (one or more categories are not associated with the " - "sensitivity)") + f"{name} is not a valid level " + f"(category {', '.join(str(c) for c in invalid_cats)} is not associated " + f"with sensitivity {l.sensitivity})") return l diff --git a/setools/policyrep/object.pxi b/setools/policyrep/object.pxi index dd87b32a..944359b2 100644 --- a/setools/policyrep/object.pxi +++ b/setools/policyrep/object.pxi @@ -72,9 +72,18 @@ cdef class PolicySymbol(PolicyObject): cdef readonly str name + def __contains__(self, other): + # Default is non-expandable. + return self is other + def __str__(self): return self.name + def expand(self): + """Expand the symbol into constitent symbols.""" + # Default is non-expandable. + yield self + cdef class Ocontext(PolicyObject): diff --git a/setools/policyrep/rbacrule.pxi b/setools/policyrep/rbacrule.pxi index 03949d73..818ed483 100644 --- a/setools/policyrep/rbacrule.pxi +++ b/setools/policyrep/rbacrule.pxi @@ -43,16 +43,6 @@ cdef class RoleAllow(PolicyRule): def __lt__(self, other): return str(self) < str(other) - @property - def tclass(self): - """The rule's object class.""" - raise RuleUseError("Role allow rules do not have an object class.") - - @property - def default(self): - """The rule's default role.""" - raise RuleUseError("Role allow rules do not have a default role.") - def expand(self): """Expand the rule into an equivalent set of rules without attributes.""" cdef RoleAllow r diff --git a/setools/policyrep/role.pxi b/setools/policyrep/role.pxi index e48241bf..a83d9de6 100644 --- a/setools/policyrep/role.pxi +++ b/setools/policyrep/role.pxi @@ -28,10 +28,6 @@ cdef class Role(PolicySymbol): #return set(RoleEbitmapIterator.factory(self.policy, &self.handle.dominates)) return frozenset() - def expand(self): - """Generator that expands this into its member roles.""" - yield self - def types(self): """Generator which yields the role's set of types.""" return iter(self._types) @@ -41,6 +37,8 @@ cdef class Role(PolicySymbol): types = list(str(t) for t in self._types) count = len(types) stmt = f"role {self.name}" + if count == 0: + return f"role {self.name};" if count == 1: return f"role {self.name} types {types[0]};" diff --git a/setools/policyrep/rule.pxi b/setools/policyrep/rule.pxi index 1d3edc0b..fd728de0 100644 --- a/setools/policyrep/rule.pxi +++ b/setools/policyrep/rule.pxi @@ -28,6 +28,33 @@ cdef class PolicyRule(PolicyObject): # Most rule types cannot be conditional. raise RuleNotConditional + @property + def default(self): + """The rule's default.""" + raise RuleUseError + + @property + def filename(self): + """The filename for this rule.""" + # Most rule types do not have filenames. + raise RuleUseError + + @property + def perms(self): + """The permissions for this rule.""" + raise RuleUseError + + @property + def tclass(self): + """The rule's object class.""" + raise RuleUseError + + @property + def xperm_type(self): + """The extended permission type for this rule.""" + # Most rule types are not extended. + raise RuleUseError + def enabled(self, **kwargs): """ Determine if the rule is enabled, given the stated boolean values. diff --git a/setools/policyrep/selinuxpolicy.pxi b/setools/policyrep/selinuxpolicy.pxi index 14bbe73a..d7b59fdf 100644 --- a/setools/policyrep/selinuxpolicy.pxi +++ b/setools/policyrep/selinuxpolicy.pxi @@ -349,7 +349,7 @@ cdef class SELinuxPolicy: if c == name or (deref and name in list(c.aliases())): return c - raise InvalidCategory("f{name} is not a valid category") + raise InvalidCategory(f"{name} is not a valid category") def lookup_class(self, name): """Look up an object class.""" @@ -367,14 +367,6 @@ cdef class SELinuxPolicy: raise InvalidCommon(f"{name} is not a valid common") - def lookup_initialsid(self, name): - """Look up an initial sid.""" - for sid in self.initialsids(): - if sid == name: - return sid - - raise InvalidInitialSid(f"{name} is not a valid initial SID") - def lookup_level(self, level): """Look up a MLS level.""" return Level.factory_from_string(self, level) @@ -685,7 +677,7 @@ cdef class SELinuxPolicy: if sepol.sepol_policydb_read(self.handle, pfile) < 0: raise InvalidPolicy(f"Invalid policy: {filename}. A binary policy must be specified. " - "(use e.g. policy.{sepol.sepol_policy_kern_vers_max()} or " + f"(use e.g. policy.{sepol.sepol_policy_kern_vers_max()} or " "sepolicy) Source policies are not supported.") fclose(infile) diff --git a/setoolsgui/widgets/models/terule.py b/setoolsgui/widgets/models/terule.py index bbfeb55a..d2456a3f 100644 --- a/setoolsgui/widgets/models/terule.py +++ b/setoolsgui/widgets/models/terule.py @@ -45,7 +45,7 @@ def data(self, index: QtCore.QModelIndex, role: int = ModelRoles.DisplayRole): case 4: try: if rule.extended: - return f"{rule.xperm_type}: {rule.perms:,}" # type: ignore + return f"{rule.xperm_type}: {rule.perms:,}" else: return ", ".join(sorted(rule.perms)) # type: ignore except RuleUseError: diff --git a/tests-gui/conftest.py b/tests-gui/conftest.py deleted file mode 100644 index 1b44eb30..00000000 --- a/tests-gui/conftest.py +++ /dev/null @@ -1,103 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# pylint: disable=attribute-defined-outside-init - -from unittest.mock import Mock - -import pytest -import setools - - -class SortableMock(Mock): - - """Mock class that can be sorted.""" - - def __lt__(self, other): - return self.name < other.name - - def __repr__(self): - return f"<{self.__class__} name={self.name}>" - - -@pytest.fixture -def mock_policy() -> Mock: - """Build a mock policy.""" - foo_bool = SortableMock(setools.Boolean) - foo_bool.name = "foo_bool" - bar_bool = SortableMock(setools.Boolean) - bar_bool.name = "bar_bool" - - common = SortableMock(setools.Common) - common.name = "common_perm_set" - common.perms = frozenset(("common_perm",)) - - foo_class = SortableMock(setools.ObjClass) - foo_class.name = "foo_class" - foo_class.perms = frozenset(("foo_perm1", "foo_perm2")) - foo_class.common = common - bar_class = SortableMock(setools.ObjClass) - bar_class.name = "bar_class" - bar_class.perms = frozenset(("bar_perm1", "bar_perm2")) - bar_class.common = common - - fooattr = SortableMock(setools.TypeAttribute) - fooattr.name = "foo_type" - barattr = SortableMock(setools.TypeAttribute) - barattr.name = "bar_type" - - foo_t = SortableMock(setools.Type) - foo_t.name = "foo_t" - foo_t.attributes.return_value = (fooattr,) - fooattr.expand.return_value = (foo_t,) - bar_t = SortableMock(setools.Type) - bar_t.name = "bar_t" - bar_t.attributes.return_value = (barattr,) - barattr.expand.return_value = (bar_t,) - - foo_r = SortableMock(setools.Role) - foo_r.name = "foo_r" - foo_r.types.return_value = (foo_t,) - bar_r = SortableMock(setools.Role) - bar_r.name = "bar_r" - bar_r.types.return_value = (bar_t,) - - foo_u = SortableMock(setools.User) - foo_u.name = "foo_u" - foo_u.roles.return_value = (foo_r,) - bar_u = SortableMock(setools.User) - bar_u.name = "bar_u" - bar_u.roles.return_value = (bar_r,) - - foo_cat = SortableMock(setools.Category) - foo_cat.name = "foo_cat" - foo_cat.aliases.return_value = ("foo_cat_alias",) - bar_cat = SortableMock(setools.Category) - bar_cat.name = "bar_cat" - bar_cat.aliases.return_value = ("bar_cat_alias",) - - foo_sen = SortableMock(setools.Sensitivity) - foo_sen.name = "foo_sen" - foo_sen.aliases.return_value = ("foo_sen_alias",) - bar_sen = SortableMock(setools.Sensitivity) - bar_sen.name = "bar_sen" - bar_sen.aliases.return_value = ("bar_sen_alias",) - - policy = Mock(setools.SELinuxPolicy) - policy.mls = False - policy.bools.return_value = (foo_bool, bar_bool) - policy.categories.return_value = (foo_cat, bar_cat) - policy.classes.return_value = (foo_class, bar_class) - policy.commons.return_value = (common,) - policy.roles.return_value = (foo_r, bar_r) - policy.sensitivities.return_value = (foo_sen, bar_sen) - policy.types.return_value = (foo_t, bar_t) - policy.typeattributes.return_value = (fooattr, barattr) - policy.users.return_value = (foo_u, bar_u) - return policy - - -@pytest.fixture -def mock_query(mock_policy) -> Mock: - """Build a mock query with mocked policy.""" - query = Mock(setools.PolicyQuery) - query.policy = mock_policy - return query diff --git a/tests/checker/test_assertrbac.py b/tests/checker/test_assertrbac.py deleted file mode 100644 index 3b7ef7d9..00000000 --- a/tests/checker/test_assertrbac.py +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright 2020, Microsoft Corporation -# Copyright 2020, Chris PeBenito -# -# This file is part of SETools. -# -# SETools is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 2.1 of -# the License, or (at your option) any later version. -# -# SETools is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with SETools. If not, see -# . -# - -import os -import unittest - -from ..policyrep.util import compile_policy - -from setools import RBACRuletype -from setools.checker.assertrbac import AssertRBAC -from setools.exception import InvalidCheckValue, InvalidCheckOption - - -class AssertRBACTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/checker/assertrbac.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_unconfigured(self): - """Test unconfigured.""" - with self.assertRaises(InvalidCheckValue): - config = {} - check = AssertRBAC(self.p, "test_unconfigured", config) - - def test_invalid_option(self): - """Test invalid option""" - with self.assertRaises(InvalidCheckOption): - config = {"INVALID": "option"} - check = AssertRBAC(self.p, "test_invalid_option", config) - - def test_source(self): - """Test source setting.""" - - with self.subTest("Success"): - config = {"source": "src"} - check = AssertRBAC(self.p, "test_source", config) - - expected = self.p.lookup_role("src") - self.assertEqual(expected, check.source) - - with self.subTest("Failure"): - with self.assertRaises(InvalidCheckValue): - config = {"source": "FAIL"} - check = AssertRBAC(self.p, "test_source_fail", config) - - def test_target(self): - """Test target setting.""" - - with self.subTest("Success"): - config = {"target": "tgt"} - check = AssertRBAC(self.p, "test_target", config) - - expected = self.p.lookup_role("tgt") - self.assertEqual(expected, check.target) - - with self.subTest("Failure"): - with self.assertRaises(InvalidCheckValue): - config = {"target": "FAIL2"} - check = AssertRBAC(self.p, "test_target_fail", config) - - def test_exempt_source(self): - """Test exempt_source setting.""" - with self.subTest("Success"): - config = {"source": "system", - "exempt_source": " exempt_src1 exempt_src2 "} - check = AssertRBAC(self.p, "test_exempt_source", config) - - # exempt_src2 is an attr - expected = set((self.p.lookup_role("exempt_src1"), - self.p.lookup_role("exempt_src2"))) - self.assertIsInstance(check.exempt_source, frozenset) - self.assertSetEqual(expected, check.exempt_source) - - with self.subTest("Success, missing role ignored"): - """Test exempt_source missing role is ignroed.""" - config = {"source": "system", - "exempt_source": "FAIL exempt_src2"} - check = AssertRBAC(self.p, "test_source_missing_ignored", config) - - # exempt_src2 is an attr - expected = set((self.p.lookup_role("exempt_src2"),)) - self.assertIsInstance(check.exempt_source, frozenset) - self.assertSetEqual(expected, check.exempt_source) - - def test_exempt_target(self): - """Test exempt_target setting.""" - with self.subTest("Success"): - config = {"target": "system", - "exempt_target": " exempt_tgt1 exempt_tgt2 "} - check = AssertRBAC(self.p, "test_exempt_target", config) - - # exempt_tgt2 is an attr - expected = set((self.p.lookup_role("exempt_tgt1"), - self.p.lookup_role("exempt_tgt2"))) - self.assertIsInstance(check.exempt_target, frozenset) - self.assertSetEqual(expected, check.exempt_target) - - with self.subTest("Success, missing role ignored"): - config = {"target": "system", - "exempt_target": "FAIL exempt_tgt2"} - check = AssertRBAC(self.p, "test_target_missing_ignored", config) - - # exempt_tgt2 is an attr - expected = set((self.p.lookup_role("exempt_tgt2"),)) - self.assertIsInstance(check.exempt_target, frozenset) - self.assertSetEqual(expected, check.exempt_target) - - def test_expect_source(self): - """Test expect_source setting.""" - with self.subTest("Success"): - config = {"target": "tgt", - "expect_source": " exempt_src1 exempt_src2 "} - check = AssertRBAC(self.p, "test_expect_source", config) - - # exempt_src2 is an attr - expected = set((self.p.lookup_role("exempt_src1"), - self.p.lookup_role("exempt_src2"))) - self.assertIsInstance(check.expect_source, frozenset) - self.assertSetEqual(expected, check.expect_source) - - with self.subTest("Failure"): - with self.assertRaises(InvalidCheckValue): - config = {"target": "tgt", - "expect_source": " source1 INVALID "} - check = AssertRBAC(self.p, "test_expect_source_fail", config) - - def test_expect_target(self): - """Test expect_target setting.""" - with self.subTest("Success"): - config = {"source": "src", - "expect_target": " exempt_tgt1 exempt_tgt2 "} - check = AssertRBAC(self.p, "test_expect_target", config) - - # exempt_tgt2 is an attr - expected = set((self.p.lookup_role("exempt_tgt1"), - self.p.lookup_role("exempt_tgt2"))) - self.assertIsInstance(check.expect_target, frozenset) - self.assertSetEqual(expected, check.expect_target) - - with self.subTest("Failure"): - with self.assertRaises(InvalidCheckValue): - config = {"source": "src", - "expect_target": " target1 INVALID "} - check = AssertRBAC(self.p, "test_expect_target_fail", config) - - def test_check_passes(self): - """Test the check passes, no matches""" - config = {"source": "src", - "target": "tgt"} - check = AssertRBAC(self.p, "test_check_passes", config) - self.assertFalse(check.run()) - - def test_check_passes_exempt_source_role(self): - """Test the check passes, exempt_source_role""" - config = {"target": "target1", - "exempt_source": "source1"} - check = AssertRBAC(self.p, "test_check_passes_exempt_source_role", config) - self.assertFalse(check.run()) - - def test_check_passes_exempt_target_role(self): - """Test the check passes, exempt_target_role""" - config = {"target": "target2", - "exempt_source": "source2"} - check = AssertRBAC(self.p, "test_check_passes_exempt_target_role", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_source(self): - """Test the check passes, expect_source""" - config = {"target": "target3", - "expect_source": "source3a source3b"} - check = AssertRBAC(self.p, "test_check_passes_expect_source", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_target(self): - """Test the check passes, expect_target""" - config = {"source": "source4", - "expect_target": "target4a target4b"} - check = AssertRBAC(self.p, "test_check_passes_expect_target", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_exempt_source(self): - """"Test the check passes with both expected and exempted sources.""" - config = {"target": "target5", - "expect_source": "source5a", - "exempt_source": "source5b"} - check = AssertRBAC(self.p, "test_check_passes_expect_exempt_source", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_exempt_target(self): - """"Test the check passes with both expected and exempted targets.""" - config = {"source": "source6", - "expect_target": "target6a", - "exempt_target": "target6b"} - check = AssertRBAC(self.p, "test_check_passes_expect_exempt_target", config) - self.assertFalse(check.run()) - - def test_check_fails(self): - """Test the check fails""" - with open("/dev/null", "w") as fd: - config = {"source": "source7", - "expect_target": "target7a", - "exempt_target": "target7b"} - check = AssertRBAC(self.p, "test_check_passes_exempt_target_attr", config) - check.output = fd - result = check.run() - self.assertEqual(1, len(result), msg=result) - rule = result[0] - self.assertEqual(RBACRuletype.allow, rule.ruletype) - self.assertEqual("source7", rule.source) - self.assertEqual("target7c", rule.target) - - def test_check_fails_expect_source(self): - """Test the check fails, expect_source""" - config = {"target": "target8", - "expect_source": "source8"} - check = AssertRBAC(self.p, "test_check_fails_expect_source", config) - result = check.run() - self.assertEqual(1, len(result), msg=result) - self.assertIn("source8", result[0]) - - def test_check_fails_expect_target(self): - """Test the check fails, expect_target""" - config = {"source": "source9", - "expect_target": "target9"} - check = AssertRBAC(self.p, "test_check_fails_expect_target", config) - result = check.run() - self.assertEqual(1, len(result), msg=result) - self.assertIn("target9", result[0]) diff --git a/tests/checker/test_assertte.py b/tests/checker/test_assertte.py deleted file mode 100644 index d9319c5c..00000000 --- a/tests/checker/test_assertte.py +++ /dev/null @@ -1,330 +0,0 @@ -# Copyright 2020, Microsoft Corporation -# Copyright 2020, Chris PeBenito -# -# This file is part of SETools. -# -# SETools is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 2.1 of -# the License, or (at your option) any later version. -# -# SETools is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with SETools. If not, see -# . -# - -import os -import logging -import unittest - -from .. import mixins -from ..policyrep.util import compile_policy - -from setools import TERuletype -from setools.checker.assertte import AssertTE -from setools.exception import InvalidCheckValue, InvalidCheckOption - - -class AssertTETest(mixins.ValidateRule, unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/checker/assertte.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_unconfigured(self): - """Test unconfigured.""" - with self.assertRaises(InvalidCheckValue): - config = {} - check = AssertTE(self.p, "test_unconfigured", config) - - def test_invalid_option(self): - """Test invalid option""" - with self.assertRaises(InvalidCheckOption): - config = {"INVALID": "option"} - check = AssertTE(self.p, "test_invalid_option", config) - - def test_source(self): - """Test source setting.""" - config = {"source": "src"} - check = AssertTE(self.p, "test_source", config) - - expected = self.p.lookup_type("src") - self.assertEqual(expected, check.source) - - def test_source_fail(self): - """Test source setting failure.""" - with self.assertRaises(InvalidCheckValue): - config = {"source": "FAIL"} - check = AssertTE(self.p, "test_source_fail", config) - - def test_target(self): - """Test target setting.""" - config = {"target": "tgt"} - check = AssertTE(self.p, "test_target", config) - - expected = self.p.lookup_type("tgt") - self.assertEqual(expected, check.target) - - def test_target_fail(self): - """Test target setting failure.""" - with self.assertRaises(InvalidCheckValue): - config = {"target": "FAIL2"} - check = AssertTE(self.p, "test_target_fail", config) - - def test_exempt_source(self): - """Test exempt_source setting.""" - config = {"source": "system", - "exempt_source": " exempt_src1 exempt_src2 "} - check = AssertTE(self.p, "test_exempt_source", config) - - # exempt_src2 is an attr - expected = set((self.p.lookup_type("exempt_src1"), - self.p.lookup_type("exempt_source_type"))) - self.assertIsInstance(check.exempt_source, frozenset) - self.assertSetEqual(expected, check.exempt_source) - - def test_source_missing_ignored(self): - """Test exempt_source missing type is ignroed.""" - config = {"source": "system", - "exempt_source": "FAIL exempt_src2"} - check = AssertTE(self.p, "test_source_missing_ignored", config) - - # exempt_src2 is an attr - expected = set((self.p.lookup_type("exempt_source_type"),)) - self.assertIsInstance(check.exempt_source, frozenset) - self.assertSetEqual(expected, check.exempt_source) - - def test_exempt_target(self): - """Test exempt_target setting.""" - config = {"target": "system", - "exempt_target": " exempt_tgt1 exempt_tgt2 "} - check = AssertTE(self.p, "test_exempt_target", config) - - # exempt_tgt2 is an attr - expected = set((self.p.lookup_type("exempt_tgt1"), - self.p.lookup_type("exempt_target_type"))) - self.assertIsInstance(check.exempt_target, frozenset) - self.assertSetEqual(expected, check.exempt_target) - - def test_target_missing_ignored(self): - """Test exempt_target missing type is ignroed.""" - config = {"target": "system", - "exempt_target": "FAIL exempt_tgt2"} - check = AssertTE(self.p, "test_target_missing_ignored", config) - - # exempt_tgt2 is an attr - expected = set((self.p.lookup_type("exempt_target_type"),)) - self.assertIsInstance(check.exempt_target, frozenset) - self.assertSetEqual(expected, check.exempt_target) - - def test_expect_source(self): - """Test expect_source setting.""" - with self.subTest("Success"): - config = {"tclass": "infoflow3", - "expect_source": " exempt_src1 exempt_src2 "} - check = AssertTE(self.p, "test_expect_source", config) - - # exempt_src2 is an attr - expected = set((self.p.lookup_type("exempt_src1"), - self.p.lookup_type("exempt_source_type"))) - self.assertIsInstance(check.expect_source, frozenset) - self.assertSetEqual(expected, check.expect_source) - - with self.subTest("Failure"): - with self.assertRaises(InvalidCheckValue): - config = {"tclass": "infoflow3", - "expect_source": " source1 INVALID "} - check = AssertTE(self.p, "test_expect_source_fail", config) - - def test_expect_target(self): - """Test expect_target setting.""" - with self.subTest("Success"): - config = {"tclass": "infoflow3", - "expect_target": " exempt_tgt1 exempt_tgt2 "} - check = AssertTE(self.p, "test_expect_target", config) - - # exempt_tgt2 is an attr - expected = set((self.p.lookup_type("exempt_tgt1"), - self.p.lookup_type("exempt_target_type"))) - self.assertIsInstance(check.expect_target, frozenset) - self.assertSetEqual(expected, check.expect_target) - - with self.subTest("Failure"): - with self.assertRaises(InvalidCheckValue): - config = {"tclass": "infoflow3", - "expect_target": " target1 INVALID "} - check = AssertTE(self.p, "test_expect_target_fail", config) - - def test_tclass(self): - """Test tclass setting.""" - config = {"tclass": "infoflow3 infoflow2"} - check = AssertTE(self.p, "test_tclass", config) - - expected = set((self.p.lookup_class("infoflow3"), - self.p.lookup_class("infoflow2"))) - self.assertEqual(expected, check.tclass) - - def test_tclass_fail(self): - """Test tclass setting failure.""" - with self.assertRaises(InvalidCheckValue): - config = {"tclass": "FAIL_class"} - check = AssertTE(self.p, "test_tclass_fail", config) - - def test_perms(self): - """Test perms setting.""" - config = {"perms": " hi_w super_r "} - check = AssertTE(self.p, "test_perms", config) - - expected = set(("hi_w", "super_r")) - self.assertEqual(expected, check.perms) - - def test_perms_fail(self): - """Test perms setting failure.""" - with self.assertRaises(InvalidCheckValue): - config = {"perms": "FAIL_perms"} - check = AssertTE(self.p, "test_perms_fail", config) - - def test_check_passes(self): - """Test the check passes, no matches""" - config = {"perms": "null"} - check = AssertTE(self.p, "test_check_passes", config) - self.assertFalse(check.run()) - - def test_check_passes_empty_source(self): - """Test the check passes, empty source attribute""" - config = {"tclass": "infoflow7", - "perms": "super_w"} - check = AssertTE(self.p, "test_check_passes_empty_source", config) - self.assertFalse(check.run()) - - def test_check_passes_empty_target(self): - """Test the check passes, empty target attribute""" - config = {"tclass": "infoflow7", - "perms": "super_r"} - check = AssertTE(self.p, "test_check_passes_empty_target", config) - self.assertFalse(check.run()) - - def test_check_passes_exempt_source_type(self): - """Test the check passes, exempt_source_type""" - config = {"tclass": "infoflow6", - "perms": "hi_w", - "exempt_source": "source1"} - check = AssertTE(self.p, "test_check_passes_exempt_source_type", config) - self.assertFalse(check.run()) - - def test_check_passes_exempt_source_attr(self): - """Test the check passes, exempt_source_attr""" - config = {"tclass": "infoflow6", - "perms": "hi_r", - "exempt_source": "all_sources"} - check = AssertTE(self.p, "test_check_passes_exempt_source_attr", config) - self.assertFalse(check.run()) - - def test_check_passes_exempt_target_type(self): - """Test the check passes, exempt_target_type""" - config = {"tclass": "infoflow5", - "perms": "low_w", - "exempt_source": "source1"} - check = AssertTE(self.p, "test_check_passes_exempt_target_type", config) - self.assertFalse(check.run()) - - def test_check_passes_exempt_target_attr(self): - """Test the check passes, exempt_target_attr""" - config = {"tclass": "infoflow5", - "perms": "low_r", - "exempt_target": "all_targets"} - check = AssertTE(self.p, "test_check_passes_exempt_target_attr", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_source(self): - """Test the check passes, expect_source""" - config = {"tclass": "infoflow6", - "perms": "hi_r", - "expect_source": "source1 source2"} - check = AssertTE(self.p, "test_check_passes_expect_source", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_source_attr(self): - """Test the check passes, expect_source with attribute""" - config = {"tclass": "infoflow4", - "perms": "med_w", - "expect_source": "all_sources"} - check = AssertTE(self.p, "test_check_passes_expect_source_attr", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_target(self): - """Test the check passes, expect_target""" - config = {"tclass": "infoflow6", - "perms": "hi_r", - "expect_target": "target1 target2"} - check = AssertTE(self.p, "test_check_passes_expect_target", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_target_attr(self): - """Test the check passes, expect_target with attribute""" - config = {"tclass": "infoflow4", - "perms": "med_w", - "expect_target": "all_targets"} - check = AssertTE(self.p, "test_check_passes_expect_target_attr", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_exempt_source(self): - """"Test the check passes with both expected and exempted sources.""" - config = {"tclass": "infoflow5", - "perms": "low_r", - "expect_source": "source1", - "exempt_source": "source2"} - check = AssertTE(self.p, "test_check_passes_expect_exempt_source", config) - self.assertFalse(check.run()) - - def test_check_passes_expect_exempt_target(self): - """"Test the check passes with both expected and exempted targets.""" - config = {"tclass": "infoflow5", - "perms": "low_r", - "expect_source": "source1", - "exempt_source": "source2"} - check = AssertTE(self.p, "test_check_passes_expect_exempt_target", config) - self.assertFalse(check.run()) - - def test_check_fails(self): - """Test the check fails""" - with open("/dev/null", "w") as fd: - config = {"tclass": "infoflow4", - "perms": "med_w", - "exempt_source": "source1", - "exempt_target": "target2"} - check = AssertTE(self.p, "test_check_passes_exempt_target_attr", config) - check.output = fd - result = check.run() - self.assertEqual(1, len(result), msg=result) - self.validate_rule(result[0], TERuletype.allow, "source3", "target3", "infoflow4", - set(["med_w"])) - - def test_check_fails_expect_source(self): - """Test the check fails, expect_source""" - config = {"tclass": "infoflow7", - "perms": "super_w", - "expect_source": "source1"} - check = AssertTE(self.p, "test_check_fails_expect_source", config) - result = check.run() - self.assertEqual(1, len(result), msg=result) - self.assertIn("source1", result[0]) - - def test_check_fails_expect_target(self): - """Test the check fails, expect_target""" - config = {"tclass": "infoflow7", - "perms": "super_r", - "expect_target": "target2"} - check = AssertTE(self.p, "test_check_fails_expect_target", config) - result = check.run() - self.assertEqual(1, len(result), msg=result) - self.assertIn("target2", result[0]) diff --git a/tests/checker/test_checker.py b/tests/checker/test_checker.py deleted file mode 100644 index 3fe37eb4..00000000 --- a/tests/checker/test_checker.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright 2020, Microsoft Corporation -# -# This file is part of SETools. -# -# SETools is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 2.1 of -# the License, or (at your option) any later version. -# -# SETools is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with SETools. If not, see -# . -# - -import os -import unittest -from unittest.mock import Mock - -from ..policyrep.util import compile_policy - -from setools.checker import PolicyChecker -from setools.exception import InvalidCheckerConfig, InvalidCheckerModule, InvalidCheckOption, \ - InvalidCheckValue - - -class PolicyCheckerTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/checker/checker.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_config_empty(self): - """Test empty config file""" - with self.assertRaises(InvalidCheckerConfig): - PolicyChecker(self.p, "/dev/null") - - def test_config_check_missing_type(self): - """Test check missing check type""" - with self.assertRaises(InvalidCheckerModule): - PolicyChecker(self.p, "tests/checker/checker-missingtype.ini") - - def test_config_check_invalid_type(self): - """Test check invalid check type""" - with self.assertRaises(InvalidCheckerModule): - PolicyChecker(self.p, "tests/checker/checker-invalidtype.ini") - - def test_config_check_invalid_option(self): - """Test check invalid check option""" - with self.assertRaises(InvalidCheckOption): - PolicyChecker(self.p, "tests/checker/checker-invalidoption.ini") - - def test_config_check_invalid_value(self): - """Test check invalid check type""" - with self.assertRaises(InvalidCheckValue): - PolicyChecker(self.p, "tests/checker/checker-invalidvalue.ini") - - def test_run_pass(self): - """Test run with passing config.""" - with open(os.devnull, "w") as fd: - checker = PolicyChecker(self.p, "tests/checker/checker-valid.ini") - - # create additional disabled mock test - newcheck = Mock() - newcheck.checkname = "disabled" - newcheck.disable = True - newcheck.validate_config.return_value = None - newcheck.run.return_value = [] - checker.checks.append(newcheck) - - self.assertEqual(4, len(checker.checks)) - result = checker.run(output=fd) - self.assertEqual(0, result) - newcheck.run.assert_not_called() - - def test_run_fail(self): - """Test run with failing config.""" - with open(os.devnull, "w") as fd: - checker = PolicyChecker(self.p, "tests/checker/checker-valid.ini") - - # create additional failing mock test - newcheck = Mock() - newcheck.checkname = "failing test" - newcheck.disable = False - newcheck.validate_config.return_value = None - newcheck.run.return_value = list(range(13)) - checker.checks.append(newcheck) - - self.assertEqual(4, len(checker.checks)) - - result = checker.run(output=fd) - newcheck.run.assert_called() - self.assertEqual(13, result) diff --git a/tests/checker/test_emptyattr.py b/tests/checker/test_emptyattr.py deleted file mode 100644 index 3d44ff43..00000000 --- a/tests/checker/test_emptyattr.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2020, Microsoft Corporation -# -# This file is part of SETools. -# -# SETools is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 2.1 of -# the License, or (at your option) any later version. -# -# SETools is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with SETools. If not, see -# . -# - -import os -import unittest - -from ..policyrep.util import compile_policy - -from setools.checker.emptyattr import EmptyTypeAttr -from setools.exception import InvalidCheckOption, InvalidCheckValue - - -class EmptyTypeAttrTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/checker/emptyattr.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_invalid_option(self): - """Test invalid option""" - with self.assertRaises(InvalidCheckOption): - config = {"INVALID": "option"} - check = EmptyTypeAttr(self.p, "test_invalid_option", config) - - def test_attr_setting(self): - """EmptyTypeAttr test attr setting.""" - config = {"attr": "test1"} - check = EmptyTypeAttr(self.p, "test_attr_setting", config) - - expected = self.p.lookup_typeattr("test1") - self.assertEqual(expected, check.attr) - - def test_attr_setting_fail(self): - """EmptyTypeAttr test attr setting with invalid attr.""" - with self.assertRaises(InvalidCheckValue): - config = {"attr": "FAILATTR"} - check = EmptyTypeAttr(self.p, "test_attr_setting_fail", config) - - def test_attr_setting_missing(self): - """EmptyTypeAttr test attr setting missing.""" - with self.assertRaises(InvalidCheckValue): - config = {} - check = EmptyTypeAttr(self.p, "test_attr_setting_missing", config) - - def test_missingok_setting(self): - """EmptyTypeAttr test missing_ok setting.""" - config = {"attr": "test1", - "missing_ok": "true"} - check = EmptyTypeAttr(self.p, "test_missingok_setting", config) - self.assertTrue(check.missing_ok) - - config = {"attr": "test1", - "missing_ok": " YeS "} - check = EmptyTypeAttr(self.p, "test_missingok_setting", config) - self.assertTrue(check.missing_ok) - - config = {"attr": "test1", - "missing_ok": " 1 "} - check = EmptyTypeAttr(self.p, "test_missingok_setting", config) - self.assertTrue(check.missing_ok) - - config = {"attr": "test1", - "missing_ok": " No "} - check = EmptyTypeAttr(self.p, "test_missingok_setting", config) - self.assertFalse(check.missing_ok) - - def test_pass(self): - """EmptyTypeAttr test pass.""" - with open("/dev/null", "w") as fd: - config = {"attr": "test1"} - check = EmptyTypeAttr(self.p, "test_pass", config) - check.output = fd - result = check.run() - self.assertEqual(0, len(result)) - - def test_pass_missingok(self): - """EmptyTypeAttr test pass by missing.""" - with open("/dev/null", "w") as fd: - config = {"attr": "test2", - "missing_ok": "true"} - check = EmptyTypeAttr(self.p, "test_pass_missingok", config) - check.output = fd - result = check.run() - self.assertEqual(0, len(result)) - - def test_fail(self): - """EmptyTypeAttr test fail.""" - with open("/dev/null", "w") as fd: - # also verify missing_ok doesn't induce a pass - # when the attr exists - config = {"attr": "test3", - "missing_ok": "true"} - check = EmptyTypeAttr(self.p, "test_fail", config) - check.output = fd - result = check.run() - expected = [self.p.lookup_type("test3_hit1"), - self.p.lookup_type("test3_hit2")] - self.assertListEqual(expected, result) diff --git a/tests/checker/test_roexec.py b/tests/checker/test_roexec.py deleted file mode 100644 index 19b028c5..00000000 --- a/tests/checker/test_roexec.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright 2020, Microsoft Corporation -# -# This file is part of SETools. -# -# SETools is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 2.1 of -# the License, or (at your option) any later version. -# -# SETools is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with SETools. If not, see -# . -# - -import os -import unittest - -from ..policyrep.util import compile_policy - -from setools.checker.roexec import ReadOnlyExecutables -from setools.exception import InvalidCheckOption, InvalidCheckValue - - -class ReadOnlyExecutablesTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/checker/roexec.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_invalid_option(self): - """Test invalid option""" - with self.assertRaises(InvalidCheckOption): - config = {"INVALID": "option"} - check = ReadOnlyExecutables(self.p, "test_invalid_option", config) - - def test_all_exec(self): - """Test all executables are returned for no-option test..""" - config = {} - check = ReadOnlyExecutables(self.p, "test_all_exec", config) - result = check._collect_executables() - - # becasue of unconfined, nonexec is executable - expected = set(("roexec", "execfile1", "execfile2", "nonexec", "exempt_file")) - self.assertSetEqual(expected, set(result.keys())) - - def test_exempt_exec_domain(self): - """Test for exempting an exec domain.""" - config = {"exempt_exec_domain": "unconfined"} - check = ReadOnlyExecutables(self.p, "test_exempt_exec_domain", config) - result = check._collect_executables() - - expected = set(("execfile1", "execfile2", "roexec")) - self.assertSetEqual(expected, set(result.keys())) - - def test_exempt_file(self): - """Test for exempting a file.""" - config = {"exempt_file": "exempt_file"} - check = ReadOnlyExecutables(self.p, "test_exempt_file", config) - result = check._collect_executables() - - expected = set(("roexec", "execfile1", "execfile2", "nonexec")) - self.assertSetEqual(expected, set(result.keys())) - - def test_exempt_file_attr(self): - """Test for exempting a file by attribute.""" - config = {"exempt_file": "exempt_files_attr"} - check = ReadOnlyExecutables(self.p, "test_exempt_file_attr", config) - result = check._collect_executables() - - expected = set(("roexec", "nonexec", "exempt_file")) - self.assertSetEqual(expected, set(result.keys())) - - def test_fail(self): - """Test for failing.""" - with open("/dev/null", "w") as fd: - config = {"exempt_exec_domain": "unconfined", - "exempt_write_domain": "unconfined"} - check = ReadOnlyExecutables(self.p, "test_fail", config) - check.output = fd - result = check.run() - - expected = [self.p.lookup_type("execfile1"), - self.p.lookup_type("execfile2")] - self.assertListEqual(expected, result) - - def test_pass(self): - """Test for passing.""" - with open("/dev/null", "w") as fd: - config = {"exempt_exec_domain": "unconfined", - "exempt_write_domain": "domain1 domain2 unconfined"} - check = ReadOnlyExecutables(self.p, "test_pass", config) - check.output = fd - result = check.run() - - self.assertFalse(result) - - def test_pass2(self): - """Test for passing with alternate exemptions.""" - with open("/dev/null", "w") as fd: - config = {"exempt_exec_domain": "unconfined", - "exempt_file": "execfile2", - "exempt_write_domain": "domain1 unconfined"} - check = ReadOnlyExecutables(self.p, "test_pass2", config) - check.output = fd - result = check.run() - - self.assertFalse(result) diff --git a/tests/checker/util.py b/tests/checker/util.py deleted file mode 100644 index a4d4e97e..00000000 --- a/tests/checker/util.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2020, Microsoft Corporation -# -# This file is part of SETools. -# -# SETools is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation, either version 2.1 of -# the License, or (at your option) any later version. -# -# SETools is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with SETools. If not, see -# . -# - -import os -import logging -import unittest - - -from setools.checker import util - - -class CheckerUtilTest(unittest.TestCase): - - def test_config_bool_value(self): - """Test config_bool_value""" - self.assertTrue(util.config_bool_value(" TrUe ")) - self.assertTrue((util.config_bool_value(" 1 "))) - self.assertTrue((util.config_bool_value(" YeS "))) - self.assertFalse((util.config_bool_value(" FalsE "))) - self.assertFalse((util.config_bool_value(" 0 "))) - self.assertFalse((util.config_bool_value(" No "))) - - self.assertTrue(util.config_bool_value(True)) - self.assertFalse((util.config_bool_value(None))) - self.assertFalse((util.config_bool_value(False))) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..ce123dc9 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,254 @@ +# SPDX-License-Identifier: GPL-2.0-only +# pylint: disable=attribute-defined-outside-init +import os +from collections.abc import Iterable +from contextlib import suppress +import subprocess +import tempfile +from unittest.mock import Mock + +import pytest +import setools + + +class SortableMock(Mock): + + """Mock class that can be sorted.""" + + def __lt__(self, other): + return self.name < other.name + + def __repr__(self): + return f"<{self.__class__} name={self.name}>" + + +@pytest.fixture +def mock_role(): + generated_roles: dict[str, setools.Role] = {} + + def _factory(name: str, /, *, types: frozenset[setools.Type] | None = None) -> setools.Role: + """Factory function for Role objects.""" + with suppress(KeyError): + return generated_roles[name] + + role = SortableMock(setools.Role) + role.name = name + + if types is not None: + role.types.return_value = types + + generated_roles[name] = role + return role + + return _factory + + +@pytest.fixture +def mock_type(): + generated_types: dict[str, setools.Type] = {} + + def _factory(name: str, attrs: Iterable[setools.TypeAttribute] | None = None, + alias: Iterable[str] | None = None, perm: bool = False) -> setools.Type: + """Factory function for Type objects.""" + with suppress(KeyError): + return generated_types[name] + + type_ = SortableMock(setools.Type) + type_.name = name + type_.ispermissive = perm + type_.attributes.return_value = attrs if attrs is not None else () + type_.aliases.return_value = alias if alias is not None else () + generated_types[name] = type_ + return type_ + + return _factory + + +@pytest.fixture +def mock_typeattr(): + generated_attrs: dict[str, setools.TypeAttribute] = {} + + def _factory(name: str, types: Iterable[setools.Type] | None = None) -> setools.TypeAttribute: + """Factory function for TypeAttribute objects, using a mock qpol object.""" + attr = SortableMock(setools.TypeAttribute) + attr.name = name + attr.expand.return_value = types if types is not None else () + generated_attrs[name] = attr + return attr + + return _factory + + +@pytest.fixture +def mock_user(mock_role): + generated_users: dict[str, setools.User] = {} + + def _factory(name: str, /, *, roles: frozenset[setools.Role] | None = None, + level: setools.Level | None = None, + range_: setools.Range | None = None) -> setools.User: + """Factory function for User objects.""" + with suppress(KeyError): + return generated_users[name] + + assert (level and range_) or (not level and not range_) + + user = SortableMock(setools.User) + user.name = name + + if roles is not None: + # inject object_r, like the compiler does + full_roles = {mock_role("object_r"), *roles} + user.roles.return_value = frozenset(full_roles) + + if level: + user._level = level + user._range = range_ + else: + user._level = None + user._range = None + + generated_users[name] = user + return user + + return _factory + + +@pytest.fixture +def mock_policy(mock_type, mock_typeattr, mock_user, mock_role) -> setools.SELinuxPolicy: + """Build a mock policy.""" + foo_bool = SortableMock(setools.Boolean) + foo_bool.name = "foo_bool" + bar_bool = SortableMock(setools.Boolean) + bar_bool.name = "bar_bool" + + common = SortableMock(setools.Common) + common.name = "common_perm_set" + common.perms = frozenset(("common_perm",)) + + foo_class = SortableMock(setools.ObjClass) + foo_class.name = "foo_class" + foo_class.perms = frozenset(("foo_perm1", "foo_perm2")) + foo_class.common = common + bar_class = SortableMock(setools.ObjClass) + bar_class.name = "bar_class" + bar_class.perms = frozenset(("bar_perm1", "bar_perm2")) + bar_class.common = common + + fooattr = mock_typeattr("foo_type") + barattr = mock_typeattr("bar_type") + + foo_t = mock_type("foo_t", attrs=(fooattr,)) + fooattr.expand.return_value = (foo_t,) + bar_t = mock_type("bar_t", attrs=(barattr,)) + barattr.expand.return_value = (bar_t,) + + foo_r = mock_role("foo_r", types=frozenset((foo_t,))) + bar_r = mock_role("bar_r", types=frozenset((bar_t,))) + + foo_u = mock_user("foo_u", roles=frozenset((foo_r,))) + bar_u = mock_user("bar_u", roles=frozenset((bar_r,))) + + foo_cat = SortableMock(setools.Category) + foo_cat.name = "foo_cat" + foo_cat.aliases.return_value = ("foo_cat_alias",) + bar_cat = SortableMock(setools.Category) + bar_cat.name = "bar_cat" + bar_cat.aliases.return_value = ("bar_cat_alias",) + + foo_sen = SortableMock(setools.Sensitivity) + foo_sen.name = "foo_sen" + foo_sen.aliases.return_value = ("foo_sen_alias",) + bar_sen = SortableMock(setools.Sensitivity) + bar_sen.name = "bar_sen" + bar_sen.aliases.return_value = ("bar_sen_alias",) + + policy = Mock(setools.SELinuxPolicy) + policy.mls = False + policy.bools.return_value = (foo_bool, bar_bool) + policy.categories.return_value = (foo_cat, bar_cat) + policy.classes.return_value = (foo_class, bar_class) + policy.commons.return_value = (common,) + policy.roles.return_value = (foo_r, bar_r) + policy.sensitivities.return_value = (foo_sen, bar_sen) + policy.types.return_value = (foo_t, bar_t) + policy.typeattributes.return_value = (fooattr, barattr) + policy.users.return_value = (foo_u, bar_u) + return policy + + +@pytest.fixture +def mock_query(mock_policy) -> setools.PolicyQuery: + """Build a mock query with mocked policy.""" + query = Mock(setools.PolicyQuery) + query.policy = mock_policy + return query + + +def _do_compile(source_file: str, output_file: str, /, *, mls: bool = True, + xen: bool = False) -> setools.SELinuxPolicy: + """ + Compile the specified source policy. Checkpolicy is + assumed to be /usr/bin/checkpolicy. Otherwise the path + must be specified in the CHECKPOLICY environment variable. + + Return: + A SELinuxPolicy object. + """ + user_src = os.getenv("USERSPACE_SRC") + checkpol = os.getenv("CHECKPOLICY") + + if user_src: + command = [user_src + "/checkpolicy/checkpolicy"] + elif checkpol: + command = [checkpol] + else: + command = ["/usr/bin/checkpolicy"] + + if mls: + command.append("-M") + + if xen: + command.extend(["-t", "xen", "-c", "30"]) + + command.extend(["-o", output_file, "-U", "reject", source_file]) + + with open(os.devnull, "w") as null: + subprocess.check_call(command, stdout=null, shell=False, close_fds=True) + + return setools.SELinuxPolicy(output_file) + + +@pytest.fixture(scope="class") +def compiled_policy(request: pytest.FixtureRequest) -> Iterable[setools.SELinuxPolicy]: + """Build a compiled policy.""" + marker = request.node.get_closest_marker("obj_args") + args = marker.args if marker else () + kwargs = marker.kwargs if marker else {} + + source_file = args[0] + + with tempfile.NamedTemporaryFile("w") as fd: + yield _do_compile(source_file, fd.name, mls=kwargs.get("mls", True), + xen=kwargs.get("xen", False)) + + +@pytest.fixture(scope="class") +def policy_pair(request: pytest.FixtureRequest) -> \ + Iterable[tuple[setools.SELinuxPolicy, setools.SELinuxPolicy]]: + """Build a compiled policy.""" + marker = request.node.get_closest_marker("obj_args") + args = marker.args if marker else () + kwargs = marker.kwargs if marker else {} + + source_file_left = args[0] + source_file_right = args[1] + + with tempfile.NamedTemporaryFile("w") as fd_left: + with tempfile.NamedTemporaryFile("w") as fd_right: + left = _do_compile(source_file_left, fd_left.name, + mls=kwargs.get("mls_left", True), + xen=kwargs.get("xen_left", False)) + right = _do_compile(source_file_right, fd_right.name, + mls=kwargs.get("mls_right", True), + xen=kwargs.get("xen_right", False)) + yield left, right diff --git a/tests-gui/__init__.py b/tests/gui/__init__.py similarity index 100% rename from tests-gui/__init__.py rename to tests/gui/__init__.py diff --git a/tests/gui/conftest.py b/tests/gui/conftest.py new file mode 100644 index 00000000..03de29a8 --- /dev/null +++ b/tests/gui/conftest.py @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-only + +import os +import pathlib +import pytest + +try: + import PyQt6 + have_pyqt6 = True +except ImportError: + have_pyqt6 = False + +try: + import pytestqt + have_pqtestqt = True +except ImportError: + have_pqtestqt = False + + +def pytest_ignore_collect(collection_path: pathlib.Path, path, + config: pytest.Config) -> bool | None: + + """Ignore GUI tests if DISPLAY is not set or PyQt is not available.""" + + xdisp = bool(os.getenv("DISPLAY")) + + # Return True to prevent considering this path for collection. + if all((xdisp, have_pyqt6, have_pqtestqt)): + return False + + return True diff --git a/tests-gui/widgets/__init__.py b/tests/gui/widgets/__init__.py similarity index 100% rename from tests-gui/widgets/__init__.py rename to tests/gui/widgets/__init__.py diff --git a/tests-gui/widgets/criteria/__init__.py b/tests/gui/widgets/criteria/__init__.py similarity index 100% rename from tests-gui/widgets/criteria/__init__.py rename to tests/gui/widgets/criteria/__init__.py diff --git a/tests-gui/widgets/criteria/test_boolean.py b/tests/gui/widgets/criteria/test_boolean.py similarity index 100% rename from tests-gui/widgets/criteria/test_boolean.py rename to tests/gui/widgets/criteria/test_boolean.py diff --git a/tests-gui/widgets/criteria/test_checkboxset.py b/tests/gui/widgets/criteria/test_checkboxset.py similarity index 100% rename from tests-gui/widgets/criteria/test_checkboxset.py rename to tests/gui/widgets/criteria/test_checkboxset.py diff --git a/tests-gui/widgets/criteria/test_common.py b/tests/gui/widgets/criteria/test_common.py similarity index 100% rename from tests-gui/widgets/criteria/test_common.py rename to tests/gui/widgets/criteria/test_common.py diff --git a/tests-gui/widgets/criteria/test_list.py b/tests/gui/widgets/criteria/test_list.py similarity index 100% rename from tests-gui/widgets/criteria/test_list.py rename to tests/gui/widgets/criteria/test_list.py diff --git a/tests-gui/widgets/criteria/test_name.py b/tests/gui/widgets/criteria/test_name.py similarity index 100% rename from tests-gui/widgets/criteria/test_name.py rename to tests/gui/widgets/criteria/test_name.py diff --git a/tests-gui/widgets/criteria/test_objclass.py b/tests/gui/widgets/criteria/test_objclass.py similarity index 100% rename from tests-gui/widgets/criteria/test_objclass.py rename to tests/gui/widgets/criteria/test_objclass.py diff --git a/tests-gui/widgets/criteria/test_permission.py b/tests/gui/widgets/criteria/test_permission.py similarity index 100% rename from tests-gui/widgets/criteria/test_permission.py rename to tests/gui/widgets/criteria/test_permission.py diff --git a/tests-gui/widgets/criteria/test_rbacruletype.py b/tests/gui/widgets/criteria/test_rbacruletype.py similarity index 100% rename from tests-gui/widgets/criteria/test_rbacruletype.py rename to tests/gui/widgets/criteria/test_rbacruletype.py diff --git a/tests-gui/widgets/criteria/test_role.py b/tests/gui/widgets/criteria/test_role.py similarity index 100% rename from tests-gui/widgets/criteria/test_role.py rename to tests/gui/widgets/criteria/test_role.py diff --git a/tests-gui/widgets/criteria/test_teruletype.py b/tests/gui/widgets/criteria/test_teruletype.py similarity index 100% rename from tests-gui/widgets/criteria/test_teruletype.py rename to tests/gui/widgets/criteria/test_teruletype.py diff --git a/tests-gui/widgets/criteria/test_type.py b/tests/gui/widgets/criteria/test_type.py similarity index 100% rename from tests-gui/widgets/criteria/test_type.py rename to tests/gui/widgets/criteria/test_type.py diff --git a/tests-gui/widgets/criteria/test_user.py b/tests/gui/widgets/criteria/test_user.py similarity index 100% rename from tests-gui/widgets/criteria/test_user.py rename to tests/gui/widgets/criteria/test_user.py diff --git a/tests-gui/widgets/test_boolquery.py b/tests/gui/widgets/test_boolquery.py similarity index 100% rename from tests-gui/widgets/test_boolquery.py rename to tests/gui/widgets/test_boolquery.py diff --git a/tests-gui/widgets/test_boundsquery.py b/tests/gui/widgets/test_boundsquery.py similarity index 100% rename from tests-gui/widgets/test_boundsquery.py rename to tests/gui/widgets/test_boundsquery.py diff --git a/tests-gui/widgets/test_categoryquery.py b/tests/gui/widgets/test_categoryquery.py similarity index 100% rename from tests-gui/widgets/test_categoryquery.py rename to tests/gui/widgets/test_categoryquery.py diff --git a/tests-gui/widgets/test_commonquery.py b/tests/gui/widgets/test_commonquery.py similarity index 100% rename from tests-gui/widgets/test_commonquery.py rename to tests/gui/widgets/test_commonquery.py diff --git a/tests-gui/widgets/test_constraintquery.py b/tests/gui/widgets/test_constraintquery.py similarity index 100% rename from tests-gui/widgets/test_constraintquery.py rename to tests/gui/widgets/test_constraintquery.py diff --git a/tests-gui/widgets/test_defaultquery.py b/tests/gui/widgets/test_defaultquery.py similarity index 100% rename from tests-gui/widgets/test_defaultquery.py rename to tests/gui/widgets/test_defaultquery.py diff --git a/tests-gui/widgets/test_fsusequery.py b/tests/gui/widgets/test_fsusequery.py similarity index 100% rename from tests-gui/widgets/test_fsusequery.py rename to tests/gui/widgets/test_fsusequery.py diff --git a/tests-gui/widgets/test_genfsconquery.py b/tests/gui/widgets/test_genfsconquery.py similarity index 100% rename from tests-gui/widgets/test_genfsconquery.py rename to tests/gui/widgets/test_genfsconquery.py diff --git a/tests-gui/widgets/test_ibendportconquery.py b/tests/gui/widgets/test_ibendportconquery.py similarity index 100% rename from tests-gui/widgets/test_ibendportconquery.py rename to tests/gui/widgets/test_ibendportconquery.py diff --git a/tests-gui/widgets/test_ibpkeyconquery.py b/tests/gui/widgets/test_ibpkeyconquery.py similarity index 100% rename from tests-gui/widgets/test_ibpkeyconquery.py rename to tests/gui/widgets/test_ibpkeyconquery.py diff --git a/tests-gui/widgets/test_initialsidquery.py b/tests/gui/widgets/test_initialsidquery.py similarity index 100% rename from tests-gui/widgets/test_initialsidquery.py rename to tests/gui/widgets/test_initialsidquery.py diff --git a/tests-gui/widgets/test_mlsrulequery.py b/tests/gui/widgets/test_mlsrulequery.py similarity index 100% rename from tests-gui/widgets/test_mlsrulequery.py rename to tests/gui/widgets/test_mlsrulequery.py diff --git a/tests-gui/widgets/test_netifconquery.py b/tests/gui/widgets/test_netifconquery.py similarity index 100% rename from tests-gui/widgets/test_netifconquery.py rename to tests/gui/widgets/test_netifconquery.py diff --git a/tests-gui/widgets/test_nodeconquery.py b/tests/gui/widgets/test_nodeconquery.py similarity index 100% rename from tests-gui/widgets/test_nodeconquery.py rename to tests/gui/widgets/test_nodeconquery.py diff --git a/tests-gui/widgets/test_objclassquery.py b/tests/gui/widgets/test_objclassquery.py similarity index 100% rename from tests-gui/widgets/test_objclassquery.py rename to tests/gui/widgets/test_objclassquery.py diff --git a/tests-gui/widgets/test_portconquery.py b/tests/gui/widgets/test_portconquery.py similarity index 100% rename from tests-gui/widgets/test_portconquery.py rename to tests/gui/widgets/test_portconquery.py diff --git a/tests-gui/widgets/test_rbacrulequery.py b/tests/gui/widgets/test_rbacrulequery.py similarity index 100% rename from tests-gui/widgets/test_rbacrulequery.py rename to tests/gui/widgets/test_rbacrulequery.py diff --git a/tests-gui/widgets/test_rolequery.py b/tests/gui/widgets/test_rolequery.py similarity index 100% rename from tests-gui/widgets/test_rolequery.py rename to tests/gui/widgets/test_rolequery.py diff --git a/tests-gui/widgets/test_sensitivityquery.py b/tests/gui/widgets/test_sensitivityquery.py similarity index 100% rename from tests-gui/widgets/test_sensitivityquery.py rename to tests/gui/widgets/test_sensitivityquery.py diff --git a/tests-gui/widgets/test_tab.py b/tests/gui/widgets/test_tab.py similarity index 100% rename from tests-gui/widgets/test_tab.py rename to tests/gui/widgets/test_tab.py diff --git a/tests-gui/widgets/test_terulequery.py b/tests/gui/widgets/test_terulequery.py similarity index 100% rename from tests-gui/widgets/test_terulequery.py rename to tests/gui/widgets/test_terulequery.py diff --git a/tests-gui/widgets/test_typeattrquery.py b/tests/gui/widgets/test_typeattrquery.py similarity index 100% rename from tests-gui/widgets/test_typeattrquery.py rename to tests/gui/widgets/test_typeattrquery.py diff --git a/tests-gui/widgets/test_typequery.py b/tests/gui/widgets/test_typequery.py similarity index 100% rename from tests-gui/widgets/test_typequery.py rename to tests/gui/widgets/test_typequery.py diff --git a/tests-gui/widgets/test_userquery.py b/tests/gui/widgets/test_userquery.py similarity index 100% rename from tests-gui/widgets/test_userquery.py rename to tests/gui/widgets/test_userquery.py diff --git a/tests/checker/__init__.py b/tests/library/__init__.py similarity index 100% rename from tests/checker/__init__.py rename to tests/library/__init__.py diff --git a/tests/boolquery.conf b/tests/library/boolquery.conf similarity index 100% rename from tests/boolquery.conf rename to tests/library/boolquery.conf diff --git a/tests/boundsquery.conf b/tests/library/boundsquery.conf similarity index 100% rename from tests/boundsquery.conf rename to tests/library/boundsquery.conf diff --git a/tests/categoryquery.conf b/tests/library/categoryquery.conf similarity index 100% rename from tests/categoryquery.conf rename to tests/library/categoryquery.conf diff --git a/tests/policyrep/__init__.py b/tests/library/checker/__init__.py similarity index 100% rename from tests/policyrep/__init__.py rename to tests/library/checker/__init__.py diff --git a/tests/checker/assertrbac.conf b/tests/library/checker/assertrbac.conf similarity index 100% rename from tests/checker/assertrbac.conf rename to tests/library/checker/assertrbac.conf diff --git a/tests/checker/assertte.conf b/tests/library/checker/assertte.conf similarity index 100% rename from tests/checker/assertte.conf rename to tests/library/checker/assertte.conf diff --git a/tests/checker/checker-invalidoption.ini b/tests/library/checker/checker-invalidoption.ini similarity index 100% rename from tests/checker/checker-invalidoption.ini rename to tests/library/checker/checker-invalidoption.ini diff --git a/tests/checker/checker-invalidtype.ini b/tests/library/checker/checker-invalidtype.ini similarity index 100% rename from tests/checker/checker-invalidtype.ini rename to tests/library/checker/checker-invalidtype.ini diff --git a/tests/checker/checker-invalidvalue.ini b/tests/library/checker/checker-invalidvalue.ini similarity index 100% rename from tests/checker/checker-invalidvalue.ini rename to tests/library/checker/checker-invalidvalue.ini diff --git a/tests/checker/checker-missingtype.ini b/tests/library/checker/checker-missingtype.ini similarity index 100% rename from tests/checker/checker-missingtype.ini rename to tests/library/checker/checker-missingtype.ini diff --git a/tests/checker/checker-valid.ini b/tests/library/checker/checker-valid.ini similarity index 100% rename from tests/checker/checker-valid.ini rename to tests/library/checker/checker-valid.ini diff --git a/tests/checker/checker.conf b/tests/library/checker/checker.conf similarity index 100% rename from tests/checker/checker.conf rename to tests/library/checker/checker.conf diff --git a/tests/checker/emptyattr.conf b/tests/library/checker/emptyattr.conf similarity index 100% rename from tests/checker/emptyattr.conf rename to tests/library/checker/emptyattr.conf diff --git a/tests/checker/roexec.conf b/tests/library/checker/roexec.conf similarity index 100% rename from tests/checker/roexec.conf rename to tests/library/checker/roexec.conf diff --git a/tests/library/checker/test_assertrbac.py b/tests/library/checker/test_assertrbac.py new file mode 100644 index 00000000..53540d19 --- /dev/null +++ b/tests/library/checker/test_assertrbac.py @@ -0,0 +1,241 @@ +# Copyright 2020, Microsoft Corporation +# Copyright 2020, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# +import os + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/checker/assertrbac.conf") +class TestAssertRBAC: + + def test_unconfigured(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test unconfigured.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config: dict[str, str] = {} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_unconfigured", config) + + def test_invalid_option(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test invalid option""" + with pytest.raises(setools.exception.InvalidCheckOption): + config = {"INVALID": "option"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_invalid_option", config) + + def test_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test source setting.""" + config = {"source": "src"} + check = setools.checker.assertrbac.AssertRBAC(compiled_policy, "test_source", config) + expected = compiled_policy.lookup_role("src") + assert expected == check.source + + def test_source_error(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test source bad setting.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"source": "FAIL"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_source_fail", config) + + def test_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test target setting.""" + config = {"target": "tgt"} + check = setools.checker.assertrbac.AssertRBAC(compiled_policy, "test_target", config) + expected = compiled_policy.lookup_role("tgt") + assert expected == check.target + + def test_target_error(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test target bad setting.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"target": "FAIL2"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_target_fail", config) + + def test_exempt_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_source setting.""" + config = {"source": "system", + "exempt_source": " exempt_src1 exempt_src2 "} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_exempt_source", config) + + # exempt_src2 is an attr + expected = set((compiled_policy.lookup_role("exempt_src1"), + compiled_policy.lookup_role("exempt_src2"))) + assert expected == check.exempt_source + + def test_exempt_source_missing(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_source missing role is ignroed.""" + config = {"source": "system", + "exempt_source": "FAIL exempt_src2"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_source_missing_ignored", config) + + # exempt_src2 is an attr + expected = set((compiled_policy.lookup_role("exempt_src2"),)) + assert expected == check.exempt_source + + def test_exempt_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_target setting.""" + config = {"target": "system", + "exempt_target": " exempt_tgt1 exempt_tgt2 "} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_exempt_target", config) + + # exempt_tgt2 is an attr + expected = set((compiled_policy.lookup_role("exempt_tgt1"), + compiled_policy.lookup_role("exempt_tgt2"))) + assert expected == check.exempt_target + + def test_exempt_target_missing(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Success, missing role ignored""" + config = {"target": "system", + "exempt_target": "FAIL exempt_tgt2"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_target_missing_ignored", config) + + # exempt_tgt2 is an attr + expected = set((compiled_policy.lookup_role("exempt_tgt2"),)) + assert expected == check.exempt_target + + def test_expect_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test expect_source setting.""" + config = {"target": "tgt", + "expect_source": " exempt_src1 exempt_src2 "} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_expect_source", config) + + # exempt_src2 is an attr + expected = set((compiled_policy.lookup_role("exempt_src1"), + compiled_policy.lookup_role("exempt_src2"))) + assert expected == check.expect_source + + def test_expect_source_error(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test bad expect_source setting.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"target": "tgt", + "expect_source": " source1 INVALID "} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_expect_source_fail", config) + + def test_expect_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test expect_target setting.""" + config = {"source": "src", + "expect_target": " exempt_tgt1 exempt_tgt2 "} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_expect_target", config) + + # exempt_tgt2 is an attr + expected = set((compiled_policy.lookup_role("exempt_tgt1"), + compiled_policy.lookup_role("exempt_tgt2"))) + assert expected == check.expect_target + + def test_expect_target_error(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test bad expect_target setting.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"source": "src", + "expect_target": " target1 INVALID "} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_expect_target_fail", config) + + def test_check_passes(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, no matches""" + config = {"source": "src", + "target": "tgt"} + check = setools.checker.assertrbac.AssertRBAC(compiled_policy, "test_check_passes", config) + assert not check.run() + + def test_check_passes_exempt_source_role(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, exempt_source_role""" + config = {"target": "target1", + "exempt_source": "source1"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_exempt_source_role", config) + assert not check.run() + + def test_check_passes_exempt_target_role(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, exempt_target_role""" + config = {"target": "target2", + "exempt_source": "source2"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_exempt_target_role", config) + assert not check.run() + + def test_check_passes_expect_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, expect_source""" + config = {"target": "target3", + "expect_source": "source3a source3b"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_expect_source", config) + assert not check.run() + + def test_check_passes_expect_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, expect_target""" + config = {"source": "source4", + "expect_target": "target4a target4b"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_expect_target", config) + assert not check.run() + + def test_check_passes_expect_exempt_source(self, + compiled_policy: setools.SELinuxPolicy) -> None: + """"Test the check passes with both expected and exempted sources.""" + config = {"target": "target5", + "expect_source": "source5a", + "exempt_source": "source5b"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_expect_exempt_source", config) + assert not check.run() + + def test_check_passes_expect_exempt_target(self, + compiled_policy: setools.SELinuxPolicy) -> None: + """"Test the check passes with both expected and exempted targets.""" + config = {"source": "source6", + "expect_target": "target6a", + "exempt_target": "target6b"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_expect_exempt_target", config) + assert not check.run() + + def test_check_fails(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check fails""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"source": "source7", + "expect_target": "target7a", + "exempt_target": "target7b"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_passes_exempt_target_attr", config) + check.output = fd + result = check.run() + assert 1 == len(result) + rule = result[0] + assert isinstance(rule, setools.RoleAllow) + assert setools.RBACRuletype.allow == rule.ruletype + assert "source7" == rule.source + assert "target7c" == rule.target + + def test_check_fails_expect_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check fails, expect_source""" + config = {"target": "target8", + "expect_source": "source8"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_fails_expect_source", config) + result = check.run() + assert 1 == len(result) + msg = result.pop() + assert isinstance(msg, str) + assert "source8" in msg + + def test_check_fails_expect_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check fails, expect_target""" + config = {"source": "source9", + "expect_target": "target9"} + check = setools.checker.assertrbac.AssertRBAC( + compiled_policy, "test_check_fails_expect_target", config) + result = check.run() + assert 1 == len(result) + msg = result.pop() + assert isinstance(msg, str) + assert "target9" in msg diff --git a/tests/library/checker/test_assertte.py b/tests/library/checker/test_assertte.py new file mode 100644 index 00000000..bd23a8e1 --- /dev/null +++ b/tests/library/checker/test_assertte.py @@ -0,0 +1,327 @@ +# Copyright 2020, Microsoft Corporation +# Copyright 2020, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# + +import os + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/checker/assertte.conf") +class TestAssertTE: + + def test_unconfigured(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test unconfigured.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = dict[str, str]() + check = setools.checker.assertte.AssertTE(compiled_policy, "test_unconfigured", config) + + def test_invalid_option(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test invalid option""" + with pytest.raises(setools.exception.InvalidCheckOption): + config = {"INVALID": "option"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_invalid_option", config) + + def test_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test source setting.""" + config = {"source": "src"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_source", config) + + expected = compiled_policy.lookup_type("src") + assert expected == check.source + + def test_source_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test source setting failure.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"source": "FAIL"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_source_fail", config) + + def test_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test target setting.""" + config = {"target": "tgt"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_target", config) + + expected = compiled_policy.lookup_type("tgt") + assert expected == check.target + + def test_target_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test target setting failure.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"target": "FAIL2"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_target_fail", config) + + def test_exempt_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_source setting.""" + config = {"source": "system", + "exempt_source": " exempt_src1 exempt_src2 "} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_exempt_source", config) + + # exempt_src2 is an attr + expected = set((compiled_policy.lookup_type("exempt_src1"), + compiled_policy.lookup_type("exempt_source_type"))) + assert expected == check.exempt_source + + def test_source_missing_ignored(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_source missing type is ignroed.""" + config = {"source": "system", + "exempt_source": "FAIL exempt_src2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_source_missing_ignored", config) + + # exempt_src2 is an attr + expected = set((compiled_policy.lookup_type("exempt_source_type"),)) + assert expected == check.exempt_source + + def test_exempt_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_target setting.""" + config = {"target": "system", + "exempt_target": " exempt_tgt1 exempt_tgt2 "} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_exempt_target", config) + + # exempt_tgt2 is an attr + expected = set((compiled_policy.lookup_type("exempt_tgt1"), + compiled_policy.lookup_type("exempt_target_type"))) + assert expected == check.exempt_target + + def test_target_missing_ignored(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test exempt_target missing type is ignroed.""" + config = {"target": "system", + "exempt_target": "FAIL exempt_tgt2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_target_missing_ignored", config) + + # exempt_tgt2 is an attr + expected = set((compiled_policy.lookup_type("exempt_target_type"),)) + assert expected == check.exempt_target + + def test_expect_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test expect_source setting.""" + config = {"tclass": "infoflow3", + "expect_source": " exempt_src1 exempt_src2 "} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_expect_source", config) + + # exempt_src2 is an attr + expected = set((compiled_policy.lookup_type("exempt_src1"), + compiled_policy.lookup_type("exempt_source_type"))) + assert expected == check.expect_source + + def test_expect_source_error(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test bad expect_source setting.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"tclass": "infoflow3", + "expect_source": " source1 INVALID "} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_expect_source_fail", config) + + def test_expect_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test expect_target setting.""" + config = {"tclass": "infoflow3", + "expect_target": " exempt_tgt1 exempt_tgt2 "} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_expect_target", config) + + # exempt_tgt2 is an attr + expected = set((compiled_policy.lookup_type("exempt_tgt1"), + compiled_policy.lookup_type("exempt_target_type"))) + assert expected == check.expect_target + + def test_expect_target_error(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test bad expect_target setting.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"tclass": "infoflow3", + "expect_target": " target1 INVALID "} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_expect_target_fail", config) + + def test_tclass(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test tclass setting.""" + config = {"tclass": "infoflow3 infoflow2"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_tclass", config) + + expected = set((compiled_policy.lookup_class("infoflow3"), + compiled_policy.lookup_class("infoflow2"))) + assert expected == check.tclass + + def test_tclass_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test tclass setting failure.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"tclass": "FAIL_class"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_tclass_fail", config) + + def test_perms(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test perms setting.""" + config = {"perms": " hi_w super_r "} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_perms", config) + + expected = set(("hi_w", "super_r")) + assert expected == check.perms + + def test_perms_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test perms setting failure.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"perms": "FAIL_perms"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_perms_fail", config) + + def test_check_passes(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, no matches""" + config = {"perms": "null"} + check = setools.checker.assertte.AssertTE(compiled_policy, "test_check_passes", config) + assert not check.run() + + def test_check_passes_empty_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, empty source attribute""" + config = {"tclass": "infoflow7", + "perms": "super_w"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_empty_source", config) + assert not check.run() + + def test_check_passes_empty_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, empty target attribute""" + config = {"tclass": "infoflow7", + "perms": "super_r"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_empty_target", config) + assert not check.run() + + def test_check_passes_exempt_source_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, exempt_source_type""" + config = {"tclass": "infoflow6", + "perms": "hi_w", + "exempt_source": "source1"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_exempt_source_type", config) + assert not check.run() + + def test_check_passes_exempt_source_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, exempt_source_attr""" + config = {"tclass": "infoflow6", + "perms": "hi_r", + "exempt_source": "all_sources"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_exempt_source_attr", config) + assert not check.run() + + def test_check_passes_exempt_target_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, exempt_target_type""" + config = {"tclass": "infoflow5", + "perms": "low_w", + "exempt_source": "source1"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_exempt_target_type", config) + assert not check.run() + + def test_check_passes_exempt_target_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, exempt_target_attr""" + config = {"tclass": "infoflow5", + "perms": "low_r", + "exempt_target": "all_targets"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_exempt_target_attr", config) + assert not check.run() + + def test_check_passes_expect_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, expect_source""" + config = {"tclass": "infoflow6", + "perms": "hi_r", + "expect_source": "source1 source2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_expect_source", config) + assert not check.run() + + def test_check_passes_expect_source_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, expect_source with attribute""" + config = {"tclass": "infoflow4", + "perms": "med_w", + "expect_source": "all_sources"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_expect_source_attr", config) + assert not check.run() + + def test_check_passes_expect_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, expect_target""" + config = {"tclass": "infoflow6", + "perms": "hi_r", + "expect_target": "target1 target2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_expect_target", config) + assert not check.run() + + def test_check_passes_expect_target_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check passes, expect_target with attribute""" + config = {"tclass": "infoflow4", + "perms": "med_w", + "expect_target": "all_targets"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_expect_target_attr", config) + assert not check.run() + + def test_check_passes_expect_exempt_source(self, + compiled_policy: setools.SELinuxPolicy) -> None: + """"Test the check passes with both expected and exempted sources.""" + config = {"tclass": "infoflow5", + "perms": "low_r", + "expect_source": "source1", + "exempt_source": "source2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_expect_exempt_source", config) + assert not check.run() + + def test_check_passes_expect_exempt_target(self, + compiled_policy: setools.SELinuxPolicy) -> None: + """"Test the check passes with both expected and exempted targets.""" + config = {"tclass": "infoflow5", + "perms": "low_r", + "expect_source": "source1", + "exempt_source": "source2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_expect_exempt_target", config) + assert not check.run() + + def test_check_fails(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check fails""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"tclass": "infoflow4", + "perms": "med_w", + "exempt_source": "source1", + "exempt_target": "target2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_passes_exempt_target_attr", config) + check.output = fd + result = check.run() + assert 1 == len(result) + rule = result.pop() + assert isinstance(rule, setools.AVRule) + assert rule.ruletype == setools.TERuletype.allow + assert rule.source == "source3" + assert rule.target == "target3" + assert rule.tclass == "infoflow4" + assert rule.perms == set(["med_w"]) + + def test_check_fails_expect_source(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check fails, expect_source""" + config = {"tclass": "infoflow7", + "perms": "super_w", + "expect_source": "source1"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_fails_expect_source", config) + result = check.run() + assert 1 == len(result) + msg = result.pop() + assert isinstance(msg, str) + assert "source1" in msg + + def test_check_fails_expect_target(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test the check fails, expect_target""" + config = {"tclass": "infoflow7", + "perms": "super_r", + "expect_target": "target2"} + check = setools.checker.assertte.AssertTE( + compiled_policy, "test_check_fails_expect_target", config) + result = check.run() + msg = result.pop() + assert isinstance(msg, str) + assert "target2" in msg diff --git a/tests/library/checker/test_checker.py b/tests/library/checker/test_checker.py new file mode 100644 index 00000000..5aa6bb2e --- /dev/null +++ b/tests/library/checker/test_checker.py @@ -0,0 +1,81 @@ +# Copyright 2020, Microsoft Corporation +# +# SPDX-License-Identifier: GPL-2.0-only +# +import os +from unittest.mock import Mock + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/checker/checker.conf") +class TestPolicyChecker: + + def test_config_empty(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test empty config file""" + with pytest.raises(setools.exception.InvalidCheckerConfig): + setools.checker.PolicyChecker(compiled_policy, os.devnull) + + def test_config_check_missing_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test check missing check type""" + with pytest.raises(setools.exception.InvalidCheckerModule): + setools.checker.PolicyChecker(compiled_policy, + "tests/library/checker/checker-missingtype.ini") + + def test_config_check_invalid_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test check invalid check type""" + with pytest.raises(setools.exception.InvalidCheckerModule): + setools.checker.PolicyChecker(compiled_policy, + "tests/library/checker/checker-invalidtype.ini") + + def test_config_check_invalid_option(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test check invalid check option""" + with pytest.raises(setools.exception.InvalidCheckOption): + setools.checker.PolicyChecker(compiled_policy, + "tests/library/checker/checker-invalidoption.ini") + + def test_config_check_invalid_value(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test check invalid check type""" + with pytest.raises(setools.exception.InvalidCheckValue): + setools.checker.PolicyChecker(compiled_policy, + "tests/library/checker/checker-invalidvalue.ini") + + def test_run_pass(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test run with passing config.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + checker = setools.checker.PolicyChecker(compiled_policy, + "tests/library/checker/checker-valid.ini") + + # create additional disabled mock test + newcheck = Mock() + newcheck.checkname = "disabled" + newcheck.disable = True + newcheck.validate_config.return_value = None + newcheck.run.return_value = [] + checker.checks.append(newcheck) + + assert 4 == len(checker.checks) + result = checker.run(output=fd) + assert 0 == result + newcheck.run.assert_not_called() + + def test_run_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test run with failing config.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + checker = setools.checker.PolicyChecker(compiled_policy, + "tests/library/checker/checker-valid.ini") + + # create additional failing mock test + newcheck = Mock() + newcheck.checkname = "failing test" + newcheck.disable = False + newcheck.validate_config.return_value = None + newcheck.run.return_value = list(range(13)) + checker.checks.append(newcheck) + + assert 4 == len(checker.checks) + + result = checker.run(output=fd) + newcheck.run.assert_called() + assert 13 == result diff --git a/tests/library/checker/test_emptyattr.py b/tests/library/checker/test_emptyattr.py new file mode 100644 index 00000000..ed081d17 --- /dev/null +++ b/tests/library/checker/test_emptyattr.py @@ -0,0 +1,102 @@ +# Copyright 2020, Microsoft Corporation +# +# SPDX-License-Identifier: GPL-2.0-only +# +import os + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/checker/emptyattr.conf") +class TestEmptyTypeAttr: + + def test_invalid_option(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test invalid option""" + with pytest.raises(setools.exception.InvalidCheckOption): + config = {"INVALID": "option"} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_invalid_option", config) + + def test_attr_setting(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test attr setting.""" + config = {"attr": "test1"} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_attr_setting", config) + + expected = compiled_policy.lookup_typeattr("test1") + assert expected == check.attr + + def test_attr_setting_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test attr setting with invalid attr.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = {"attr": "FAILATTR"} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_attr_setting_fail", config) + + def test_attr_setting_missing(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test attr setting missing.""" + with pytest.raises(setools.exception.InvalidCheckValue): + config = dict[str, str]() + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_attr_setting_missing", config) + + def test_missingok_setting(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test missing_ok setting.""" + config = {"attr": "test1", + "missing_ok": "true"} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_missingok_setting", config) + assert check.missing_ok + + config = {"attr": "test1", + "missing_ok": " YeS "} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_missingok_setting", config) + assert check.missing_ok + + config = {"attr": "test1", + "missing_ok": " 1 "} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_missingok_setting", config) + assert check.missing_ok + + config = {"attr": "test1", + "missing_ok": " No "} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_missingok_setting", config) + assert not check.missing_ok + + def test_pass(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test pass.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"attr": "test1"} + check = setools.checker.emptyattr.EmptyTypeAttr(compiled_policy, "test_pass", config) + check.output = fd + result = check.run() + assert 0 == len(result) + + def test_pass_missingok(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test pass by missing.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"attr": "test2", + "missing_ok": "true"} + check = setools.checker.emptyattr.EmptyTypeAttr( + compiled_policy, "test_pass_missingok", config) + check.output = fd + result = check.run() + assert 0 == len(result) + + def test_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """EmptyTypeAttr test fail.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + # also verify missing_ok doesn't induce a pass + # when the attr exists + config = {"attr": "test3", + "missing_ok": "true"} + check = setools.checker.emptyattr.EmptyTypeAttr(compiled_policy, "test_fail", config) + check.output = fd + result = check.run() + expected = [compiled_policy.lookup_type("test3_hit1"), + compiled_policy.lookup_type("test3_hit2")] + assert expected == result diff --git a/tests/library/checker/test_roexec.py b/tests/library/checker/test_roexec.py new file mode 100644 index 00000000..6a44f47a --- /dev/null +++ b/tests/library/checker/test_roexec.py @@ -0,0 +1,99 @@ +# Copyright 2020, Microsoft Corporation +# +# SPDX-License-Identifier: GPL-2.0-only +# +import os + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/checker/roexec.conf") +class TestReadOnlyExecutables: + + def test_invalid_option(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test invalid option""" + with pytest.raises(setools.exception.InvalidCheckOption): + config = {"INVALID": "option"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_invalid_option", config) + + def test_all_exec(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test all executables are returned for no-option test..""" + config = dict[str, str]() + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_all_exec", config) + result = check._collect_executables() + + # becasue of unconfined, nonexec is executable + expected = set(("roexec", "execfile1", "execfile2", "nonexec", "exempt_file")) + assert expected == set(result.keys()) + + def test_exempt_exec_domain(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test for exempting an exec domain.""" + config = {"exempt_exec_domain": "unconfined"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_exempt_exec_domain", config) + result = check._collect_executables() + + expected = set(("execfile1", "execfile2", "roexec")) + assert expected == set(result.keys()) + + def test_exempt_file(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test for exempting a file.""" + config = {"exempt_file": "exempt_file"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_exempt_file", config) + result = check._collect_executables() + + expected = set(("roexec", "execfile1", "execfile2", "nonexec")) + assert expected == result.keys() + + def test_exempt_file_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test for exempting a file by attribute.""" + config = {"exempt_file": "exempt_files_attr"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_exempt_file_attr", config) + result = check._collect_executables() + + expected = set(("roexec", "nonexec", "exempt_file")) + assert expected == result.keys() + + def test_fail(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test for failing.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"exempt_exec_domain": "unconfined", + "exempt_write_domain": "unconfined"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_fail", config) + check.output = fd + result = check.run() + + expected = [compiled_policy.lookup_type("execfile1"), + compiled_policy.lookup_type("execfile2")] + assert expected == result + + def test_pass(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test for passing.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"exempt_exec_domain": "unconfined", + "exempt_write_domain": "domain1 domain2 unconfined"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_pass", config) + check.output = fd + result = check.run() + + assert not result + + def test_pass2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Test for passing with alternate exemptions.""" + with open(os.devnull, "w", encoding="utf-8") as fd: + config = {"exempt_exec_domain": "unconfined", + "exempt_file": "execfile2", + "exempt_write_domain": "domain1 unconfined"} + check = setools.checker.roexec.ReadOnlyExecutables( + compiled_policy, "test_pass2", config) + check.output = fd + result = check.run() + + assert not result diff --git a/tests/library/checker/util.py b/tests/library/checker/util.py new file mode 100644 index 00000000..c2318b3e --- /dev/null +++ b/tests/library/checker/util.py @@ -0,0 +1,21 @@ +# Copyright 2020, Microsoft Corporation +# +# SPDX-License-Identifier: GPL-2.0-only +# +from setools.checker import util + + +class TestCheckerUtil: + + def test_config_bool_value(self): + """Test config_bool_value""" + assert util.config_bool_value(" TrUe ") + assert (util.config_bool_value(" 1 ")) + assert (util.config_bool_value(" YeS ")) + assert not util.config_bool_value(" FalsE ") + assert not util.config_bool_value(" 0 ") + assert not util.config_bool_value(" No ") + + assert util.config_bool_value(True) + assert not util.config_bool_value(None) + assert not util.config_bool_value(False) diff --git a/tests/commonquery.conf b/tests/library/commonquery.conf similarity index 100% rename from tests/commonquery.conf rename to tests/library/commonquery.conf diff --git a/tests/conditionalinfoflow.conf b/tests/library/conditionalinfoflow.conf similarity index 100% rename from tests/conditionalinfoflow.conf rename to tests/library/conditionalinfoflow.conf diff --git a/tests/constraintquery.conf b/tests/library/constraintquery.conf similarity index 100% rename from tests/constraintquery.conf rename to tests/library/constraintquery.conf diff --git a/tests/defaultquery.conf b/tests/library/defaultquery.conf similarity index 100% rename from tests/defaultquery.conf rename to tests/library/defaultquery.conf diff --git a/tests/devicetreeconquery.conf b/tests/library/devicetreeconquery.conf similarity index 100% rename from tests/devicetreeconquery.conf rename to tests/library/devicetreeconquery.conf diff --git a/tests/diff_left.conf b/tests/library/diff_left.conf similarity index 100% rename from tests/diff_left.conf rename to tests/library/diff_left.conf diff --git a/tests/diff_left_redundant.conf b/tests/library/diff_left_redundant.conf similarity index 100% rename from tests/diff_left_redundant.conf rename to tests/library/diff_left_redundant.conf diff --git a/tests/diff_left_standard.conf b/tests/library/diff_left_standard.conf similarity index 100% rename from tests/diff_left_standard.conf rename to tests/library/diff_left_standard.conf diff --git a/tests/diff_right.conf b/tests/library/diff_right.conf similarity index 100% rename from tests/diff_right.conf rename to tests/library/diff_right.conf diff --git a/tests/diff_right_rmisid.conf b/tests/library/diff_right_rmisid.conf similarity index 100% rename from tests/diff_right_rmisid.conf rename to tests/library/diff_right_rmisid.conf diff --git a/tests/dta.conf b/tests/library/dta.conf similarity index 100% rename from tests/dta.conf rename to tests/library/dta.conf diff --git a/tests/fsusequery.conf b/tests/library/fsusequery.conf similarity index 100% rename from tests/fsusequery.conf rename to tests/library/fsusequery.conf diff --git a/tests/genfsconquery.conf b/tests/library/genfsconquery.conf similarity index 100% rename from tests/genfsconquery.conf rename to tests/library/genfsconquery.conf diff --git a/tests/ibendportconquery.conf b/tests/library/ibendportconquery.conf similarity index 100% rename from tests/ibendportconquery.conf rename to tests/library/ibendportconquery.conf diff --git a/tests/ibpkeyconquery.conf b/tests/library/ibpkeyconquery.conf similarity index 100% rename from tests/ibpkeyconquery.conf rename to tests/library/ibpkeyconquery.conf diff --git a/tests/infoflow.conf b/tests/library/infoflow.conf similarity index 100% rename from tests/infoflow.conf rename to tests/library/infoflow.conf diff --git a/tests/initsidquery.conf b/tests/library/initsidquery.conf similarity index 100% rename from tests/initsidquery.conf rename to tests/library/initsidquery.conf diff --git a/tests/invalid_perm_maps/bad-class-keyword b/tests/library/invalid_perm_maps/bad-class-keyword similarity index 100% rename from tests/invalid_perm_maps/bad-class-keyword rename to tests/library/invalid_perm_maps/bad-class-keyword diff --git a/tests/invalid_perm_maps/bad-perm-weight-high b/tests/library/invalid_perm_maps/bad-perm-weight-high similarity index 100% rename from tests/invalid_perm_maps/bad-perm-weight-high rename to tests/library/invalid_perm_maps/bad-perm-weight-high diff --git a/tests/invalid_perm_maps/bad-perm-weight-low b/tests/library/invalid_perm_maps/bad-perm-weight-low similarity index 100% rename from tests/invalid_perm_maps/bad-perm-weight-low rename to tests/library/invalid_perm_maps/bad-perm-weight-low diff --git a/tests/invalid_perm_maps/bad-permcount b/tests/library/invalid_perm_maps/bad-permcount similarity index 100% rename from tests/invalid_perm_maps/bad-permcount rename to tests/library/invalid_perm_maps/bad-permcount diff --git a/tests/invalid_perm_maps/extra-class b/tests/library/invalid_perm_maps/extra-class similarity index 100% rename from tests/invalid_perm_maps/extra-class rename to tests/library/invalid_perm_maps/extra-class diff --git a/tests/invalid_perm_maps/extra-perms b/tests/library/invalid_perm_maps/extra-perms similarity index 100% rename from tests/invalid_perm_maps/extra-perms rename to tests/library/invalid_perm_maps/extra-perms diff --git a/tests/invalid_perm_maps/invalid-flowdir b/tests/library/invalid_perm_maps/invalid-flowdir similarity index 100% rename from tests/invalid_perm_maps/invalid-flowdir rename to tests/library/invalid_perm_maps/invalid-flowdir diff --git a/tests/invalid_perm_maps/invalid-perm-weight b/tests/library/invalid_perm_maps/invalid-perm-weight similarity index 100% rename from tests/invalid_perm_maps/invalid-perm-weight rename to tests/library/invalid_perm_maps/invalid-perm-weight diff --git a/tests/invalid_perm_maps/negative-classcount b/tests/library/invalid_perm_maps/negative-classcount similarity index 100% rename from tests/invalid_perm_maps/negative-classcount rename to tests/library/invalid_perm_maps/negative-classcount diff --git a/tests/invalid_perm_maps/negative-permcount b/tests/library/invalid_perm_maps/negative-permcount similarity index 100% rename from tests/invalid_perm_maps/negative-permcount rename to tests/library/invalid_perm_maps/negative-permcount diff --git a/tests/invalid_perm_maps/non-number-classcount b/tests/library/invalid_perm_maps/non-number-classcount similarity index 100% rename from tests/invalid_perm_maps/non-number-classcount rename to tests/library/invalid_perm_maps/non-number-classcount diff --git a/tests/iomemconquery.conf b/tests/library/iomemconquery.conf similarity index 100% rename from tests/iomemconquery.conf rename to tests/library/iomemconquery.conf diff --git a/tests/ioportconquery.conf b/tests/library/ioportconquery.conf similarity index 100% rename from tests/ioportconquery.conf rename to tests/library/ioportconquery.conf diff --git a/tests/mlsrulequery.conf b/tests/library/mlsrulequery.conf similarity index 100% rename from tests/mlsrulequery.conf rename to tests/library/mlsrulequery.conf diff --git a/tests/netifconquery.conf b/tests/library/netifconquery.conf similarity index 100% rename from tests/netifconquery.conf rename to tests/library/netifconquery.conf diff --git a/tests/nodeconquery.conf b/tests/library/nodeconquery.conf similarity index 100% rename from tests/nodeconquery.conf rename to tests/library/nodeconquery.conf diff --git a/tests/objclassquery.conf b/tests/library/objclassquery.conf similarity index 100% rename from tests/objclassquery.conf rename to tests/library/objclassquery.conf diff --git a/tests/pcideviceconquery.conf b/tests/library/pcideviceconquery.conf similarity index 100% rename from tests/pcideviceconquery.conf rename to tests/library/pcideviceconquery.conf diff --git a/tests/perm_map b/tests/library/perm_map similarity index 100% rename from tests/perm_map rename to tests/library/perm_map diff --git a/tests/permmap.conf b/tests/library/permmap.conf similarity index 100% rename from tests/permmap.conf rename to tests/library/permmap.conf diff --git a/tests/pirqconquery.conf b/tests/library/pirqconquery.conf similarity index 100% rename from tests/pirqconquery.conf rename to tests/library/pirqconquery.conf diff --git a/tests/polcapquery.conf b/tests/library/polcapquery.conf similarity index 100% rename from tests/polcapquery.conf rename to tests/library/polcapquery.conf diff --git a/tests/library/policyrep/__init__.py b/tests/library/policyrep/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/library/policyrep/common.conf b/tests/library/policyrep/common.conf new file mode 100644 index 00000000..943c2109 --- /dev/null +++ b/tests/library/policyrep/common.conf @@ -0,0 +1,113 @@ +class infoflow +class infoflow2 +class infoflow3 +class infoflow4 +class infoflow7 +class infoflow8 +class infoflow10 + +sid kernel +sid security + +common infoflow +{ + low_w + low_r +} + +class infoflow +inherits infoflow + +class infoflow2 +inherits infoflow +{ + super_w + super_r +} + +class infoflow3 +{ + null +} + +class infoflow4 +inherits infoflow +{ + super_w + super_r + super_none + super_both + super_unmapped +} + +class infoflow7 +inherits infoflow +{ + unmapped +} + +class infoflow8 +{ + super_w + super_r +} + +class infoflow10 +{ + read + write +} + +sensitivity low_s; +sensitivity medium_s alias med; +sensitivity high_s; + +dominance { low_s med high_s } + +category here; +category there; +category elsewhere alias lost; + +#level decl +level low_s:here.there; +level med:here, elsewhere; +level high_s:here.lost; + +#some constraints +mlsconstrain infoflow low_r ((l1 dom l2) or (t1 == mls_exempt)); + +attribute mls_exempt; + +type system; +role system; +role system types system; + +allow system self:infoflow3 null; + +#users +user system roles system level med range low_s - high_s:here.lost; + +#normal constraints +constrain infoflow low_w (u1 == u2); + +#isids +sid kernel system:system:system:medium_s:here +sid security system:system:system:high_s:lost + +#fs_use +fs_use_trans devpts system:object_r:system:low_s; +fs_use_xattr ext3 system:object_r:system:low_s; +fs_use_task pipefs system:object_r:system:low_s; + +#genfscon +genfscon proc / system:object_r:system:med +genfscon proc /sys system:object_r:system:low_s +genfscon selinuxfs / system:object_r:system:high_s:here.there + +portcon tcp 80 system:object_r:system:low_s + +netifcon eth0 system:object_r:system:low_s system:object_r:system:low_s + +nodecon 127.0.0.1 255.255.255.255 system:object_r:system:low_s:here +nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:low_s:here + diff --git a/tests/library/policyrep/default.conf b/tests/library/policyrep/default.conf new file mode 100644 index 00000000..a9dee03e --- /dev/null +++ b/tests/library/policyrep/default.conf @@ -0,0 +1,126 @@ +class infoflow +class infoflow2 +class infoflow3 +class infoflow4 +class infoflow7 +class infoflow8 +class infoflow10 + +sid kernel +sid security + +common infoflow +{ + low_w + low_r +} + +class infoflow +inherits infoflow + +class infoflow2 +inherits infoflow +{ + super_w + super_r +} + +class infoflow3 +{ + null +} + +class infoflow4 +inherits infoflow +{ + super_w + super_r + super_none + super_both + super_unmapped +} + +class infoflow7 +inherits infoflow +{ + unmapped +} + +class infoflow8 +{ + super_w + super_r +} + +class infoflow10 +{ + read + write +} + +default_user infoflow target; + +default_role infoflow2 source; + +default_type infoflow3 target; + +default_range infoflow4 source high; + +default_user infoflow10 source; +default_role infoflow10 source; +default_type infoflow10 source; +default_range infoflow10 source low; + +sensitivity low_s; +sensitivity medium_s alias med; +sensitivity high_s; + +dominance { low_s med high_s } + +category here; +category there; +category elsewhere alias lost; + +#level decl +level low_s:here.there; +level med:here, elsewhere; +level high_s:here.lost; + +#some constraints +mlsconstrain infoflow low_r ((l1 dom l2) or (t1 == mls_exempt)); + +attribute mls_exempt; + +type system; +role system; +role system types system; + +allow system self:infoflow3 null; + +#users +user system roles system level med range low_s - high_s:here.lost; + +#normal constraints +constrain infoflow low_w (u1 == u2); + +#isids +sid kernel system:system:system:medium_s:here +sid security system:system:system:high_s:lost + +#fs_use +fs_use_trans devpts system:object_r:system:low_s; +fs_use_xattr ext3 system:object_r:system:low_s; +fs_use_task pipefs system:object_r:system:low_s; + +#genfscon +genfscon proc / system:object_r:system:med +genfscon proc /sys system:object_r:system:low_s +genfscon selinuxfs / system:object_r:system:high_s:here.there + +portcon tcp 80 system:object_r:system:low_s + +netifcon eth0 system:object_r:system:low_s system:object_r:system:low_s + +nodecon 127.0.0.1 255.255.255.255 system:object_r:system:low_s:here +nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:low_s:here + diff --git a/tests/policyrep/initsid.conf b/tests/library/policyrep/initsid.conf similarity index 97% rename from tests/policyrep/initsid.conf rename to tests/library/policyrep/initsid.conf index 1b2db897..c0ff3347 100644 --- a/tests/policyrep/initsid.conf +++ b/tests/library/policyrep/initsid.conf @@ -7,7 +7,6 @@ class infoflow6 class infoflow7 sid kernel -sid security common infoflow { @@ -118,7 +117,6 @@ constrain infoflow hi_w (u1 == u2); #isids sid kernel system:system:system:s0 -sid security system:system:system:s0 #fs_use fs_use_trans devpts system:object_r:system:s0; diff --git a/tests/policyrep/invalid_policies/nodecon-invalid-range.conf b/tests/library/policyrep/invalid_policies/nodecon-invalid-range.conf similarity index 100% rename from tests/policyrep/invalid_policies/nodecon-invalid-range.conf rename to tests/library/policyrep/invalid_policies/nodecon-invalid-range.conf diff --git a/tests/policyrep/invalid_policies/user-level-not-in-range.conf b/tests/library/policyrep/invalid_policies/user-level-not-in-range.conf similarity index 100% rename from tests/policyrep/invalid_policies/user-level-not-in-range.conf rename to tests/library/policyrep/invalid_policies/user-level-not-in-range.conf diff --git a/tests/library/policyrep/mls.conf b/tests/library/policyrep/mls.conf new file mode 100644 index 00000000..0be737e2 --- /dev/null +++ b/tests/library/policyrep/mls.conf @@ -0,0 +1,177 @@ +class infoflow +class infoflow2 +class infoflow3 +class infoflow4 +class infoflow5 +class infoflow6 +class infoflow7 + +sid kernel +sid security + +common infoflow +{ + low_w + med_w + hi_w + low_r + med_r + hi_r +} + +class infoflow +inherits infoflow + +class infoflow2 +inherits infoflow +{ + super_w + super_r +} + +class infoflow3 +{ + null +} + +class infoflow4 +inherits infoflow + +class infoflow5 +inherits infoflow + +class infoflow6 +inherits infoflow + +class infoflow7 +inherits infoflow +{ + super_w + super_r + super_none + super_both + super_unmapped +} + +sensitivity s0 alias sname1; +sensitivity s1 alias { sname2 sname3 }; +sensitivity s2; +sensitivity s3; +sensitivity s4; +sensitivity s5; +sensitivity s6; +sensitivity s7; +sensitivity s8; +sensitivity s9; +sensitivity s10; +sensitivity s11; +sensitivity s12; +sensitivity s13; +sensitivity s14; +sensitivity s15; +sensitivity s16; +sensitivity s17; +sensitivity s18; +sensitivity s19; +sensitivity s20; +sensitivity s21; +sensitivity s22; +sensitivity s23; +dominance { s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 } + +category c0; +category c1; +category c2; +category c3; +category c4; +category c5; +category c6; +category c7; +category c8; +category c9; +category c10; +category c11; +category c12; +category c13; + +#level decl +level s0:c0.c13; +level s1:c0.c13; +level s2:c0.c13; +level s3:c0.c13; +level s4:c0.c13; +level s5:c0.c13; +level s6:c0.c13; +level s7:c0.c13; +level s8:c0.c13; +level s9:c0.c13; +level s10:c0.c13; +level s11:c0.c13; +level s12:c0.c13; +level s13:c0.c13; +level s14:c0.c13; +level s15:c0.c13; +level s16:c0.c13; +level s17:c0.c13; +level s18:c0.c13; +level s19:c0.c13; +level s20:c0.c13; +level s21:c0.c13; +level s22:c0.c13; +level s23:c0.c13; + +#some constraints +mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt)); + +attribute mls_exempt; + +type system; +role system; +role system types system; + +role role20_r; +role role21a_r; +role role21b_r; +role role21c_r; + +role role20_r types system; +role role21a_r types system; +role role21b_r types system; +role role21c_r types system; + +type type30; +type type31a; +type type31b; +type type31c; +role system types { type30 type31a type31b type31c }; + +allow system self:infoflow hi_w; + +#users +user system roles { system role20_r role21a_r role21b_r role21c_r } level s0 range s0 - s2:c0.c4; +user user10 roles system level s0 range s0 - s2:c0.c4; +user user11a roles system level s0 range s0 - s2:c0.c4; +user user11b roles system level s0 range s0 - s2:c0.c4; +user user11c roles system level s0 range s0 - s2:c0.c4; + +#normal constraints +constrain infoflow hi_w (u1 == u2); + +#isids +sid kernel system:system:system:s0 +sid security system:system:system:s0 + +#fs_use +fs_use_trans devpts system:object_r:system:s0; +fs_use_xattr ext3 system:object_r:system:s0; +fs_use_task pipefs system:object_r:system:s0; + +#genfscon +genfscon proc / system:object_r:system:s1 +genfscon proc /sys system:object_r:system:s0 +genfscon selinuxfs / system:object_r:system:s2:c0.c4 +portcon tcp 1 system:system:system:s0:c0.c1 +netifcon eth0 system:object_r:system:s0 system:object_r:system:s0 +nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0 +nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0 + diff --git a/tests/policyrep/objclass.conf b/tests/library/policyrep/objclass.conf similarity index 97% rename from tests/policyrep/objclass.conf rename to tests/library/policyrep/objclass.conf index e19200b6..daeee4af 100644 --- a/tests/policyrep/objclass.conf +++ b/tests/library/policyrep/objclass.conf @@ -74,6 +74,10 @@ inherits com_a class infoflow6 inherits com_b +{ + perm1 + perm2 +} class infoflow7 inherits infoflow @@ -120,6 +124,8 @@ type system; role system; role system types system; +allow system self:infoflow3 null; + #users user system roles system level med range low_s - high_s:here.lost; diff --git a/tests/policyrep/mls.conf b/tests/library/policyrep/polcap.conf similarity index 90% rename from tests/policyrep/mls.conf rename to tests/library/policyrep/polcap.conf index 1b2db897..3da440d7 100644 --- a/tests/policyrep/mls.conf +++ b/tests/library/policyrep/polcap.conf @@ -82,6 +82,8 @@ level s2:c0.c13; #some constraints mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt)); +policycap open_perms; + attribute mls_exempt; type system; @@ -108,10 +110,8 @@ allow system self:infoflow hi_w; #users user system roles { system role20_r role21a_r role21b_r role21c_r } level s0 range s0 - s2:c0.c4; -user user10 roles system level s0 range s0 - s2:c0.c4; -user user11a roles system level s0 range s0 - s2:c0.c4; -user user11b roles system level s0 range s0 - s2:c0.c4; -user user11c roles system level s0 range s0 - s2:c0.c4; +user user10 roles system level s1:c2 range s1 - s2:c0.c4; +user user20 roles { role20_r role21a_r } level s0 range s0 - s2:c0.c4; #normal constraints constrain infoflow hi_w (u1 == u2); diff --git a/tests/policyrep/role.conf b/tests/library/policyrep/role.conf similarity index 94% rename from tests/policyrep/role.conf rename to tests/library/policyrep/role.conf index 1b2db897..a3668a2e 100644 --- a/tests/policyrep/role.conf +++ b/tests/library/policyrep/role.conf @@ -92,6 +92,9 @@ role role20_r; role role21a_r; role role21b_r; role role21c_r; +role rolename21; +role rolename22; +role rolename23; role role20_r types system; role role21a_r types system; @@ -102,6 +105,8 @@ type type30; type type31a; type type31b; type type31c; +role rolename21 types { type31a type31b }; +role rolename23 types { type31b type31c }; role system types { type30 type31a type31b type31c }; allow system self:infoflow hi_w; diff --git a/tests/library/policyrep/rules.conf b/tests/library/policyrep/rules.conf new file mode 100644 index 00000000..12329b71 --- /dev/null +++ b/tests/library/policyrep/rules.conf @@ -0,0 +1,155 @@ +class infoflow +class infoflow2 +class infoflow3 +class infoflow4 +class infoflow5 +class infoflow6 +class infoflow7 + +sid kernel +sid security + +common infoflow +{ + low_w + med_w + hi_w + low_r + med_r + hi_r + ioctl +} + +class infoflow +inherits infoflow + +class infoflow2 +inherits infoflow +{ + super_w + super_r +} + +class infoflow3 +{ + null +} + +class infoflow4 +inherits infoflow + +class infoflow5 +inherits infoflow + +class infoflow6 +inherits infoflow + +class infoflow7 +inherits infoflow +{ + super_w + super_r + super_none + super_both + super_unmapped +} + +sensitivity s0; +sensitivity s1; +sensitivity s2; + +dominance { s0 s1 s2 } + +category c0; +category c1; +category c2; +category c3; +category c4; +category c5; +category c6; +category c7; +category c8; +category c9; +category c10; +category c11; +category c12; +category c13; + +#level decl +level s0:c0.c2; +level s1:c0.c13; +level s2:c0.c13; + +#some constraints +mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt)); + +attribute mls_exempt; + +bool a_bool false; + +type system; +role system; +role system types system; + +role role20_r; +role role21a_r; +role role21b_r; +role role21c_r; + +role role20_r types system; +role role21a_r types system; +role role21b_r types system; +role role21c_r types system; + +type type30; +type type31a; +type type31b; +type type31c; +role system types { type30 type31a type31b type31c }; + +allow role21a_r role21b_r; +role_transition role21b_r type30:infoflow role20_r; + +allow system type30:infoflow3 null; +auditallow type31c type31a:infoflow6 { hi_r hi_w }; +if (a_bool) { + dontaudit type31c type31b:infoflow7 { super_w super_r }; +} else { + type_change type31c type31b:infoflow2 system; +} +type_transition type31b system:infoflow4 type30 "the_filename"; + +allowxperm type30 type31a:infoflow ioctl 0x00ff; +auditallowxperm type31a type31b:infoflow ioctl { 0x001-0x0003 }; + +allow system self:infoflow hi_w; +range_transition type30 system:infoflow7 s0:c1 - s2:c0.c4; + +#users +user system roles { system role20_r role21a_r role21b_r role21c_r } level s0 range s0 - s2:c0.c4; +user user10 roles system level s0 range s0 - s2:c0.c4; +user user11a roles system level s0 range s0 - s2:c0.c4; +user user11b roles system level s0 range s0 - s2:c0.c4; +user user11c roles system level s0 range s0 - s2:c0.c4; + +#normal constraints +constrain infoflow hi_w (u1 == u2); + +#isids +sid kernel system:system:system:s0 +sid security system:system:system:s0 + +#fs_use +fs_use_trans devpts system:object_r:system:s0; +fs_use_xattr ext3 system:object_r:system:s0; +fs_use_task pipefs system:object_r:system:s0; + +#genfscon +genfscon proc / system:object_r:system:s1 +genfscon proc /sys system:object_r:system:s0 +genfscon selinuxfs / system:object_r:system:s2:c0.c4 +portcon tcp 1 system:system:system:s0:c0.c1 +netifcon eth0 system:object_r:system:s0 system:object_r:system:s0 +nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0 +nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0 + diff --git a/tests/policyrep/selinuxpolicy.conf b/tests/library/policyrep/selinuxpolicy.conf similarity index 100% rename from tests/policyrep/selinuxpolicy.conf rename to tests/library/policyrep/selinuxpolicy.conf diff --git a/tests/policyrep/terule_issue74.conf b/tests/library/policyrep/terule_issue74.conf similarity index 100% rename from tests/policyrep/terule_issue74.conf rename to tests/library/policyrep/terule_issue74.conf diff --git a/tests/library/policyrep/test_common.py b/tests/library/policyrep/test_common.py new file mode 100644 index 00000000..81a78629 --- /dev/null +++ b/tests/library/policyrep/test_common.py @@ -0,0 +1,34 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/common.conf") +class TestCommon: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common: string representation""" + com = list(compiled_policy.commons()).pop() + assert "infoflow" == str(com), str(com) + + def test_perms(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common: permissions""" + com = list(compiled_policy.commons()).pop() + assert set(["low_w", "low_r"]) == com.perms, com.perms + + def test_statment(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common: statement.""" + com = list(compiled_policy.commons()).pop() + assert com.statement() in ( + "common infoflow\n{\n\tlow_w\n\tlow_r\n}", + "common infoflow\n{\n\tlow_r\n\tlow_w\n}"), \ + com.statement() + + def test_contains(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common: contains""" + com = list(compiled_policy.commons()).pop() + assert "low_r" in com + assert "med_r" not in com diff --git a/tests/library/policyrep/test_default.py b/tests/library/policyrep/test_default.py new file mode 100644 index 00000000..f74113aa --- /dev/null +++ b/tests/library/policyrep/test_default.py @@ -0,0 +1,56 @@ +# Copyright 2016, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +from collections import defaultdict + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/default.conf") +class TestDefault: + + @pytest.fixture(autouse=True) + def _load_defaults(self, compiled_policy: setools.SELinuxPolicy) -> None: + self.defaults = defaultdict[str, list[setools.Default]](list) + for d in compiled_policy.defaults(): + self.defaults[d.tclass.name].append(d) + + def test_user(self) -> None: + """Default: default_user methods/attributes.""" + d = self.defaults["infoflow"].pop() + assert setools.DefaultRuletype.default_user == d.ruletype + assert "infoflow" == d.tclass + assert setools.DefaultValue.target == d.default + assert "default_user infoflow target;" == str(d) + assert str(d) == d.statement() + + def test_role(self) -> None: + """Default: default_role methods/attributes.""" + d = self.defaults["infoflow2"].pop() + assert setools.DefaultRuletype.default_role, d.ruletype + assert "infoflow2" == d.tclass + assert setools.DefaultValue.source, d.default + assert "default_role infoflow2 source;" == str(d) + assert str(d) == d.statement() + + def test_type(self) -> None: + """Default: default_type methods/attributes.""" + d = self.defaults["infoflow3"].pop() + assert setools.DefaultRuletype.default_type, d.ruletype + assert "infoflow3" == d.tclass + assert setools.DefaultValue.target, d.default + assert "default_type infoflow3 target;" == str(d) + assert str(d) == d.statement() + + def test_range(self) -> None: + """Default: default_range methods/attributes.""" + d = self.defaults["infoflow4"].pop() + assert isinstance(d, setools.DefaultRange) + assert setools.DefaultRuletype.default_range, d.ruletype + assert "infoflow4" == d.tclass + assert setools.DefaultValue.source, d.default + assert setools.DefaultRangeValue.high == d.default_range + assert "default_range infoflow4 source high;" == str(d) + assert str(d) == d.statement() diff --git a/tests/library/policyrep/test_initsid.py b/tests/library/policyrep/test_initsid.py new file mode 100644 index 00000000..d9edab7f --- /dev/null +++ b/tests/library/policyrep/test_initsid.py @@ -0,0 +1,28 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/initsid.conf") +class TestInitialSID: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """InitialSID: basic string rendering.""" + sids = list(compiled_policy.initialsids()) + assert len(sids) == 1 + assert "kernel" == str(sids[0]) + + def test_context(self, compiled_policy: setools.SELinuxPolicy) -> None: + """InitialSID: context.""" + sids = list(compiled_policy.initialsids()) + assert len(sids) == 1 + assert "system:system:system:s0" == sids[0].context, sids[0].context + + def test_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """InitialSID: statement.""" + sids = list(compiled_policy.initialsids()) + assert len(sids) == 1 + assert "sid kernel system:system:system:s0" == sids[0].statement(), sids[0].statement() diff --git a/tests/library/policyrep/test_mls.py b/tests/library/policyrep/test_mls.py new file mode 100644 index 00000000..5cedc8d9 --- /dev/null +++ b/tests/library/policyrep/test_mls.py @@ -0,0 +1,375 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/mls.conf") +class TestSensitivity: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity basic string rendering.""" + sens = compiled_policy.lookup_sensitivity("s0") + assert "s0" == str(sens), f"{sens}" + + def test_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity basic statement rendering.""" + sens = compiled_policy.lookup_sensitivity("s2") + assert "sensitivity s2;" == sens.statement(), sens.statement() + + def test_statement_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity one alias statement rendering.""" + sens = compiled_policy.lookup_sensitivity("s0") + assert "sensitivity s0 alias sname1;" == sens.statement() + + def test_statement_alias2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity two alias statement rendering.""" + sens = compiled_policy.lookup_sensitivity("s1") + assert sens.statement() in ("sensitivity s1 alias { sname2 sname3 };", + "sensitivity s1 alias { sname3 sname2 };"), sens.statement() + + def test_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity equal.""" + sens1 = compiled_policy.lookup_sensitivity("s0") + sens2 = compiled_policy.lookup_sensitivity("s0") + assert sens1 == sens2 + + def test_equal_str(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity equal to string.""" + sens = compiled_policy.lookup_sensitivity("s17") + assert "s17" == sens + + def test_not_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity not equal.""" + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s23") + assert sens1 != sens2 + + def test_not_equal_str(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity not equal to string.""" + sens = compiled_policy.lookup_sensitivity("s17") + assert "s0" != sens + + def test_lt(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity less-than.""" + # less + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s23") + assert sens1 < sens2 + + # equal + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s17") + assert not (sens1 < sens2) + + # greater + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s0") + assert not (sens1 < sens2) + + def test_le(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity less-than-or-equal.""" + # less + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s23") + assert sens1 <= sens2 + + # equal + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s17") + assert sens1 <= sens2 + + # greater + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s0") + assert not (sens1 <= sens2) + + def test_ge(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity greater-than-or-equal.""" + # less + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s23") + assert not (sens1 >= sens2) + + # equal + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s17") + assert sens1 >= sens2 + + # greater + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s0") + assert sens1 >= sens2 + + def test_gt(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity greater-than.""" + # less + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s23") + assert not (sens1 > sens2) + + # equal + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s17") + assert not (sens1 > sens2) + + # greater + sens1 = compiled_policy.lookup_sensitivity("s17") + sens2 = compiled_policy.lookup_sensitivity("s0") + assert sens1 > sens2 + + +@pytest.mark.obj_args("tests/library/policyrep/mls.conf") +class TestCategory: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Category basic string rendering.""" + cat = compiled_policy.lookup_category("c0") + assert "c0" == str(cat), f"{cat}" + + def test_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Category basic statement rendering.""" + cat = compiled_policy.lookup_category("c2") + assert "category c2;" == cat.statement(), cat.statement() + + +@pytest.mark.obj_args("tests/library/policyrep/mls.conf") +class TestLevel: + + def test_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level equal.""" + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s0:c0.c3") + assert level1 == level2 + + def test_equal_str(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level equal to string.""" + level = compiled_policy.lookup_level("s2:c0.c3") + assert "s2:c0.c3" == level, f"{level}" + + def test_not_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level not equal.""" + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s0") + assert level1 != level2, f"{level1} ||| {level2}" + + def test_not_equal_str(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level not equal to string.""" + level = compiled_policy.lookup_level("s0:c0.c3") + assert "s0:c0.c2" != level, f"{level}" + + def test_dom(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level dominate (ge).""" + # equal + level1 = compiled_policy.lookup_level("s1:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 >= level2 + + # sens dominate + level1 = compiled_policy.lookup_level("s2:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 >= level2 + + # cat set dominate + level1 = compiled_policy.lookup_level("s1:c0.c4") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 >= level2 + + # sens domby + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 >= level2) + + # cat set domby + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 >= level2) + + # incomp + level1 = compiled_policy.lookup_level("s1:c0.c3") + level2 = compiled_policy.lookup_level("s1:c4.c7") + assert not (level1 >= level2) + + def test_domby(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level dominate-by (le).""" + # equal + level1 = compiled_policy.lookup_level("s1:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 <= level2 + + # sens dominate + level1 = compiled_policy.lookup_level("s2:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 <= level2) + + # cat set dominate + level1 = compiled_policy.lookup_level("s1:c0.c4") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 <= level2) + + # sens domby + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 <= level2 + + # cat set domby + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 <= level2 + + # incomp + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c7.c9") + assert not (level1 <= level2) + + def test_proper_dom(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level proper dominate (gt).""" + # equal + level1 = compiled_policy.lookup_level("s1:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 > level2) + + # sens dominate + level1 = compiled_policy.lookup_level("s2:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 > level2 + + # cat set dominate + level1 = compiled_policy.lookup_level("s1:c0.c4") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 > level2 + + # sens domby + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 > level2) + + # cat set domby + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 > level2) + + # incomp + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c7.c9") + assert not (level1 > level2) + + def test_proper_domby(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level proper dominate-by (lt).""" + # equal + level1 = compiled_policy.lookup_level("s1:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 < level2) + + # sens dominate + level1 = compiled_policy.lookup_level("s2:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 < level2) + + # cat set dominate + level1 = compiled_policy.lookup_level("s1:c0.c4") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 < level2) + + # sens domby + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 < level2 + + # cat set domby + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert level1 < level2 + + # incomp + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c7.c9") + assert not (level1 < level2) + + def test_incomp(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level incomparable (xor).""" + # equal + level1 = compiled_policy.lookup_level("s1:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 ^ level2) + + # sens dominate + level1 = compiled_policy.lookup_level("s2:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 ^ level2) + + # cat set dominate + level1 = compiled_policy.lookup_level("s1:c0.c4") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 ^ level2) + + # sens domby + level1 = compiled_policy.lookup_level("s0:c0.c3") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 ^ level2) + + # cat set domby + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c0.c3") + assert not (level1 ^ level2) + + # incomp + level1 = compiled_policy.lookup_level("s1:c0.c2") + level2 = compiled_policy.lookup_level("s1:c7.c9") + assert level1 ^ level2 + + def test_level_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Level has no statement.""" + level = compiled_policy.lookup_level("s1") + with pytest.raises(setools.exception.NoStatement): + level.statement() + + +@pytest.mark.obj_args("tests/library/policyrep/mls.conf") +class TestRange: + + def test_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Range equality.""" + rangeobj1 = compiled_policy.lookup_range("s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") + rangeobj2 = compiled_policy.lookup_range("s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") + assert rangeobj1 == rangeobj2 + + def test_equal_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Range equal to string.""" + rangeobj = compiled_policy.lookup_range("s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") + assert "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13" == rangeobj + assert "s0:c0.c2- s2:c0.c5,c7,c9.c11,c13" == rangeobj + assert "s0:c0.c2 -s2:c0.c5,c7,c9.c11,c13" == rangeobj + assert "s0:c0.c2 - s2:c0.c5,c7,c9.c11,c13" == rangeobj + + def test_contains(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Range contains a level.""" + rangeobj = compiled_policy.lookup_range("s0:c1-s2:c0.c10") + + # too low + level1 = compiled_policy.lookup_level("s0") + assert not (level1 in rangeobj) + + # low level + level2 = compiled_policy.lookup_level("s0:c1") + assert level2 in rangeobj + + # mid + level3 = compiled_policy.lookup_level("s1:c1,c5") + assert level3 in rangeobj + + # high level + level4 = compiled_policy.lookup_level("s2:c0.c10") + assert level4 in rangeobj + + # too high + level5 = compiled_policy.lookup_level("s2:c0.c11") + assert not (level5 in rangeobj) + + def test_range_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Range has no statement.""" + rangeobj = compiled_policy.lookup_range("s0") + with pytest.raises(setools.exception.NoStatement): + rangeobj.statement() diff --git a/tests/library/policyrep/test_objclass.py b/tests/library/policyrep/test_objclass.py new file mode 100644 index 00000000..92df9114 --- /dev/null +++ b/tests/library/policyrep/test_objclass.py @@ -0,0 +1,54 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/objclass.conf") +class TestObjClass: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: string representation""" + cls = compiled_policy.lookup_class("infoflow") + assert "infoflow" == str(cls), str(cls) + + def test_perms(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: permissions""" + cls = compiled_policy.lookup_class("infoflow8") + assert frozenset(["super_w", "super_r"]) == cls.perms, f"{cls.perms}" + + def test_statment_wo_common_w_unique(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: statement, no common.""" + cls = compiled_policy.lookup_class("infoflow8") + assert cls.statement() in ( + "class infoflow8\n{\n\tsuper_w\n\tsuper_r\n}", + "class infoflow8\n{\n\tsuper_r\n\tsuper_w\n}"), \ + cls.statement() + + def test_statment_w_common_w_unique(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: statement, with common.""" + cls = compiled_policy.lookup_class("infoflow6") + assert cls.statement() in ( + "class infoflow6\ninherits com_b\n{\n\tperm1\n\tperm2\n}", + "class infoflow6\ninherits com_b\n{\n\tperm2\n\tperm1\n}"), \ + cls.statement() + + def test_statment_w_common_wo_unique(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: statement, with common, no class perms.""" + cls = compiled_policy.lookup_class("infoflow5") + assert cls.statement() == "class infoflow5\ninherits com_a\n", cls.statement() + + def test_contains_wo_common(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: contains""" + cls = compiled_policy.lookup_class("infoflow10") + assert "read" in cls + assert "execute" not in cls + + def test_contains_w_common(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ObjClass: contains, with common""" + cls = compiled_policy.lookup_class("infoflow4") + assert "super_both" in cls + assert "hi_w" in cls + assert "unmapped" not in cls diff --git a/tests/library/policyrep/test_polcap.py b/tests/library/policyrep/test_polcap.py new file mode 100644 index 00000000..b71021ab --- /dev/null +++ b/tests/library/policyrep/test_polcap.py @@ -0,0 +1,21 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest + + +@pytest.mark.obj_args("tests/library/policyrep/polcap.conf") +class TestPolicyCapability: + + def test_string(self, compiled_policy): + """PolCap: basic string rendering.""" + caps = list(compiled_policy.polcaps()) + assert len(caps) == 1 + assert "open_perms" == str(caps[0]) + + def test_statement(self, compiled_policy): + """PolCap: statement.""" + caps = list(compiled_policy.polcaps()) + assert len(caps) == 1 + assert "policycap open_perms;" == caps[0].statement() diff --git a/tests/library/policyrep/test_role.py b/tests/library/policyrep/test_role.py new file mode 100644 index 00000000..eb12a193 --- /dev/null +++ b/tests/library/policyrep/test_role.py @@ -0,0 +1,45 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/role.conf") +class TestRole: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role basic string rendering.""" + role = compiled_policy.lookup_role("role20_r") + assert "role20_r" == str(role), f"{role}" + + def test_statement_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role statement, one type.""" + role = compiled_policy.lookup_role("role20_r") + assert "role role20_r types system;" == role.statement(), role.statement() + + def test_statement_two_types(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role statement, two types.""" + role = compiled_policy.lookup_role("rolename21") + assert "role rolename21 types { type31a type31b };" == role.statement(), role.statement() + + def test_statement_decl(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role statement, no types.""" + # This is an unlikely corner case, where a role + # has been declared but has no types. + role = compiled_policy.lookup_role("rolename22") + assert "role rolename22;" == role.statement(), role.statement() + + def test_types(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role types generator.""" + role = compiled_policy.lookup_role("rolename23") + types = sorted(role.types()) + assert ["type31b", "type31c"] == types, types + + def test_expand(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role expansion""" + role = compiled_policy.lookup_role("system") + expanded = list(role.expand()) + assert 1 == len(expanded), expanded + assert role == expanded[0], expanded diff --git a/tests/library/policyrep/test_rules.py b/tests/library/policyrep/test_rules.py new file mode 100644 index 00000000..6ff6a040 --- /dev/null +++ b/tests/library/policyrep/test_rules.py @@ -0,0 +1,217 @@ +# +# SPDX-License-Identifier: GPL-2.0-only +# +from contextlib import suppress +import dataclasses +import enum + +import pytest +import setools + + +@dataclasses.dataclass +class RuleTestCase: + + """ + Rule test case + + If the field is None, it is not supported by the rule type. + """ + + ruletype: enum.Enum + source: str + target: str + statement: str + type_: type # the rule's policyrep class + tclass: str | None = None + xperm: str | None = None + perms: set[str] | setools.IoctlSet | None = None + default: str | None = None + filename: str | None = None + conditional: str | None = None + + +rule_test_data = [ + RuleTestCase(setools.RBACRuletype.allow, "role21a_r", "role21b_r", + type_=setools.RoleAllow, statement="allow role21a_r role21b_r;"), + RuleTestCase(setools.RBACRuletype.role_transition, "role21b_r", "type30", + type_=setools.RoleTransition, default="role20_r", tclass="infoflow", + statement="role_transition role21b_r type30:infoflow role20_r;"), + RuleTestCase(setools.MLSRuletype.range_transition, "type30", "system", tclass="infoflow7", + default="s0:c1 - s2:c0.c4", type_=setools.MLSRule, + statement="range_transition type30 system:infoflow7 s0:c1 - s2:c0.c4;"), + RuleTestCase(setools.TERuletype.allow, "system", "type30", tclass="infoflow3", + perms=set(("null",)), type_=setools.AVRule, + statement="allow system type30:infoflow3 null;"), + RuleTestCase(setools.TERuletype.auditallow, "type31c", "type31a", tclass="infoflow6", + perms=set(("hi_r", "hi_w")), type_=setools.AVRule, + statement="auditallow type31c type31a:infoflow6 { hi_r hi_w };"), + RuleTestCase(setools.TERuletype.dontaudit, "type31c", "type31b", tclass="infoflow7", + perms=set(("super_w", "super_r")), type_=setools.AVRule, conditional="a_bool", + statement="dontaudit type31c type31b:infoflow7 " + "{ super_r super_w }; [ a_bool ]:True"), + RuleTestCase(setools.TERuletype.type_transition, "type31b", "system", tclass="infoflow4", + default="type30", type_=setools.FileNameTERule, filename="the_filename", + statement="type_transition type31b system:infoflow4 type30 the_filename;"), + RuleTestCase(setools.TERuletype.type_change, "type31c", "type31b", tclass="infoflow2", + default="system", type_=setools.TERule, conditional="a_bool", + statement="type_change type31c type31b:infoflow2 system; [ a_bool ]:False"), + RuleTestCase(setools.TERuletype.allowxperm, "type30", "type31a", tclass="infoflow", + xperm="ioctl", perms=setools.IoctlSet((0x00ff,)), type_=setools.AVRuleXperm, + statement="allowxperm type30 type31a:infoflow ioctl 0x00ff;"), + RuleTestCase(setools.TERuletype.auditallowxperm, "type31a", "type31b", tclass="infoflow", + xperm="ioctl", perms=setools.IoctlSet((1, 2, 3)), type_=setools.AVRuleXperm, + statement="auditallowxperm type31a type31b:infoflow ioctl 0x0001-0x0003;")] + + +@pytest.mark.obj_args("tests/library/policyrep/rules.conf") +@pytest.mark.parametrize("testcase", rule_test_data) +class TestRules: + + @pytest.fixture(autouse=True) + def _get_rules(self, compiled_policy: setools.SELinuxPolicy) -> None: + self.rules = dict[enum.Enum, setools.policyrep.PolicyRule]() + self.rules |= {r.ruletype: r for r in compiled_policy.terules()} + self.rules |= {r.ruletype: r for r in compiled_policy.rbacrules()} + self.rules |= {r.ruletype: r for r in compiled_policy.mlsrules()} + + def test_ruletype(self, testcase: RuleTestCase) -> None: + """Rule type""" + rule = self.rules[testcase.ruletype] + assert testcase.ruletype == rule.ruletype, f"{testcase.ruletype} != {rule.ruletype}" + assert isinstance(rule, testcase.type_), f"{type(rule)}, {rule=}" + + def test_source_type(self, testcase: RuleTestCase) -> None: + """Source object""" + rule = self.rules[testcase.ruletype] + assert testcase.source == rule.source, f"{testcase.source} != {rule.source}" + + def test_target_type(self, testcase: RuleTestCase) -> None: + """Target object""" + rule = self.rules[testcase.ruletype] + assert testcase.target == rule.target, f"{testcase.target} != {rule.target}" + + def test_object_class(self, testcase: RuleTestCase) -> None: + """Object class""" + rule = self.rules[testcase.ruletype] + if testcase.tclass is None: + with pytest.raises(setools.exception.RuleUseError): + rule.tclass + else: + assert testcase.tclass == rule.tclass, f"{testcase.tclass} != {rule.tclass}" + + def test_xperm_type(self, testcase: RuleTestCase) -> None: + """Extended permission type""" + rule = self.rules[testcase.ruletype] + if testcase.xperm is None: + assert rule.extended is False + with pytest.raises(setools.exception.RuleUseError): + rule.xperm_type + else: + assert rule.extended is True + assert testcase.xperm == rule.xperm_type, f"{testcase.xperm} != {rule.xperm_type}" + + def test_permissions_or_default(self, testcase: RuleTestCase) -> None: + """Test default/permissions""" + assert not (testcase.default is not None and testcase.perms is not None), \ + f"Test case setup error {testcase=}" + + rule = self.rules[testcase.ruletype] + if testcase.perms is not None: + assert testcase.perms == rule.perms, f"{testcase.perms} != {rule.perms}" + with pytest.raises(setools.exception.RuleUseError): + rule.default + elif testcase.default is not None: + assert testcase.default == rule.default, f"{testcase.default} != {rule.default}" + with pytest.raises(setools.exception.RuleUseError): + rule.perms + else: + with pytest.raises(setools.exception.RuleUseError): + rule.perms + + with pytest.raises(setools.exception.RuleUseError): + rule.default + + def test_conditional(self, testcase: RuleTestCase) -> None: + """Conditional expression""" + rule = self.rules[testcase.ruletype] + if testcase.conditional is None: + with pytest.raises(setools.exception.RuleNotConditional): + rule.conditional + + with pytest.raises(setools.exception.RuleNotConditional): + rule.conditional_block + else: + assert testcase.conditional == rule.conditional, f"{rule.conditional}" + assert isinstance(rule.conditional_block, bool), f"{rule.conditional_block}" + + def test_filename(self, testcase: RuleTestCase) -> None: + """Filename""" + rule = self.rules[testcase.ruletype] + if testcase.filename is None: + if rule.ruletype == setools.TERuletype.type_transition: + with pytest.raises(setools.exception.TERuleNoFilename): + rule.filename + else: + with pytest.raises(setools.exception.RuleUseError): + rule.filename + else: + assert testcase.filename == rule.filename, f"{testcase.filename} != {rule.filename}" + + def test_statement(self, testcase: RuleTestCase) -> None: + """Statement""" + rule = self.rules[testcase.ruletype] + assert testcase.statement == rule.statement(), \ + f"\"{testcase.statement}\" != \"{rule.statement()}\"" + + def test_expand(self, testcase: RuleTestCase) -> None: + """Expand""" + rule = self.rules[testcase.ruletype] + for expanded_rule in rule.expand(): + assert isinstance(expanded_rule, type(rule)) + if expanded_rule is rule: + # the rule can't be expanded + pass + else: + assert expanded_rule.origin == rule + assert expanded_rule.source in rule.source + assert expanded_rule.target in rule.target + + with suppress(setools.exception.RuleUseError): + assert expanded_rule.tclass == rule.tclass + + with suppress(setools.exception.RuleUseError): + assert expanded_rule.xperm_type == rule.xperm_type + + with suppress(setools.exception.RuleUseError): + assert expanded_rule.perms == rule.perms + + with suppress(setools.exception.RuleUseError): + assert expanded_rule.default == rule.default + + with suppress(setools.exception.RuleNotConditional): + assert expanded_rule.conditional == rule.conditional + assert expanded_rule.conditional_block == rule.conditional_block + + with suppress(setools.exception.RuleUseError): + assert expanded_rule.filename == rule.filename + + +@pytest.mark.obj_args("tests/library/policyrep/terule_issue74.conf") +class TestAVRuleXpermIssue74: + + """ + Regression test for xperm ranges starting with 0x00 not being loaded. + https://github.com/SELinuxProject/setools/issues/74 + """ + + def test_regression(self, compiled_policy: setools.SELinuxPolicy): + """Regression test for GitHub issue 74.""" + rules = sorted(compiled_policy.terules()) + assert 2 == len(rules) + + # expect 2 rules: + # allowxperm init_type_t init_type_t : unix_dgram_socket ioctl { 0x8910 }; + # allowxperm init_type_t init_type_t : unix_dgram_socket ioctl { 0x0-0xff }; + assert setools.IoctlSet(range(0x100)) == rules[0].perms, f"{rules[0].perms}" + assert setools.IoctlSet([0x8910]) == rules[1].perms, f"{rules[1].perms}" diff --git a/tests/library/policyrep/test_selinuxpolicy.py b/tests/library/policyrep/test_selinuxpolicy.py new file mode 100644 index 00000000..9d8ebfde --- /dev/null +++ b/tests/library/policyrep/test_selinuxpolicy.py @@ -0,0 +1,282 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# + +import copy +import dataclasses + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/selinuxpolicy.conf") +class TestSELinuxPolicy: + + def test_open_policy_non_existant(self) -> None: + """SELinuxPolicy: Non existant policy on open.""" + with pytest.raises(OSError): + setools.SELinuxPolicy("tests/policyrep/DOES_NOT_EXIST") + + def test_deepcopy(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: Deep copy""" + p = copy.deepcopy(compiled_policy) + assert p is compiled_policy + + def test_handle_unknown(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: handle unknown setting.""" + assert compiled_policy.handle_unknown == setools.HandleUnknown.reject + + def test_mls(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: MLS status.""" + assert compiled_policy.mls + + def test_version(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: version.""" + assert compiled_policy.version + + def test_allow_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: allow count""" + assert compiled_policy.allow_count == 113 + + def test_auditallow_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: auditallow count""" + assert compiled_policy.auditallow_count == 109 + + def test_boolean_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: Boolean count.""" + assert compiled_policy.boolean_count == 127 + + # def test_bounds_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + + def test_category_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: category count""" + assert compiled_policy.category_count == 17 + + def test_class_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: object class count""" + assert compiled_policy.class_count == 7 + + def test_common_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: common permisison set count""" + assert compiled_policy.common_count == 3 + + def test_conditional_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: conditional (expression) count""" + assert compiled_policy.conditional_count == 67 + + def test_constraint_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: standard constraint count""" + assert compiled_policy.constraint_count == 19 + + # def test_default_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + + def test_dontaudit_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: dontaudit rule count""" + assert compiled_policy.dontaudit_count == 107 + + def test_fs_use_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: fs_use_* count""" + assert compiled_policy.fs_use_count == 149 + + def test_genfscon_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: genfscon count""" + assert compiled_policy.genfscon_count == 151 + + def test_initial_sid_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: initial sid count""" + assert compiled_policy.initialsids_count == 11 + + def test_level_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: MLS level count""" + assert compiled_policy.level_count == 13 + + def test_mls_constraint_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: MLS constraint count""" + assert compiled_policy.mlsconstraint_count == 23 + + def test_mls_validatetrans_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: MLS validatetrans count""" + assert compiled_policy.mlsvalidatetrans_count == 3 + + def test_netifcon_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: netifcon count""" + assert compiled_policy.netifcon_count == 167 + + def test_neverallow_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: neverallow rule count""" + # changed after dropping source policy support + # assert compiled_policy.neverallow_count == 103) + assert compiled_policy.neverallow_count == 0 + + def test_nodecon_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: nodecon count""" + assert compiled_policy.nodecon_count == 173 + + def test_permission_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: permission count""" + assert compiled_policy.permission_count == 29 + + def test_permissive_types_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: permissive types count""" + assert compiled_policy.permissives_count == 73 + + def test_polcap_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: policy capability count""" + assert compiled_policy.polcap_count == 2 + + def test_portcon_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: portcon count""" + assert compiled_policy.portcon_count == 163 + + def test_range_transition_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: range_transition count""" + assert compiled_policy.range_transition_count == 71 + + def test_role_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: role count""" + assert compiled_policy.role_count == 131 + + # def test_role_attribute_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + + def test_role_allow_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: (role) allow count""" + assert compiled_policy.role_allow_count == 83 + + def test_role_transition_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: role_transition count""" + assert compiled_policy.role_transition_count == 79 + + def test_type_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: type count""" + assert compiled_policy.type_count == 137 + + def test_type_attribute_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: type attribute count""" + assert compiled_policy.type_attribute_count == 157 + + def test_type_change_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: type_change rule count""" + assert compiled_policy.type_change_count == 89 + + def test_type_member_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: type_member rule count""" + assert compiled_policy.type_member_count == 61 + + def test_type_transition_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: type_transition rule count""" + assert compiled_policy.type_transition_count == 97 + + def test_user_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: user count""" + assert compiled_policy.user_count == 101 + + def test_validatetrans_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: validatetrans count""" + assert compiled_policy.validatetrans_count == 5 + + def test_allowxperm_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: allowxperm rount""" + assert compiled_policy.allowxperm_count == 179 + + def test_auditallowxperm_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: auditallowxperm rount""" + assert compiled_policy.auditallowxperm_count == 181 + + def test_neverallowxperm_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: neverallowxperm rount""" + # changed after dropping source policy support + # assert compiled_policy.neverallowxperm_count == 191) + assert compiled_policy.neverallowxperm_count == 0 + + def test_dontauditxperm_count(self, compiled_policy: setools.SELinuxPolicy) -> None: + """SELinuxPolicy: dontauditxperm rount""" + assert compiled_policy.dontauditxperm_count == 193 + + +@dataclasses.dataclass +class LookupTestCase: + + method_name: str + obj_name: str + exc_type: type[Exception] + alias_name: str | None = None + + +lookup_test_data = [ + LookupTestCase("lookup_boolean", "bool13", setools.exception.InvalidBoolean), + LookupTestCase("lookup_category", "c15", setools.exception.InvalidCategory), + LookupTestCase("lookup_category", "c2", setools.exception.InvalidCategory, "cat_alias2"), + LookupTestCase("lookup_class", "infoflow6", setools.exception.InvalidClass), + LookupTestCase("lookup_common", "hi_c", setools.exception.InvalidCommon), + LookupTestCase("lookup_level", "s4:c5", setools.exception.InvalidLevel), + LookupTestCase("lookup_range", "s0 - s3", setools.exception.InvalidRange), + LookupTestCase("lookup_role", "role50", setools.exception.InvalidRole), + LookupTestCase("lookup_sensitivity", "s3", setools.exception.InvalidSensitivity), + LookupTestCase("lookup_sensitivity", "s0", setools.exception.InvalidSensitivity, + "sens_alias0"), + LookupTestCase("lookup_type", "type32", setools.exception.InvalidType), + LookupTestCase("lookup_type", "type1", setools.exception.InvalidType, "type_alias1"), + LookupTestCase("lookup_type_or_attr", "type97", setools.exception.InvalidType), + LookupTestCase("lookup_type_or_attr", "type2", setools.exception.InvalidType, "type_alias2"), + LookupTestCase("lookup_type_or_attr", "attr13", setools.exception.InvalidType), + LookupTestCase("lookup_typeattr", "attr17", setools.exception.InvalidType), + LookupTestCase("lookup_user", "user57", setools.exception.InvalidUser) +] + + +@pytest.mark.obj_args("tests/library/policyrep/selinuxpolicy.conf") +@pytest.mark.parametrize("testcase", lookup_test_data) +class TestSELinuxPolicyLookup: + + """Generated test cases for the SELinuxPolicy lookup methods.""" + + def test_lookup(self, testcase: LookupTestCase, + compiled_policy: setools.SELinuxPolicy) -> None: + """Test successful policy lookup.""" + method = getattr(compiled_policy, testcase.method_name) + if testcase.alias_name: + # look up by alias + obj = method(testcase.alias_name) + else: + obj = method(testcase.obj_name) + + assert testcase.obj_name == obj, f"{obj}" + + def test_lookup_invalid(self, testcase: LookupTestCase, + compiled_policy: setools.SELinuxPolicy) -> None: + """Test failed lookup.""" + method = getattr(compiled_policy, testcase.method_name) + with pytest.raises(testcase.exc_type): + obj = method("INVALID") + + def test_lookup_alias(self, testcase: LookupTestCase, + compiled_policy: setools.SELinuxPolicy) -> None: + """Test successful policy lookup by alias.""" + if not testcase.alias_name: + pytest.skip("Alias not configured for testcase.") + + method = getattr(compiled_policy, testcase.method_name) + # look up by alias + obj = method(testcase.alias_name, deref=True) + assert testcase.obj_name == obj, f"{obj}" + + def test_lookup_invalid_alias(self, testcase: LookupTestCase, + compiled_policy: setools.SELinuxPolicy) -> None: + """Test failed lookup due to invalid alias.""" + if not testcase.alias_name: + pytest.skip("Alias not configured for testcase.") + + method = getattr(compiled_policy, testcase.method_name) + with pytest.raises(testcase.exc_type): + obj = method("INVALID", deref=True) + + def test_lookup_no_deref_alias(self, testcase: LookupTestCase, + compiled_policy: setools.SELinuxPolicy) -> None: + """Test failed lookup due to disabled dereference.""" + if not testcase.alias_name: + pytest.skip("Alias not configured for testcase.") + + method = getattr(compiled_policy, testcase.method_name) + with pytest.raises(testcase.exc_type): + obj = method(testcase.alias_name, deref=False) diff --git a/tests/library/policyrep/test_type.py b/tests/library/policyrep/test_type.py new file mode 100644 index 00000000..660d8032 --- /dev/null +++ b/tests/library/policyrep/test_type.py @@ -0,0 +1,86 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/type.conf") +class TestType: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type basic string rendering.""" + type_ = compiled_policy.lookup_type("name10") + assert "name10" == str(type_), f"{type_}" + + def test_attrs(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type with type attributes""" + type_ = compiled_policy.lookup_type("name20") + assert ["attr1", "attr2", "attr3"] == sorted(type_.attributes()), type_.attributes() + + def test_aliases(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type aliases""" + type_ = compiled_policy.lookup_type("name30") + assert ["alias1", "alias2", "alias3"] == sorted(type_.aliases()), type_.aliases() + + def test_expand(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type expansion""" + type_ = compiled_policy.lookup_type("name40") + expanded = list(type_.expand()) + assert 1 == len(expanded), len(expanded) + assert expanded[0] is type_ + + def test_permissive(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type is permissive""" + type_ = compiled_policy.lookup_type("name50a") + permtype = compiled_policy.lookup_type("name50b") + assert not type_.ispermissive + assert permtype.ispermissive + + def test_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type basic statement""" + type_ = compiled_policy.lookup_type("name60") + assert "type name60;" == type_.statement(), type_.statement() + + def test_statement_one_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, one attribute""" + type_ = compiled_policy.lookup_type("name61") + assert "type name61, attr1;" == type_.statement(), type_.statement() + + def test_statement_two_attr(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, two attributes""" + type_ = compiled_policy.lookup_type("name62") + assert "type name62, attr1, attr2;" == type_.statement(), type_.statement() + + def test_statement_one_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, one alias""" + type_ = compiled_policy.lookup_type("name63") + assert "type name63 alias alias4;" == type_.statement(), type_.statement() + + def test_statement_two_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, two aliases""" + type_ = compiled_policy.lookup_type("name64") + assert "type name64 alias { alias5 alias6 };" == type_.statement(), type_.statement() + + def test_statement_one_attr_one_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, one attribute, one alias""" + type_ = compiled_policy.lookup_type("name65") + assert "type name65 alias alias7, attr1;" == type_.statement(), type_.statement() + + def test_statement_two_attr_one_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, two attributes, one alias""" + type_ = compiled_policy.lookup_type("name66") + assert "type name66 alias alias8, attr2, attr3;" == type_.statement(), type_.statement() + + def test_statement_one_attr_two_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, one attribute, two aliases""" + type_ = compiled_policy.lookup_type("name67") + assert "type name67 alias { alias10 alias11 }, attr3;" == type_.statement(), \ + type_.statement() + + def test_statement_two_attr_two_alias(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type statement, two attributes, two aliases""" + type_ = compiled_policy.lookup_type("name68") + assert "type name68 alias { alias12 alias13 }, attr1, attr3;" == type_.statement(), \ + type_.statement() diff --git a/tests/library/policyrep/test_typeattr.py b/tests/library/policyrep/test_typeattr.py new file mode 100644 index 00000000..eb844a26 --- /dev/null +++ b/tests/library/policyrep/test_typeattr.py @@ -0,0 +1,48 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/typeattr.conf") +class TestTypeAttribute: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TypeAttribute basic string rendering.""" + attr = compiled_policy.lookup_typeattr("name10") + assert "name10" == str(attr), f"{attr}" + + def test_attrs(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TypeAttribute attributes""" + attr = compiled_policy.lookup_typeattr("name20") + with pytest.raises(setools.exception.SymbolUseError): + attr.attributes() + + def test_aliases(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TypeAttribute aliases""" + attr = compiled_policy.lookup_typeattr("name30") + with pytest.raises(setools.exception.SymbolUseError): + attr.aliases() + + def test_expand(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TypeAttribute expansion""" + attr = compiled_policy.lookup_typeattr("name40") + assert ['type31a', 'type31b', 'type31c'] == sorted(attr.expand()), sorted(attr.expand()) + + def test_permissive(self, compiled_policy: setools.SELinuxPolicy) -> None: + attr = compiled_policy.lookup_typeattr("name50") + with pytest.raises(setools.exception.SymbolUseError): + attr.ispermissive + + def test_statement(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TypeAttribute basic statement""" + attr = compiled_policy.lookup_typeattr("name60") + assert "attribute name60;" == attr.statement(), attr.statement() + + def test_contains(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TypeAttribute: contains""" + attr = compiled_policy.lookup_typeattr("name70") + assert "type31b" in attr + assert "type30" not in attr diff --git a/tests/library/policyrep/test_user.py b/tests/library/policyrep/test_user.py new file mode 100644 index 00000000..c6c4fb92 --- /dev/null +++ b/tests/library/policyrep/test_user.py @@ -0,0 +1,75 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/policyrep/user_mls.conf") +class TestUserMLS: + + def test_string(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User basic string rendering.""" + user = compiled_policy.lookup_user("system") + assert "system" == str(user), f"{user}" + + def test_statement_one_role_mls(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User statement, one role, MLS.""" + user = compiled_policy.lookup_user("user10") + assert "user user10 roles system level s1:c2 range s1 - s2:c0.c4;" == \ + user.statement(), user.statement() + + def test_023_statement_two_roles_mls(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User statement, two roles, MLS.""" + user = compiled_policy.lookup_user("user20") + # roles are stored in a set, so the role order may vary + assert user.statement() in ( + "user user20 roles { role20_r role21a_r } level s0 range s0 - s2:c0.c4;", + "user user20 roles { role21a_r role20_r } level s0 range s0 - s2:c0.c4;"), \ + user.statement() + + def test_roles(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User roles.""" + user = compiled_policy.lookup_user("user20") + assert set(['role20_r', 'role21a_r']) == user.roles, user.roles + + def test_level(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User level.""" + user = compiled_policy.lookup_user("user10") + assert "s1:c2" == user.mls_level, user.mls_level + + def test_range(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User level.""" + user = compiled_policy.lookup_user("user20") + assert "s0 - s2:c0.c4" == user.mls_range, user.mls_range + + +@pytest.mark.obj_args("tests/library/policyrep/user_standard.conf", mls=False) +class TestUserStandard: + + def test_statement_role(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User statement, one role.""" + user = compiled_policy.lookup_user("user10") + assert "user user10 roles system;" == user.statement(), user.statement() + + def test_statement_two_roles(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User statement, two roles.""" + user = compiled_policy.lookup_user("user20") + # roles are stored in a set, so the role order may vary + assert user.statement() in ( + "user user20 roles { role20_r role21a_r };", + "user user20 roles { role21a_r role20_r };"), \ + user.statement() + + def test_level(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User level, MLS disabled.""" + user = compiled_policy.lookup_user("user10") + with pytest.raises(setools.exception.MLSDisabled): + user.mls_level + + def test_range(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User level, MLS disabled.""" + user = compiled_policy.lookup_user("user20") + with pytest.raises(setools.exception.MLSDisabled): + user.mls_range diff --git a/tests/library/policyrep/type.conf b/tests/library/policyrep/type.conf new file mode 100644 index 00000000..85daea2e --- /dev/null +++ b/tests/library/policyrep/type.conf @@ -0,0 +1,158 @@ +class infoflow +class infoflow2 +class infoflow3 +class infoflow4 +class infoflow5 +class infoflow6 +class infoflow7 + +sid kernel +sid security + +common infoflow +{ + low_w + med_w + hi_w + low_r + med_r + hi_r +} + +class infoflow +inherits infoflow + +class infoflow2 +inherits infoflow +{ + super_w + super_r +} + +class infoflow3 +{ + null +} + +class infoflow4 +inherits infoflow + +class infoflow5 +inherits infoflow + +class infoflow6 +inherits infoflow + +class infoflow7 +inherits infoflow +{ + super_w + super_r + super_none + super_both + super_unmapped +} + +sensitivity s0; +sensitivity s1; +sensitivity s2; + +dominance { s0 s1 s2 } + +category c0; +category c1; +category c2; +category c3; +category c4; +category c5; +category c6; +category c7; +category c8; +category c9; +category c10; +category c11; +category c12; +category c13; + +#level decl +level s0:c0.c2; +level s1:c0.c13; +level s2:c0.c13; + +#some constraints +mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt)); + +attribute mls_exempt; +attribute attr1; +attribute attr2; +attribute attr3; + +type system alias sysalias; +role system; +role system types system; + +role role20_r; +role role21a_r; +role role21b_r; +role role21c_r; + +role role20_r types system; +role role21a_r types system; +role role21b_r types system; +role role21c_r types system; + +type name10; +type name20, attr1, attr2, attr3; +type name30 alias { alias1 alias2 alias3}; +type name40; +type name50a; +type name50b; +permissive name50b; +type name60; +type name61, attr1; +type name62, attr1, attr2; +type name63 alias alias4; +type name64 alias { alias5 alias6 }; +type name65 alias alias7, attr1; +type name66 alias alias8, attr2, attr3; +type name67 alias { alias10 alias11 }, attr3; +type name68 alias { alias12 alias13 }, attr1, attr3; + +type type30; +type type31a; +type type31b; +type type31c; +role system types { type30 type31a type31b type31c }; + +#type everything alias { alias1 alias2 }, attr1, attr2; + +allow system self:infoflow hi_w; + +#users +user system roles { system role20_r role21a_r role21b_r role21c_r } level s0 range s0 - s2:c0.c4; +user user10 roles system level s0 range s0 - s2:c0.c4; +user user11a roles system level s0 range s0 - s2:c0.c4; +user user11b roles system level s0 range s0 - s2:c0.c4; +user user11c roles system level s0 range s0 - s2:c0.c4; + +#normal constraints +constrain infoflow hi_w (u1 == u2); + +#isids +sid kernel system:system:system:s0 +sid security system:system:system:s0 + +#fs_use +fs_use_trans devpts system:object_r:system:s0; +fs_use_xattr ext3 system:object_r:system:s0; +fs_use_task pipefs system:object_r:system:s0; + +#genfscon +genfscon proc / system:object_r:system:s1 +genfscon proc /sys system:object_r:system:s0 +genfscon selinuxfs / system:object_r:system:s2:c0.c4 +portcon tcp 1 system:system:system:s0:c0.c1 +netifcon eth0 system:object_r:system:s0 system:object_r:system:s0 +nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0 +nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0 + diff --git a/tests/policyrep/typeattr.conf b/tests/library/policyrep/typeattr.conf similarity index 91% rename from tests/policyrep/typeattr.conf rename to tests/library/policyrep/typeattr.conf index 94c1086c..0e330ee4 100644 --- a/tests/policyrep/typeattr.conf +++ b/tests/library/policyrep/typeattr.conf @@ -87,6 +87,14 @@ attribute attr1; attribute attr2; attribute attr3; +attribute name10; +attribute name20; +attribute name30; +attribute name40; +attribute name50; +attribute name60; +attribute name70; + type system alias sysalias; role system; role system types system; @@ -102,9 +110,9 @@ role role21b_r types system; role role21c_r types system; type type30; -type type31a; -type type31b; -type type31c; +type type31a, name40, name70; +type type31b, name40, name70; +type type31c, name40, name70; role system types { type30 type31a type31b type31c }; type everything alias { alias1 alias2 }, attr1, attr2; diff --git a/tests/policyrep/user.conf b/tests/library/policyrep/user_mls.conf similarity index 90% rename from tests/policyrep/user.conf rename to tests/library/policyrep/user_mls.conf index 1b2db897..18564850 100644 --- a/tests/policyrep/user.conf +++ b/tests/library/policyrep/user_mls.conf @@ -108,10 +108,8 @@ allow system self:infoflow hi_w; #users user system roles { system role20_r role21a_r role21b_r role21c_r } level s0 range s0 - s2:c0.c4; -user user10 roles system level s0 range s0 - s2:c0.c4; -user user11a roles system level s0 range s0 - s2:c0.c4; -user user11b roles system level s0 range s0 - s2:c0.c4; -user user11c roles system level s0 range s0 - s2:c0.c4; +user user10 roles system level s1:c2 range s1 - s2:c0.c4; +user user20 roles { role20_r role21a_r } level s0 range s0 - s2:c0.c4; #normal constraints constrain infoflow hi_w (u1 == u2); diff --git a/tests/library/policyrep/user_standard.conf b/tests/library/policyrep/user_standard.conf new file mode 100644 index 00000000..c4774044 --- /dev/null +++ b/tests/library/policyrep/user_standard.conf @@ -0,0 +1,105 @@ +class infoflow +class infoflow2 +class infoflow3 +class infoflow4 +class infoflow5 +class infoflow6 +class infoflow7 + +sid kernel +sid security + +common infoflow +{ + low_w + med_w + hi_w + low_r + med_r + hi_r +} + +class infoflow +inherits infoflow + +class infoflow2 +inherits infoflow +{ + super_w + super_r +} + +class infoflow3 +{ + null +} + +class infoflow4 +inherits infoflow + +class infoflow5 +inherits infoflow + +class infoflow6 +inherits infoflow + +class infoflow7 +inherits infoflow +{ + super_w + super_r + super_none + super_both + super_unmapped +} + +attribute mls_exempt; + +type system; +role system; +role system types system; + +role role20_r; +role role21a_r; +role role21b_r; +role role21c_r; + +role role20_r types system; +role role21a_r types system; +role role21b_r types system; +role role21c_r types system; + +type type30; +type type31a; +type type31b; +type type31c; +role system types { type30 type31a type31b type31c }; + +allow system self:infoflow hi_w; + +#users +user system roles { system role20_r role21a_r role21b_r role21c_r }; +user user10 roles system; +user user20 roles { role20_r role21a_r }; + +#normal constraints +constrain infoflow hi_w (u1 == u2); + +#isids +sid kernel system:system:system +sid security system:system:system + +#fs_use +fs_use_trans devpts system:object_r:system; +fs_use_xattr ext3 system:object_r:system; +fs_use_task pipefs system:object_r:system; + +#genfscon +genfscon proc / system:object_r:system +genfscon proc /sys system:object_r:system +genfscon selinuxfs / system:object_r:system +portcon tcp 1 system:system:system +netifcon eth0 system:object_r:system system:object_r:system +nodecon 127.0.0.1 255.255.255.255 system:object_r:system +nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system + diff --git a/tests/portconquery.conf b/tests/library/portconquery.conf similarity index 100% rename from tests/portconquery.conf rename to tests/library/portconquery.conf diff --git a/tests/rbacrulequery.conf b/tests/library/rbacrulequery.conf similarity index 100% rename from tests/rbacrulequery.conf rename to tests/library/rbacrulequery.conf diff --git a/tests/rolequery.conf b/tests/library/rolequery.conf similarity index 100% rename from tests/rolequery.conf rename to tests/library/rolequery.conf diff --git a/tests/sensitivityquery.conf b/tests/library/sensitivityquery.conf similarity index 100% rename from tests/sensitivityquery.conf rename to tests/library/sensitivityquery.conf diff --git a/tests/terulequery.conf b/tests/library/terulequery.conf similarity index 100% rename from tests/terulequery.conf rename to tests/library/terulequery.conf diff --git a/tests/terulequery2.conf b/tests/library/terulequery2.conf similarity index 100% rename from tests/terulequery2.conf rename to tests/library/terulequery2.conf diff --git a/tests/library/test_boolquery.py b/tests/library/test_boolquery.py new file mode 100644 index 00000000..2be3761b --- /dev/null +++ b/tests/library/test_boolquery.py @@ -0,0 +1,41 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/boolquery.conf") +class TestBoolQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Boolean query with no criteria.""" + # query with no parameters gets all Booleans. + allbools = sorted(str(b) for b in compiled_policy.bools()) + + q = setools.BoolQuery(compiled_policy) + qbools = sorted(str(b) for b in q.results()) + + assert allbools == qbools + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Boolean query with exact match""" + q = setools.BoolQuery(compiled_policy, name="test1") + + bools = sorted(str(b) for b in q.results()) + assert ["test1"] == bools + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Boolean query with regex match.""" + q = setools.BoolQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + bools = sorted(str(b) for b in q.results()) + assert ["test2a", "test2b"] == bools + + def test_default(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Boolean query with default state match.""" + q = setools.BoolQuery(compiled_policy, default=False) + + bools = sorted(str(b) for b in q.results()) + assert ["test10a", "test10b"] == bools diff --git a/tests/library/test_boundsquery.py b/tests/library/test_boundsquery.py new file mode 100644 index 00000000..3dc951d7 --- /dev/null +++ b/tests/library/test_boundsquery.py @@ -0,0 +1,74 @@ +# Copyright 2016, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/boundsquery.conf") +class TestBoundsQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Bounds query with no criteria.""" + # query with no parameters gets all bounds. + allbounds = sorted(compiled_policy.bounds()) + + q = setools.BoundsQuery(compiled_policy) + qbounds = sorted(q.results()) + + assert allbounds == qbounds + + def test_parent_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Bounds query with exact parent match.""" + q = setools.BoundsQuery(compiled_policy, parent="test1_parent", parent_regex=False) + qbounds = sorted(q.results()) + assert 1 == len(qbounds) + + b = qbounds[0] + assert setools.BoundsRuletype.typebounds == b.ruletype + assert "test1_parent" == b.parent + assert "test1_child" == b.child + + def test_parent_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Bounds query with regex parent match.""" + q = setools.BoundsQuery(compiled_policy, parent="test2_parent?", parent_regex=True) + qbounds = sorted(q.results()) + assert 2 == len(qbounds) + + b = qbounds[0] + assert setools.BoundsRuletype.typebounds == b.ruletype + assert "test2_parent1" == b.parent + assert "test2_child2" == b.child + + b = qbounds[1] + assert setools.BoundsRuletype.typebounds == b.ruletype + assert "test2_parent2" == b.parent + assert "test2_child1" == b.child + + def test_child_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Bounds query with exact child match.""" + q = setools.BoundsQuery(compiled_policy, child="test10_child", child_regex=False) + qbounds = sorted(q.results()) + assert 1 == len(qbounds) + + b = qbounds[0] + assert setools.BoundsRuletype.typebounds == b.ruletype + assert "test10_parent" == b.parent + assert "test10_child" == b.child + + def test_child_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Bounds query with regex child match.""" + q = setools.BoundsQuery(compiled_policy, child="test11_child?", child_regex=True) + qbounds = sorted(q.results()) + assert 2 == len(qbounds) + + b = qbounds[0] + assert setools.BoundsRuletype.typebounds == b.ruletype + assert "test11_parent1" == b.parent + assert "test11_child2" == b.child + + b = qbounds[1] + assert setools.BoundsRuletype.typebounds == b.ruletype + assert "test11_parent2" == b.parent + assert "test11_child1" == b.child diff --git a/tests/library/test_categoryquery.py b/tests/library/test_categoryquery.py new file mode 100644 index 00000000..296100fa --- /dev/null +++ b/tests/library/test_categoryquery.py @@ -0,0 +1,47 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/categoryquery.conf") +class TestCategoryQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS category query with no criteria.""" + # query with no parameters gets all categories. + allcats = sorted(str(c) for c in compiled_policy.categories()) + + q = setools.CategoryQuery(compiled_policy) + qcats = sorted(str(c) for c in q.results()) + assert allcats == qcats + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS category query with exact name match.""" + q = setools.CategoryQuery(compiled_policy, name="test1") + + cats = sorted(str(c) for c in q.results()) + assert ["test1"] == cats + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS category query with regex name match.""" + q = setools.CategoryQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + cats = sorted(str(c) for c in q.results()) + assert ["test2a", "test2b"] == cats + + def test_alias_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS category query with exact alias match.""" + q = setools.CategoryQuery(compiled_policy, alias="test10a") + + cats = sorted(str(t) for t in q.results()) + assert ["test10c1"] == cats + + def test_alias_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS category query with regex alias match.""" + q = setools.CategoryQuery(compiled_policy, alias="test11(a|b)", alias_regex=True) + + cats = sorted(str(t) for t in q.results()) + assert ["test11c1", "test11c2"] == cats diff --git a/tests/library/test_commonquery.py b/tests/library/test_commonquery.py new file mode 100644 index 00000000..5018ec41 --- /dev/null +++ b/tests/library/test_commonquery.py @@ -0,0 +1,55 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/commonquery.conf") +class TestCommonQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common query with no criteria.""" + # query with no parameters gets all types. + commons = sorted(compiled_policy.commons()) + + q = setools.CommonQuery(compiled_policy) + q_commons = sorted(q.results()) + + assert commons == q_commons + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common query with exact name match.""" + q = setools.CommonQuery(compiled_policy, name="test1") + + commons = sorted(str(c) for c in q.results()) + assert ["test1"] == commons + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common query with regex name match.""" + q = setools.CommonQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + commons = sorted(str(c) for c in q.results()) + assert ["test2a", "test2b"] == commons + + def test_perm_indirect_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common query with intersect permission name patch.""" + q = setools.CommonQuery(compiled_policy, perms=set(["null"]), perms_equal=False) + + commons = sorted(str(c) for c in q.results()) + assert ["test10a", "test10b"] == commons + + def test_perm_indirect_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common query with equal permission name patch.""" + q = setools.CommonQuery(compiled_policy, perms=set(["read", "write"]), perms_equal=True) + + commons = sorted(str(c) for c in q.results()) + assert ["test11a"] == commons + + def test_perm_indirect_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Common query with regex permission name patch.""" + q = setools.CommonQuery(compiled_policy, perms="sig.+", perms_regex=True) + + commons = sorted(str(c) for c in q.results()) + assert ["test12a", "test12b"] == commons diff --git a/tests/library/test_conditionalinfoflow.py b/tests/library/test_conditionalinfoflow.py new file mode 100644 index 00000000..dedd0e90 --- /dev/null +++ b/tests/library/test_conditionalinfoflow.py @@ -0,0 +1,120 @@ +# Copyright 2014-2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + +# Note: the testing for having correct rules on every edge is only +# performed once on the full graph, since it is assumed that NetworkX's +# Digraph.subgraph() function correctly copies the edge attributes into +# the subgraph. + + +@pytest.fixture +def analysis(compiled_policy: setools.SELinuxPolicy) -> setools.InfoFlowAnalysis: + perm_map = setools.PermissionMap("tests/library/perm_map") + ret = setools.InfoFlowAnalysis(compiled_policy, perm_map) + ret._build_graph() + return ret + + +@pytest.mark.obj_args("tests/library/conditionalinfoflow.conf", mls=False) +class TestConditionalInfoFlowAnalysis: + + def test_keep_conditional_rules(self, analysis: setools.InfoFlowAnalysis) -> None: + """Keep all conditional rules.""" + analysis.booleans = None + analysis.rebuildgraph = True + analysis._build_subgraph() + + source = analysis.policy.lookup_type("src") + target = analysis.policy.lookup_type("tgt") + flow_true = analysis.policy.lookup_type("flow_true") + flow_false = analysis.policy.lookup_type("flow_false") + + r = analysis.G.edges[source, flow_true]["rules"] + assert len(r) == 1 + r = analysis.G.edges[flow_true, target]["rules"] + assert len(r) == 1 + r = analysis.G.edges[source, flow_false]["rules"] + assert len(r) == 1 + r = analysis.G.edges[flow_false, target]["rules"] + assert len(r) == 1 + + def test_default_conditional_rules(self, analysis: setools.InfoFlowAnalysis) -> None: + """Keep only default conditional rules.""" + analysis.booleans = {} + analysis.rebuildgraph = True + analysis._build_subgraph() + + source = analysis.policy.lookup_type("src") + target = analysis.policy.lookup_type("tgt") + flow_true = analysis.policy.lookup_type("flow_true") + flow_false = analysis.policy.lookup_type("flow_false") + + r = analysis.G.edges[source, flow_true]["rules"] + assert len(r) == 0 + r = analysis.G.edges[flow_true, target]["rules"] + assert len(r) == 0 + r = analysis.G.edges[source, flow_false]["rules"] + assert len(r) == 1 + r = analysis.G.edges[flow_false, target]["rules"] + assert len(r) == 1 + + def test_user_conditional_true(self, analysis: setools.InfoFlowAnalysis) -> None: + """Keep only conditional rules selected by user specified booleans (True Case.)""" + analysis.booleans = {"condition": True} + analysis.rebuildgraph = True + analysis._build_subgraph() + + source = analysis.policy.lookup_type("src") + target = analysis.policy.lookup_type("tgt") + flow_true = analysis.policy.lookup_type("flow_true") + flow_false = analysis.policy.lookup_type("flow_false") + + r = analysis.G.edges[source, flow_true]["rules"] + assert len(r) == 1 + r = analysis.G.edges[flow_true, target]["rules"] + assert len(r) == 1 + r = analysis.G.edges[source, flow_false]["rules"] + assert len(r) == 0 + r = analysis.G.edges[flow_false, target]["rules"] + assert len(r) == 0 + + def test_user_conditional_false(self, analysis: setools.InfoFlowAnalysis) -> None: + """Keep only conditional rules selected by user specified booleans (False Case.)""" + analysis.booleans = {"condition": False} + analysis.rebuildgraph = True + analysis._build_subgraph() + + source = analysis.policy.lookup_type("src") + target = analysis.policy.lookup_type("tgt") + flow_true = analysis.policy.lookup_type("flow_true") + flow_false = analysis.policy.lookup_type("flow_false") + + r = analysis.G.edges[source, flow_true]["rules"] + assert len(r) == 0 + r = analysis.G.edges[flow_true, target]["rules"] + assert len(r) == 0 + r = analysis.G.edges[source, flow_false]["rules"] + assert len(r) == 1 + r = analysis.G.edges[flow_false, target]["rules"] + assert len(r) == 1 + + def test_remaining_edges(self, analysis: setools.InfoFlowAnalysis) -> None: + """Keep edges when rules are deleted, but there are still remaining rules on the edge.""" + analysis.booleans = {} + analysis.rebuildgraph = True + analysis._build_subgraph() + + source = analysis.policy.lookup_type("src_remain") + target = analysis.policy.lookup_type("tgt_remain") + flow = analysis.policy.lookup_type("flow_remain") + + r = analysis.G.edges[source, flow]["rules"] + assert len(r) == 1 + assert str(r[0]) == 'allow src_remain flow_remain:infoflow hi_w;' + r = analysis.G.edges[flow, target]["rules"] + assert len(r) == 1 + assert str(r[0]) == 'allow tgt_remain flow_remain:infoflow hi_r;' diff --git a/tests/library/test_constraintquery.py b/tests/library/test_constraintquery.py new file mode 100644 index 00000000..4462d7c4 --- /dev/null +++ b/tests/library/test_constraintquery.py @@ -0,0 +1,96 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/constraintquery.conf") +class TestConstraintQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with no criteria.""" + allconstraint = sorted(c.tclass for c in compiled_policy.constraints()) + + q = setools.ConstraintQuery(compiled_policy) + qconstraint = sorted(c.tclass for c in q.results()) + assert allconstraint == qconstraint + + def test_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with rule type match.""" + q = setools.ConstraintQuery(compiled_policy, ruletype=["mlsconstrain"]) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test1"] == constraint + + def test_class_list(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with object class list match.""" + q = setools.ConstraintQuery(compiled_policy, tclass=["test11a", "test11b"]) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test11a", "test11b"] == constraint + + def test_class_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with object class regex match.""" + q = setools.ConstraintQuery(compiled_policy, tclass="test12(a|c)", tclass_regex=True) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test12a", "test12c"] == constraint + + def test_perms_any(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with permission set intersection match.""" + q = setools.ConstraintQuery(compiled_policy, perms=["test20ap", "test20bp"]) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test20a", "test20b"] == constraint + + def test_perms_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with permission set equality match.""" + q = setools.ConstraintQuery(compiled_policy, perms=["test21ap", "test21bp"], + perms_equal=True) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test21c"] == constraint + + def test_role_match_single(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with role match.""" + q = setools.ConstraintQuery(compiled_policy, role="test30r") + + constraint = sorted(c.tclass for c in q.results()) + assert ["test30"] == constraint + + def test_role_match_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with regex role match.""" + q = setools.ConstraintQuery(compiled_policy, role="test31r.", role_regex=True) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test31a", "test31b"] == constraint + + def test_type_match_single(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with type match.""" + q = setools.ConstraintQuery(compiled_policy, type_="test40t") + + constraint = sorted(c.tclass for c in q.results()) + assert ["test40"] == constraint + + def test_type_match_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with regex type match.""" + q = setools.ConstraintQuery(compiled_policy, type_="test41t.", type_regex=True) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test41a", "test41b"] == constraint + + def test_user_match_single(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with user match.""" + q = setools.ConstraintQuery(compiled_policy, user="test50u") + + constraint = sorted(c.tclass for c in q.results()) + assert ["test50"] == constraint + + def test_user_match_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Constraint query with regex user match.""" + q = setools.ConstraintQuery(compiled_policy, user="test51u.", user_regex=True) + + constraint = sorted(c.tclass for c in q.results()) + assert ["test51a", "test51b"] == constraint diff --git a/tests/library/test_defaultquery.py b/tests/library/test_defaultquery.py new file mode 100644 index 00000000..55a9ec75 --- /dev/null +++ b/tests/library/test_defaultquery.py @@ -0,0 +1,79 @@ +# Copyright 2016, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/defaultquery.conf") +class TestDefaultQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: no criteria.""" + # query with no parameters gets all defaults + alldefaults = sorted(compiled_policy.defaults()) + + q = setools.DefaultQuery(compiled_policy) + qdefaults = sorted(q.results()) + + assert alldefaults == qdefaults + + def test_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: ruletype criterion.""" + q = setools.DefaultQuery(compiled_policy, ruletype=["default_user"]) + defaults = list(q.results()) + assert 1 == len(defaults) + + d = defaults[0] + assert setools.DefaultRuletype.default_user == d.ruletype + assert "infoflow" == d.tclass + assert setools.DefaultValue.target == d.default + + def test_class_list(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: object class list match.""" + q = setools.DefaultQuery(compiled_policy, tclass=["infoflow3", "infoflow4"]) + + defaults = sorted(d.tclass for d in q.results()) + assert ["infoflow3", "infoflow4"] == defaults + + def test_class_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: object class regex match.""" + q = setools.DefaultQuery(compiled_policy, tclass="infoflow(3|5)", tclass_regex=True) + + defaults = sorted(c.tclass for c in q.results()) + assert ["infoflow3", "infoflow5"] == defaults + + def test_default(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: default setting.""" + q = setools.DefaultQuery(compiled_policy, default="source") + + defaults = sorted(c.tclass for c in q.results()) + assert ["infoflow", "infoflow3"] == defaults + + def test_default_range(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: default_range setting.""" + q = setools.DefaultQuery(compiled_policy, default_range="high") + + defaults = sorted(c.tclass for c in q.results()) + assert ["infoflow7"] == defaults + + def test_invalid_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: invalid ruletype""" + with pytest.raises(KeyError): + q = setools.DefaultQuery(compiled_policy, ruletype=["INVALID"]) + + def test_invalid_class(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: invalid object class""" + with pytest.raises(setools.exception.InvalidClass): + q = setools.DefaultQuery(compiled_policy, tclass=["INVALID"]) + + def test_invalid_default_value(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: invalid default value""" + with pytest.raises(KeyError): + q = setools.DefaultQuery(compiled_policy, default="INVALID") + + def test_invalid_default_range(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Default query: invalid default range""" + with pytest.raises(KeyError): + q = setools.DefaultQuery(compiled_policy, default_range="INVALID") diff --git a/tests/library/test_devicetreeconquery.py b/tests/library/test_devicetreeconquery.py new file mode 100644 index 00000000..6c0623c4 --- /dev/null +++ b/tests/library/test_devicetreeconquery.py @@ -0,0 +1,203 @@ +# Derived from tests/portconquery.py +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/devicetreeconquery.conf", xen=True) +class TestDevicetreeconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with no criteria""" + # query with no parameters gets all PCI paths. + rules = sorted(compiled_policy.devicetreecons()) + + q = setools.DevicetreeconQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context user exact match""" + q = setools.DevicetreeconQuery(compiled_policy, user="user10", user_regex=False) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree10")] == path + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context user regex match""" + q = setools.DevicetreeconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree11"), ("/dev/tree11000")] == path + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context role exact match""" + q = setools.DevicetreeconQuery(compiled_policy, role="role20_r", role_regex=False) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree20")] == path + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context role regex match""" + q = setools.DevicetreeconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree21"), ("/dev/tree21001")] == path + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context type exact match""" + q = setools.DevicetreeconQuery(compiled_policy, type_="type30", type_regex=False) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree30")] == path + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context type regex match""" + q = setools.DevicetreeconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree31000"), ("/dev/tree31001")] == path + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range exact match""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree40")] == path + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range overlap match (equal)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", + range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree41")] == path + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range overlap match (subset)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree41")] == path + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range overlap match (superset)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree41")] == path + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range overlap match (overlap low level)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree41")] == path + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range overlap match (overlap high level)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree41")] == path + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range subset match""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree42")] == path + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range subset match (equal)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", + range_overlap=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree42")] == path + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range superset match""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s3 - s3:c0.c4", + range_superset=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree43")] == path + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range superset match (equal)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", + range_superset=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree43")] == path + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper subset match""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree44")] == path + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper subset match (equal)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", + range_subset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [] == path + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper subset match (equal low only)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", + range_subset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree44")] == path + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper subset match (equal high only)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree44")] == path + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper superset match""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s5 - s5:c0.c4", + range_superset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree45")] == path + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper superset match (equal)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", + range_superset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [] == path + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper superset match (equal low)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", + range_superset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree45")] == path + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Devicetreecon query with context range proper superset match (equal high)""" + q = setools.DevicetreeconQuery(compiled_policy, range_="s5 - s5:c1.c3", + range_superset=True, range_proper=True) + + path = sorted(p.path for p in q.results()) + assert [("/dev/tree45")] == path diff --git a/tests/library/test_diff.py b/tests/library/test_diff.py new file mode 100644 index 00000000..c2ae1d78 --- /dev/null +++ b/tests/library/test_diff.py @@ -0,0 +1,2888 @@ +# Copyright 2015-2016, Tresys Technology, LLC +# Copyright 2016, 2017, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# +from dataclasses import astuple +from ipaddress import IPv6Address, IPv4Network, IPv6Network + +import pytest +import setools +from setools import PolicyDifference, PortconProtocol, PortconRange +from setools import BoundsRuletype as BRT +from setools import ConstraintRuletype as CRT +from setools import DefaultRuletype as DRT +from setools import DefaultRangeValue as DRV +from setools import DefaultValue as DV +from setools import FSUseRuletype as FSURT +from setools import MLSRuletype as MRT +from setools import RBACRuletype as RRT +from setools import TERuletype as TRT + +from . import util + + +@pytest.fixture(scope="class") +def analysis(policy_pair: tuple[setools.SELinuxPolicy, setools.SELinuxPolicy]) -> PolicyDifference: + return PolicyDifference(*policy_pair) + + +@pytest.mark.obj_args("tests/library/diff_left.conf", "tests/library/diff_right.conf") +class TestPolicyDifference: + + """Policy difference tests.""" + + # + # Types + # + def test_added_types(self, analysis: setools.PolicyDifference) -> None: + """Diff: added type""" + assert set(["added_type"]) == analysis.added_types + + def test_removed_types(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type""" + assert set(["removed_type"]) == analysis.removed_types + + def test_modified_types_count(self, analysis: setools.PolicyDifference) -> None: + """Diff: total modified types""" + assert 6 == len(analysis.modified_types) + + def test_modified_types_remove_attr(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type with removed attribute.""" + # modified_remove_attr + analysis.modified_types.sort() + type_ = analysis.modified_types[4] + assert set(["an_attr"]) == type_.removed_attributes + assert not type_.added_attributes + assert not type_.matched_attributes + assert not type_.modified_permissive + assert not type_.permissive + assert not type_.added_aliases + assert not type_.removed_aliases + assert not type_.matched_aliases + + def test_modified_types_remove_alias(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type with removed alias.""" + # modified_remove_alias + analysis.modified_types.sort() + type_ = analysis.modified_types[3] + assert set(["an_alias"]) == type_.removed_aliases + assert not type_.added_attributes + assert not type_.removed_attributes + assert not type_.matched_attributes + assert not type_.modified_permissive + assert not type_.permissive + assert not type_.added_aliases + assert not type_.matched_aliases + + def test_modified_types_remove_permissive(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type with removed permissve.""" + # modified_remove_permissive + analysis.modified_types.sort() + type_ = analysis.modified_types[5] + assert not type_.added_attributes + assert not type_.removed_attributes + assert not type_.matched_attributes + assert type_.modified_permissive + assert type_.permissive + assert not type_.added_aliases + assert not type_.removed_aliases + assert not type_.matched_aliases + + def test_modified_types_add_attr(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type with added attribute.""" + # modified_add_attr + analysis.modified_types.sort() + type_ = analysis.modified_types[1] + assert set(["an_attr"]) == type_.added_attributes + assert not type_.removed_attributes + assert not type_.matched_attributes + assert not type_.modified_permissive + assert not type_.permissive + assert not type_.added_aliases + assert not type_.removed_aliases + assert not type_.matched_aliases + + def test_modified_types_add_alias(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type with added alias.""" + # modified_add_alias + analysis.modified_types.sort() + type_ = analysis.modified_types[0] + assert set(["an_alias"]) == type_.added_aliases + assert not type_.added_attributes + assert not type_.removed_attributes + assert not type_.matched_attributes + assert not type_.modified_permissive + assert not type_.permissive + assert not type_.removed_aliases + assert not type_.matched_aliases + + def test_modified_types_add_permissive(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type with added permissive.""" + # modified_add_permissive + analysis.modified_types.sort() + type_ = analysis.modified_types[2] + assert not type_.added_attributes + assert not type_.removed_attributes + assert not type_.matched_attributes + assert type_.modified_permissive + assert not type_.permissive + assert not type_.added_aliases + assert not type_.removed_aliases + assert not type_.matched_aliases + + # + # Roles + # + def test_added_role(self, analysis: setools.PolicyDifference) -> None: + """Diff: added role.""" + assert set(["added_role"]) == analysis.added_roles + + def test_removed_role(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed role.""" + assert set(["removed_role"]) == analysis.removed_roles + + def test_modified_role_count(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified role.""" + assert 2 == len(analysis.modified_roles) + + def test_modified_role_add_type(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified role with added type.""" + # modified_add_type + analysis.modified_roles.sort() + assert set(["system"]) == analysis.modified_roles[0].added_types + assert not analysis.modified_roles[0].removed_types + + def test_modified_role_remove_type(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified role with removed type.""" + # modified_remove_type + analysis.modified_roles.sort() + assert set(["system"]) == analysis.modified_roles[1].removed_types + assert not analysis.modified_roles[1].added_types + + # + # Commons + # + def test_added_common(self, analysis: setools.PolicyDifference) -> None: + """Diff: added common.""" + assert set(["added_common"]) == analysis.added_commons + + def test_removed_common(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed common.""" + assert set(["removed_common"]) == analysis.removed_commons + + def test_modified_common_count(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified common count.""" + assert 2 == len(analysis.modified_commons) + + def test_modified_common_add_perm(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified common with added perm.""" + # modified_add_perm + analysis.modified_commons.sort() + assert set(["added_perm"]) == analysis.modified_commons[0].added_perms + assert not analysis.modified_commons[0].removed_perms + + def test_modified_common_remove_perm(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified common with removed perm.""" + # modified_remove_perm + analysis.modified_commons.sort() + assert set(["removed_perm"]) == analysis.modified_commons[1].removed_perms + assert not analysis.modified_commons[1].added_perms + + # + # Classes + # + def test_added_class(self, analysis: setools.PolicyDifference) -> None: + """Diff: added class.""" + assert set(["added_class"]) == analysis.added_classes + + def test_removed_class(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed class.""" + assert set(["removed_class"]) == analysis.removed_classes + + def test_modified_class_count(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified class count.""" + assert 3 == len(analysis.modified_classes) + + def test_modified_class_add_perm(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified class with added perm.""" + # modified_add_perm + analysis.modified_classes.sort() + assert set(["added_perm"]) == analysis.modified_classes[0].added_perms + assert not analysis.modified_classes[0].removed_perms + + def test_modified_class_remove_perm(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified class with removed perm.""" + # modified_remove_perm + analysis.modified_classes.sort() + assert set(["removed_perm"]) == analysis.modified_classes[2].removed_perms + assert not analysis.modified_classes[2].added_perms + + def test_modified_class_change_common(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified class due to modified common.""" + # modified_change_common + analysis.modified_classes.sort() + assert set(["old_com"]) == analysis.modified_classes[1].removed_perms + assert set(["new_com"]) == analysis.modified_classes[1].added_perms + + # + # Allow rules + # + def test_added_allow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added allow rules.""" + rules = sorted(analysis.added_allows) + assert 5 == len(rules) + + # added rule with existing types + util.validate_rule(rules[0], TRT.allow, "added_rule_source", "added_rule_target", + tclass="infoflow", perms=set(["med_w"])) + + # added rule with new type + util.validate_rule(rules[1], TRT.allow, "added_type", "added_type", tclass="infoflow2", + perms=set(["med_w"])) + + # rule moved out of a conditional + util.validate_rule(rules[2], TRT.allow, "move_from_bool", "move_from_bool", + tclass="infoflow4", perms=set(["hi_r"])) + + # rule moved into a conditional + util.validate_rule(rules[3], TRT.allow, "move_to_bool", "move_to_bool", + tclass="infoflow4", perms=set(["hi_w"]), cond="move_to_bool_b", + cond_block=True) + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[4], TRT.allow, "system", "switch_block", tclass="infoflow6", + perms=set(["hi_r"]), cond="switch_block_b", cond_block=False) + + def test_removed_allow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed allow rules.""" + rules = sorted(analysis.removed_allows) + assert 5 == len(rules) + + # rule moved out of a conditional + util.validate_rule(rules[0], TRT.allow, "move_from_bool", "move_from_bool", + tclass="infoflow4", perms=set(["hi_r"]), cond="move_from_bool_b", + cond_block=True) + + # rule moved into a conditional + util.validate_rule(rules[1], TRT.allow, "move_to_bool", "move_to_bool", tclass="infoflow4", + perms=set(["hi_w"])) + + # removed rule with existing types + util.validate_rule(rules[2], TRT.allow, "removed_rule_source", "removed_rule_target", + tclass="infoflow", perms=set(["hi_r"])) + + # removed rule with new type + util.validate_rule(rules[3], TRT.allow, "removed_type", "removed_type", tclass="infoflow3", + perms=set(["null"])) + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[4], TRT.allow, "system", "switch_block", tclass="infoflow6", + perms=set(["hi_r"]), cond="switch_block_b", cond_block=True) + + def test_modified_allow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified allow rules.""" + lst = sorted(analysis.modified_allows, key=lambda x: x.rule) + assert 3 == len(lst) + + # add permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) + assert TRT.allow == rule.ruletype + assert "modified_rule_add_perms" == rule.source + assert "modified_rule_add_perms" == rule.target + assert "infoflow" == rule.tclass + assert set(["hi_w"]) == added_perms + assert not removed_perms + assert set(["hi_r"]) == matched_perms + + # add and remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) + assert TRT.allow == rule.ruletype + assert "modified_rule_add_remove_perms" == rule.source + assert "modified_rule_add_remove_perms" == rule.target + assert "infoflow2" == rule.tclass + assert set(["super_r"]) == added_perms + assert set(["super_w"]) == removed_perms + assert set(["low_w"]) == matched_perms + + # remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) + assert TRT.allow == rule.ruletype + assert "modified_rule_remove_perms" == rule.source + assert "modified_rule_remove_perms" == rule.target + assert "infoflow" == rule.tclass + assert not added_perms + assert set(["low_r"]) == removed_perms + assert set(["low_w"]) == matched_perms + + # + # Auditallow rules + # + def test_added_auditallow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added auditallow rules.""" + rules = sorted(analysis.added_auditallows) + assert 5 == len(rules) + + # added rule with existing types + util.validate_rule(rules[0], TRT.auditallow, "aa_added_rule_source", + "aa_added_rule_target", tclass="infoflow", perms=set(["med_w"])) + + # rule moved out of a conditional + util.validate_rule(rules[1], TRT.auditallow, "aa_move_from_bool", "aa_move_from_bool", + tclass="infoflow4", perms=set(["hi_r"])) + + # rule moved into a conditional + util.validate_rule(rules[2], TRT.auditallow, "aa_move_to_bool", "aa_move_to_bool", + tclass="infoflow4", perms=set(["hi_w"]), cond="aa_move_to_bool_b", + cond_block=True) + + # added rule with new type + util.validate_rule(rules[3], TRT.auditallow, "added_type", "added_type", tclass="infoflow7", + perms=set(["super_none"])) + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[4], TRT.auditallow, "system", "aa_switch_block", + tclass="infoflow6", perms=set(["hi_r"]), cond="aa_switch_block_b", + cond_block=False) + + def test_removed_auditallow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed auditallow rules.""" + rules = sorted(analysis.removed_auditallows) + assert 5 == len(rules) + + # rule moved out of a conditional + util.validate_rule(rules[0], TRT.auditallow, "aa_move_from_bool", "aa_move_from_bool", + tclass="infoflow4", perms=set(["hi_r"]), cond="aa_move_from_bool_b", + cond_block=True) + + # rule moved into a conditional + util.validate_rule(rules[1], TRT.auditallow, "aa_move_to_bool", "aa_move_to_bool", + tclass="infoflow4", perms=set(["hi_w"])) + + # removed rule with existing types + util.validate_rule(rules[2], TRT.auditallow, "aa_removed_rule_source", + "aa_removed_rule_target", tclass="infoflow", perms=set(["hi_r"])) + + # removed rule with new type + util.validate_rule(rules[3], TRT.auditallow, "removed_type", "removed_type", + tclass="infoflow7", perms=set(["super_unmapped"])) + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[4], TRT.auditallow, "system", "aa_switch_block", + tclass="infoflow6", perms=set(["hi_r"]), cond="aa_switch_block_b", + cond_block=True) + + def test_modified_auditallow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified auditallow rules.""" + lst = sorted(analysis.modified_auditallows, key=lambda x: x.rule) + assert 3 == len(lst) + + # add permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) + assert TRT.auditallow == rule.ruletype + assert "aa_modified_rule_add_perms" == rule.source + assert "aa_modified_rule_add_perms" == rule.target + assert "infoflow" == rule.tclass + assert set(["hi_w"]) == added_perms + assert not removed_perms + assert set(["hi_r"]) == matched_perms + + # add and remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) + assert TRT.auditallow == rule.ruletype + assert "aa_modified_rule_add_remove_perms" == rule.source + assert "aa_modified_rule_add_remove_perms" == rule.target + assert "infoflow2" == rule.tclass + assert set(["super_r"]) == added_perms + assert set(["super_w"]) == removed_perms + assert set(["low_w"]) == matched_perms + + # remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) + assert TRT.auditallow == rule.ruletype + assert "aa_modified_rule_remove_perms" == rule.source + assert "aa_modified_rule_remove_perms" == rule.target + assert "infoflow" == rule.tclass + assert not added_perms + assert set(["low_r"]) == removed_perms + assert set(["low_w"]) == matched_perms + + # + # Dontaudit rules + # + def test_added_dontaudit_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added dontaudit rules.""" + rules = sorted(analysis.added_dontaudits) + assert 5 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], TRT.dontaudit, "added_type", "added_type", tclass="infoflow7", + perms=set(["super_none"])) + + # added rule with existing types + util.validate_rule(rules[1], TRT.dontaudit, "da_added_rule_source", "da_added_rule_target", + tclass="infoflow", perms=set(["med_w"])) + + # rule moved out of a conditional + util.validate_rule(rules[2], TRT.dontaudit, "da_move_from_bool", "da_move_from_bool", + tclass="infoflow4", perms=set(["hi_r"])) + + # rule moved into a conditional + util.validate_rule(rules[3], TRT.dontaudit, "da_move_to_bool", "da_move_to_bool", + tclass="infoflow4", perms=set(["hi_w"]), cond="da_move_to_bool_b", + cond_block=True) + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[4], TRT.dontaudit, "system", "da_switch_block", + tclass="infoflow6", perms=set(["hi_r"]), cond="da_switch_block_b", + cond_block=False) + + def test_removed_dontaudit_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed dontaudit rules.""" + rules = sorted(analysis.removed_dontaudits) + assert 5 == len(rules) + + # rule moved out of a conditional + util.validate_rule(rules[0], TRT.dontaudit, "da_move_from_bool", "da_move_from_bool", + tclass="infoflow4", perms=set(["hi_r"]), cond="da_move_from_bool_b", + cond_block=True) + + # rule moved into a conditional + util.validate_rule(rules[1], TRT.dontaudit, "da_move_to_bool", "da_move_to_bool", + tclass="infoflow4", perms=set(["hi_w"])) + + # removed rule with existing types + util.validate_rule(rules[2], TRT.dontaudit, "da_removed_rule_source", + "da_removed_rule_target", tclass="infoflow", perms=set(["hi_r"])) + + # removed rule with new type + util.validate_rule(rules[3], TRT.dontaudit, "removed_type", "removed_type", + tclass="infoflow7", perms=set(["super_both"])) + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[4], TRT.dontaudit, "system", "da_switch_block", + tclass="infoflow6", perms=set(["hi_r"]), cond="da_switch_block_b", + cond_block=True) + + def test_modified_dontaudit_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified dontaudit rules.""" + lst = sorted(analysis.modified_dontaudits, key=lambda x: x.rule) + assert 3 == len(lst) + + # add permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) + assert TRT.dontaudit == rule.ruletype + assert "da_modified_rule_add_perms" == rule.source + assert "da_modified_rule_add_perms" == rule.target + assert "infoflow" == rule.tclass + assert set(["hi_w"]) == added_perms + assert not removed_perms + assert set(["hi_r"]) == matched_perms + + # add and remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) + assert TRT.dontaudit == rule.ruletype + assert "da_modified_rule_add_remove_perms" == rule.source + assert "da_modified_rule_add_remove_perms" == rule.target + assert "infoflow2" == rule.tclass + assert set(["super_r"]) == added_perms + assert set(["super_w"]) == removed_perms + assert set(["low_w"]) == matched_perms + + # remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) + assert TRT.dontaudit == rule.ruletype + assert "da_modified_rule_remove_perms" == rule.source + assert "da_modified_rule_remove_perms" == rule.target + assert "infoflow" == rule.tclass + assert not added_perms + assert set(["low_r"]) == removed_perms + assert set(["low_w"]) == matched_perms + + # + # Neverallow rules + # + def test_added_neverallow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added neverallow rules.""" + assert not analysis.added_neverallows + # changed after dropping source policy support + + # rules = sorted(analysis.added_neverallows) + # assert 2 == len(rules) + + # added rule with new type + # util.validate_rule(rules[0], TRT.neverallow, "added_type", "added_type", "added_class", + # set(["new_class_perm"])) + + # added rule with existing types + # util.validate_rule(rules[1], TRT.neverallow, "na_added_rule_source", + # "na_added_rule_target", "infoflow", set(["med_w"])) + + def test_removed_neverallow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed neverallow rules.""" + assert not analysis.removed_neverallows + # changed after dropping source policy support + # rules = sorted(analysis.removed_neverallows) + # assert 2 == len(rules) + + # removed rule with existing types + # util.validate_rule(rules[0], TRT.neverallow, "na_removed_rule_source", + # "na_removed_rule_target", "infoflow", set(["hi_r"])) + + # removed rule with new type + # util.validate_rule(rules[1], TRT.neverallow, "removed_type", "removed_type", + # "removed_class", set(["null_perm"])) + + def test_modified_neverallow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified neverallow rules.""" + # changed after dropping source policy support + assert not analysis.modified_neverallows + # l = sorted(analysis.modified_neverallows, key=lambda x: x.rule) + # assert 3 == len(l) + # + # # add permissions + # rule, added_perms, removed_perms, matched_perms = l[0] + # assert TRT.neverallow == rule.ruletype + # assert "na_modified_rule_add_perms" == rule.source + # assert "na_modified_rule_add_perms" == rule.target + # assert "infoflow" == rule.tclass + # assert set(["hi_w"]) == added_perms + # assert not removed_perms + # assert set(["hi_r"]) == matched_perms + # + # # add and remove permissions + # rule, added_perms, removed_perms, matched_perms = l[1] + # assert TRT.neverallow == rule.ruletype + # assert "na_modified_rule_add_remove_perms" == rule.source + # assert "na_modified_rule_add_remove_perms" == rule.target + # assert "infoflow2" == rule.tclass + # assert set(["super_r"]) == added_perms + # assert set(["super_w"]) == removed_perms + # assert set(["low_w"]) == matched_perms + # + # # remove permissions + # rule, added_perms, removed_perms, matched_perms = l[2] + # assert TRT.neverallow == rule.ruletype + # assert "na_modified_rule_remove_perms" == rule.source + # assert "na_modified_rule_remove_perms" == rule.target + # assert "infoflow" == rule.tclass + # assert not added_perms + # assert set(["low_r"]) == removed_perms + # assert set(["low_w"]) == matched_perms + + # + # Type_transition rules + # + def test_added_type_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added type_transition rules.""" + rules = sorted(analysis.added_type_transitions) + assert 5 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], TRT.type_transition, "added_type", "system", + tclass="infoflow4", default="system") + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[1], TRT.type_transition, "system", "tt_switch_block", + tclass="infoflow6", default="system", cond="tt_switch_block_b", + cond_block=False) + + # added rule with existing types + util.validate_rule(rules[2], TRT.type_transition, "tt_added_rule_source", + "tt_added_rule_target", tclass="infoflow", default="system") + + # rule moved out of a conditional + util.validate_rule(rules[3], TRT.type_transition, "tt_move_from_bool", "system", + tclass="infoflow4", default="system") + + # rule moved into a conditional + util.validate_rule(rules[4], TRT.type_transition, "tt_move_to_bool", "system", + tclass="infoflow3", default="system", cond="tt_move_to_bool_b", + cond_block=True) + + def test_removed_type_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed type_transition rules.""" + rules = sorted(analysis.removed_type_transitions) + assert 5 == len(rules) + + # removed rule with new type + util.validate_rule(rules[0], TRT.type_transition, "removed_type", "system", + tclass="infoflow4", default="system") + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[1], TRT.type_transition, "system", "tt_switch_block", + tclass="infoflow6", default="system", cond="tt_switch_block_b", + cond_block=True) + + # rule moved out of a conditional + util.validate_rule(rules[2], TRT.type_transition, "tt_move_from_bool", "system", + tclass="infoflow4", default="system", cond="tt_move_from_bool_b", + cond_block=True) + + # rule moved into a conditional + util.validate_rule(rules[3], TRT.type_transition, "tt_move_to_bool", "system", + tclass="infoflow3", default="system") + + # removed rule with existing types + util.validate_rule(rules[4], TRT.type_transition, "tt_removed_rule_source", + "tt_removed_rule_target", tclass="infoflow", default="system") + + def test_modified_type_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type_transition rules.""" + lst = sorted(analysis.modified_type_transitions, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_default, removed_default = astuple(lst[0]) + assert TRT.type_transition == rule.ruletype + assert "tt_matched_source" == rule.source + assert "system" == rule.target + assert "infoflow" == rule.tclass + assert "tt_new_type" == added_default + assert "tt_old_type" == removed_default + + # + # Type_change rules + # + def test_added_type_change_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added type_change rules.""" + rules = sorted(analysis.added_type_changes) + assert 5 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], TRT.type_change, "added_type", "system", tclass="infoflow4", + default="system") + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[1], TRT.type_change, "system", "tc_switch_block", + tclass="infoflow6", default="system", cond="tc_switch_block_b", + cond_block=False) + + # added rule with existing types + util.validate_rule(rules[2], TRT.type_change, "tc_added_rule_source", + "tc_added_rule_target", tclass="infoflow", default="system") + + # rule moved out of a conditional + util.validate_rule(rules[3], TRT.type_change, "tc_move_from_bool", "system", + tclass="infoflow4", default="system") + + # rule moved into a conditional + util.validate_rule(rules[4], TRT.type_change, "tc_move_to_bool", "system", + tclass="infoflow3", default="system", cond="tc_move_to_bool_b", + cond_block=True) + + def test_removed_type_change_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed type_change rules.""" + rules = sorted(analysis.removed_type_changes) + assert 5 == len(rules) + + # removed rule with new type + util.validate_rule(rules[0], TRT.type_change, "removed_type", "system", tclass="infoflow4", + default="system") + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[1], TRT.type_change, "system", "tc_switch_block", + tclass="infoflow6", default="system", cond="tc_switch_block_b", + cond_block=True) + + # rule moved out of a conditional + util.validate_rule(rules[2], TRT.type_change, "tc_move_from_bool", "system", + tclass="infoflow4", default="system", cond="tc_move_from_bool_b", + cond_block=True) + + # rule moved into a conditional + util.validate_rule(rules[3], TRT.type_change, "tc_move_to_bool", "system", + tclass="infoflow3", default="system") + + # removed rule with existing types + util.validate_rule(rules[4], TRT.type_change, "tc_removed_rule_source", + "tc_removed_rule_target", tclass="infoflow", default="system") + + def test_modified_type_change_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type_change rules.""" + lst = sorted(analysis.modified_type_changes, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_default, removed_default = astuple(lst[0]) + assert TRT.type_change == rule.ruletype + assert "tc_matched_source" == rule.source + assert "system" == rule.target + assert "infoflow" == rule.tclass + assert "tc_new_type" == added_default + assert "tc_old_type" == removed_default + + # + # Type_member rules + # + def test_added_type_member_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added type_member rules.""" + rules = sorted(analysis.added_type_members) + assert 5 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], TRT.type_member, "added_type", "system", tclass="infoflow4", + default="system") + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[1], TRT.type_member, "system", "tm_switch_block", + tclass="infoflow6", default="system", cond="tm_switch_block_b", + cond_block=False) + + # added rule with existing types + util.validate_rule(rules[2], TRT.type_member, "tm_added_rule_source", + "tm_added_rule_target", tclass="infoflow", default="system") + + # rule moved out of a conditional + util.validate_rule(rules[3], TRT.type_member, "tm_move_from_bool", "system", + tclass="infoflow4", default="system") + + # rule moved into a conditional + util.validate_rule(rules[4], TRT.type_member, "tm_move_to_bool", "system", + tclass="infoflow3", default="system", cond="tm_move_to_bool_b", + cond_block=True) + + def test_removed_type_member_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed type_member rules.""" + rules = sorted(analysis.removed_type_members) + assert 5 == len(rules) + + # removed rule with new type + util.validate_rule(rules[0], TRT.type_member, "removed_type", "system", tclass="infoflow4", + default="system") + + # rule moved from one conditional block to another (true to false) + util.validate_rule(rules[1], TRT.type_member, "system", "tm_switch_block", + tclass="infoflow6", default="system", cond="tm_switch_block_b", + cond_block=True) + + # rule moved out of a conditional + util.validate_rule(rules[2], TRT.type_member, "tm_move_from_bool", "system", + tclass="infoflow4", default="system", cond="tm_move_from_bool_b", + cond_block=True) + + # rule moved into a conditional + util.validate_rule(rules[3], TRT.type_member, "tm_move_to_bool", "system", + tclass="infoflow3", default="system") + + # removed rule with existing types + util.validate_rule(rules[4], TRT.type_member, "tm_removed_rule_source", + "tm_removed_rule_target", tclass="infoflow", default="system") + + def test_modified_type_member_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type_member rules.""" + lst = sorted(analysis.modified_type_members, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_default, removed_default = astuple(lst[0]) + assert TRT.type_member == rule.ruletype + assert "tm_matched_source" == rule.source + assert "system" == rule.target + assert "infoflow" == rule.tclass + assert "tm_new_type" == added_default + assert "tm_old_type" == removed_default + + # + # Range_transition rules + # + def test_added_range_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added range_transition rules.""" + rules = sorted(analysis.added_range_transitions) + assert 2 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], MRT.range_transition, "added_type", "system", + tclass="infoflow4", default="s3") + + # added rule with existing types + util.validate_rule(rules[1], MRT.range_transition, "rt_added_rule_source", + "rt_added_rule_target", tclass="infoflow", default="s3") + + def test_removed_range_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed range_transition rules.""" + rules = sorted(analysis.removed_range_transitions) + assert 2 == len(rules) + + # removed rule with new type + util.validate_rule(rules[0], MRT.range_transition, "removed_type", "system", + tclass="infoflow4", default="s1") + + # removed rule with existing types + util.validate_rule(rules[1], MRT.range_transition, "rt_removed_rule_source", + "rt_removed_rule_target", tclass="infoflow", default="s1") + + def test_modified_range_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified range_transition rules.""" + lst = sorted(analysis.modified_range_transitions, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_default, removed_default = astuple(lst[0]) + assert MRT.range_transition == rule.ruletype + assert "rt_matched_source" == rule.source + assert "system" == rule.target + assert "infoflow" == rule.tclass + assert "s0:c0,c4 - s1:c0.c2,c4" == added_default + assert "s2:c0 - s3:c0.c2" == removed_default + + # + # Role allow rules + # + def test_added_role_allow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added role_allow rules.""" + rules = sorted(analysis.added_role_allows) + assert 2 == len(rules) + + # added rule with existing roles + assert RRT.allow == rules[0].ruletype + assert "added_role" == rules[0].source + assert "system" == rules[0].target + + # added rule with new roles + assert RRT.allow == rules[1].ruletype + assert "added_rule_source_r" == rules[1].source + assert "added_rule_target_r" == rules[1].target + + def test_removed_role_allow_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed role_allow rules.""" + rules = sorted(analysis.removed_role_allows) + assert 2 == len(rules) + + # removed rule with removed role + assert RRT.allow == rules[0].ruletype + assert "removed_role" == rules[0].source + assert "system" == rules[0].target + + # removed rule with existing roles + assert RRT.allow == rules[1].ruletype + assert "removed_rule_source_r" == rules[1].source + assert "removed_rule_target_r" == rules[1].target + + # + # Role_transition rules + # + def test_added_role_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added role_transition rules.""" + rules = sorted(analysis.added_role_transitions) + assert 2 == len(rules) + + # added rule with new role + util.validate_rule(rules[0], RRT.role_transition, "added_role", "system", + tclass="infoflow4", default="system") + + # added rule with existing roles + util.validate_rule(rules[1], RRT.role_transition, "role_tr_added_rule_source", + "role_tr_added_rule_target", tclass="infoflow6", default="system") + + def test_removed_role_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed role_transition rules.""" + rules = sorted(analysis.removed_role_transitions) + assert 2 == len(rules) + + # removed rule with new role + util.validate_rule(rules[0], RRT.role_transition, "removed_role", "system", + tclass="infoflow4", default="system") + + # removed rule with existing roles + util.validate_rule(rules[1], RRT.role_transition, "role_tr_removed_rule_source", + "role_tr_removed_rule_target", tclass="infoflow5", default="system") + + def test_modified_role_transition_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified role_transition rules.""" + lst = sorted(analysis.modified_role_transitions, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_default, removed_default = astuple(lst[0]) + assert RRT.role_transition == rule.ruletype + assert "role_tr_matched_source" == rule.source + assert "role_tr_matched_target" == rule.target + assert "infoflow3" == rule.tclass + assert "role_tr_new_role" == added_default + assert "role_tr_old_role" == removed_default + + # + # Users + # + def test_added_user(self, analysis: setools.PolicyDifference) -> None: + """Diff: added user.""" + assert set(["added_user"]) == analysis.added_users + + def test_removed_user(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed user.""" + assert set(["removed_user"]) == analysis.removed_users + + def test_modified_user_count(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified user count.""" + assert 4 == len(analysis.modified_users) + + def test_modified_user_add_role(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified user with added role.""" + # modified_add_role + analysis.modified_users.sort() + assert set(["added_role"]) == analysis.modified_users[0].added_roles + assert not analysis.modified_users[0].removed_roles + + def test_modified_user_remove_role(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified user with removed role.""" + # modified_remove_role + analysis.modified_users.sort() + assert set(["removed_role"]) == analysis.modified_users[3].removed_roles + assert not analysis.modified_users[3].added_roles + + def test_modified_user_change_level(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified user due to modified default level.""" + # modified_change_level + analysis.modified_users.sort() + assert "s2:c0" == analysis.modified_users[1].removed_level + assert "s2:c1" == analysis.modified_users[1].added_level + + def test_modified_user_change_range(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified user due to modified range.""" + # modified_change_range + analysis.modified_users.sort() + assert "s3:c1 - s3:c1.c3" == analysis.modified_users[2].removed_range + assert "s3:c1 - s3:c1.c4" == analysis.modified_users[2].added_range + + # + # Type attributes + # + def test_added_type_attribute(self, analysis: setools.PolicyDifference) -> None: + """Diff: added type attribute.""" + assert set(["added_attr"]) == analysis.added_type_attributes + + def test_removed_type_attribute(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed type attribute.""" + assert set(["removed_attr"]) == analysis.removed_type_attributes + + def test_modified_type_attribute(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified type attribute.""" + assert 1 == len(analysis.modified_type_attributes) + assert set(["modified_add_attr"]) == analysis.modified_type_attributes[0].added_types + assert set(["modified_remove_attr"]) == analysis.modified_type_attributes[0].removed_types + + # + # Booleans + # + def test_added_boolean(self, analysis: setools.PolicyDifference) -> None: + """Diff: added boolean.""" + assert set(["added_bool"]) == analysis.added_booleans + + def test_removed_boolean(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed boolean.""" + assert set(["removed_bool"]) == analysis.removed_booleans + + def test_modified_boolean(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified boolean.""" + assert 1 == len(analysis.modified_booleans) + assert analysis.modified_booleans[0].added_state + assert not analysis.modified_booleans[0].removed_state + + # + # Categories + # + def test_added_category(self, analysis: setools.PolicyDifference) -> None: + """Diff: added category.""" + assert set(["c6"]) == analysis.added_categories + + def test_removed_category(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed category.""" + assert set(["c5"]) == analysis.removed_categories + + def test_modified_category(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified categories.""" + assert 2 == len(analysis.modified_categories) + analysis.modified_categories.sort() + + # add alias on c1 + assert set(["foo"]) == analysis.modified_categories[1].added_aliases + assert not analysis.modified_categories[1].removed_aliases + + # remove alias on c0 + assert not analysis.modified_categories[0].added_aliases + assert set(["eggs"]) == analysis.modified_categories[0].removed_aliases + + # + # Sensitivity + # + def test_added_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """Diff: added sensitivities.""" + assert set(["s46"]) == analysis.added_sensitivities + + def test_removed_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed sensitivities.""" + assert set(["s47"]) == analysis.removed_sensitivities + + def test_modified_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified sensitivities.""" + assert 2 == len(analysis.modified_sensitivities) + analysis.modified_sensitivities.sort() + + # add alias to s1 + assert set(["al4"]) == analysis.modified_sensitivities[1].added_aliases + assert not analysis.modified_sensitivities[1].removed_aliases + + # remove alias from s0 + assert not analysis.modified_sensitivities[0].added_aliases + assert set(["al2"]) == analysis.modified_sensitivities[0].removed_aliases + + # + # Initial SIDs + # + def test_added_initialsids(self, analysis: setools.PolicyDifference) -> None: + """Diff: added initialsids.""" + assert set(["file_labels"]) == analysis.added_initialsids + + @pytest.mark.skip("Moved to PolicyDifferenceRmIsidTest.") + def test_removed_initialsids(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed initialsids.""" + assert set(["removed_sid"]) == analysis.removed_initialsids + + def test_modified_initialsids(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified initialsids.""" + assert 1 == len(analysis.modified_initialsids) + assert "system:system:system:s0" == analysis.modified_initialsids[0].added_context + assert "removed_user:system:system:s0" == analysis.modified_initialsids[0].removed_context + + # + # fs_use_* + # + def test_added_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """Diff: added fs_uses.""" + lst = sorted(analysis.added_fs_uses) + assert 1 == len(lst) + + rule = lst[0] + assert FSURT.fs_use_xattr == rule.ruletype + assert "added_fsuse" == rule.fs + assert "system:object_r:system:s0" == rule.context + + def test_removed_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed fs_uses.""" + lst = sorted(analysis.removed_fs_uses) + assert 1 == len(lst) + + rule = lst[0] + assert FSURT.fs_use_task == rule.ruletype + assert "removed_fsuse" == rule.fs + assert "system:object_r:system:s0" == rule.context + + def test_modified_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified fs_uses.""" + lst = sorted(analysis.modified_fs_uses, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_context, removed_context = astuple(lst[0]) + assert FSURT.fs_use_trans == rule.ruletype + assert "modified_fsuse" == rule.fs + assert "added_user:object_r:system:s1" == added_context + assert "removed_user:object_r:system:s0" == removed_context + + # + # genfscon + # + def test_added_genfscons(self, analysis: setools.PolicyDifference) -> None: + """Diff: added genfscons.""" + lst = sorted(analysis.added_genfscons) + assert 2 == len(lst) + + rule = lst[0] + assert "added_genfs" == rule.fs + assert "/" == rule.path + assert "added_user:object_r:system:s0" == rule.context + + rule = lst[1] + assert "change_path" == rule.fs + assert "/new" == rule.path + assert "system:object_r:system:s0" == rule.context + + def test_removed_genfscons(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed genfscons.""" + lst = sorted(analysis.removed_genfscons) + assert 2 == len(lst) + + rule = lst[0] + assert "change_path" == rule.fs + assert "/old" == rule.path + assert "system:object_r:system:s0" == rule.context + + rule = lst[1] + assert "removed_genfs" == rule.fs + assert "/" == rule.path + assert "system:object_r:system:s0" == rule.context + + def test_modified_genfscons(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified genfscons.""" + lst = sorted(analysis.modified_genfscons, key=lambda x: x.rule) + assert 1 == len(lst) + + rule, added_context, removed_context = astuple(lst[0]) + assert "modified_genfs" == rule.fs + assert "/" == rule.path + assert "added_user:object_r:system:s0" == added_context + assert "removed_user:object_r:system:s0" == removed_context + + # + # level decl + # + def test_added_levels(self, analysis: setools.PolicyDifference) -> None: + """Diff: added levels.""" + lst = sorted(analysis.added_levels) + assert 1 == len(lst) + assert "s46:c0.c4" == lst[0] + + def test_removed_levels(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed levels.""" + lst = sorted(analysis.removed_levels) + assert 1 == len(lst) + assert "s47:c0.c4" == lst[0] + + def test_modified_levels(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified levels.""" + lst = sorted(analysis.modified_levels) + assert 2 == len(lst) + + level = lst[0] + assert "s40" == level.level.sensitivity + assert set(["c3"]) == level.added_categories + assert not level.removed_categories + + level = lst[1] + assert "s41" == level.level.sensitivity + assert not level.added_categories + assert set(["c4"]) == level.removed_categories + + # + # netifcon + # + def test_added_netifcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: added netifcons.""" + lst = sorted(analysis.added_netifcons) + assert 1 == len(lst) + + rule = lst[0] + assert "added_netif" == rule.netif + assert "system:object_r:system:s0" == rule.context + assert "system:object_r:system:s0" == rule.packet + + def test_removed_netifcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed netifcons.""" + lst = sorted(analysis.removed_netifcons) + assert 1 == len(lst) + + rule = lst[0] + assert "removed_netif" == rule.netif + assert "system:object_r:system:s0" == rule.context + assert "system:object_r:system:s0" == rule.packet + + def test_modified_netifcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified netifcons.""" + lst = sorted(analysis.modified_netifcons, key=lambda x: x.rule) + assert 3 == len(lst) + + # modified both contexts + rule, added_context, removed_context, added_packet, removed_packet = astuple(lst[0]) + assert "mod_both_netif" == rule.netif + assert "added_user:object_r:system:s0" == added_context + assert "removed_user:object_r:system:s0" == removed_context + assert "added_user:object_r:system:s0" == added_packet + assert "removed_user:object_r:system:s0" == removed_packet + + # modified context + rule, added_context, removed_context, added_packet, removed_packet = astuple(lst[1]) + assert "mod_ctx_netif" == rule.netif + assert "added_user:object_r:system:s0" == added_context + assert "removed_user:object_r:system:s0" == removed_context + assert added_packet is None + assert removed_packet is None + + # modified packet context + rule, added_context, removed_context, added_packet, removed_packet = astuple(lst[2]) + assert "mod_pkt_netif" == rule.netif + assert added_context is None + assert removed_context is None + assert "added_user:object_r:system:s0" == added_packet + assert "removed_user:object_r:system:s0" == removed_packet + + # + # nodecons + # + def test_added_nodecons(self, analysis: setools.PolicyDifference) -> None: + """Diff: added nodecons.""" + lst = sorted(analysis.added_nodecons) + assert 4 == len(lst) + + # new IPv4 + nodecon = lst[0] + assert IPv4Network("124.0.0.0/8") == nodecon.network + + # changed IPv4 netmask + nodecon = lst[1] + assert IPv4Network("125.0.0.0/16") == nodecon.network + + # new IPv6 + nodecon = lst[2] + assert IPv6Network("ff04::/62") == nodecon.network + + # changed IPv6 netmask + nodecon = lst[3] + assert IPv6Network("ff05::/60") == nodecon.network + + def test_removed_nodecons(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed nodecons.""" + lst = sorted(analysis.removed_nodecons) + assert 4 == len(lst) + + # new IPv4 + nodecon = lst[0] + assert IPv4Network("122.0.0.0/8") == nodecon.network + + # changed IPv4 netmask + nodecon = lst[1] + assert IPv4Network("125.0.0.0/8") == nodecon.network + + # new IPv6 + nodecon = lst[2] + assert IPv6Network("ff02::/62") == nodecon.network + + # changed IPv6 netmask + nodecon = lst[3] + assert IPv6Network("ff05::/62") == nodecon.network + + def test_modified_nodecons(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified nodecons.""" + lst = sorted(analysis.modified_nodecons, key=lambda x: x.rule) + assert 2 == len(lst) + + # changed IPv4 + nodecon, added_context, removed_context = astuple(lst[0]) + assert IPv4Network("123.0.0.0/8") == nodecon.network + assert "modified_change_level:object_r:system:s2:c0" == added_context + assert "modified_change_level:object_r:system:s2:c1" == removed_context + + # changed IPv6 + nodecon, added_context, removed_context = astuple(lst[1]) + assert IPv6Network("ff03::/62") == nodecon.network + assert "modified_change_level:object_r:system:s2:c1" == added_context + assert "modified_change_level:object_r:system:s2:c0.c1" == removed_context + + # + # Policy capabilities + # + def test_added_polcaps(self, analysis: setools.PolicyDifference) -> None: + """Diff: added polcaps.""" + assert set(["always_check_network"]) == analysis.added_polcaps + + def test_removed_polcaps(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed polcaps.""" + assert set(["network_peer_controls"]) == analysis.removed_polcaps + + # + # portcons + # + def test_added_portcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: added portcons.""" + lst = sorted(analysis.added_portcons) + assert 2 == len(lst) + + portcon = lst[0] + assert PortconProtocol.tcp == portcon.protocol + assert PortconRange(2024, 2026) == portcon.ports + + portcon = lst[1] + assert PortconProtocol.udp == portcon.protocol + assert PortconRange(2024, 2024) == portcon.ports + + def test_removed_portcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed portcons.""" + lst = sorted(analysis.removed_portcons) + assert 2 == len(lst) + + portcon = lst[0] + assert PortconProtocol.tcp == portcon.protocol + assert PortconRange(1024, 1026) == portcon.ports + + portcon = lst[1] + assert PortconProtocol.udp == portcon.protocol + assert PortconRange(1024, 1024) == portcon.ports + + def test_modified_portcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified portcons.""" + lst = sorted(analysis.modified_portcons, key=lambda x: x.rule) + assert 2 == len(lst) + + portcon, added_context, removed_context = astuple(lst[0]) + assert PortconProtocol.tcp == portcon.protocol + assert PortconRange(3024, 3026) == portcon.ports + assert "added_user:object_r:system:s1" == added_context + assert "removed_user:object_r:system:s0" == removed_context + + portcon, added_context, removed_context = astuple(lst[1]) + assert PortconProtocol.udp == portcon.protocol + assert PortconRange(3024, 3024) == portcon.ports + assert "added_user:object_r:system:s1" == added_context + assert "removed_user:object_r:system:s0" == removed_context + + # + # defaults + # + def test_added_defaults(self, analysis: setools.PolicyDifference) -> None: + """Diff: added defaults.""" + lst = sorted(analysis.added_defaults) + assert 2 == len(lst) + + default = lst[0] + assert DRT.default_range == default.ruletype + assert "infoflow2" == default.tclass + + default = lst[1] + assert DRT.default_user == default.ruletype + assert "infoflow2" == default.tclass + + def test_removed_defaults(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed defaults.""" + lst = sorted(analysis.removed_defaults) + assert 2 == len(lst) + + default = lst[0] + assert DRT.default_range == default.ruletype + assert "infoflow3" == default.tclass + + default = lst[1] + assert DRT.default_role == default.ruletype + assert "infoflow3" == default.tclass + + def test_modified_defaults(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified defaults.""" + lst = sorted(analysis.modified_defaults, key=lambda x: x.rule) + assert 4 == len(lst) + + default, added_default, removed_default, added_range, removed_range = astuple(lst[0]) + assert DRT.default_range == default.ruletype + assert "infoflow4" == default.tclass + assert DV.target == added_default + assert DV.source == removed_default + assert added_range is None + assert removed_range is None + + default, added_default, removed_default, added_range, removed_range = astuple(lst[1]) + assert DRT.default_range == default.ruletype + assert "infoflow5" == default.tclass + assert added_default is None + assert removed_default is None + assert DRV.high == added_range + assert DRV.low == removed_range + + default, added_default, removed_default, added_range, removed_range = astuple(lst[2]) + assert DRT.default_range == default.ruletype + assert "infoflow6" == default.tclass + assert DV.target == added_default + assert DV.source == removed_default + assert DRV.low == added_range + assert DRV.high == removed_range + + default, added_default, removed_default, added_range, removed_range = astuple(lst[3]) + assert DRT.default_type == default.ruletype + assert "infoflow4" == default.tclass + assert DV.target == added_default + assert DV.source == removed_default + assert added_range is None + assert removed_range is None + + # + # constrains + # + def test_added_constrains(self, analysis: setools.PolicyDifference) -> None: + """Diff: added constrains.""" + lst = sorted(analysis.added_constrains) + assert 2 == len(lst) + + constrain = lst[0] + assert CRT.constrain == constrain.ruletype + assert "infoflow3" == constrain.tclass + assert set(["null"]) == constrain.perms + assert ["u1", "u2", "!="] == constrain.expression + + constrain = lst[1] + assert CRT.constrain == constrain.ruletype + assert "infoflow5" == constrain.tclass + assert set(["hi_r"]) == constrain.perms + assert ['u1', 'u2', '==', 'r1', 'r2', '==', 'and', 't1', set(["system"]), '!=', 'or'] \ + == constrain.expression + + def test_removed_constrains(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed constrains.""" + lst = sorted(analysis.removed_constrains) + assert 2 == len(lst) + + constrain = lst[0] + assert CRT.constrain == constrain.ruletype + assert "infoflow4" == constrain.tclass + assert set(["hi_w"]) == constrain.perms + assert ["u1", "u2", "!="] == constrain.expression + + constrain = lst[1] + assert CRT.constrain == constrain.ruletype + assert "infoflow5" == constrain.tclass + assert set(["hi_r"]) == constrain.perms + assert ['u1', 'u2', '==', 'r1', 'r2', '==', 'and', 't1', set(["system"]), '==', 'or'] == \ + constrain.expression + + # + # mlsconstrains + # + def test_added_mlsconstrains(self, analysis: setools.PolicyDifference) -> None: + """Diff: added mlsconstrains.""" + lst = sorted(analysis.added_mlsconstrains) + assert 2 == len(lst) + + mlsconstrain = lst[0] + assert CRT.mlsconstrain == mlsconstrain.ruletype + assert "infoflow3" == mlsconstrain.tclass + assert set(["null"]) == mlsconstrain.perms + assert ['l1', 'l2', 'domby', 'h1', 'h2', 'domby', 'and', + 't1', set(["mls_exempt"]), '!=', 'or'] == mlsconstrain.expression + + mlsconstrain = lst[1] + assert CRT.mlsconstrain == mlsconstrain.ruletype + assert "infoflow5" == mlsconstrain.tclass + assert set(["hi_r"]) == mlsconstrain.perms + assert ['l1', 'l2', 'domby', 'h1', 'h2', 'incomp', + 'and', 't1', set(["mls_exempt"]), '==', 'or'] == mlsconstrain.expression + + def test_removed_mlsconstrains(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed mlsconstrains.""" + lst = sorted(analysis.removed_mlsconstrains) + assert 2 == len(lst) + + mlsconstrain = lst[0] + assert CRT.mlsconstrain == mlsconstrain.ruletype + assert "infoflow4" == mlsconstrain.tclass + assert set(["hi_w"]) == mlsconstrain.perms + assert ['l1', 'l2', 'domby', 'h1', 'h2', 'domby', 'and', + 't1', set(["mls_exempt"]), '==', 'or'] == mlsconstrain.expression + + mlsconstrain = lst[1] + assert CRT.mlsconstrain == mlsconstrain.ruletype + assert "infoflow5" == mlsconstrain.tclass + assert set(["hi_r"]) == mlsconstrain.perms + assert ['l1', 'l2', 'domby', 'h1', 'h2', 'dom', 'and', 't1', set(["mls_exempt"]), '==', + 'or'] == mlsconstrain.expression + + # + # validatetrans + # + def test_added_validatetrans(self, analysis: setools.PolicyDifference) -> None: + """Diff: added validatetrans.""" + lst = sorted(analysis.added_validatetrans) + assert 2 == len(lst) + + validatetrans = lst[0] + assert CRT.validatetrans == validatetrans.ruletype + assert "infoflow3" == validatetrans.tclass + assert ['t1', 't2', '==', 't3', set(["system"]), '==', 'or'] == validatetrans.expression + + validatetrans = lst[1] + assert CRT.validatetrans == validatetrans.ruletype + assert "infoflow5" == validatetrans.tclass + assert ['u1', 'u2', '!=', 'r1', 'r2', '==', 'and', 't3', set(["system"]), '==', 'or'] \ + == validatetrans.expression + + def test_removed_validatetrans(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed validatetrans.""" + lst = sorted(analysis.removed_validatetrans) + assert 2 == len(lst) + + validatetrans = lst[0] + assert CRT.validatetrans == validatetrans.ruletype + assert "infoflow4" == validatetrans.tclass + assert ['u1', 'u2', '==', 't3', set(["system"]), '==', 'or'] == validatetrans.expression + + validatetrans = lst[1] + assert CRT.validatetrans == validatetrans.ruletype + assert "infoflow5" == validatetrans.tclass + assert ['u1', 'u2', '==', 'r1', 'r2', '!=', 'and', 't3', set(["system"]), '==', 'or'] \ + == validatetrans.expression + + # + # mlsvalidatetrans + # + def test_added_mlsvalidatetrans(self, analysis: setools.PolicyDifference) -> None: + """Diff: added mlsvalidatetrans.""" + lst = sorted(analysis.added_mlsvalidatetrans) + assert 2 == len(lst) + + mlsvalidatetrans = lst[0] + assert CRT.mlsvalidatetrans == mlsvalidatetrans.ruletype + assert "infoflow3" == mlsvalidatetrans.tclass + assert ['l1', 'l2', '==', 'h1', 'h2', '==', 'and', 't3', set(["mls_exempt"]), '==', + 'or'] == mlsvalidatetrans.expression + + mlsvalidatetrans = lst[1] + assert CRT.mlsvalidatetrans == mlsvalidatetrans.ruletype + assert "infoflow5" == mlsvalidatetrans.tclass + assert ['l1', 'l2', 'incomp', 'h1', 'h2', 'domby', 'and', 't3', set(["mls_exempt"]), '==', + 'or'] == mlsvalidatetrans.expression + + def test_removed_mlsvalidatetrans(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed mlsvalidatetrans.""" + lst = sorted(analysis.removed_mlsvalidatetrans) + assert 2 == len(lst) + + mlsvalidatetrans = lst[0] + assert CRT.mlsvalidatetrans == mlsvalidatetrans.ruletype + assert "infoflow4" == mlsvalidatetrans.tclass + assert ['l1', 'l2', '==', 'h1', 'h2', '==', 'and', 't3', set(["mls_exempt"]), '==', + 'or'] == mlsvalidatetrans.expression + + mlsvalidatetrans = lst[1] + assert CRT.mlsvalidatetrans == mlsvalidatetrans.ruletype + assert "infoflow5" == mlsvalidatetrans.tclass + assert ['l1', 'l2', 'dom', 'h1', 'h2', 'dom', 'and', 't3', set(["mls_exempt"]), '==', + 'or'] == mlsvalidatetrans.expression + + # + # typebounds + # + def test_added_typebounds(self, analysis: setools.PolicyDifference) -> None: + """Diff: added typebounds.""" + lst = sorted(analysis.added_typebounds) + assert 1 == len(lst) + + bounds = lst[0] + assert BRT.typebounds == bounds.ruletype + assert "added_parent" == bounds.parent + assert "added_child" == bounds.child + + def test_removed_typebounds(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed typebounds.""" + lst = sorted(analysis.removed_typebounds) + assert 1 == len(lst) + + bounds = lst[0] + assert BRT.typebounds == bounds.ruletype + assert "removed_parent" == bounds.parent + assert "removed_child" == bounds.child + + def test_modified_typebounds(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified typebounds.""" + lst = sorted(analysis.modified_typebounds, key=lambda x: x.rule) + assert 1 == len(lst) + + bounds, added_bound, removed_bound = astuple(lst[0]) + assert BRT.typebounds == bounds.ruletype + assert "mod_child" == bounds.child + assert "mod_parent_added" == added_bound + assert "mod_parent_removed" == removed_bound + + # + # Allowxperm rules + # + def test_added_allowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added allowxperm rules.""" + rules = sorted(analysis.added_allowxperms) + assert 2 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], TRT.allowxperm, "added_type", "added_type", + tclass="infoflow7", perms=setools.IoctlSet([0x0009]), xperm="ioctl") + + # added rule with existing types + util.validate_rule(rules[1], TRT.allowxperm, "ax_added_rule_source", + "ax_added_rule_target", tclass="infoflow", + perms=setools.IoctlSet([0x0002]), xperm="ioctl") + + def test_removed_allowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed allowxperm rules.""" + rules = sorted(analysis.removed_allowxperms) + assert 2 == len(rules) + + # removed rule with existing types + util.validate_rule(rules[0], TRT.allowxperm, "ax_removed_rule_source", + "ax_removed_rule_target", tclass="infoflow", + perms=setools.IoctlSet([0x0002]), xperm="ioctl") + + # removed rule with new type + util.validate_rule(rules[1], TRT.allowxperm, "removed_type", "removed_type", + tclass="infoflow7", perms=setools.IoctlSet([0x0009]), xperm="ioctl") + + def test_modified_allowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified allowxperm rules.""" + lst = sorted(analysis.modified_allowxperms, key=lambda x: x.rule) + assert 3 == len(lst) + + # add permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) + assert TRT.allowxperm == rule.ruletype + assert "ax_modified_rule_add_perms" == rule.source + assert "ax_modified_rule_add_perms" == rule.target + assert "infoflow" == rule.tclass + assert setools.IoctlSet([0x000f]) == added_perms + assert not removed_perms + assert setools.IoctlSet([0x0004]) == matched_perms + + # add and remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) + assert TRT.allowxperm == rule.ruletype + assert "ax_modified_rule_add_remove_perms" == rule.source + assert "ax_modified_rule_add_remove_perms" == rule.target + assert "infoflow2" == rule.tclass + assert setools.IoctlSet([0x0006]) == added_perms + assert setools.IoctlSet([0x0007]) == removed_perms + assert setools.IoctlSet([0x0008]) == matched_perms + + # remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) + assert TRT.allowxperm == rule.ruletype + assert "ax_modified_rule_remove_perms" == rule.source + assert "ax_modified_rule_remove_perms" == rule.target + assert "infoflow" == rule.tclass + assert not added_perms + assert setools.IoctlSet([0x0006]) == removed_perms + assert setools.IoctlSet([0x0005]) == matched_perms + + # + # Auditallowxperm rules + # + def test_added_auditallowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added auditallowxperm rules.""" + rules = sorted(analysis.added_auditallowxperms) + assert 2 == len(rules) + + # added rule with existing types + util.validate_rule(rules[0], TRT.auditallowxperm, "aax_added_rule_source", + "aax_added_rule_target", tclass="infoflow", + perms=setools.IoctlSet([0x0002]), xperm="ioctl") + + # added rule with new type + util.validate_rule(rules[1], TRT.auditallowxperm, "added_type", "added_type", + tclass="infoflow7", perms=setools.IoctlSet([0x0009]), xperm="ioctl") + + def test_removed_auditallowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed auditallowxperm rules.""" + rules = sorted(analysis.removed_auditallowxperms) + assert 2 == len(rules) + + # removed rule with existing types + util.validate_rule(rules[0], TRT.auditallowxperm, "aax_removed_rule_source", + "aax_removed_rule_target", tclass="infoflow", + perms=setools.IoctlSet([0x0002]), xperm="ioctl") + + # removed rule with new type + util.validate_rule(rules[1], TRT.auditallowxperm, "removed_type", "removed_type", + tclass="infoflow7", perms=setools.IoctlSet([0x0009]), xperm="ioctl") + + def test_modified_auditallowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified auditallowxperm rules.""" + lst = sorted(analysis.modified_auditallowxperms, key=lambda x: x.rule) + assert 3 == len(lst) + + # add permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) + assert TRT.auditallowxperm == rule.ruletype + assert "aax_modified_rule_add_perms" == rule.source + assert "aax_modified_rule_add_perms" == rule.target + assert "infoflow" == rule.tclass + assert setools.IoctlSet([0x000f]) == added_perms + assert not removed_perms + assert setools.IoctlSet([0x0004]) == matched_perms + + # add and remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) + assert TRT.auditallowxperm == rule.ruletype + assert "aax_modified_rule_add_remove_perms" == rule.source + assert "aax_modified_rule_add_remove_perms" == rule.target + assert "infoflow2" == rule.tclass + assert setools.IoctlSet([0x0006]) == added_perms + assert setools.IoctlSet([0x0007]) == removed_perms + assert setools.IoctlSet([0x0008]) == matched_perms + + # remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) + assert TRT.auditallowxperm == rule.ruletype + assert "aax_modified_rule_remove_perms" == rule.source + assert "aax_modified_rule_remove_perms" == rule.target + assert "infoflow" == rule.tclass + assert not added_perms + assert setools.IoctlSet([0x0006]) == removed_perms + assert setools.IoctlSet([0x0005]) == matched_perms + + # + # Neverallowxperm rules + # + def test_added_neverallowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added neverallowxperm rules.""" + assert not analysis.added_neverallowxperms + # changed after dropping source policy support + # rules = sorted(analysis.added_neverallowxperms) + # assert 2 == len(rules) + # + # # added rule with new type + # util.validate_rule(rules[0], TRT.neverallowxperm, "added_type", "added_type", + # "infoflow7", setools.IoctlSet([0x0009]), xperm="ioctl") + # + # # added rule with existing types + # util.validate_rule(rules[1], TRT.neverallowxperm, "nax_added_rule_source", + # "nax_added_rule_target", "infoflow", setools.IoctlSet([0x0002]), + # xperm="ioctl") + + def test_removed_neverallowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed neverallowxperm rules.""" + assert not analysis.removed_neverallowxperms + # changed after dropping source policy support + # rules = sorted(analysis.removed_neverallowxperms) + # assert 2 == len(rules) + # + # # removed rule with existing types + # util.validate_rule(rules[0], TRT.neverallowxperm, "nax_removed_rule_source", + # "nax_removed_rule_target", "infoflow", setools.IoctlSet([0x0002]), + # xperm="ioctl") + # + # # removed rule with new type + # util.validate_rule(rules[1], TRT.neverallowxperm, "removed_type", "removed_type", + # "infoflow7", setools.IoctlSet([0x0009]), xperm="ioctl") + + def test_modified_neverallowxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified neverallowxperm rules.""" + assert not analysis.modified_neverallowxperms + # changed after dropping source policy support + # l = sorted(analysis.modified_neverallowxperms, key=lambda x: x.rule) + # assert 3 == len(l) + # + # # add permissions + # rule, added_perms, removed_perms, matched_perms = l[0] + # assert TRT.neverallowxperm == rule.ruletype + # assert "nax_modified_rule_add_perms" == rule.source + # assert "nax_modified_rule_add_perms" == rule.target + # assert "infoflow" == rule.tclass + # assert setools.IoctlSet([0x000f]) == added_perms + # assert not removed_perms + # assert setools.IoctlSet([0x0004]) == matched_perms + # + # # add and remove permissions + # rule, added_perms, removed_perms, matched_perms = l[1] + # assert TRT.neverallowxperm == rule.ruletype + # assert "nax_modified_rule_add_remove_perms" == rule.source + # assert "nax_modified_rule_add_remove_perms" == rule.target + # assert "infoflow2" == rule.tclass + # assert setools.IoctlSet([0x0006]) == added_perms + # assert setools.IoctlSet([0x0007]) == removed_perms + # assert setools.IoctlSet([0x0008]) == matched_perms + # + # # remove permissions + # rule, added_perms, removed_perms, matched_perms = l[2] + # assert TRT.neverallowxperm == rule.ruletype + # assert "nax_modified_rule_remove_perms" == rule.source + # assert "nax_modified_rule_remove_perms" == rule.target + # assert "infoflow" == rule.tclass + # assert not added_perms + # assert setools.IoctlSet([0x0006]) == removed_perms + # assert setools.IoctlSet([0x0005]) == matched_perms + + # + # Dontauditxperm rules + # + def test_added_dontauditxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: added dontauditxperm rules.""" + rules = sorted(analysis.added_dontauditxperms) + assert 2 == len(rules) + + # added rule with new type + util.validate_rule(rules[0], TRT.dontauditxperm, "added_type", "added_type", + tclass="infoflow7", perms=setools.IoctlSet([0x0009]), xperm="ioctl") + + # added rule with existing types + util.validate_rule(rules[1], TRT.dontauditxperm, "dax_added_rule_source", + "dax_added_rule_target", tclass="infoflow", + perms=setools.IoctlSet([0x0002]), xperm="ioctl") + + def test_removed_dontauditxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed dontauditxperm rules.""" + rules = sorted(analysis.removed_dontauditxperms) + assert 2 == len(rules) + + # removed rule with existing types + util.validate_rule(rules[0], TRT.dontauditxperm, "dax_removed_rule_source", + "dax_removed_rule_target", tclass="infoflow", + perms=setools.IoctlSet([0x0002]), xperm="ioctl") + + # removed rule with new type + util.validate_rule(rules[1], TRT.dontauditxperm, "removed_type", "removed_type", + tclass="infoflow7", perms=setools.IoctlSet([0x0009]), xperm="ioctl") + + def test_modified_dontauditxperm_rules(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified dontauditxperm rules.""" + lst = sorted(analysis.modified_dontauditxperms, key=lambda x: x.rule) + assert 3 == len(lst) + + # add permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) + assert TRT.dontauditxperm == rule.ruletype + assert "dax_modified_rule_add_perms" == rule.source + assert "dax_modified_rule_add_perms" == rule.target + assert "infoflow" == rule.tclass + assert setools.IoctlSet([0x000f]) == added_perms + assert not removed_perms + assert setools.IoctlSet([0x0004]) == matched_perms + + # add and remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) + assert TRT.dontauditxperm == rule.ruletype + assert "dax_modified_rule_add_remove_perms" == rule.source + assert "dax_modified_rule_add_remove_perms" == rule.target + assert "infoflow2" == rule.tclass + assert setools.IoctlSet([0x0006]) == added_perms + assert setools.IoctlSet([0x0007]) == removed_perms + assert setools.IoctlSet([0x0008]) == matched_perms + + # remove permissions + rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) + assert TRT.dontauditxperm == rule.ruletype + assert "dax_modified_rule_remove_perms" == rule.source + assert "dax_modified_rule_remove_perms" == rule.target + assert "infoflow" == rule.tclass + assert not added_perms + assert setools.IoctlSet([0x0006]) == removed_perms + assert setools.IoctlSet([0x0005]) == matched_perms + + # + # Ibendportcon statements + # + def test_added_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: added ibendportcon statements.""" + rules = sorted(analysis.added_ibendportcons) + assert 1 == len(rules) + assert "add" == rules[0].name + assert 23 == rules[0].port + assert "system:system:system:s0" == rules[0].context + + def test_removed_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed ibendportcon statements.""" + rules = sorted(analysis.removed_ibendportcons) + assert 1 == len(rules) + assert "removed" == rules[0].name + assert 7 == rules[0].port + assert "system:system:system:s0" == rules[0].context + + def test_modified_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified ibendportcon statements""" + rules = sorted(analysis.modified_ibendportcons) + assert 1 == len(rules) + + rule, added, removed = astuple(rules[0]) + assert "modified" == rule.name + assert 13 == rule.port + assert "modified_change_level:object_r:system:s2" == added + assert "modified_change_level:object_r:system:s2:c0.c1" == removed + + # + # Ibpkeycon statements + # + def test_added_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """Diff: added ibpkeycon statements.""" + rules = sorted(analysis.added_ibpkeycons) + assert 2 == len(rules) + + rule = rules[0] + assert IPv6Address("beef::") == rule.subnet_prefix + assert 0xe == rule.pkeys.low + assert 0xe == rule.pkeys.high + assert "system:system:system:s0" == rule.context + + rule = rules[1] + assert IPv6Address("dead::") == rule.subnet_prefix + assert 0xbeef == rule.pkeys.low + assert 0xdead == rule.pkeys.high + assert "system:system:system:s0" == rule.context + + def test_removed_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed ibpkeycon statements.""" + rules = sorted(analysis.removed_ibpkeycons) + assert 2 == len(rules) + + rule = rules[0] + assert IPv6Address("dccc::") == rule.subnet_prefix + assert 0xc == rule.pkeys.low + assert 0xc == rule.pkeys.high + assert "system:system:system:s0" == rule.context + + rule = rules[1] + assert IPv6Address("feee::") == rule.subnet_prefix + assert 0xaaaa == rule.pkeys.low + assert 0xbbbb == rule.pkeys.high + assert "system:system:system:s0" == rule.context + + def test_modified_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """Diff: modified ibpkeycon statements""" + rules = sorted(analysis.modified_ibpkeycons) + assert 2 == len(rules) + + rule, added, removed = astuple(rules[0]) + assert IPv6Address("aaaa::") == rule.subnet_prefix + assert 0xcccc == rule.pkeys.low + assert 0xdddd == rule.pkeys.high + assert "modified_change_level:object_r:system:s2:c0" == added + assert "modified_change_level:object_r:system:s2:c1" == removed + + rule, added, removed = astuple(rules[1]) + assert IPv6Address("bbbb::") == rule.subnet_prefix + assert 0xf == rule.pkeys.low + assert 0xf == rule.pkeys.high + assert "modified_change_level:object_r:system:s2:c1" == added + assert "modified_change_level:object_r:system:s2:c0.c1" == removed + + +@pytest.mark.obj_args("tests/library/diff_left.conf", "tests/library/diff_right_rmisid.conf") +class TestPolicyDifferenceRmIsid: + + """ + Policy difference test for removed initial SID. + + Since initial SID names are fixed (they don't exist in the binary policy) + this cannot be in the above test suite. + """ + + def test_removed_initialsids(self, analysis: setools.PolicyDifference) -> None: + """Diff: removed initialsids.""" + assert set(["file"]) == analysis.removed_initialsids + + +@pytest.mark.obj_args("tests/library/diff_left.conf", "tests/library/diff_left.conf") +class TestPolicyDifferenceTestNoDiff: + + """Policy difference test with no policy differences.""" + + def test_added_types(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added types""" + assert not analysis.added_types + + def test_removed_types(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed types""" + assert not analysis.removed_types + + def test_modified_types(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified types""" + assert not analysis.modified_types + + def test_added_roles(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added roles.""" + assert not analysis.added_roles + + def test_removed_roles(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed roles.""" + assert not analysis.removed_roles + + def test_modified_roles(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified roles.""" + assert not analysis.modified_roles + + def test_added_commons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added commons.""" + assert not analysis.added_commons + + def test_removed_commons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed commons.""" + assert not analysis.removed_commons + + def test_modified_commons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified commons.""" + assert not analysis.modified_commons + + def test_added_classes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added classes.""" + assert not analysis.added_classes + + def test_removed_classes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed classes.""" + assert not analysis.removed_classes + + def test_modified_classes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified classes.""" + assert not analysis.modified_classes + + def test_added_allows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added allow rules.""" + assert not analysis.added_allows + + def test_removed_allows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed allow rules.""" + assert not analysis.removed_allows + + def test_modified_allows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified allow rules.""" + assert not analysis.modified_allows + + def test_added_auditallows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added auditallow rules.""" + assert not analysis.added_auditallows + + def test_removed_auditallows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed auditallow rules.""" + assert not analysis.removed_auditallows + + def test_modified_auditallows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified auditallow rules.""" + assert not analysis.modified_auditallows + + def test_added_neverallows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added neverallow rules.""" + assert not analysis.added_neverallows + + def test_removed_neverallows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed neverallow rules.""" + assert not analysis.removed_neverallows + + def test_modified_neverallows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified neverallow rules.""" + assert not analysis.modified_neverallows + + def test_added_dontaudits(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added dontaudit rules.""" + assert not analysis.added_dontaudits + + def test_removed_dontaudits(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed dontaudit rules.""" + assert not analysis.removed_dontaudits + + def test_modified_dontaudits(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified dontaudit rules.""" + assert not analysis.modified_dontaudits + + def test_added_type_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added type_transition rules.""" + assert not analysis.added_type_transitions + + def test_removed_type_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed type_transition rules.""" + assert not analysis.removed_type_transitions + + def test_modified_type_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified type_transition rules.""" + assert not analysis.modified_type_transitions + + def test_added_type_changes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added type_change rules.""" + assert not analysis.added_type_changes + + def test_removed_type_changes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed type_change rules.""" + assert not analysis.removed_type_changes + + def test_modified_type_changes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified type_change rules.""" + assert not analysis.modified_type_changes + + def test_added_type_members(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added type_member rules.""" + assert not analysis.added_type_members + + def test_removed_type_members(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed type_member rules.""" + assert not analysis.removed_type_members + + def test_modified_type_members(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified type_member rules.""" + assert not analysis.modified_type_members + + def test_added_range_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added range_transition rules.""" + assert not analysis.added_range_transitions + + def test_removed_range_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed range_transition rules.""" + assert not analysis.removed_range_transitions + + def test_modified_range_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified range_transition rules.""" + assert not analysis.modified_range_transitions + + def test_added_role_allows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added role_allow rules.""" + assert not analysis.added_role_allows + + def test_removed_role_allows(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed role_allow rules.""" + assert not analysis.removed_role_allows + + def test_added_role_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added role_transition rules.""" + assert not analysis.added_role_transitions + + def test_removed_role_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed role_transition rules.""" + assert not analysis.removed_role_transitions + + def test_modified_role_transitions(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified role_transition rules.""" + assert not analysis.modified_role_transitions + + def test_added_users(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added users.""" + assert not analysis.added_users + + def test_removed_users(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed users.""" + assert not analysis.removed_users + + def test_modified_users(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified user rules.""" + assert not analysis.modified_users + + def test_added_type_attributes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added type attribute.""" + assert not analysis.added_type_attributes + + def test_removed_type_attributes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed type attributes.""" + assert not analysis.removed_type_attributes + + def test_modified_type_attributes(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified type attributes.""" + assert not analysis.modified_type_attributes + + def test_added_booleans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added booleans.""" + assert not analysis.added_booleans + + def test_removed_booleans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed booleans.""" + assert not analysis.removed_booleans + + def test_modified_booleans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified booleans.""" + assert not analysis.modified_booleans + + def test_added_categories(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added categories.""" + assert not analysis.added_categories + + def test_removed_categories(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed categories.""" + assert not analysis.removed_categories + + def test_modified_categories(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified categories.""" + assert not analysis.modified_categories + + def test_added_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added sensitivities.""" + assert not analysis.added_sensitivities + + def test_removed_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed sensitivities.""" + assert not analysis.removed_sensitivities + + def test_modified_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified sensitivities.""" + assert not analysis.modified_sensitivities + + def test_added_initialsids(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added initialsids.""" + assert not analysis.added_initialsids + + def test_removed_initialsids(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed initialsids.""" + assert not analysis.removed_initialsids + + def test_modified_initialsids(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified initialsids.""" + assert not analysis.modified_initialsids + + def test_added_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added fs_uses.""" + assert not analysis.added_fs_uses + + def test_removed_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed fs_uses.""" + assert not analysis.removed_fs_uses + + def test_modified_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified fs_uses.""" + assert not analysis.modified_fs_uses + + def test_added_genfscons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added genfscons.""" + assert not analysis.added_genfscons + + def test_removed_genfscons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed genfscons.""" + assert not analysis.removed_genfscons + + def test_modified_genfscons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified genfscons.""" + assert not analysis.modified_genfscons + + def test_added_levels(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added levels.""" + assert not analysis.added_levels + + def test_removed_levels(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed levels.""" + assert not analysis.removed_levels + + def test_modified_levels(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified levels.""" + assert not analysis.modified_levels + + def test_added_netifcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added netifcons.""" + assert not analysis.added_netifcons + + def test_removed_netifcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed netifcons.""" + assert not analysis.removed_netifcons + + def test_modified_netifcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified netifcons.""" + assert not analysis.modified_netifcons + + def test_added_nodecons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added nodecons.""" + assert not analysis.added_nodecons + + def test_removed_nodecons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed nodecons.""" + assert not analysis.removed_nodecons + + def test_modified_nodecons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified nodecons.""" + assert not analysis.modified_nodecons + + def test_added_polcaps(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added polcaps.""" + assert not analysis.added_polcaps + + def test_removed_polcaps(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed polcaps.""" + assert not analysis.removed_polcaps + + def test_added_portcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added portcons.""" + assert not analysis.added_portcons + + def test_removed_portcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed portcons.""" + assert not analysis.removed_portcons + + def test_modified_portcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified portcons.""" + assert not analysis.modified_portcons + + def test_modified_properties(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified properties.""" + assert not analysis.modified_properties + + def test_added_defaults(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added defaults.""" + assert not analysis.added_defaults + + def test_removed_defaults(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed defaults.""" + assert not analysis.removed_defaults + + def test_modified_defaults(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified defaults.""" + assert not analysis.modified_defaults + + def test_added_constrains(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added constrains.""" + assert not analysis.added_constrains + + def test_removed_constrains(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed constrains.""" + assert not analysis.removed_constrains + + def test_added_mlsconstrains(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added mlsconstrains.""" + assert not analysis.added_mlsconstrains + + def test_removed_mlsconstrains(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed mlsconstrains.""" + assert not analysis.removed_mlsconstrains + + def test_added_validatetrans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added validatetrans.""" + assert not analysis.added_validatetrans + + def test_removed_validatetrans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed validatetrans.""" + assert not analysis.removed_validatetrans + + def test_added_mlsvalidatetrans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added mlsvalidatetrans.""" + assert not analysis.added_mlsvalidatetrans + + def test_removed_mlsvalidatetrans(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed mlsvalidatetrans.""" + assert not analysis.removed_mlsvalidatetrans + + def test_added_typebounds(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added typebounds.""" + assert not analysis.added_typebounds + + def test_removed_typebounds(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed typebounds.""" + assert not analysis.removed_typebounds + + def test_modified_typebounds(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified typebounds.""" + assert not analysis.modified_typebounds + + def test_added_allowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added allowxperm rules.""" + assert not analysis.added_allowxperms + + def test_removed_allowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed allowxperm rules.""" + assert not analysis.removed_allowxperms + + def test_modified_allowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified allowxperm rules.""" + assert not analysis.modified_allowxperms + + def test_added_auditallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added auditallowxperm rules.""" + assert not analysis.added_auditallowxperms + + def test_removed_auditallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed auditallowxperm rules.""" + assert not analysis.removed_auditallowxperms + + def test_modified_auditallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified auditallowxperm rules.""" + assert not analysis.modified_auditallowxperms + + def test_added_neverallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added neverallowxperm rules.""" + assert not analysis.added_neverallowxperms + + def test_removed_neverallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed neverallowxperm rules.""" + assert not analysis.removed_neverallowxperms + + def test_modified_neverallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified neverallowxperm rules.""" + assert not analysis.modified_neverallowxperms + + def test_added_dontauditxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added dontauditxperm rules.""" + assert not analysis.added_dontauditxperms + + def test_removed_dontauditxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed dontauditxperm rules.""" + assert not analysis.removed_dontauditxperms + + def test_modified_dontauditxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified dontauditxperm rules.""" + assert not analysis.modified_dontauditxperms + + def test_added_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added ibendportcon rules.""" + assert not analysis.added_ibendportcons + + def test_removed_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed ibendportcon rules.""" + assert not analysis.removed_ibendportcons + + def test_modified_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified ibendportcon rules.""" + assert not analysis.modified_ibendportcons + + def test_added_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added ibpkeycon rules.""" + assert not analysis.added_ibpkeycons + + def test_removed_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed ibpkeycon rules.""" + assert not analysis.removed_ibpkeycons + + def test_modified_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified ibpkeycon rules.""" + assert not analysis.modified_ibpkeycons + + +@pytest.mark.obj_args("tests/library/diff_left.conf", "tests/library/diff_left_standard.conf", + mls_right=False) +class TestPolicyDifferenceTestMLStoStandard: + + """ + Policy difference test between MLS and standard (non-MLS) policy. + + The left policy is an MLS policy. The right policy is identical to the + left policy, except with MLS disabled. + """ + + def test_added_types(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added types""" + assert not analysis.added_types + + def test_removed_types(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed types""" + assert not analysis.removed_types + + def test_modified_types(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified types""" + assert not analysis.modified_types + + def test_added_roles(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added roles.""" + assert not analysis.added_roles + + def test_removed_roles(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed roles.""" + assert not analysis.removed_roles + + def test_modified_roles(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified roles.""" + assert not analysis.modified_roles + + def test_added_commons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added commons.""" + assert not analysis.added_commons + + def test_removed_commons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed commons.""" + assert not analysis.removed_commons + + def test_modified_commons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified commons.""" + assert not analysis.modified_commons + + def test_added_classes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added classes.""" + assert not analysis.added_classes + + def test_removed_classes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed classes.""" + assert not analysis.removed_classes + + def test_modified_classes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified classes.""" + assert not analysis.modified_classes + + def test_added_allows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added allow rules.""" + assert not analysis.added_allows + + def test_removed_allows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed allow rules.""" + assert not analysis.removed_allows + + def test_modified_allows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified allow rules.""" + assert not analysis.modified_allows + + def test_added_auditallows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added auditallow rules.""" + assert not analysis.added_auditallows + + def test_removed_auditallows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed auditallow rules.""" + assert not analysis.removed_auditallows + + def test_modified_auditallows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified auditallow rules.""" + assert not analysis.modified_auditallows + + def test_added_neverallows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added neverallow rules.""" + assert not analysis.added_neverallows + + def test_removed_neverallows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed neverallow rules.""" + assert not analysis.removed_neverallows + + def test_modified_neverallows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified neverallow rules.""" + assert not analysis.modified_neverallows + + def test_added_dontaudits(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added dontaudit rules.""" + assert not analysis.added_dontaudits + + def test_removed_dontaudits(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed dontaudit rules.""" + assert not analysis.removed_dontaudits + + def test_modified_dontaudits(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified dontaudit rules.""" + assert not analysis.modified_dontaudits + + def test_added_type_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added type_transition rules.""" + assert not analysis.added_type_transitions + + def test_removed_type_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed type_transition rules.""" + assert not analysis.removed_type_transitions + + def test_modified_type_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified type_transition rules.""" + assert not analysis.modified_type_transitions + + def test_added_type_changes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added type_change rules.""" + assert not analysis.added_type_changes + + def test_removed_type_changes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed type_change rules.""" + assert not analysis.removed_type_changes + + def test_modified_type_changes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified type_change rules.""" + assert not analysis.modified_type_changes + + def test_added_type_members(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added type_member rules.""" + assert not analysis.added_type_members + + def test_removed_type_members(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed type_member rules.""" + assert not analysis.removed_type_members + + def test_modified_type_members(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified type_member rules.""" + assert not analysis.modified_type_members + + def test_added_range_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added range_transition rules.""" + assert not analysis.added_range_transitions + + def test_removed_range_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all range_transition rules removed.""" + assert analysis.left_policy.range_transition_count == \ + len(analysis.removed_range_transitions) + + def test_modified_range_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified range_transition rules.""" + assert not analysis.modified_range_transitions + + def test_added_role_allows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added role_allow rules.""" + assert not analysis.added_role_allows + + def test_removed_role_allows(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed role_allow rules.""" + assert not analysis.removed_role_allows + + def test_added_role_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added role_transition rules.""" + assert not analysis.added_role_transitions + + def test_removed_role_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed role_transition rules.""" + assert not analysis.removed_role_transitions + + def test_modified_role_transitions(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified role_transition rules.""" + assert not analysis.modified_role_transitions + + def test_added_users(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added users.""" + assert not analysis.added_users + + def test_removed_users(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed users.""" + assert not analysis.removed_users + + def test_modified_users(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all users modified.""" + assert analysis.left_policy.user_count == len(analysis.modified_users) + + def test_added_type_attributes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added type attribute.""" + assert not analysis.added_type_attributes + + def test_removed_type_attributes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed type attributes.""" + assert not analysis.removed_type_attributes + + def test_modified_type_attributes(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified type attributes.""" + assert not analysis.modified_type_attributes + + def test_added_booleans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added booleans.""" + assert not analysis.added_booleans + + def test_removed_booleans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed booleans.""" + assert not analysis.removed_booleans + + def test_modified_booleans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified booleans.""" + assert not analysis.modified_booleans + + def test_added_categories(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added categories.""" + assert not analysis.added_categories + + def test_removed_categories(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all categories removed.""" + assert analysis.left_policy.category_count == len(analysis.removed_categories) + + def test_modified_categories(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified categories.""" + assert not analysis.modified_categories + + def test_added_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added sensitivities.""" + assert not analysis.added_sensitivities + + def test_removed_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all sensitivities removed.""" + assert analysis.left_policy.level_count == len(analysis.removed_sensitivities) + + def test_modified_sensitivities(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified sensitivities.""" + assert not analysis.modified_sensitivities + + def test_added_initialsids(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added initialsids.""" + assert not analysis.added_initialsids + + def test_removed_initialsids(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed initialsids.""" + assert not analysis.removed_initialsids + + def test_modified_initialsids(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all initialsids modified.""" + assert analysis.left_policy.initialsids_count == len(analysis.modified_initialsids) + + def test_added_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added fs_uses.""" + assert not analysis.added_fs_uses + + def test_removed_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed fs_uses.""" + assert not analysis.removed_fs_uses + + def test_modified_fs_uses(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all fs_uses modified.""" + assert analysis.left_policy.fs_use_count == len(analysis.modified_fs_uses) + + def test_added_genfscons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added genfscons.""" + assert not analysis.added_genfscons + + def test_removed_genfscons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed genfscons.""" + assert not analysis.removed_genfscons + + def test_modified_genfscons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all genfscons modified.""" + assert analysis.left_policy.genfscon_count == len(analysis.modified_genfscons) + + def test_added_levels(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added levels.""" + assert not analysis.added_levels + + def test_removed_levels(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all levels removed.""" + assert analysis.left_policy.level_count == len(analysis.removed_levels) + + def test_modified_levels(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified levels.""" + assert not analysis.modified_levels + + def test_added_netifcons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added netifcons.""" + assert not analysis.added_netifcons + + def test_removed_netifcons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed netifcons.""" + assert not analysis.removed_netifcons + + def test_modified_netifcons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all netifcons modified.""" + assert analysis.left_policy.netifcon_count == len(analysis.modified_netifcons) + + def test_added_nodecons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added nodecons.""" + assert not analysis.added_nodecons + + def test_removed_nodecons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed nodecons.""" + assert not analysis.removed_nodecons + + def test_modified_nodecons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all nodecons modified.""" + assert analysis.left_policy.nodecon_count == len(analysis.modified_nodecons) + + def test_added_polcaps(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added polcaps.""" + assert not analysis.added_polcaps + + def test_removed_polcaps(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed polcaps.""" + assert not analysis.removed_polcaps + + def test_added_portcons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added portcons.""" + assert not analysis.added_portcons + + def test_removed_portcons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed portcons.""" + assert not analysis.removed_portcons + + def test_modified_portcons(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all portcons modified.""" + assert analysis.left_policy.portcon_count == len(analysis.modified_portcons) + + def test_modified_properties(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: MLS property modified only.""" + assert 1 == len(analysis.modified_properties) + + name, added, removed = astuple(analysis.modified_properties[0]) + assert "MLS" == name + assert added is False + assert removed is True + + def test_added_defaults(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added defaults.""" + assert not analysis.added_defaults + + def test_removed_defaults(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all default_range removed.""" + assert sum(1 for d in analysis.left_policy.defaults() if d.ruletype == DRT.default_range) \ + == len(analysis.removed_defaults) + + def test_modified_defaults(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no defaults modified.""" + assert not analysis.modified_defaults + + def test_added_constraints(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added constraints.""" + assert not analysis.added_constrains + + def test_removed_constraints(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed constraints.""" + assert not analysis.removed_constrains + + def test_added_validatetrans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added validatetrans.""" + assert not analysis.added_validatetrans + + def test_removed_validatetrans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed validatetrans.""" + assert not analysis.removed_validatetrans + + def test_added_mlsconstraints(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added mlsconstraints.""" + assert not analysis.added_mlsconstrains + + def test_removed_mlsconstraints(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all mlsconstraints removed.""" + assert sum(1 for m in analysis.left_policy.constraints() if + m.ruletype == CRT.mlsconstrain) == len(analysis.removed_mlsconstrains) + + def test_added_mlsvalidatetrans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added mlsvalidatetrans.""" + assert not analysis.added_mlsvalidatetrans + + def test_removed_mlsvalidatetrans(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: all mlsvalidatetrans removed.""" + assert sum(1 for m in analysis.left_policy.constraints() + if m.ruletype == CRT.mlsvalidatetrans) == \ + len(analysis.removed_mlsvalidatetrans) + + def test_added_typebounds(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no added typebounds.""" + assert not analysis.added_typebounds + + def test_removed_typebounds(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no removed typebounds.""" + assert not analysis.removed_typebounds + + def test_modified_typebounds(self, analysis: setools.PolicyDifference) -> None: + """MLSvsStandardDiff: no modified typebounds.""" + assert not analysis.modified_typebounds + + def test_added_allowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added allowxperm rules.""" + assert not analysis.added_allowxperms + + def test_removed_allowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed allowxperm rules.""" + assert not analysis.removed_allowxperms + + def test_modified_allowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified allowxperm rules.""" + assert not analysis.modified_allowxperms + + def test_added_auditallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added auditallowxperm rules.""" + assert not analysis.added_auditallowxperms + + def test_removed_auditallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed auditallowxperm rules.""" + assert not analysis.removed_auditallowxperms + + def test_modified_auditallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified auditallowxperm rules.""" + assert not analysis.modified_auditallowxperms + + def test_added_neverallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added neverallowxperm rules.""" + assert not analysis.added_neverallowxperms + + def test_removed_neverallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed neverallowxperm rules.""" + assert not analysis.removed_neverallowxperms + + def test_modified_neverallowxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified neverallowxperm rules.""" + assert not analysis.modified_neverallowxperms + + def test_added_dontauditxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added dontauditxperm rules.""" + assert not analysis.added_dontauditxperms + + def test_removed_dontauditxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed dontauditxperm rules.""" + assert not analysis.removed_dontauditxperms + + def test_modified_dontauditxperms(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified dontauditxperm rules.""" + assert not analysis.modified_dontauditxperms + + def test_added_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added ibpkeycon rules.""" + assert not analysis.added_ibpkeycons + + def test_removed_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed ibpkeycon rules.""" + assert not analysis.removed_ibpkeycons + + def test_modified_ibpkeycons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified ibpkeycon rules.""" + assert analysis.left_policy.ibpkeycon_count == len(analysis.modified_ibpkeycons) + + def test_added_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no added ibendportcon rules.""" + assert not analysis.added_ibendportcons + + def test_removed_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no removed ibendportcon rules.""" + assert not analysis.removed_ibendportcons + + def test_modified_ibendportcons(self, analysis: setools.PolicyDifference) -> None: + """NoDiff: no modified ibendportcon rules.""" + assert analysis.left_policy.ibendportcon_count == len(analysis.modified_ibendportcons) + + +@pytest.mark.obj_args("tests/library/diff_left.conf", "tests/library/diff_left_redundant.conf") +class TestPolicyDifferenceTestRedundant: + + """ + Policy difference test with redundant rules. + There should be no policy differences. + """ + + def test_added_allows(self, analysis: setools.PolicyDifference) -> None: + """Redundant: no added allow rules.""" + assert not analysis.added_allows + + def test_removed_allows(self, analysis: setools.PolicyDifference) -> None: + """Redundant: no removed allow rules.""" + assert not analysis.removed_allows + + def test_modified_allows(self, analysis: setools.PolicyDifference) -> None: + """Redundant: no modified allow rules.""" + assert not analysis.modified_allows diff --git a/tests/library/test_dta.py b/tests/library/test_dta.py new file mode 100644 index 00000000..69536c7c --- /dev/null +++ b/tests/library/test_dta.py @@ -0,0 +1,902 @@ +# Copyright 2014-2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import typing + +import pytest +import setools +from setools import TERuletype as TERT + +from . import util + + +@pytest.fixture +def analysis(compiled_policy: setools.SELinuxPolicy) -> setools.DomainTransitionAnalysis: + ret = setools.DomainTransitionAnalysis(compiled_policy) + ret._build_graph() + return ret + + +@pytest.mark.obj_args("tests/library/dta.conf") +class TestDomainTransitionAnalysis: + + def test_graph_structure(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: verify graph structure.""" + # don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + start = analysis.policy.lookup_type("start") + trans1 = analysis.policy.lookup_type("trans1") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.G.out_edges()) + assert set([(dyntrans100, bothtrans200), + (start, dyntrans100), + (start, trans1), + (trans1, trans2), + (trans2, trans3), + (trans3, trans5)]) == edges + + def test_bothtrans(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: type_transition, setexeccon(), and setcon() transitions.""" + + s = analysis.policy.lookup_type("dyntrans100") + t = analysis.policy.lookup_type("bothtrans200") + e = analysis.policy.lookup_type("bothtrans200_exec") + + # regular transition + r = analysis.G.edges[s, t]["transition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", + perms=set(["transition", "dyntransition"])) + + # setexec perms + r = analysis.G.edges[s, t]["setexec"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, s, tclass="process", + perms=set(["setexec", "setcurrent"])) + + # exec perms + k = sorted(analysis.G.edges[s, t]["execute"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["execute"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, e, tclass="file", perms=set(["execute"])) + + # entrypoint perms + k = sorted(analysis.G.edges[s, t]["entrypoint"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["entrypoint"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, t, e, tclass="file", perms=set(["entrypoint"])) + + # type_transition + k = sorted(analysis.G.edges[s, t]["type_transition"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["type_transition"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.type_transition, s, e, tclass="process", default=t) + + # dynamic transition + r = analysis.G.edges[s, t]["dyntransition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", + perms=set(["transition", "dyntransition"])) + + # setcurrent + r = analysis.G.edges[s, t]["setcurrent"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, s, tclass="process", + perms=set(["setexec", "setcurrent"])) + + def test_dyntrans(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: setcon() transition.""" + + s = analysis.policy.lookup_type("start") + t = analysis.policy.lookup_type("dyntrans100") + + # regular transition + r = analysis.G.edges[s, t]["transition"] + assert len(r) == 0 + + # setexec perms + r = analysis.G.edges[s, t]["setexec"] + assert len(r) == 0 + + # exec perms + k = sorted(analysis.G.edges[s, t]["execute"].keys()) + assert len(k) == 0 + + # entrypoint perms + k = sorted(analysis.G.edges[s, t]["entrypoint"].keys()) + assert len(k) == 0 + + # type_transition + k = sorted(analysis.G.edges[s, t]["type_transition"].keys()) + assert len(k) == 0 + + # dynamic transition + r = analysis.G.edges[s, t]["dyntransition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", + perms=set(["dyntransition"])) + + # setcurrent + r = analysis.G.edges[s, t]["setcurrent"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, s, tclass="process", + perms=set(["setcurrent"])) + + def test_trans(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: type_transition transition.""" + + s = analysis.policy.lookup_type("start") + t = analysis.policy.lookup_type("trans1") + e = analysis.policy.lookup_type("trans1_exec") + + # regular transition + r = analysis.G.edges[s, t]["transition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", + perms=set(["transition"])) + + # setexec perms + r = analysis.G.edges[s, t]["setexec"] + assert len(r) == 0 + + # exec perms + k = sorted(analysis.G.edges[s, t]["execute"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["execute"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, e, tclass="file", + perms=set(["execute"])) + + # entrypoint perms + k = sorted(analysis.G.edges[s, t]["entrypoint"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["entrypoint"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, t, e, tclass="file", + perms=set(["entrypoint"])) + + # type_transition + k = sorted(analysis.G.edges[s, t]["type_transition"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["type_transition"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.type_transition, s, e, tclass="process", + default=t) + + # dynamic transition + r = analysis.G.edges[s, t]["dyntransition"] + assert len(r) == 0 + + # setcurrent + r = analysis.G.edges[s, t]["setcurrent"] + assert len(r) == 0 + + def test_setexec(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: setexec() transition.""" + + s = analysis.policy.lookup_type("trans1") + t = analysis.policy.lookup_type("trans2") + e = analysis.policy.lookup_type("trans2_exec") + + # regular transition + r = analysis.G.edges[s, t]["transition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", perms=set(["transition"])) + + # setexec perms + r = analysis.G.edges[s, t]["setexec"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, s, tclass="process", perms=set(["setexec"])) + + # exec perms + k = sorted(analysis.G.edges[s, t]["execute"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["execute"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, e, tclass="file", perms=set(["execute"])) + + # entrypoint perms + k = sorted(analysis.G.edges[s, t]["entrypoint"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["entrypoint"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, t, e, tclass="file", perms=set(["entrypoint"])) + + # type_transition + k = sorted(analysis.G.edges[s, t]["type_transition"].keys()) + assert len(k) == 0 + + # dynamic transition + r = analysis.G.edges[s, t]["dyntransition"] + assert len(r) == 0 + + # setcurrent + r = analysis.G.edges[s, t]["setcurrent"] + assert len(r) == 0 + + def test_two_entrypoint(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: 2 entrypoints, only one by type_transition.""" + + s = analysis.policy.lookup_type("trans2") + t = analysis.policy.lookup_type("trans3") + e = [analysis.policy.lookup_type("trans3_exec1"), + analysis.policy.lookup_type("trans3_exec2")] + + # regular transition + r = analysis.G.edges[s, t]["transition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", perms=set(["transition"])) + + # setexec perms + r = analysis.G.edges[s, t]["setexec"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, s, tclass="process", perms=set(["setexec"])) + + # exec perms + k = sorted(analysis.G.edges[s, t]["execute"].keys()) + assert k == e + + r = analysis.G.edges[s, t]["execute"][e[0]] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, e[0], tclass="file", perms=set(["execute"])) + + r = analysis.G.edges[s, t]["execute"][e[1]] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, e[1], tclass="file", perms=set(["execute"])) + + # entrypoint perms + k = sorted(analysis.G.edges[s, t]["entrypoint"].keys()) + assert k == e + + r = analysis.G.edges[s, t]["entrypoint"][e[0]] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, t, e[0], tclass="file", perms=set(["entrypoint"])) + + r = analysis.G.edges[s, t]["entrypoint"][e[1]] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, t, e[1], tclass="file", perms=set(["entrypoint"])) + + # type_transition + k = sorted(analysis.G.edges[s, t]["type_transition"].keys()) + assert k == [e[0]] + + r = analysis.G.edges[s, t]["type_transition"][e[0]] + assert len(r) == 1 + util.validate_rule(r[0], TERT.type_transition, s, e[0], tclass="process", default=t) + + # dynamic transition + r = analysis.G.edges[s, t]["dyntransition"] + assert len(r) == 0 + + # setcurrent + r = analysis.G.edges[s, t]["setcurrent"] + assert len(r) == 0 + + def test_cond_type_trans(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: conditional type_transition.""" + + s = analysis.policy.lookup_type("trans3") + t = analysis.policy.lookup_type("trans5") + e = analysis.policy.lookup_type("trans5_exec") + + # regular transition + r = analysis.G.edges[s, t]["transition"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, t, tclass="process", perms=set(["transition"])) + + # setexec perms + r = analysis.G.edges[s, t]["setexec"] + assert len(r) == 0 + + # exec perms + k = sorted(analysis.G.edges[s, t]["execute"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["execute"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, s, e, tclass="file", perms=set(["execute"])) + + # entrypoint perms + k = sorted(analysis.G.edges[s, t]["entrypoint"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["entrypoint"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, t, e, tclass="file", perms=set(["entrypoint"])) + + # type_transition + k = sorted(analysis.G.edges[s, t]["type_transition"].keys()) + assert k == [e] + + r = analysis.G.edges[s, t]["type_transition"][e] + assert len(r) == 1 + util.validate_rule(r[0], TERT.type_transition, s, e, tclass="process", default=t, + cond="trans5", cond_block=True) + + # dynamic transition + r = analysis.G.edges[s, t]["dyntransition"] + assert len(r) == 0 + + # setcurrent + r = analysis.G.edges[s, t]["setcurrent"] + assert len(r) == 0 + + def test_forward_subgraph_structure(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: verify forward subgraph structure.""" + # The purpose is to ensure the subgraph is reversed + # only when the reverse option is set, not that + # graph reversal is correct (assumed that NetworkX + # does it correctly). + # Don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + analysis.reverse = False + analysis._build_subgraph() + + start = analysis.policy.lookup_type("start") + trans1 = analysis.policy.lookup_type("trans1") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.subG.out_edges()) + assert set([(dyntrans100, bothtrans200), + (start, dyntrans100), + (start, trans1), + (trans1, trans2), + (trans2, trans3), + (trans3, trans5)]) == edges + + def test_reverse_subgraph_structure(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: verify reverse subgraph structure.""" + # The purpose is to ensure the subgraph is reversed + # only when the reverse option is set, not that + # graph reversal is correct (assumed that NetworkX + # does it correctly). + # Don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + analysis.reverse = True + analysis._build_subgraph() + + start = analysis.policy.lookup_type("start") + trans1 = analysis.policy.lookup_type("trans1") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.subG.out_edges()) + assert set([(bothtrans200, dyntrans100), + (dyntrans100, start), + (trans1, start), + (trans2, trans1), + (trans3, trans2), + (trans5, trans3)]) == edges + + def test_exclude_domain(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: exclude domain type.""" + # Don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + analysis.reverse = False + analysis.exclude = ["trans1"] # type: ignore[list-item] + analysis._build_subgraph() + + start = analysis.policy.lookup_type("start") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.subG.out_edges()) + assert set([(dyntrans100, bothtrans200), + (start, dyntrans100), + (trans2, trans3), + (trans3, trans5)]) == edges + + def test_exclude_entryoint_with_2entrypoints( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: exclude entrypoint type without transition deletion (other entrypoints).""" + # Don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + analysis.reverse = False + analysis.exclude = ["trans3_exec1"] # type: ignore[list-item] + analysis._build_subgraph() + + start = analysis.policy.lookup_type("start") + trans1 = analysis.policy.lookup_type("trans1") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.subG.out_edges()) + assert set([(dyntrans100, bothtrans200), + (start, dyntrans100), + (start, trans1), + (trans1, trans2), + (trans2, trans3), + (trans3, trans5)]) == edges + + def test_exclude_entryoint_with_dyntrans( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: exclude entrypoint type without transition deletion (dyntrans).""" + # Don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + analysis.reverse = False + analysis.exclude = ["bothtrans200_exec"] # type: ignore[list-item] + analysis._build_subgraph() + + start = analysis.policy.lookup_type("start") + trans1 = analysis.policy.lookup_type("trans1") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.subG.out_edges()) + assert set([(dyntrans100, bothtrans200), + (start, dyntrans100), + (start, trans1), + (trans1, trans2), + (trans2, trans3), + (trans3, trans5)]) == edges + + def test_exclude_entryoint_delete_transition( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: exclude entrypoint type with transition deletion.""" + # Don't check node list since the disconnected nodes are not + # removed after removing invalid domain transitions + + analysis.reverse = False + analysis.exclude = ["trans2_exec"] # type: ignore[list-item] + analysis._build_subgraph() + + start = analysis.policy.lookup_type("start") + trans1 = analysis.policy.lookup_type("trans1") + trans2 = analysis.policy.lookup_type("trans2") + trans3 = analysis.policy.lookup_type("trans3") + trans5 = analysis.policy.lookup_type("trans5") + dyntrans100 = analysis.policy.lookup_type("dyntrans100") + bothtrans200 = analysis.policy.lookup_type("bothtrans200") + + edges = set(analysis.subG.out_edges()) + assert set([(dyntrans100, bothtrans200), + (start, dyntrans100), + (start, trans1), + (trans2, trans3), + (trans3, trans5)]) == edges + + def test_all_paths(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths output""" + analysis.reverse = False + analysis.exclude = [] + analysis.source = "start" + analysis.target = "bothtrans200" + analysis.depth_limit = 3 + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + + expected_path = ["start", "dyntrans100", "bothtrans200"] + + paths = list(analysis.results()) + assert 1 == len(paths) + + for path in paths: + for stepnum, step in enumerate(typing.cast(setools.DTAPath, path)): + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert expected_path[stepnum] == step.source + assert expected_path[stepnum + 1] == step.target + + for r in step.transition: + assert "transition" in r.perms + + for e in step.entrypoints: + assert isinstance(e.name, setools.Type) + + for r in e.entrypoint: + assert "entrypoint" in r.perms + + for r in e.execute: + assert "execute" in r.perms + + for r in e.type_transition: + assert TERT.type_transition == r.ruletype + + for r in step.setexec: + assert "setexec" in r.perms + + for r in step.dyntransition: + assert "dyntransition" in r.perms + + for r in step.setcurrent: + assert "setcurrent" in r.perms + + def test_all_shortest_paths(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all shortest paths output""" + analysis.reverse = False + analysis.exclude = [] + analysis.source = "start" + analysis.target = "bothtrans200" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + + expected_path = ["start", "dyntrans100", "bothtrans200"] + + paths = list(analysis.results()) + assert 1 == len(paths) + + for path in paths: + for stepnum, step in enumerate(typing.cast(setools.DTAPath, path)): + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert expected_path[stepnum] == step.source + assert expected_path[stepnum + 1] == step.target + + for r in step.transition: + assert "transition" in r.perms + + for e in step.entrypoints: + assert isinstance(e.name, setools.Type) + + for r in e.entrypoint: + assert "entrypoint" in r.perms + + for r in e.execute: + assert "execute" in r.perms + + for r in e.type_transition: + assert TERT.type_transition == r.ruletype + + for r in step.setexec: + assert "setexec" in r.perms + + for r in step.dyntransition: + assert "dyntransition" in r.perms + + for r in step.setcurrent: + assert "setcurrent" in r.perms + + def test_transitions(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: transitions output""" + analysis.reverse = False + analysis.exclude = [] + analysis.source = "start" + analysis.depth_limit = 1 + analysis.mode = setools.DomainTransitionAnalysis.Mode.TransitionsOut + + transitions = list(analysis.results()) + assert 2 == len(transitions) + + for step in transitions: + assert isinstance(step, setools.DomainTransition) + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert "start" == step.source + + for r in step.transition: + assert "transition" in r.perms + + for e in step.entrypoints: + assert isinstance(e.name, setools.Type) + + for r in e.entrypoint: + assert "entrypoint" in r.perms + + for r in e.execute: + assert "execute" in r.perms + + for r in e.type_transition: + assert TERT.type_transition == r.ruletype + + for r in step.setexec: + assert "setexec" in r.perms + + for r in step.dyntransition: + assert "dyntransition" in r.perms + + for r in step.setcurrent: + assert "setcurrent" in r.perms + + def test_all_paths_reversed(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths output reverse DTA""" + analysis.reverse = True + analysis.exclude = [] + analysis.source = "bothtrans200" + analysis.target = "start" + analysis.depth_limit = 3 + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + + expected_path = ["bothtrans200", "dyntrans100", "start"] + + paths = list(analysis.results()) + assert 1 == len(paths) + + for path in paths: + for stepnum, step in enumerate(typing.cast(setools.DTAPath, path)): + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert step.source == expected_path[stepnum + 1] + assert step.target == expected_path[stepnum] + + for r in step.transition: + assert "transition" in r.perms + + for e in step.entrypoints: + assert isinstance(e.name, setools.Type) + + for r in e.entrypoint: + assert "entrypoint" in r.perms + + for r in e.execute: + assert "execute" in r.perms + + for r in e.type_transition: + assert TERT.type_transition == r.ruletype + + for r in step.setexec: + assert "setexec" in r.perms + + for r in step.dyntransition: + assert "dyntransition" in r.perms + + for r in step.setcurrent: + assert "setcurrent" in r.perms + + def test_all_shortest_paths_reversed(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all shortest paths output reverse DTA""" + analysis.reverse = True + analysis.exclude = [] + analysis.source = "bothtrans200" + analysis.target = "start" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + + expected_path = ["bothtrans200", "dyntrans100", "start"] + + paths = list(analysis.results()) + assert 1 == len(paths) + + for path in paths: + for stepnum, step in enumerate(typing.cast(setools.DTAPath, path)): + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert step.source == expected_path[stepnum + 1] + assert step.target == expected_path[stepnum] + + for r in step.transition: + assert "transition" in r.perms + + for e in step.entrypoints: + assert isinstance(e.name, setools.Type) + + for r in e.entrypoint: + assert "entrypoint" in r.perms + + for r in e.execute: + assert "execute" in r.perms + + for r in e.type_transition: + assert TERT.type_transition == r.ruletype + + for r in step.setexec: + assert "setexec" in r.perms + + for r in step.dyntransition: + assert "dyntransition" in r.perms + + for r in step.setcurrent: + assert "setcurrent" in r.perms + + def test_transitions_reversed(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: transitions output reverse DTA""" + analysis.reverse = False + analysis.exclude = [] + analysis.target = "bothtrans200" + analysis.depth_limit = 1 + analysis.mode = setools.DomainTransitionAnalysis.Mode.TransitionsIn + + transitions = list(analysis.results()) + assert 1 == len(transitions) + + for step in transitions: + assert isinstance(step, setools.DomainTransition) + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert "bothtrans200" == step.target + + for r in step.transition: + assert "transition" in r.perms + + for e in step.entrypoints: + assert isinstance(e.name, setools.Type) + + for r in e.entrypoint: + assert "entrypoint" in r.perms + + for r in e.execute: + assert "execute" in r.perms + + for r in e.type_transition: + assert TERT.type_transition == r.ruletype + + for r in step.setexec: + assert "setexec" in r.perms + + for r in step.dyntransition: + assert "dyntransition" in r.perms + + for r in step.setcurrent: + assert "setcurrent" in r.perms + + def test_set_exclude_invalid_type(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: set invalid excluded type.""" + analysis.reverse = False + analysis.exclude = [] + with pytest.raises(setools.exception.InvalidType): + analysis.exclude = ["trans1", "invalid_type"] # type: ignore[list-item] + + def test_all_paths_invalid_source(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with invalid source type.""" + analysis.reverse = False + analysis.exclude = [] + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + with pytest.raises(setools.exception.InvalidType): + analysis.source = "invalid_type" + + def test_all_paths_invalid_target(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with invalid target type.""" + analysis.reverse = False + analysis.exclude = [] + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + with pytest.raises(setools.exception.InvalidType): + analysis.target = "invalid_type" + + def test_all_paths_invalid_maxlen(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with invalid max path length.""" + analysis.reverse = False + analysis.exclude = [] + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + with pytest.raises(ValueError): + analysis.depth_limit = -2 + + def test_all_paths_source_excluded(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with excluded source type.""" + analysis.reverse = False + analysis.exclude = ["trans1"] # type: ignore[list-item] + analysis.source = "trans1" + analysis.target = "trans2" + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_paths_target_excluded(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with excluded target type.""" + analysis.reverse = False + analysis.exclude = ["trans2"] # type: ignore[list-item] + analysis.source = "trans1" + analysis.target = "trans2" + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_paths_source_disconnected( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with disconnected source type.""" + analysis.reverse = False + analysis.exclude = [] + analysis.source = "trans5" + analysis.target = "trans2" + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_paths_target_disconnected( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all paths with disconnected target type.""" + analysis.reverse = False + analysis.exclude = ["trans3"] # type: ignore[list-item] + analysis.source = "trans2" + analysis.target = "trans5" + analysis.mode = setools.DomainTransitionAnalysis.Mode.AllPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_shortest_path_target_disconnected( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: shortest path with disconnected target type.""" + analysis.reverse = False + analysis.exclude = ["trans3"] # type: ignore[list-item] + analysis.source = "trans2" + analysis.target = "trans5" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_source_excluded( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all shortest paths with excluded source type.""" + analysis.reverse = False + analysis.exclude = ["trans1"] # type: ignore[list-item] + analysis.source = "trans1" + analysis.target = "trans2" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_target_excluded( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all shortest paths with excluded target type.""" + analysis.reverse = False + analysis.exclude = ["trans2"] # type: ignore[list-item] + analysis.source = "trans1" + analysis.target = "trans2" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_source_disconnected( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all shortest paths with disconnected source type.""" + analysis.reverse = False + analysis.exclude = [] + analysis.source = "trans5" + analysis.target = "trans2" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_target_disconnected( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: all shortest paths with disconnected target type.""" + analysis.reverse = False + analysis.exclude = ["trans3"] # type: ignore[list-item] + analysis.source = "trans2" + analysis.target = "trans5" + analysis.mode = setools.DomainTransitionAnalysis.Mode.ShortestPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_transitions_source_excluded(self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: transitions with excluded source type.""" + analysis.reverse = False + analysis.exclude = ["trans1"] # type: ignore[list-item] + analysis.mode = setools.DomainTransitionAnalysis.Mode.TransitionsOut + analysis.source = "trans1" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_transitions_source_disconnected( + self, analysis: setools.DomainTransitionAnalysis) -> None: + """DTA: transitions with disconnected source type.""" + analysis.reverse = False + analysis.exclude = ["trans3"] # type: ignore[list-item] + analysis.source = "trans5" + analysis.mode = setools.DomainTransitionAnalysis.Mode.TransitionsOut + paths = list(analysis.results()) + assert 0 == len(paths) diff --git a/tests/library/test_fsusequery.py b/tests/library/test_fsusequery.py new file mode 100644 index 00000000..dd36aa26 --- /dev/null +++ b/tests/library/test_fsusequery.py @@ -0,0 +1,217 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/fsusequery.conf") +class TestFSUseQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with no criteria""" + # query with no parameters gets all fs_use_*. + fsu = sorted(compiled_policy.fs_uses()) + + q = setools.FSUseQuery(compiled_policy) + q_fsu = sorted(q.results()) + + assert fsu == q_fsu + + def test_fs_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with exact fs match""" + q = setools.FSUseQuery(compiled_policy, fs="test1", fs_regex=False) + + fsu = sorted(s.fs for s in q.results()) + assert ["test1"] == fsu + + def test_fs_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with regex fs match""" + q = setools.FSUseQuery(compiled_policy, fs="test2(a|b)", fs_regex=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test2a", "test2b"] == fsu + + def test_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with ruletype match""" + q = setools.FSUseQuery(compiled_policy, ruletype=['fs_use_trans', 'fs_use_task']) + + fsu = sorted(s.fs for s in q.results()) + assert ["test10a", "test10b"] == fsu + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context user exact match""" + q = setools.FSUseQuery(compiled_policy, user="user20", user_regex=False) + + fsu = sorted(s.fs for s in q.results()) + assert ["test20"] == fsu + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context user regex match""" + q = setools.FSUseQuery(compiled_policy, user="user21(a|b)", user_regex=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test21a", "test21b"] == fsu + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context role exact match""" + q = setools.FSUseQuery(compiled_policy, role="role30_r", role_regex=False) + + fsu = sorted(s.fs for s in q.results()) + assert ["test30"] == fsu + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context role regex match""" + q = setools.FSUseQuery(compiled_policy, role="role31(a|c)_r", role_regex=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test31a", "test31c"] == fsu + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context type exact match""" + q = setools.FSUseQuery(compiled_policy, type_="type40", type_regex=False) + + fsu = sorted(s.fs for s in q.results()) + assert ["test40"] == fsu + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context type regex match""" + q = setools.FSUseQuery(compiled_policy, type_="type41(b|c)", type_regex=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test41b", "test41c"] == fsu + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range exact match""" + q = setools.FSUseQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + fsu = sorted(s.fs for s in q.results()) + assert ["test50"] == fsu + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range overlap match (equal)""" + q = setools.FSUseQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test51"] == fsu + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range overlap match (subset)""" + q = setools.FSUseQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test51"] == fsu + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range overlap match (superset)""" + q = setools.FSUseQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test51"] == fsu + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range overlap match (overlap low level)""" + q = setools.FSUseQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test51"] == fsu + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range overlap match (overlap high level)""" + q = setools.FSUseQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test51"] == fsu + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range subset match""" + q = setools.FSUseQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test52"] == fsu + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range subset match (equal)""" + q = setools.FSUseQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test52"] == fsu + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range superset match""" + q = setools.FSUseQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test53"] == fsu + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range superset match (equal)""" + q = setools.FSUseQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test53"] == fsu + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper subset match""" + q = setools.FSUseQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test54"] == fsu + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper subset match (equal)""" + q = setools.FSUseQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert [] == fsu + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper subset match (equal low only)""" + q = setools.FSUseQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test54"] == fsu + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper subset match (equal high only)""" + q = setools.FSUseQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test54"] == fsu + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper superset match""" + q = setools.FSUseQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test55"] == fsu + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper superset match (equal)""" + q = setools.FSUseQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert [] == fsu + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper superset match (equal low)""" + q = setools.FSUseQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test55"] == fsu + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """fs_use_* query with context range proper superset match (equal high)""" + q = setools.FSUseQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + fsu = sorted(s.fs for s in q.results()) + assert ["test55"] == fsu diff --git a/tests/library/test_genfsconquery.py b/tests/library/test_genfsconquery.py new file mode 100644 index 00000000..ac5b934b --- /dev/null +++ b/tests/library/test_genfsconquery.py @@ -0,0 +1,236 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import stat + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/genfsconquery.conf") +class TestGenfsconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with no criteria""" + # query with no parameters gets all genfs. + genfs = sorted(compiled_policy.genfscons()) + + q = setools.GenfsconQuery(compiled_policy) + q_genfs = sorted(q.results()) + + assert genfs == q_genfs + + def test_fs_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with exact fs match""" + q = setools.GenfsconQuery(compiled_policy, fs="test1", fs_regex=False) + + genfs = sorted(s.fs for s in q.results()) + assert ["test1"] == genfs + + def test_fs_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with regex fs match""" + q = setools.GenfsconQuery(compiled_policy, fs="test2(a|b)", fs_regex=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test2a", "test2b"] == genfs + + def test_path_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with exact path match""" + q = setools.GenfsconQuery(compiled_policy, path="/sys", path_regex=False) + + genfs = sorted(s.fs for s in q.results()) + assert ["test10"] == genfs + + def test_path_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with regex path match""" + q = setools.GenfsconQuery(compiled_policy, path="/(spam|eggs)", path_regex=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test11a", "test11b"] == genfs + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context user exact match""" + q = setools.GenfsconQuery(compiled_policy, user="user20", user_regex=False) + + genfs = sorted(s.fs for s in q.results()) + assert ["test20"] == genfs + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context user regex match""" + q = setools.GenfsconQuery(compiled_policy, user="user21(a|b)", user_regex=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test21a", "test21b"] == genfs + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context role exact match""" + q = setools.GenfsconQuery(compiled_policy, role="role30_r", role_regex=False) + + genfs = sorted(s.fs for s in q.results()) + assert ["test30"] == genfs + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context role regex match""" + q = setools.GenfsconQuery(compiled_policy, role="role31(a|c)_r", role_regex=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test31a", "test31c"] == genfs + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context type exact match""" + q = setools.GenfsconQuery(compiled_policy, type_="type40", type_regex=False) + + genfs = sorted(s.fs for s in q.results()) + assert ["test40"] == genfs + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context type regex match""" + q = setools.GenfsconQuery(compiled_policy, type_="type41(b|c)", type_regex=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test41b", "test41c"] == genfs + + def test_file_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with file type match""" + q = setools.GenfsconQuery(compiled_policy, filetype=stat.S_IFBLK) + + genfs = sorted(s.fs for s in q.results()) + assert ["test50b"] == genfs + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range exact match""" + q = setools.GenfsconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + genfs = sorted(s.fs for s in q.results()) + assert ["test60"] == genfs + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range overlap match (equal)""" + q = setools.GenfsconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test61"] == genfs + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range overlap match (subset)""" + q = setools.GenfsconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test61"] == genfs + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range overlap match (superset)""" + q = setools.GenfsconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test61"] == genfs + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range overlap match (overlap low level)""" + q = setools.GenfsconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test61"] == genfs + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range overlap match (overlap high level)""" + q = setools.GenfsconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test61"] == genfs + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range subset match""" + q = setools.GenfsconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test62"] == genfs + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range subset match (equal)""" + q = setools.GenfsconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test62"] == genfs + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range superset match""" + q = setools.GenfsconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test63"] == genfs + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range superset match (equal)""" + q = setools.GenfsconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test63"] == genfs + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper subset match""" + q = setools.GenfsconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test64"] == genfs + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper subset match (equal)""" + q = setools.GenfsconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert [] == genfs + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper subset match (equal low only)""" + q = setools.GenfsconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test64"] == genfs + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper subset match (equal high only)""" + q = setools.GenfsconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test64"] == genfs + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper superset match""" + q = setools.GenfsconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test65"] == genfs + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper superset match (equal)""" + q = setools.GenfsconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert [] == genfs + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper superset match (equal low)""" + q = setools.GenfsconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test65"] == genfs + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Genfscon query with context range proper superset match (equal high)""" + q = setools.GenfsconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + genfs = sorted(s.fs for s in q.results()) + assert ["test65"] == genfs diff --git a/tests/library/test_ibendportconquery.py b/tests/library/test_ibendportconquery.py new file mode 100644 index 00000000..6441e82e --- /dev/null +++ b/tests/library/test_ibendportconquery.py @@ -0,0 +1,223 @@ +# Copyright 2018, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/ibendportconquery.conf") +class TestIbendportconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with no criteria""" + # query with no parameters gets all ibendportcons. + ibendportcons = sorted(compiled_policy.ibendportcons()) + + q = setools.IbendportconQuery(compiled_policy) + q_ibendportcons = sorted(q.results()) + + assert ibendportcons == q_ibendportcons + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with exact name match.""" + q = setools.IbendportconQuery(compiled_policy, name="test1", name_regex=False) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test1"] == ibendportcons + + def test_name_regext(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with regex name match.""" + q = setools.IbendportconQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test2a", "test2b"] == ibendportcons + + def test_port(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with port match.""" + q = setools.IbendportconQuery(compiled_policy, port=10) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test10"] == ibendportcons + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context user exact match""" + q = setools.IbendportconQuery(compiled_policy, user="user20", user_regex=False) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test20"] == ibendportcons + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context user regex match""" + q = setools.IbendportconQuery(compiled_policy, user="user21(a|b)", user_regex=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test21a", "test21b"] == ibendportcons + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context role exact match""" + q = setools.IbendportconQuery(compiled_policy, role="role30_r", role_regex=False) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test30"] == ibendportcons + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context role regex match""" + q = setools.IbendportconQuery(compiled_policy, role="role31(a|c)_r", role_regex=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test31a", "test31c"] == ibendportcons + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context type exact match""" + q = setools.IbendportconQuery(compiled_policy, type_="type40", type_regex=False) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test40"] == ibendportcons + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context type regex match""" + q = setools.IbendportconQuery(compiled_policy, type_="type41(b|c)", type_regex=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test41b", "test41c"] == ibendportcons + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range exact match""" + q = setools.IbendportconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test50"] == ibendportcons + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range overlap match (equal)""" + q = setools.IbendportconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", + range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test51"] == ibendportcons + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range overlap match (subset)""" + q = setools.IbendportconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test51"] == ibendportcons + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range overlap match (superset)""" + q = setools.IbendportconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test51"] == ibendportcons + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range overlap match (overlap low level)""" + q = setools.IbendportconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test51"] == ibendportcons + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range overlap match (overlap high level)""" + q = setools.IbendportconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test51"] == ibendportcons + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range subset match""" + q = setools.IbendportconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test52"] == ibendportcons + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range subset match (equal)""" + q = setools.IbendportconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", + range_overlap=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test52"] == ibendportcons + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range superset match""" + q = setools.IbendportconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test53"] == ibendportcons + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range superset match (equal)""" + q = setools.IbendportconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", + range_superset=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test53"] == ibendportcons + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper subset match""" + q = setools.IbendportconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test54"] == ibendportcons + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper subset match (equal)""" + q = setools.IbendportconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", + range_subset=True, range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert [] == ibendportcons + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper subset match (equal low only)""" + q = setools.IbendportconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", + range_subset=True, range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test54"] == ibendportcons + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper subset match (equal high only)""" + q = setools.IbendportconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test54"] == ibendportcons + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper superset match""" + q = setools.IbendportconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test55"] == ibendportcons + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper superset match (equal)""" + q = setools.IbendportconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", + range_superset=True, range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert [] == ibendportcons + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper superset match (equal low)""" + q = setools.IbendportconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", + range_superset=True, range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test55"] == ibendportcons + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibendportcon query with context range proper superset match (equal high)""" + q = setools.IbendportconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + ibendportcons = sorted(n.name for n in q.results()) + assert ["test55"] == ibendportcons diff --git a/tests/library/test_ibpkeyconquery.py b/tests/library/test_ibpkeyconquery.py new file mode 100644 index 00000000..7d9e6d7e --- /dev/null +++ b/tests/library/test_ibpkeyconquery.py @@ -0,0 +1,269 @@ +# Copyright 2018, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/ibpkeyconquery.conf") +class TestIbpkeyconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with no criteria""" + # query with no parameters gets all ibpkeycons. + ibpkeycons = sorted(compiled_policy.ibpkeycons()) + + q = setools.IbpkeyconQuery(compiled_policy) + q_ibpkeycons = sorted(q.results()) + + assert ibpkeycons == q_ibpkeycons + + def test_subnet_mask(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with subnet mask match.""" + q = setools.IbpkeyconQuery(compiled_policy, subnet_prefix="fe81::") + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(1, 1)] == ibpkeycons + + def test_pkey_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with exact pkey match.""" + q = setools.IbpkeyconQuery(compiled_policy, pkeys=(0x10c, 0x10e)) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(0x10c, 0x10e)] == ibpkeycons + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context user exact match""" + q = setools.IbpkeyconQuery(compiled_policy, user="user20", user_regex=False) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(20, 20)] == ibpkeycons + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context user regex match""" + q = setools.IbpkeyconQuery(compiled_policy, user="user21(a|b)", user_regex=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(0x21a, 0x21a), + setools.IbpkeyconRange(0x21b, 0x21b)] == ibpkeycons + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context role exact match""" + q = setools.IbpkeyconQuery(compiled_policy, role="role30_r", role_regex=False) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(30, 30)] == ibpkeycons + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context role regex match""" + q = setools.IbpkeyconQuery(compiled_policy, role="role31(a|c)_r", role_regex=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(0x31a, 0x31a), + setools.IbpkeyconRange(0x31c, 0x31c)] == ibpkeycons + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context type exact match""" + q = setools.IbpkeyconQuery(compiled_policy, type_="type40", type_regex=False) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(40, 40)] == ibpkeycons + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context type regex match""" + q = setools.IbpkeyconQuery(compiled_policy, type_="type41(b|c)", type_regex=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(0x41b, 0x41b), + setools.IbpkeyconRange(0x41c, 0x41c)] == ibpkeycons + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range exact match""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(50, 50)] == ibpkeycons + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range overlap match (equal)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(51, 51)] == ibpkeycons + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range overlap match (subset)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(51, 51)] == ibpkeycons + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range overlap match (superset)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(51, 51)] == ibpkeycons + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range overlap match (overlap low level)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(51, 51)] == ibpkeycons + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range overlap match (overlap high level)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(51, 51)] == ibpkeycons + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range subset match""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(52, 52)] == ibpkeycons + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range subset match (equal)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(52, 52)] == ibpkeycons + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range superset match""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(53, 53)] == ibpkeycons + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range superset match (equal)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(53, 53)] == ibpkeycons + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper subset match""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(54, 54)] == ibpkeycons + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper subset match (equal)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [] == ibpkeycons + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper subset match (equal low only)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(54, 54)] == ibpkeycons + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper subset match (equal high only)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(54, 54)] == ibpkeycons + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper superset match""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(55, 55)] == ibpkeycons + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper superset match (equal)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [] == ibpkeycons + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper superset match (equal low)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(55, 55)] == ibpkeycons + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """ibpkeycon query with context range proper superset match (equal high)""" + q = setools.IbpkeyconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + ibpkeycons = sorted(n.pkeys for n in q.results()) + assert [setools.IbpkeyconRange(55, 55)] == ibpkeycons + + def test_invalid_subnet_prefix(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with invalid subnet prefix""" + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, subnet_prefix="INVALID") + + def test_invalid_pkey_negative(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with negative pkey""" + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(-1, -1)) + + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(1, -1)) + + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(-1, 1)) + + def test_invalid_pkey_zero(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with 0 pkey""" + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(0, 0)) + + def test_invalid_pkey_over_max(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with pkey over maximum value""" + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(1, 0xfffff)) + + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(0xfffff, 1)) + + with pytest.raises(ValueError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(0xfffff, 0xfffff)) + + def test_invalid_pkey_not_a_number(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with pkey is not a number""" + with pytest.raises(TypeError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(1, "INVALID")) + + with pytest.raises(TypeError): + setools.IbpkeyconQuery(compiled_policy, pkeys=("INVALID", 2)) + + def test_invalid_pkey_not_tuple(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with pkey is not a tuple""" + with pytest.raises(TypeError): + setools.IbpkeyconQuery(compiled_policy, pkeys=1) + + def test_invalid_pkey_wrong_tuple_length(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ibpkeycon query with pkey is not correct tuple size""" + with pytest.raises(TypeError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(1,)) + + with pytest.raises(TypeError): + setools.IbpkeyconQuery(compiled_policy, pkeys=(1, 2, 3)) diff --git a/tests/library/test_infoflow.py b/tests/library/test_infoflow.py new file mode 100644 index 00000000..6af34124 --- /dev/null +++ b/tests/library/test_infoflow.py @@ -0,0 +1,431 @@ +# Copyright 2014-2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import collections +import typing + +import pytest +import setools +from setools import TERuletype as TERT + +from . import util + + +# Note: the testing for having correct rules on every edge is only +# performed once on the full graph, since it is assumed that NetworkX's +# Digraph.subgraph() function correctly copies the edge attributes into +# the subgraph. + +@pytest.fixture +def analysis(compiled_policy: setools.SELinuxPolicy) -> setools.InfoFlowAnalysis: + perm_map = setools.PermissionMap("tests/library/perm_map") + ret = setools.InfoFlowAnalysis(compiled_policy, perm_map) + ret._build_graph() + return ret + + +@pytest.mark.obj_args("tests/library/infoflow.conf") +class TestInfoFlowAnalysis: + + def test_full_graph(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis full graph.""" + + disconnected1 = analysis.policy.lookup_type("disconnected1") + disconnected2 = analysis.policy.lookup_type("disconnected2") + node1 = analysis.policy.lookup_type("node1") + node2 = analysis.policy.lookup_type("node2") + node3 = analysis.policy.lookup_type("node3") + node4 = analysis.policy.lookup_type("node4") + node5 = analysis.policy.lookup_type("node5") + node6 = analysis.policy.lookup_type("node6") + node7 = analysis.policy.lookup_type("node7") + node8 = analysis.policy.lookup_type("node8") + node9 = analysis.policy.lookup_type("node9") + + nodes = set(analysis.G.nodes()) + assert set([disconnected1, disconnected2, node1, node2, node3, node4, node5, node6, node7, + node8, node9]) == nodes + + edges = set(analysis.G.out_edges()) + assert set([(disconnected1, disconnected2), + (disconnected2, disconnected1), + (node1, node2), + (node1, node3), + (node2, node4), + (node3, node5), + (node4, node6), + (node5, node8), + (node6, node5), + (node6, node7), + (node8, node9), + (node9, node8)]) == edges + + r = analysis.G.edges[disconnected1, disconnected2]["rules"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "disconnected1", "disconnected2", tclass="infoflow2", + perms=set(["super"])) + + r = analysis.G.edges[disconnected2, disconnected1]["rules"] + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "disconnected1", "disconnected2", tclass="infoflow2", + perms=set(["super"])) + + r = sorted(analysis.G.edges[node1, node2]["rules"]) + assert len(r) == 2 + util.validate_rule(r[0], TERT.allow, "node1", "node2", tclass="infoflow", + perms=set(["med_w"])) + util.validate_rule(r[1], TERT.allow, "node2", "node1", tclass="infoflow", + perms=set(["hi_r"])) + + r = sorted(analysis.G.edges[node1, node3]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node3", "node1", tclass="infoflow", + perms=set(["low_r", "med_r"])) + + r = sorted(analysis.G.edges[node2, node4]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node2", "node4", tclass="infoflow", + perms=set(["hi_w"])) + + r = sorted(analysis.G.edges[node3, node5]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node5", "node3", tclass="infoflow", + perms=set(["low_r"])) + + r = sorted(analysis.G.edges[node4, node6]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node4", "node6", tclass="infoflow2", + perms=set(["hi_w"])) + + r = sorted(analysis.G.edges[node5, node8]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node5", "node8", tclass="infoflow2", + perms=set(["hi_w"])) + + r = sorted(analysis.G.edges[node6, node5]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node5", "node6", tclass="infoflow", + perms=set(["med_r"])) + + r = sorted(analysis.G.edges[node6, node7]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node6", "node7", tclass="infoflow", + perms=set(["hi_w"])) + + r = sorted(analysis.G.edges[node8, node9]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node8", "node9", tclass="infoflow2", + perms=set(["super"])) + + r = sorted(analysis.G.edges[node9, node8]["rules"]) + assert len(r) == 1 + util.validate_rule(r[0], TERT.allow, "node8", "node9", tclass="infoflow2", + perms=set(["super"])) + + def test_minimum_3(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis with minimum weight 3.""" + + analysis.exclude = [] + analysis.min_weight = 3 + analysis._build_subgraph() + + disconnected1 = analysis.policy.lookup_type("disconnected1") + disconnected2 = analysis.policy.lookup_type("disconnected2") + node1 = analysis.policy.lookup_type("node1") + node2 = analysis.policy.lookup_type("node2") + node3 = analysis.policy.lookup_type("node3") + node4 = analysis.policy.lookup_type("node4") + node5 = analysis.policy.lookup_type("node5") + node6 = analysis.policy.lookup_type("node6") + node7 = analysis.policy.lookup_type("node7") + node8 = analysis.policy.lookup_type("node8") + node9 = analysis.policy.lookup_type("node9") + + # don't test nodes list, as disconnected nodes + # are not removed by subgraph generation. we + # assume NetworkX copies into the subgraph + # correctly. + + edges = set(analysis.subG.out_edges()) + assert set([(disconnected1, disconnected2), + (disconnected2, disconnected1), + (node1, node2), + (node1, node3), + (node2, node4), + (node4, node6), + (node5, node8), + (node6, node5), + (node6, node7), + (node8, node9), + (node9, node8)]) == edges + + def test_minimum_8(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis with minimum weight 8.""" + + analysis.exclude = [] + analysis.min_weight = 8 + analysis._build_subgraph() + + disconnected1 = analysis.policy.lookup_type("disconnected1") + disconnected2 = analysis.policy.lookup_type("disconnected2") + node1 = analysis.policy.lookup_type("node1") + node2 = analysis.policy.lookup_type("node2") + node4 = analysis.policy.lookup_type("node4") + node5 = analysis.policy.lookup_type("node5") + node6 = analysis.policy.lookup_type("node6") + node7 = analysis.policy.lookup_type("node7") + node8 = analysis.policy.lookup_type("node8") + node9 = analysis.policy.lookup_type("node9") + + # don't test nodes list, as disconnected nodes + # are not removed by subgraph generation. we + # assume NetworkX copies into the subgraph + # correctly. + + edges = set(analysis.subG.out_edges()) + assert set([(disconnected1, disconnected2), + (disconnected2, disconnected1), + (node1, node2), + (node2, node4), + (node4, node6), + (node5, node8), + (node6, node7), + (node8, node9), + (node9, node8)]) == edges + + def test_all_paths(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all paths output""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.source = "node1" + analysis.target = "node4" + analysis.mode = setools.InfoFlowAnalysis.Mode.AllPaths + analysis.depth_limit = 3 + + paths = list(typing.cast(collections.abc.Iterable[setools.InfoFlowPath], + analysis.results())) + assert 1 == len(paths) + + steps = list(paths[0]) + assert 2 == len(steps) + + step = steps[0] + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert step.source == "node1" + assert step.target == "node2" + for r in steps[0].rules: + assert TERT.allow == r.ruletype + + step = steps[1] + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert step.source == "node2" + assert step.target == "node4" + for r in step.rules: + assert TERT.allow == r.ruletype + + def test_all_shortest_paths(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all shortest paths output""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.source = "node1" + analysis.target = "node4" + analysis.mode = setools.InfoFlowAnalysis.Mode.ShortestPaths + + paths = list(typing.cast(collections.abc.Iterable[setools.InfoFlowPath], + analysis.results())) + assert 1 == len(paths) + + steps = list(paths[0]) + assert 2 == len(steps) + + step = steps[0] + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert step.source == "node1" + assert step.target == "node2" + for r in steps[0].rules: + assert TERT.allow == r.ruletype + + step = steps[1] + assert isinstance(step.source, setools.Type) + assert isinstance(step.target, setools.Type) + assert step.source == "node2" + assert step.target == "node4" + for r in step.rules: + assert TERT.allow == r.ruletype + + def test_infoflows_out(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: flows out of a type""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.FlowsOut + analysis.depth_limit = 1 + analysis.source = "node6" + + for flow in analysis.results(): + assert isinstance(flow, setools.InfoFlowStep) + assert isinstance(flow.source, setools.Type) + assert isinstance(flow.target, setools.Type) + assert flow.source == "node6" + for r in flow.rules: + assert TERT.allow == r.ruletype + + def test_infoflows_in(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: flows in to a type""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.FlowsIn + analysis.depth_limit = 1 + analysis.target = "node8" + + for flow in analysis.results(): + assert isinstance(flow, setools.InfoFlowStep) + assert isinstance(flow.source, setools.Type) + assert isinstance(flow.target, setools.Type) + assert flow.target == "node8" + for r in flow.rules: + assert TERT.allow == r.ruletype + + def test_set_exclude_invalid_type(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: set invalid excluded type.""" + with pytest.raises(setools.exception.InvalidType): + analysis.exclude = ["node1", "invalid_type"] # type: ignore[list-item] + + def test_set_small_min_weight(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: set too small weight.""" + + with pytest.raises(ValueError): + analysis.min_weight = 0 + + with pytest.raises(ValueError): + analysis.min_weight = -3 + + def test_set_large_min_weight(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: set too big weight.""" + with pytest.raises(ValueError): + analysis.min_weight = 11 + + with pytest.raises(ValueError): + analysis.min_weight = 50 + + def test_invalid_source(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: invalid source type.""" + with pytest.raises(setools.exception.InvalidType): + analysis.source = "invalid_type" + + def test_invalid_target(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: invalid target type.""" + with pytest.raises(setools.exception.InvalidType): + analysis.target = "invalid_type" + + def test_all_paths_invalid_maxlen(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all paths with invalid max path length.""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.AllPaths + + with pytest.raises(ValueError): + analysis.depth_limit = -2 + + def test_all_paths_source_excluded(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all paths with excluded source type.""" + analysis.exclude = ["node1"] # type: ignore[list-item] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.AllPaths + analysis.source = "node1" + analysis.target = "node2" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_paths_target_excluded(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all paths with excluded target type.""" + analysis.exclude = ["node2"] # type: ignore[list-item] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.AllPaths + analysis.source = "node1" + analysis.target = "node2" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_paths_source_disconnected(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all paths with disconnected source type.""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.AllPaths + analysis.source = "disconnected1" + analysis.target = "node2" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_paths_target_disconnected(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all paths with disconnected target type.""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.source = "node2" + analysis.target = "disconnected1" + analysis.mode = setools.InfoFlowAnalysis.Mode.AllPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_source_excluded(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all shortest paths with excluded source type.""" + analysis.exclude = ["node1"] # type: ignore[list-item] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.ShortestPaths + analysis.source = "node1" + analysis.target = "node2" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_target_excluded(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all shortest paths with excluded target type.""" + analysis.exclude = ["node2"] # type: ignore[list-item] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.ShortestPaths + analysis.source = "node1" + analysis.target = "node2" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_source_disconnected( + self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all shortest paths with disconnected source type.""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.ShortestPaths + analysis.source = "disconnected1" + analysis.target = "node2" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_all_shortest_paths_target_disconnected( + self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: all shortest paths with disconnected target type.""" + analysis.exclude = [] + analysis.min_weight = 1 + analysis.source = "node2" + analysis.target = "disconnected1" + analysis.mode = setools.InfoFlowAnalysis.Mode.ShortestPaths + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_infoflows_source_excluded(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: infoflows with excluded source type.""" + analysis.exclude = ["node1"] # type: ignore[list-item] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.FlowsOut + analysis.source = "node1" + paths = list(analysis.results()) + assert 0 == len(paths) + + def test_infoflows_source_disconnected(self, analysis: setools.InfoFlowAnalysis) -> None: + """Information flow analysis: infoflows with disconnected source type.""" + analysis.exclude = ["disconnected2"] # type: ignore[list-item] + analysis.min_weight = 1 + analysis.mode = setools.InfoFlowAnalysis.Mode.FlowsOut + analysis.source = "disconnected1" + paths = list(analysis.results()) + assert 0 == len(paths) diff --git a/tests/library/test_initsidquery.py b/tests/library/test_initsidquery.py new file mode 100644 index 00000000..86a0b9f2 --- /dev/null +++ b/tests/library/test_initsidquery.py @@ -0,0 +1,214 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/initsidquery.conf") +class TestInitialSIDQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with no criteria""" + # query with no parameters gets all SIDs. + sids = sorted(compiled_policy.initialsids()) + + q = setools.InitialSIDQuery(compiled_policy) + q_sids = sorted(q.results()) + + assert sids == q_sids + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with exact match""" + q = setools.InitialSIDQuery(compiled_policy, name="kernel", name_regex=False) + + sids = sorted(str(s) for s in q.results()) + assert ["kernel"] == sids + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with regex match""" + q = setools.InitialSIDQuery(compiled_policy, name="(security|unlabeled)", name_regex=True) + + sids = sorted(str(s) for s in q.results()) + assert ["security", "unlabeled"] == sids + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context user exact match""" + q = setools.InitialSIDQuery(compiled_policy, user="user10", user_regex=False) + + sids = sorted(str(s) for s in q.results()) + assert ["fs"] == sids + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context user regex match""" + q = setools.InitialSIDQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + sids = sorted(str(s) for s in q.results()) + assert ["file", "file_labels"] == sids + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context role exact match""" + q = setools.InitialSIDQuery(compiled_policy, role="role20_r", role_regex=False) + + sids = sorted(str(s) for s in q.results()) + assert ["any_socket"] == sids + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context role regex match""" + q = setools.InitialSIDQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + sids = sorted(str(s) for s in q.results()) + assert ["netmsg", "port"] == sids + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context type exact match""" + q = setools.InitialSIDQuery(compiled_policy, type_="type30", type_regex=False) + + sids = sorted(str(s) for s in q.results()) + assert ["node"] == sids + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context type regex match""" + q = setools.InitialSIDQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + sids = sorted(str(s) for s in q.results()) + assert ["icmp_socket", "tcp_socket"] == sids + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range exact match""" + q = setools.InitialSIDQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_modprobe"] == sids + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range overlap match (equal)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl"] == sids + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range overlap match (subset)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl"] == sids + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range overlap match (superset)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl"] == sids + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range overlap match (overlap low level)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl"] == sids + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range overlap match (overlap high level)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl"] == sids + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range subset match""" + q = setools.InitialSIDQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_fs"] == sids + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range subset match (equal)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_fs"] == sids + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range superset match""" + q = setools.InitialSIDQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_kernel"] == sids + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range superset match (equal)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", + range_superset=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_kernel"] == sids + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper subset match""" + q = setools.InitialSIDQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_net"] == sids + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper subset match (equal)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert [] == sids + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper subset match (equal low only)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_net"] == sids + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper subset match (equal high only)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_net"] == sids + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper superset match""" + q = setools.InitialSIDQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_net_unix"] == sids + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper superset match (equal)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", + range_superset=True, range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert [] == sids + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper superset match (equal low)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", + range_superset=True, range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_net_unix"] == sids + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Initial SID query with context range proper superset match (equal high)""" + q = setools.InitialSIDQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + sids = sorted(str(s) for s in q.results()) + assert ["sysctl_net_unix"] == sids diff --git a/tests/library/test_iomemconquery.py b/tests/library/test_iomemconquery.py new file mode 100644 index 00000000..7a32786a --- /dev/null +++ b/tests/library/test_iomemconquery.py @@ -0,0 +1,429 @@ +# Derived from tests/portconquery.py +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/iomemconquery.conf", xen=True) +class TestIomemconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with no criteria""" + # query with no parameters gets all addr. + rules = sorted(compiled_policy.iomemcons()) + + q = setools.IomemconQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context user exact match""" + q = setools.IomemconQuery(compiled_policy, user="user10", user_regex=False) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(10, 10)] == addr + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context user regex match""" + q = setools.IomemconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(11, 11), setools.IomemconRange(11000, 11000)] == addr + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context role exact match""" + q = setools.IomemconQuery(compiled_policy, role="role20_r", role_regex=False) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(20, 20)] == addr + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context role regex match""" + q = setools.IomemconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(21, 21), setools.IomemconRange(21001, 21001)] == addr + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context type exact match""" + q = setools.IomemconQuery(compiled_policy, type_="type30", type_regex=False) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(30, 30)] == addr + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context type regex match""" + q = setools.IomemconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(31000, 31000), setools.IomemconRange(31001, 31001)] == addr + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range exact match""" + q = setools.IomemconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(40, 40)] == addr + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range overlap match (equal)""" + q = setools.IomemconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(41, 41)] == addr + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range overlap match (subset)""" + q = setools.IomemconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(41, 41)] == addr + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range overlap match (superset)""" + q = setools.IomemconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(41, 41)] == addr + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range overlap match (overlap low level)""" + q = setools.IomemconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(41, 41)] == addr + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range overlap match (overlap high level)""" + q = setools.IomemconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(41, 41)] == addr + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range subset match""" + q = setools.IomemconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(42, 42)] == addr + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range subset match (equal)""" + q = setools.IomemconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(42, 42)] == addr + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range superset match""" + q = setools.IomemconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(43, 43)] == addr + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range superset match (equal)""" + q = setools.IomemconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(43, 43)] == addr + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper subset match""" + q = setools.IomemconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(44, 44)] == addr + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper subset match (equal)""" + q = setools.IomemconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [] == addr + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper subset match (equal low only)""" + q = setools.IomemconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(44, 44)] == addr + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper subset match (equal high only)""" + q = setools.IomemconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(44, 44)] == addr + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper superset match""" + q = setools.IomemconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(45, 45)] == addr + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper superset match (equal)""" + q = setools.IomemconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [] == addr + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper superset match (equal low)""" + q = setools.IomemconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(45, 45)] == addr + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with context range proper superset match (equal high)""" + q = setools.IomemconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(45, 45)] == addr + + def test_single_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr exact match""" + q = setools.IomemconQuery(compiled_policy, addr=(50, 50)) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50, 50)] == addr + + def test_range_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with mem addr range exact match""" + q = setools.IomemconQuery(compiled_policy, addr=(50100, 50110)) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50100, 50110)] == addr + + def test_single_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr subset""" + q = setools.IomemconQuery(compiled_policy, addr=(50200, 50200), addr_subset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50200, 50200)] == addr + + def test_range_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range subset""" + q = setools.IomemconQuery(compiled_policy, addr=(50301, 50309), addr_subset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50300, 50310)] == addr + + def test_range_subset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range subset, equal edge case""" + q = setools.IomemconQuery(compiled_policy, addr=(50300, 50310), addr_subset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50300, 50310)] == addr + + def test_single_proper_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr proper subset""" + q = setools.IomemconQuery( + compiled_policy, addr=(50400, 50400), addr_subset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [] == addr + + def test_range_proper_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper subset""" + q = setools.IomemconQuery( + compiled_policy, addr=(50501, 50509), addr_subset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50500, 50510)] == addr + + def test_range_proper_subset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper subset, equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50500, 50510), addr_subset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [] == addr + + def test_range_proper_subset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper subset, low equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50500, 50509), addr_subset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50500, 50510)] == addr + + def test_range_proper_subset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper subset, high equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50501, 50510), addr_subset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50500, 50510)] == addr + + def test_single_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr superset""" + q = setools.IomemconQuery(compiled_policy, addr=(50600, 50602), addr_superset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50601, 50601)] == addr + + def test_single_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr superset, equal edge case""" + q = setools.IomemconQuery(compiled_policy, addr=(50601, 50601), addr_superset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50601, 50601)] == addr + + def test_range_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range superset""" + q = setools.IomemconQuery(compiled_policy, addr=(50700, 50711), addr_superset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50700, 50710)] == addr + + def test_range_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range superset, equal edge case""" + q = setools.IomemconQuery(compiled_policy, addr=(50700, 50710), addr_superset=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50700, 50710)] == addr + + def test_single_proper_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr proper superset""" + q = setools.IomemconQuery( + compiled_policy, addr=(50800, 50802), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50801, 50801)] == addr + + def test_single_proper_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr proper superset, equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50801, 50801), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [] == addr + + def test_single_proper_superset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr proper superset, low equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50801, 50802), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50801, 50801)] == addr + + def test_single_proper_superset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single mem addr proper superset, high equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50800, 50801), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50801, 50801)] == addr + + def test_range_proper_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper superset""" + q = setools.IomemconQuery( + compiled_policy, addr=(50900, 50911), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50901, 50910)] == addr + + def test_range_proper_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper superset, equal edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50901, 50910), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [] == addr + + def test_range_proper_superset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper superset, equal high mem addr edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50900, 50910), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50901, 50910)] == addr + + def test_range_proper_superset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range proper superset, equal low mem addr edge case""" + q = setools.IomemconQuery( + compiled_policy, addr=(50901, 50911), addr_superset=True, addr_proper=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(50901, 50910)] == addr + + def test_single_overlap(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single overlap""" + q = setools.IomemconQuery(compiled_policy, addr=(60001, 60001), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60001, 60001)] == addr + + def test_single_overlap_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single overlap, range match low""" + q = setools.IomemconQuery(compiled_policy, addr=(60001, 60002), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60001, 60001)] == addr + + def test_single_overlap_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single overlap, range match high""" + q = setools.IomemconQuery(compiled_policy, addr=(60000, 60001), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60001, 60001)] == addr + + def test_single_overlap_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with single overlap, range match proper superset""" + q = setools.IomemconQuery(compiled_policy, addr=(60000, 60002), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60001, 60001)] == addr + + def test_range_overlap_low_half(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range overlap, low half match""" + q = setools.IomemconQuery(compiled_policy, addr=(60100, 60105), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60101, 60110)] == addr + + def test_range_overlap_high_half(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range overlap, high half match""" + q = setools.IomemconQuery(compiled_policy, addr=(60205, 60211), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60200, 60210)] == addr + + def test_range_overlap_middle(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range overlap, middle match""" + q = setools.IomemconQuery(compiled_policy, addr=(60305, 60308), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60300, 60310)] == addr + + def test_range_overlap_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range overlap, equal match""" + q = setools.IomemconQuery(compiled_policy, addr=(60400, 60410), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60400, 60410)] == addr + + def test_range_overlap_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Iomemcon query with range overlap, superset match""" + q = setools.IomemconQuery(compiled_policy, addr=(60500, 60510), addr_overlap=True) + + addr = sorted(p.addr for p in q.results()) + assert [setools.IomemconRange(60501, 60509)] == addr diff --git a/tests/library/test_ioportconquery.py b/tests/library/test_ioportconquery.py new file mode 100644 index 00000000..e701593e --- /dev/null +++ b/tests/library/test_ioportconquery.py @@ -0,0 +1,430 @@ +# Derived from tests/portconquery.py +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/ioportconquery.conf", xen=True) +class TestIoportconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Ioportcon query with no criteria""" + # query with no parameters gets all ports. + rules = sorted(compiled_policy.ioportcons()) + + q = setools.IoportconQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context user exact match""" + q = setools.IoportconQuery(compiled_policy, user="user10", user_regex=False) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(10, 10)] == ports + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context user regex match""" + q = setools.IoportconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(11, 11), setools.IoportconRange(11000, 11000)] == ports + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context role exact match""" + q = setools.IoportconQuery(compiled_policy, role="role20_r", role_regex=False) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(20, 20)] == ports + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context role regex match""" + q = setools.IoportconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(21, 21), setools.IoportconRange(21001, 21001)] == ports + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context type exact match""" + q = setools.IoportconQuery(compiled_policy, type_="type30", type_regex=False) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(30, 30)] == ports + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context type regex match""" + q = setools.IoportconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(31000, 31000), + setools.IoportconRange(31001, 31001)] == ports + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range exact match""" + q = setools.IoportconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(40, 40)] == ports + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (equal)""" + q = setools.IoportconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(41, 41)] == ports + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (subset)""" + q = setools.IoportconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(41, 41)] == ports + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (superset)""" + q = setools.IoportconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(41, 41)] == ports + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (overlap low level)""" + q = setools.IoportconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(41, 41)] == ports + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (overlap high level)""" + q = setools.IoportconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(41, 41)] == ports + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range subset match""" + q = setools.IoportconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(42, 42)] == ports + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range subset match (equal)""" + q = setools.IoportconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(42, 42)] == ports + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range superset match""" + q = setools.IoportconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(43, 43)] == ports + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range superset match (equal)""" + q = setools.IoportconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(43, 43)] == ports + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match""" + q = setools.IoportconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(44, 44)] == ports + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match (equal)""" + q = setools.IoportconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match (equal low only)""" + q = setools.IoportconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(44, 44)] == ports + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match (equal high only)""" + q = setools.IoportconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(44, 44)] == ports + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match""" + q = setools.IoportconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(45, 45)] == ports + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match (equal)""" + q = setools.IoportconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match (equal low)""" + q = setools.IoportconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(45, 45)] == ports + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match (equal high)""" + q = setools.IoportconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(45, 45)] == ports + + def test_single_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port exact match""" + q = setools.IoportconQuery(compiled_policy, ports=(50, 50)) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50, 50)] == ports + + def test_range_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with port range exact match""" + q = setools.IoportconQuery(compiled_policy, ports=(50100, 50110)) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50100, 50110)] == ports + + def test_single_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port subset""" + q = setools.IoportconQuery(compiled_policy, ports=(50200, 50200), ports_subset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50200, 50200)] == ports + + def test_range_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range subset""" + q = setools.IoportconQuery(compiled_policy, ports=(50301, 50309), ports_subset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50300, 50310)] == ports + + def test_range_subset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range subset, equal edge case""" + q = setools.IoportconQuery(compiled_policy, ports=(50300, 50310), ports_subset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50300, 50310)] == ports + + def test_single_proper_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper subset""" + q = setools.IoportconQuery( + compiled_policy, ports=(50400, 50400), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset""" + q = setools.IoportconQuery( + compiled_policy, ports=(50501, 50509), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50500, 50510)] == ports + + def test_range_proper_subset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset, equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50500, 50510), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_subset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset, low equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50500, 50509), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50500, 50510)] == ports + + def test_range_proper_subset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset, high equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50501, 50510), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50500, 50510)] == ports + + def test_single_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port superset""" + q = setools.IoportconQuery(compiled_policy, ports=(50600, 50602), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50601, 50601)] == ports + + def test_single_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port superset, equal edge case""" + q = setools.IoportconQuery(compiled_policy, ports=(50601, 50601), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50601, 50601)] == ports + + def test_range_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range superset""" + q = setools.IoportconQuery(compiled_policy, ports=(50700, 50711), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50700, 50710)] == ports + + def test_range_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range superset, equal edge case""" + q = setools.IoportconQuery(compiled_policy, ports=(50700, 50710), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50700, 50710)] == ports + + def test_single_proper_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset""" + q = setools.IoportconQuery( + compiled_policy, ports=(50800, 50802), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50801, 50801)] == ports + + def test_single_proper_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset, equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50801, 50801), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_single_proper_superset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset, low equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50801, 50802), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50801, 50801)] == ports + + def test_single_proper_superset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset, high equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50800, 50801), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50801, 50801)] == ports + + def test_range_proper_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset""" + q = setools.IoportconQuery( + compiled_policy, ports=(50900, 50911), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50901, 50910)] == ports + + def test_range_proper_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset, equal edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50901, 50910), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_superset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset, equal high port edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50900, 50910), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50901, 50910)] == ports + + def test_range_proper_superset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset, equal low port edge case""" + q = setools.IoportconQuery( + compiled_policy, ports=(50901, 50911), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(50901, 50910)] == ports + + def test_single_overlap(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap""" + q = setools.IoportconQuery(compiled_policy, ports=(60001, 60001), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60001, 60001)] == ports + + def test_single_overlap_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap, range match low""" + q = setools.IoportconQuery(compiled_policy, ports=(60001, 60002), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60001, 60001)] == ports + + def test_single_overlap_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap, range match high""" + q = setools.IoportconQuery(compiled_policy, ports=(60000, 60001), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60001, 60001)] == ports + + def test_single_overlap_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap, range match proper superset""" + q = setools.IoportconQuery(compiled_policy, ports=(60000, 60002), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60001, 60001)] == ports + + def test_range_overlap_low_half(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, low half match""" + q = setools.IoportconQuery(compiled_policy, ports=(60100, 60105), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60101, 60110)] == ports + + def test_range_overlap_high_half(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, high half match""" + q = setools.IoportconQuery(compiled_policy, ports=(60205, 60211), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60200, 60210)] == ports + + def test_range_overlap_middle(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, middle match""" + q = setools.IoportconQuery(compiled_policy, ports=(60305, 60308), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60300, 60310)] == ports + + def test_range_overlap_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, equal match""" + q = setools.IoportconQuery(compiled_policy, ports=(60400, 60410), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60400, 60410)] == ports + + def test_range_overlap_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, superset match""" + q = setools.IoportconQuery(compiled_policy, ports=(60500, 60510), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.IoportconRange(60501, 60509)] == ports diff --git a/tests/library/test_mlsrulequery.py b/tests/library/test_mlsrulequery.py new file mode 100644 index 00000000..f283902f --- /dev/null +++ b/tests/library/test_mlsrulequery.py @@ -0,0 +1,292 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools +from setools import MLSRuleQuery +from setools import MLSRuletype as RT + +from . import util + +# Note: the test policy has been written assuming range_transition +# statements could have attributes. However, range_transition +# statements are always expanded, so the below unit tests +# have been adjusted to this fact (hence a "FAIL" in one of the +# expected type names) + + +@pytest.mark.obj_args("tests/library/mlsrulequery.conf") +class TestMLSRuleQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with no criteria.""" + # query with no parameters gets all MLS rules. + rules = sorted(compiled_policy.mlsrules()) + + q = MLSRuleQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_source_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with exact, direct, source match.""" + q = MLSRuleQuery( + compiled_policy, source="test1s", source_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test1s", "test1t", tclass="infoflow", + default="s0") + + def test_source_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with regex, direct, source match.""" + q = MLSRuleQuery( + compiled_policy, source="test3(s|aS)", source_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RT.range_transition, "test3s", "test3t", tclass="infoflow", + default="s1") + util.validate_rule(r[1], RT.range_transition, "test3s", "test3t", tclass="infoflow2", + default="s2") + + def test_issue111(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with attribute source criteria, indirect match.""" + # https://github.com/TresysTechnology/setools/issues/111 + q = MLSRuleQuery(compiled_policy, source="test5b", source_indirect=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RT.range_transition, "test5t1", "test5target", tclass="infoflow", + default="s1") + util.validate_rule(r[1], RT.range_transition, "test5t2", "test5target", tclass="infoflow7", + default="s2") + + def test_target_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with exact, direct, target match.""" + q = MLSRuleQuery( + compiled_policy, target="test10t", target_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RT.range_transition, "test10s", "test10t", tclass="infoflow", + default="s0") + util.validate_rule(r[1], RT.range_transition, "test10s", "test10t", tclass="infoflow2", + default="s1") + + def test_target_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with regex, direct, target match.""" + q = MLSRuleQuery( + compiled_policy, target="test12a.*", target_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test12s", "test12aFAIL", tclass="infoflow", + default="s2") + + def test_issue111_2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with attribute target criteria, indirect match.""" + # https://github.com/TresysTechnology/setools/issues/111 + q = MLSRuleQuery(compiled_policy, target="test14b", target_indirect=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RT.range_transition, "test14source", "test14t1", + tclass="infoflow", default="s1") + util.validate_rule(r[1], RT.range_transition, "test14source", "test14t2", + tclass="infoflow7", default="s2") + + def test_class_list(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with object class list match.""" + q = MLSRuleQuery( + compiled_policy, tclass=["infoflow3", "infoflow4"], tclass_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RT.range_transition, "test21", "test21", tclass="infoflow3", + default="s2") + util.validate_rule(r[1], RT.range_transition, "test21", "test21", tclass="infoflow4", + default="s1") + + def test_class_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with object class regex match.""" + q = MLSRuleQuery(compiled_policy, tclass="infoflow(5|6)", tclass_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RT.range_transition, "test22", "test22", tclass="infoflow5", + default="s1") + util.validate_rule(r[1], RT.range_transition, "test22", "test22", tclass="infoflow6", + default="s2") + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range exact match""" + q = MLSRuleQuery(compiled_policy, default="s40:c1 - s40:c0.c4") + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test40", "test40", tclass="infoflow", + default="s40:c1 - s40:c0.c4") + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range overlap match (equal)""" + q = MLSRuleQuery(compiled_policy, default="s41:c1 - s41:c0.c4", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test41", "test41", tclass="infoflow", + default="s41:c1 - s41:c1.c3") + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range overlap match (subset)""" + q = MLSRuleQuery(compiled_policy, default="s41:c1,c2 - s41:c0.c3", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test41", "test41", tclass="infoflow", + default="s41:c1 - s41:c1.c3") + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range overlap match (superset)""" + q = MLSRuleQuery(compiled_policy, default="s41 - s41:c0.c4", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test41", "test41", tclass="infoflow", + default="s41:c1 - s41:c1.c3") + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range overlap match (overlap low level)""" + q = MLSRuleQuery(compiled_policy, default="s41 - s41:c1,c2", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test41", "test41", tclass="infoflow", + default="s41:c1 - s41:c1.c3") + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range overlap match (overlap high level)""" + q = MLSRuleQuery(compiled_policy, default="s41:c1,c2 - s41:c0.c4", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test41", "test41", tclass="infoflow", + default="s41:c1 - s41:c1.c3") + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range subset match""" + q = MLSRuleQuery(compiled_policy, default="s42:c1,c2 - s42:c0.c3", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test42", "test42", tclass="infoflow", + default="s42:c1 - s42:c1.c3") + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range subset match (equal)""" + q = MLSRuleQuery(compiled_policy, default="s42:c1 - s42:c1.c3", default_overlap=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test42", "test42", tclass="infoflow", + default="s42:c1 - s42:c1.c3") + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range superset match""" + q = MLSRuleQuery(compiled_policy, default="s43 - s43:c0.c4", default_superset=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test43", "test43", tclass="infoflow", + default="s43:c1 - s43:c1.c3") + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range superset match (equal)""" + q = MLSRuleQuery(compiled_policy, default="s43:c1 - s43:c1.c3", default_superset=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test43", "test43", tclass="infoflow", + default="s43:c1 - s43:c1.c3") + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper subset match""" + q = MLSRuleQuery(compiled_policy, default="s44:c1,c2", default_subset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test44", "test44", tclass="infoflow", + default="s44:c1 - s44:c1.c3") + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper subset match (equal)""" + q = MLSRuleQuery(compiled_policy, default="s44:c1 - s44:c1.c3", default_subset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 0 + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper subset match (equal low only)""" + q = MLSRuleQuery(compiled_policy, default="s44:c1 - s44:c1.c2", default_subset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test44", "test44", tclass="infoflow", + default="s44:c1 - s44:c1.c3") + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper subset match (equal high only)""" + q = MLSRuleQuery(compiled_policy, default="s44:c1,c2 - s44:c1.c3", default_subset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test44", "test44", tclass="infoflow", + default="s44:c1 - s44:c1.c3") + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper superset match""" + q = MLSRuleQuery(compiled_policy, default="s45 - s45:c0.c4", default_superset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test45", "test45", tclass="infoflow", + default="s45:c1 - s45:c1.c3") + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper superset match (equal)""" + q = MLSRuleQuery(compiled_policy, default="s45:c1 - s45:c1.c3", default_superset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 0 + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper superset match (equal low)""" + q = MLSRuleQuery(compiled_policy, default="s45:c1 - s45:c1.c4", default_superset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test45", "test45", tclass="infoflow", + default="s45:c1 - s45:c1.c3") + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with context range proper superset match (equal high)""" + q = MLSRuleQuery(compiled_policy, default="s45 - s45:c1.c3", default_superset=True, + default_proper=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RT.range_transition, "test45", "test45", tclass="infoflow", + default="s45:c1 - s45:c1.c3") + + def test_invalid_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """MLS rule query with invalid rule type.""" + with pytest.raises(KeyError): + q = MLSRuleQuery(compiled_policy, ruletype=["type_transition"]) diff --git a/tests/library/test_netifconquery.py b/tests/library/test_netifconquery.py new file mode 100644 index 00000000..c9cc5369 --- /dev/null +++ b/tests/library/test_netifconquery.py @@ -0,0 +1,213 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/netifconquery.conf") +class TestNetifconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with no criteria""" + # query with no parameters gets all netifs. + netifs = sorted(compiled_policy.netifcons()) + + q = setools.NetifconQuery(compiled_policy) + q_netifs = sorted(q.results()) + + assert netifs == q_netifs + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with exact match""" + q = setools.NetifconQuery(compiled_policy, name="test1", name_regex=False) + + netifs = sorted(s.netif for s in q.results()) + assert ["test1"] == netifs + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with regex match""" + q = setools.NetifconQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test2a", "test2b"] == netifs + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context user exact match""" + q = setools.NetifconQuery(compiled_policy, user="user10", user_regex=False) + + netifs = sorted(s.netif for s in q.results()) + assert ["test10"] == netifs + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context user regex match""" + q = setools.NetifconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test11a", "test11b"] == netifs + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context role exact match""" + q = setools.NetifconQuery(compiled_policy, role="role20_r", role_regex=False) + + netifs = sorted(s.netif for s in q.results()) + assert ["test20"] == netifs + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context role regex match""" + q = setools.NetifconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test21a", "test21c"] == netifs + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context type exact match""" + q = setools.NetifconQuery(compiled_policy, type_="type30", type_regex=False) + + netifs = sorted(s.netif for s in q.results()) + assert ["test30"] == netifs + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context type regex match""" + q = setools.NetifconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test31b", "test31c"] == netifs + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range exact match""" + q = setools.NetifconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + netifs = sorted(s.netif for s in q.results()) + assert ["test40"] == netifs + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range overlap match (equal)""" + q = setools.NetifconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test41"] == netifs + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range overlap match (subset)""" + q = setools.NetifconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test41"] == netifs + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range overlap match (superset)""" + q = setools.NetifconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test41"] == netifs + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range overlap match (overlap low level)""" + q = setools.NetifconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test41"] == netifs + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range overlap match (overlap high level)""" + q = setools.NetifconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test41"] == netifs + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range subset match""" + q = setools.NetifconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test42"] == netifs + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range subset match (equal)""" + q = setools.NetifconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test42"] == netifs + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range superset match""" + q = setools.NetifconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test43"] == netifs + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range superset match (equal)""" + q = setools.NetifconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test43"] == netifs + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper subset match""" + q = setools.NetifconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test44"] == netifs + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper subset match (equal)""" + q = setools.NetifconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert [] == netifs + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper subset match (equal low only)""" + q = setools.NetifconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test44"] == netifs + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper subset match (equal high only)""" + q = setools.NetifconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test44"] == netifs + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper superset match""" + q = setools.NetifconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test45"] == netifs + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper superset match (equal)""" + q = setools.NetifconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert [] == netifs + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper superset match (equal low)""" + q = setools.NetifconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test45"] == netifs + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Netifcon query with context range proper superset match (equal high)""" + q = setools.NetifconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + netifs = sorted(s.netif for s in q.results()) + assert ["test45"] == netifs diff --git a/tests/library/test_nodeconquery.py b/tests/library/test_nodeconquery.py new file mode 100644 index 00000000..0d609056 --- /dev/null +++ b/tests/library/test_nodeconquery.py @@ -0,0 +1,235 @@ +# Copyright 2014, Tresys Technology, LLC +# Copyright 2017, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# +from socket import AF_INET6 +from ipaddress import IPv4Network, IPv6Network + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/nodeconquery.conf") +class TestNodeconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with no criteria""" + # query with no parameters gets all nodecons. + nodecons = sorted(compiled_policy.nodecons()) + + q = setools.NodeconQuery(compiled_policy) + q_nodecons = sorted(q.results()) + + assert nodecons == q_nodecons + + def test_ip_version(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with IP version match.""" + q = setools.NodeconQuery(compiled_policy, ip_version=AF_INET6) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv6Network("1100::/16"), IPv6Network("1110::/16")] == nodecons + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context user exact match""" + q = setools.NodeconQuery(compiled_policy, user="user20", user_regex=False) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.20.1/32")] == nodecons + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context user regex match""" + q = setools.NodeconQuery(compiled_policy, user="user21(a|b)", user_regex=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.21.1/32"), IPv4Network("10.1.21.2/32")] == nodecons + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context role exact match""" + q = setools.NodeconQuery(compiled_policy, role="role30_r", role_regex=False) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.30.1/32")] == nodecons + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context role regex match""" + q = setools.NodeconQuery(compiled_policy, role="role31(a|c)_r", role_regex=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.31.1/32"), IPv4Network("10.1.31.3/32")] == nodecons + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context type exact match""" + q = setools.NodeconQuery(compiled_policy, type_="type40", type_regex=False) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.40.1/32")] == nodecons + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context type regex match""" + q = setools.NodeconQuery(compiled_policy, type_="type41(b|c)", type_regex=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.41.2/32"), IPv4Network("10.1.41.3/32")] == nodecons + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range exact match""" + q = setools.NodeconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.50.1/32")] == nodecons + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range overlap match (equal)""" + q = setools.NodeconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.51.1/32")] == nodecons + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range overlap match (subset)""" + q = setools.NodeconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.51.1/32")] == nodecons + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range overlap match (superset)""" + q = setools.NodeconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.51.1/32")] == nodecons + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range overlap match (overlap low level)""" + q = setools.NodeconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.51.1/32")] == nodecons + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range overlap match (overlap high level)""" + q = setools.NodeconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.51.1/32")] == nodecons + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range subset match""" + q = setools.NodeconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.52.1/32")] == nodecons + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range subset match (equal)""" + q = setools.NodeconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.52.1/32")] == nodecons + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range superset match""" + q = setools.NodeconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.53.1/32")] == nodecons + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range superset match (equal)""" + q = setools.NodeconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.53.1/32")] == nodecons + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper subset match""" + q = setools.NodeconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.54.1/32")] == nodecons + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper subset match (equal)""" + q = setools.NodeconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [] == nodecons + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper subset match (equal low only)""" + q = setools.NodeconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.54.1/32")] == nodecons + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper subset match (equal high only)""" + q = setools.NodeconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.54.1/32")] == nodecons + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper superset match""" + q = setools.NodeconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.55.1/32")] == nodecons + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper superset match (equal)""" + q = setools.NodeconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [] == nodecons + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper superset match (equal low)""" + q = setools.NodeconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.55.1/32")] == nodecons + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with context range proper superset match (equal high)""" + q = setools.NodeconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("10.1.55.1/32")] == nodecons + + def test_v4network_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with IPv4 equal network""" + q = setools.NodeconQuery(compiled_policy, network="192.168.1.0/24", network_overlap=False) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("192.168.1.0/24")] == nodecons + + def test_v4network_overlap(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with IPv4 network overlap""" + q = setools.NodeconQuery(compiled_policy, network="192.168.201.0/24", network_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv4Network("192.168.200.0/22")] == nodecons + + def test_v6network_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with IPv6 equal network""" + q = setools.NodeconQuery(compiled_policy, network="1100::/16", network_overlap=False) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv6Network("1100::/16")] == nodecons + + def test_v6network_overlap(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Nodecon query with IPv6 network overlap""" + q = setools.NodeconQuery(compiled_policy, network="1110:8000::/17", network_overlap=True) + + nodecons = sorted(n.network for n in q.results()) + assert [IPv6Network("1110::/16")] == nodecons diff --git a/tests/library/test_objclassquery.py b/tests/library/test_objclassquery.py new file mode 100644 index 00000000..e0397c7b --- /dev/null +++ b/tests/library/test_objclassquery.py @@ -0,0 +1,97 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/objclassquery.conf") +class TestObjClassQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with no criteria.""" + # query with no parameters gets all types. + classes = sorted(compiled_policy.classes()) + + q = setools.ObjClassQuery(compiled_policy) + q_classes = sorted(q.results()) + + assert classes == q_classes + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with exact name match.""" + q = setools.ObjClassQuery(compiled_policy, name="infoflow") + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow"] == classes + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with regex name match.""" + q = setools.ObjClassQuery(compiled_policy, name="infoflow(2|3)", name_regex=True) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow2", "infoflow3"] == classes + + def test_common_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with exact common name match.""" + q = setools.ObjClassQuery(compiled_policy, common="infoflow") + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow", "infoflow2", "infoflow4", "infoflow7"] == classes + + def test_common_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with regex common name match.""" + q = setools.ObjClassQuery(compiled_policy, common="com_[ab]", common_regex=True) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow5", "infoflow6"] == classes + + def test_perm_indirect_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with indirect, intersect permission name patch.""" + q = setools.ObjClassQuery( + compiled_policy, perms=set(["send"]), perms_indirect=True, perms_equal=False) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow6"] == classes + + def test_perm_direct_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with direct, intersect permission name patch.""" + q = setools.ObjClassQuery( + compiled_policy, perms=set(["super_r"]), perms_indirect=False, perms_equal=False) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow2", "infoflow4", "infoflow8"] == classes + + def test_perm_indirect_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with indirect, equal permission name patch.""" + q = setools.ObjClassQuery(compiled_policy, perms=set( + ["low_w", "med_w", "hi_w", "low_r", "med_r", "hi_r", "unmapped"]), + perms_indirect=True, perms_equal=True) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow7"] == classes + + def test_perm_direct_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with direct, equal permission name patch.""" + q = setools.ObjClassQuery(compiled_policy, perms=set( + ["super_r", "super_w"]), perms_indirect=False, perms_equal=True) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow2", "infoflow8"] == classes + + def test_perm_indirect_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with indirect, regex permission name patch.""" + q = setools.ObjClassQuery( + compiled_policy, perms="(send|setattr)", perms_indirect=True, perms_regex=True) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow6", "infoflow9"] == classes + + def test_perm_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Class query with direct, regex permission name patch.""" + q = setools.ObjClassQuery( + compiled_policy, perms="(read|super_r)", perms_indirect=False, perms_regex=True) + + classes = sorted(str(c) for c in q.results()) + assert ["infoflow10", "infoflow2", "infoflow4", "infoflow8"] == classes diff --git a/tests/library/test_pcideviceconquery.py b/tests/library/test_pcideviceconquery.py new file mode 100644 index 00000000..bea7753a --- /dev/null +++ b/tests/library/test_pcideviceconquery.py @@ -0,0 +1,202 @@ +# Derived from tests/portconquery.py +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/pcideviceconquery.conf", xen=True) +class TestPcideviceconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with no criteria""" + # query with no parameters gets all PCI devices. + rules = sorted(compiled_policy.pcidevicecons()) + + q = setools.PcideviceconQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context user exact match""" + q = setools.PcideviceconQuery(compiled_policy, user="user10", user_regex=False) + + device = sorted(p.device for p in q.results()) + assert [(10)] == device + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context user regex match""" + q = setools.PcideviceconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + device = sorted(p.device for p in q.results()) + assert [(11), (11000)] == device + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context role exact match""" + q = setools.PcideviceconQuery(compiled_policy, role="role20_r", role_regex=False) + + device = sorted(p.device for p in q.results()) + assert [(20)] == device + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context role regex match""" + q = setools.PcideviceconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + device = sorted(p.device for p in q.results()) + assert [(21), (21001)] == device + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context type exact match""" + q = setools.PcideviceconQuery(compiled_policy, type_="type30", type_regex=False) + + device = sorted(p.device for p in q.results()) + assert [(30)] == device + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context type regex match""" + q = setools.PcideviceconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + device = sorted(p.device for p in q.results()) + assert [(31000), (31001)] == device + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range exact match""" + q = setools.PcideviceconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + device = sorted(p.device for p in q.results()) + assert [(40)] == device + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range overlap match (equal)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", + range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(41)] == device + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range overlap match (subset)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", + range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(41)] == device + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range overlap match (superset)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(41)] == device + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range overlap match (overlap low level)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(41)] == device + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range overlap match (overlap high level)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", + range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(41)] == device + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range subset match""" + q = setools.PcideviceconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", + range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(42)] == device + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range subset match (equal)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", + range_overlap=True) + + device = sorted(p.device for p in q.results()) + assert [(42)] == device + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range superset match""" + q = setools.PcideviceconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + device = sorted(p.device for p in q.results()) + assert [(43)] == device + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range superset match (equal)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", + range_superset=True) + + device = sorted(p.device for p in q.results()) + assert [(43)] == device + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper subset match""" + q = setools.PcideviceconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [(44)] == device + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper subset match (equal)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", + range_subset=True, range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [] == device + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper subset match (equal low only)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", + range_subset=True, range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [(44)] == device + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper subset match (equal high only)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", + range_subset=True, range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [(44)] == device + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper superset match""" + q = setools.PcideviceconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [(45)] == device + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper superset match (equal)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", + range_superset=True, range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [] == device + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper superset match (equal low)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", + range_superset=True, range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [(45)] == device + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pcidevicecon query with context range proper superset match (equal high)""" + q = setools.PcideviceconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + device = sorted(p.device for p in q.results()) + assert [(45)] == device diff --git a/tests/test_permmap.py b/tests/library/test_permmap.py similarity index 51% rename from tests/test_permmap.py rename to tests/library/test_permmap.py index 6388d5f0..fae5a70f 100644 --- a/tests/test_permmap.py +++ b/tests/library/test_permmap.py @@ -2,54 +2,42 @@ # # SPDX-License-Identifier: GPL-2.0-only # -import unittest -import os from unittest.mock import Mock +import pytest +import setools from setools import PermissionMap, TERuletype from setools.exception import PermissionMapParseError, RuleTypeError, \ UnmappedClass, UnmappedPermission -from .policyrep.util import compile_policy - -class PermissionMapTest(unittest.TestCase): +@pytest.mark.obj_args("tests/library/permmap.conf") +class TestPermissionMap: """Permission map unit tests.""" - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/permmap.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def validate_permmap_entry(self, permmap, cls, perm, direction, weight, enabled): + def validate_permmap_entry(self, permmap: dict, cls: str, perm: str, direction: str, + weight: int, enabled: bool) -> None: """Validate a permission map entry and settings.""" - self.assertIn(cls, permmap) - self.assertIn(perm, permmap[cls]) - self.assertIn('direction', permmap[cls][perm]) - self.assertIn('weight', permmap[cls][perm]) - self.assertIn('enabled', permmap[cls][perm]) - self.assertEqual(permmap[cls][perm]['direction'], direction) - self.assertEqual(permmap[cls][perm]['weight'], weight) - - if enabled: - self.assertTrue(permmap[cls][perm]['enabled']) - else: - self.assertFalse(permmap[cls][perm]['enabled']) - - def test_001_load(self): + assert cls in permmap + assert perm in permmap[cls] + assert 'direction' in permmap[cls][perm] + assert 'weight' in permmap[cls][perm] + assert 'enabled' in permmap[cls][perm] + assert permmap[cls][perm]['direction'] == direction + assert permmap[cls][perm]['weight'] == weight + assert permmap[cls][perm]['enabled'] == enabled + + def test_load(self) -> None: """PermMap open from path.""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") # validate permission map contents - self.assertEqual(5, len(permmap._permmap)) + assert 5 == len(permmap._permmap) # class infoflow - self.assertIn("infoflow", permmap._permmap) - self.assertEqual(6, len(permmap._permmap['infoflow'])) + assert "infoflow" in permmap._permmap + assert 6 == len(permmap._permmap['infoflow']) self.validate_permmap_entry(permmap._permmap, 'infoflow', 'low_w', 'w', 1, True) self.validate_permmap_entry(permmap._permmap, 'infoflow', 'med_w', 'w', 5, True) self.validate_permmap_entry(permmap._permmap, 'infoflow', 'hi_w', 'w', 10, True) @@ -58,8 +46,8 @@ def test_001_load(self): self.validate_permmap_entry(permmap._permmap, 'infoflow', 'hi_r', 'r', 10, True) # class infoflow2 - self.assertIn("infoflow2", permmap._permmap) - self.assertEqual(7, len(permmap._permmap['infoflow2'])) + assert "infoflow2" in permmap._permmap + assert 7 == len(permmap._permmap['infoflow2']) self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'low_w', 'w', 1, True) self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'med_w', 'w', 5, True) self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'hi_w', 'w', 10, True) @@ -69,200 +57,200 @@ def test_001_load(self): self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'super', 'b', 10, True) # class infoflow3 - self.assertIn("infoflow3", permmap._permmap) - self.assertEqual(1, len(permmap._permmap['infoflow3'])) + assert "infoflow3" in permmap._permmap + assert 1 == len(permmap._permmap['infoflow3']) self.validate_permmap_entry(permmap._permmap, 'infoflow3', 'null', 'n', 1, True) # class file - self.assertIn("file", permmap._permmap) - self.assertEqual(2, len(permmap._permmap['file'])) + assert "file" in permmap._permmap + assert 2 == len(permmap._permmap['file']) self.validate_permmap_entry(permmap._permmap, 'file', 'execute', 'r', 10, True) self.validate_permmap_entry(permmap._permmap, 'file', 'entrypoint', 'r', 10, True) # class process - self.assertIn("process", permmap._permmap) - self.assertEqual(1, len(permmap._permmap['process'])) + assert "process" in permmap._permmap + assert 1 == len(permmap._permmap['process']) self.validate_permmap_entry(permmap._permmap, 'process', 'transition', 'w', 10, True) - def test_002_load_invalid(self): + def test_load_invalid(self) -> None: """PermMap load completely wrong file type""" - with self.assertRaises(PermissionMapParseError): + with pytest.raises(PermissionMapParseError): PermissionMap("setup.py") - def test_002_load_negative_class_count(self): + def test_load_negative_class_count(self) -> None: """PermMap load negative class count""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/negative-classcount") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/negative-classcount") - def test_003_load_non_number_class_count(self): + def test_load_non_number_class_count(self) -> None: """PermMap load non-number class count""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/non-number-classcount") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/non-number-classcount") - def test_004_load_extra_class(self): + def test_load_extra_class(self) -> None: """PermMap load extra class""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/extra-class") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/extra-class") - def test_005_load_bad_class_keyword(self): + def test_load_bad_class_keyword(self) -> None: """PermMap load bad class keyword""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/bad-class-keyword") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/bad-class-keyword") # test 6: bad class name(?) - def test_007_load_negative_perm_count(self): + def test_load_negative_perm_count(self) -> None: """PermMap load negative permission count""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/negative-permcount") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/negative-permcount") - def test_008_load_bad_perm_count(self): + def test_load_bad_perm_count(self) -> None: """PermMap load bad permission count""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/bad-permcount") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/bad-permcount") # test 9: bad perm name(?) - def test_010_load_extra_perms(self): + def test_load_extra_perms(self) -> None: """PermMap load negative permission count""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/extra-perms") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/extra-perms") - def test_011_load_invalid_flow_direction(self): + def test_load_invalid_flow_direction(self) -> None: """PermMap load invalid flow direction""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/invalid-flowdir") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/invalid-flowdir") - def test_012_load_bad_perm_weight(self): + def test_load_bad_perm_weight(self) -> None: """PermMap load too high/low permission weight""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/bad-perm-weight-high") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/bad-perm-weight-high") - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/bad-perm-weight-low") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/bad-perm-weight-low") - def test_013_load_invalid_weight(self): + def test_load_invalid_weight(self) -> None: """PermMap load invalid permission weight""" - with self.assertRaises(PermissionMapParseError): - PermissionMap("tests/invalid_perm_maps/invalid-perm-weight") + with pytest.raises(PermissionMapParseError): + PermissionMap("tests/library/invalid_perm_maps/invalid-perm-weight") - def test_100_set_weight(self): + def test_set_weight(self) -> None: """PermMap set weight""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'low_w', 'w', 1, True) permmap.set_weight("infoflow2", "low_w", 10) self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'low_w', 'w', 10, True) - def test_101_set_weight_low(self): + def test_set_weight_low(self) -> None: """PermMap set weight low""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(ValueError): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(ValueError): permmap.set_weight("infoflow2", "low_w", 0) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): permmap.set_weight("infoflow2", "low_w", -10) - def test_102_set_weight_low(self): + def test_set_weight_high(self) -> None: """PermMap set weight high""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(ValueError): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(ValueError): permmap.set_weight("infoflow2", "low_w", 11) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): permmap.set_weight("infoflow2", "low_w", 50) - def test_103_set_weight_unmapped_class(self): + def test_set_weight_unmapped_class(self) -> None: """PermMap set weight unmapped class""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedClass): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedClass): permmap.set_weight("UNMAPPED", "write", 10) - def test_104_set_weight_unmapped_permission(self): + def test_set_weight_unmapped_permission(self) -> None: """PermMap set weight unmapped class""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedPermission): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedPermission): permmap.set_weight("infoflow2", "UNMAPPED", 10) - def test_110_set_direction(self): + def test_set_direction(self) -> None: """PermMap set direction""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'low_w', 'w', 1, True) permmap.set_direction("infoflow2", "low_w", "r") self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'low_w', 'r', 1, True) - def test_111_set_direction_invalid(self): + def test_set_direction_invalid(self) -> None: """PermMap set invalid direction""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(ValueError): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(ValueError): permmap.set_direction("infoflow2", "low_w", "X") - def test_112_set_direction_unmapped_class(self): + def test_set_direction_unmapped_class(self) -> None: """PermMap set direction unmapped class""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedClass): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedClass): permmap.set_direction("UNMAPPED", "write", "w") - def test_113_set_direction_unmapped_permission(self): + def test_set_direction_unmapped_permission(self) -> None: """PermMap set direction unmapped class""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedPermission): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedPermission): permmap.set_direction("infoflow2", "UNMAPPED", "w") - def test_120_exclude_perm(self): + def test_exclude_perm(self) -> None: """PermMap exclude permission.""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") permmap.exclude_permission("infoflow", "med_w") self.validate_permmap_entry(permmap._permmap, 'infoflow', 'med_w', 'w', 5, False) - def test_121_exclude_perm_unmapped_class(self): + def test_exclude_perm_unmapped_class(self) -> None: """PermMap exclude permission unmapped class.""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedClass): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedClass): permmap.exclude_permission("UNMAPPED", "med_w") - def test_122_exclude_perm_unmapped_perm(self): + def test_exclude_perm_unmapped_perm(self) -> None: """PermMap exclude permission unmapped permission.""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedPermission): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedPermission): permmap.exclude_permission("infoflow", "UNMAPPED") - def test_123_include_perm(self): + def test_include_perm(self) -> None: """PermMap include permission.""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") permmap.exclude_permission("infoflow", "med_w") self.validate_permmap_entry(permmap._permmap, 'infoflow', 'med_w', 'w', 5, False) permmap.include_permission("infoflow", "med_w") self.validate_permmap_entry(permmap._permmap, 'infoflow', 'med_w', 'w', 5, True) - def test_124_include_perm_unmapped_class(self): + def test_include_perm_unmapped_class(self) -> None: """PermMap include permission unmapped class.""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedClass): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedClass): permmap.include_permission("UNMAPPED", "med_w") - def test_125_include_perm_unmapped_perm(self): + def test_include_perm_unmapped_perm(self) -> None: """PermMap include permission unmapped permission.""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedPermission): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedPermission): permmap.include_permission("infoflow", "UNMAPPED") - def test_130_exclude_class(self): + def test_exclude_class(self) -> None: """PermMap exclude class.""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") permmap.exclude_class("file") self.validate_permmap_entry(permmap._permmap, 'file', 'execute', 'r', 10, False) self.validate_permmap_entry(permmap._permmap, 'file', 'entrypoint', 'r', 10, False) - def test_131_exclude_class_unmapped_class(self): + def test_exclude_class_unmapped_class(self) -> None: """PermMap exclude class unmapped class.""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedClass): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedClass): permmap.exclude_class("UNMAPPED") - def test_132_include_class(self): + def test_include_class(self) -> None: """PermMap exclude class.""" - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") permmap.exclude_class("file") self.validate_permmap_entry(permmap._permmap, 'file', 'execute', 'r', 10, False) self.validate_permmap_entry(permmap._permmap, 'file', 'entrypoint', 'r', 10, False) @@ -271,122 +259,122 @@ def test_132_include_class(self): self.validate_permmap_entry(permmap._permmap, 'file', 'execute', 'r', 10, True) self.validate_permmap_entry(permmap._permmap, 'file', 'entrypoint', 'r', 10, True) - def test_133_include_class_unmapped_class(self): + def test_include_class_unmapped_class(self) -> None: """PermMap include class unmapped class.""" - permmap = PermissionMap("tests/perm_map") - with self.assertRaises(UnmappedClass): + permmap = PermissionMap("tests/library/perm_map") + with pytest.raises(UnmappedClass): permmap.include_class("UNMAPPED") - def test_140_weight_read_only(self): + def test_weight_read_only(self) -> None: """PermMap get weight of read-only rule.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow" rule.perms = set(["med_r", "hi_r"]) - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") weight = permmap.rule_weight(rule) - self.assertEqual(weight.read, 10) - self.assertEqual(weight.write, 0) + assert weight.read == 10 + assert weight.write == 0 - def test_141_weight_write_only(self): + def test_weight_write_only(self) -> None: """PermMap get weight of write-only rule.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow" rule.perms = set(["low_w", "med_w"]) - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") weight = permmap.rule_weight(rule) - self.assertEqual(weight.read, 0) - self.assertEqual(weight.write, 5) + assert weight.read == 0 + assert weight.write == 5 - def test_142_weight_both(self): + def test_weight_both(self) -> None: """PermMap get weight of both rule.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow" rule.perms = set(["low_r", "hi_w"]) - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") weight = permmap.rule_weight(rule) - self.assertEqual(weight.read, 1) - self.assertEqual(weight.write, 10) + assert weight.read == 1 + assert weight.write == 10 - def test_143_weight_none(self): + def test_weight_none(self) -> None: """PermMap get weight of none rule.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow3" rule.perms = set(["null"]) - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") weight = permmap.rule_weight(rule) - self.assertEqual(weight.read, 0) - self.assertEqual(weight.write, 0) + assert weight.read == 0 + assert weight.write == 0 - def test_144_weight_unmapped_class(self): + def test_weight_unmapped_class(self) -> None: """PermMap get weight of rule with unmapped class.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "unmapped" rule.perms = set(["null"]) - permmap = PermissionMap("tests/perm_map") - self.assertRaises(UnmappedClass, permmap.rule_weight, rule) + permmap = PermissionMap("tests/library/perm_map") + pytest.raises(UnmappedClass, permmap.rule_weight, rule) - def test_145_weight_unmapped_permission(self): + def test_weight_unmapped_permission(self) -> None: """PermMap get weight of rule with unmapped permission.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow" rule.perms = set(["low_r", "unmapped"]) - permmap = PermissionMap("tests/perm_map") - self.assertRaises(UnmappedPermission, permmap.rule_weight, rule) + permmap = PermissionMap("tests/library/perm_map") + pytest.raises(UnmappedPermission, permmap.rule_weight, rule) - def test_146_weight_wrong_rule_type(self): + def test_weight_wrong_rule_type(self) -> None: """PermMap get weight of rule with wrong rule type.""" rule = Mock() rule.ruletype = TERuletype.type_transition rule.tclass = "infoflow" - permmap = PermissionMap("tests/perm_map") - self.assertRaises(RuleTypeError, permmap.rule_weight, rule) + permmap = PermissionMap("tests/library/perm_map") + pytest.raises(RuleTypeError, permmap.rule_weight, rule) - def test_147_weight_excluded_permission(self): + def test_weight_excluded_permission(self) -> None: """PermMap get weight of a rule with excluded permission.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow" rule.perms = set(["med_r", "hi_r"]) - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") permmap.exclude_permission("infoflow", "hi_r") weight = permmap.rule_weight(rule) - self.assertEqual(weight.read, 5) - self.assertEqual(weight.write, 0) + assert weight.read == 5 + assert weight.write == 0 - def test_148_weight_excluded_class(self): + def test_weight_excluded_class(self) -> None: """PermMap get weight of a rule with excluded class.""" rule = Mock() rule.ruletype = TERuletype.allow rule.tclass = "infoflow" rule.perms = set(["low_r", "med_r", "hi_r", "low_w", "med_w", "hi_w"]) - permmap = PermissionMap("tests/perm_map") + permmap = PermissionMap("tests/library/perm_map") permmap.exclude_class("infoflow") weight = permmap.rule_weight(rule) - self.assertEqual(weight.read, 0) - self.assertEqual(weight.write, 0) + assert weight.read == 0 + assert weight.write == 0 - def test_150_map_policy(self): + def test_map_policy(self, compiled_policy: setools.SELinuxPolicy) -> None: """PermMap create mappings for classes/perms in a policy.""" - permmap = PermissionMap("tests/perm_map") - permmap.map_policy(self.p) + permmap = PermissionMap("tests/library/perm_map") + permmap.map_policy(compiled_policy) self.validate_permmap_entry(permmap._permmap, 'infoflow2', 'new_perm', 'u', 1, True) - self.assertIn("new_class", permmap._permmap) - self.assertEqual(1, len(permmap._permmap['new_class'])) + assert "new_class" in permmap._permmap + assert 1 == len(permmap._permmap['new_class']) self.validate_permmap_entry(permmap._permmap, 'new_class', 'new_class_perm', 'u', 1, True) diff --git a/tests/library/test_pirqconquery.py b/tests/library/test_pirqconquery.py new file mode 100644 index 00000000..8da451a2 --- /dev/null +++ b/tests/library/test_pirqconquery.py @@ -0,0 +1,196 @@ +# Derived from tests/portconquery.py +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/pirqconquery.conf", xen=True) +class TestPirqconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with no criteria""" + # query with no parameters gets all PCI irqs. + rules = sorted(compiled_policy.pirqcons()) + + q = setools.PirqconQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context user exact match""" + q = setools.PirqconQuery(compiled_policy, user="user10", user_regex=False) + + irq = sorted(p.irq for p in q.results()) + assert [(10)] == irq + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context user regex match""" + q = setools.PirqconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + irq = sorted(p.irq for p in q.results()) + assert [(11), (11000)] == irq + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context role exact match""" + q = setools.PirqconQuery(compiled_policy, role="role20_r", role_regex=False) + + irq = sorted(p.irq for p in q.results()) + assert [(20)] == irq + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context role regex match""" + q = setools.PirqconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + irq = sorted(p.irq for p in q.results()) + assert [(21), (21001)] == irq + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context type exact match""" + q = setools.PirqconQuery(compiled_policy, type_="type30", type_regex=False) + + irq = sorted(p.irq for p in q.results()) + assert [(30)] == irq + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context type regex match""" + q = setools.PirqconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + irq = sorted(p.irq for p in q.results()) + assert [(31000), (31001)] == irq + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range exact match""" + q = setools.PirqconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + irq = sorted(p.irq for p in q.results()) + assert [(40)] == irq + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range overlap match (equal)""" + q = setools.PirqconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(41)] == irq + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range overlap match (subset)""" + q = setools.PirqconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(41)] == irq + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range overlap match (superset)""" + q = setools.PirqconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(41)] == irq + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range overlap match (overlap low level)""" + q = setools.PirqconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(41)] == irq + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range overlap match (overlap high level)""" + q = setools.PirqconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(41)] == irq + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range subset match""" + q = setools.PirqconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(42)] == irq + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range subset match (equal)""" + q = setools.PirqconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + irq = sorted(p.irq for p in q.results()) + assert [(42)] == irq + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range superset match""" + q = setools.PirqconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + irq = sorted(p.irq for p in q.results()) + assert [(43)] == irq + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range superset match (equal)""" + q = setools.PirqconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + irq = sorted(p.irq for p in q.results()) + assert [(43)] == irq + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper subset match""" + q = setools.PirqconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [(44)] == irq + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper subset match (equal)""" + q = setools.PirqconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [] == irq + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper subset match (equal low only)""" + q = setools.PirqconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [(44)] == irq + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper subset match (equal high only)""" + q = setools.PirqconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [(44)] == irq + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper superset match""" + q = setools.PirqconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [(45)] == irq + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper superset match (equal)""" + q = setools.PirqconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [] == irq + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper superset match (equal low)""" + q = setools.PirqconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [(45)] == irq + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Pirqcon query with context range proper superset match (equal high)""" + q = setools.PirqconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + irq = sorted(p.irq for p in q.results()) + assert [(45)] == irq diff --git a/tests/library/test_polcapquery.py b/tests/library/test_polcapquery.py new file mode 100644 index 00000000..494fefd1 --- /dev/null +++ b/tests/library/test_polcapquery.py @@ -0,0 +1,34 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/polcapquery.conf") +class TestPolCapQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Policy capability query with no criteria""" + # query with no parameters gets all capabilities. + allcaps = sorted(compiled_policy.polcaps()) + + q = setools.PolCapQuery(compiled_policy) + qcaps = sorted(q.results()) + + assert allcaps == qcaps + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Policy capability query with exact match""" + q = setools.PolCapQuery(compiled_policy, name="open_perms", name_regex=False) + + caps = sorted(str(c) for c in q.results()) + assert ["open_perms"] == caps + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Policy capability query with regex match""" + q = setools.PolCapQuery(compiled_policy, name="pe?er", name_regex=True) + + caps = sorted(str(c) for c in q.results()) + assert ["network_peer_controls", "open_perms"] == caps diff --git a/tests/library/test_portconquery.py b/tests/library/test_portconquery.py new file mode 100644 index 00000000..077c8add --- /dev/null +++ b/tests/library/test_portconquery.py @@ -0,0 +1,435 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +from socket import IPPROTO_UDP + +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/portconquery.conf") +class TestPortconQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with no criteria""" + # query with no parameters gets all ports. + rules = sorted(compiled_policy.portcons()) + + q = setools.PortconQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_protocol(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with protocol match""" + q = setools.PortconQuery(compiled_policy, protocol=IPPROTO_UDP) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(1, 1)] == ports + + def test_user_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context user exact match""" + q = setools.PortconQuery(compiled_policy, user="user10", user_regex=False) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(10, 10)] == ports + + def test_user_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context user regex match""" + q = setools.PortconQuery(compiled_policy, user="user11(a|b)", user_regex=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(11, 11), setools.PortconRange(11000, 11000)] == ports + + def test_role_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context role exact match""" + q = setools.PortconQuery(compiled_policy, role="role20_r", role_regex=False) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(20, 20)] == ports + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context role regex match""" + q = setools.PortconQuery(compiled_policy, role="role21(a|c)_r", role_regex=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(21, 21), setools.PortconRange(21001, 21001)] == ports + + def test_type_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context type exact match""" + q = setools.PortconQuery(compiled_policy, type_="type30", type_regex=False) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(30, 30)] == ports + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context type regex match""" + q = setools.PortconQuery(compiled_policy, type_="type31(b|c)", type_regex=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(31000, 31000), setools.PortconRange(31001, 31001)] == ports + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range exact match""" + q = setools.PortconQuery(compiled_policy, range_="s0:c1 - s0:c0.c4") + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(40, 40)] == ports + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (equal)""" + q = setools.PortconQuery(compiled_policy, range_="s1:c1 - s1:c0.c4", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(41, 41)] == ports + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (subset)""" + q = setools.PortconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(41, 41)] == ports + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (superset)""" + q = setools.PortconQuery(compiled_policy, range_="s1 - s1:c0.c4", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(41, 41)] == ports + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (overlap low level)""" + q = setools.PortconQuery(compiled_policy, range_="s1 - s1:c1,c2", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(41, 41)] == ports + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range overlap match (overlap high level)""" + q = setools.PortconQuery(compiled_policy, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(41, 41)] == ports + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range subset match""" + q = setools.PortconQuery(compiled_policy, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(42, 42)] == ports + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range subset match (equal)""" + q = setools.PortconQuery(compiled_policy, range_="s2:c1 - s2:c1.c3", range_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(42, 42)] == ports + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range superset match""" + q = setools.PortconQuery(compiled_policy, range_="s3 - s3:c0.c4", range_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(43, 43)] == ports + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range superset match (equal)""" + q = setools.PortconQuery(compiled_policy, range_="s3:c1 - s3:c1.c3", range_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(43, 43)] == ports + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match""" + q = setools.PortconQuery(compiled_policy, range_="s4:c1,c2", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(44, 44)] == ports + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match (equal)""" + q = setools.PortconQuery(compiled_policy, range_="s4:c1 - s4:c1.c3", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match (equal low only)""" + q = setools.PortconQuery(compiled_policy, range_="s4:c1 - s4:c1.c2", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(44, 44)] == ports + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper subset match (equal high only)""" + q = setools.PortconQuery(compiled_policy, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(44, 44)] == ports + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match""" + q = setools.PortconQuery(compiled_policy, range_="s5 - s5:c0.c4", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(45, 45)] == ports + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match (equal)""" + q = setools.PortconQuery(compiled_policy, range_="s5:c1 - s5:c1.c3", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match (equal low)""" + q = setools.PortconQuery(compiled_policy, range_="s5:c1 - s5:c1.c4", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(45, 45)] == ports + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with context range proper superset match (equal high)""" + q = setools.PortconQuery(compiled_policy, range_="s5 - s5:c1.c3", range_superset=True, + range_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(45, 45)] == ports + + def test_single_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port exact match""" + q = setools.PortconQuery(compiled_policy, ports=(50, 50)) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50, 50)] == ports + + def test_range_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with port range exact match""" + q = setools.PortconQuery(compiled_policy, ports=(50100, 50110)) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50100, 50110)] == ports + + def test_single_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port subset""" + q = setools.PortconQuery(compiled_policy, ports=(50200, 50200), ports_subset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50200, 50200)] == ports + + def test_range_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range subset""" + q = setools.PortconQuery(compiled_policy, ports=(50301, 50309), ports_subset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50300, 50310)] == ports + + def test_range_subset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range subset, equal edge case""" + q = setools.PortconQuery(compiled_policy, ports=(50300, 50310), ports_subset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50300, 50310)] == ports + + def test_single_proper_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper subset""" + q = setools.PortconQuery( + compiled_policy, ports=(50400, 50400), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_subset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset""" + q = setools.PortconQuery( + compiled_policy, ports=(50501, 50509), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50500, 50510)] == ports + + def test_range_proper_subset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset, equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50500, 50510), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_subset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset, low equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50500, 50509), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50500, 50510)] == ports + + def test_range_proper_subset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper subset, high equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50501, 50510), ports_subset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50500, 50510)] == ports + + def test_single_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port superset""" + q = setools.PortconQuery(compiled_policy, ports=(50600, 50602), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50601, 50601)] == ports + + def test_single_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port superset, equal edge case""" + q = setools.PortconQuery(compiled_policy, ports=(50601, 50601), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50601, 50601)] == ports + + def test_range_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range superset""" + q = setools.PortconQuery(compiled_policy, ports=(50700, 50711), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50700, 50710)] == ports + + def test_range_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range superset, equal edge case""" + q = setools.PortconQuery(compiled_policy, ports=(50700, 50710), ports_superset=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50700, 50710)] == ports + + def test_single_proper_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset""" + q = setools.PortconQuery( + compiled_policy, ports=(50800, 50802), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50801, 50801)] == ports + + def test_single_proper_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset, equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50801, 50801), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_single_proper_superset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset, low equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50801, 50802), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50801, 50801)] == ports + + def test_single_proper_superset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single port proper superset, high equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50800, 50801), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50801, 50801)] == ports + + def test_range_proper_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset""" + q = setools.PortconQuery( + compiled_policy, ports=(50900, 50911), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50901, 50910)] == ports + + def test_range_proper_superset_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset, equal edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50901, 50910), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [] == ports + + def test_range_proper_superset_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset, equal high port edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50900, 50910), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50901, 50910)] == ports + + def test_range_proper_superset_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range proper superset, equal low port edge case""" + q = setools.PortconQuery( + compiled_policy, ports=(50901, 50911), ports_superset=True, ports_proper=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(50901, 50910)] == ports + + def test_single_overlap(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap""" + q = setools.PortconQuery(compiled_policy, ports=(60001, 60001), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60001, 60001)] == ports + + def test_single_overlap_edge1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap, range match low""" + q = setools.PortconQuery(compiled_policy, ports=(60001, 60002), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60001, 60001)] == ports + + def test_single_overlap_edge2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap, range match high""" + q = setools.PortconQuery(compiled_policy, ports=(60000, 60001), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60001, 60001)] == ports + + def test_single_overlap_edge3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with single overlap, range match proper superset""" + q = setools.PortconQuery(compiled_policy, ports=(60000, 60002), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60001, 60001)] == ports + + def test_range_overlap_low_half(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, low half match""" + q = setools.PortconQuery(compiled_policy, ports=(60100, 60105), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60101, 60110)] == ports + + def test_range_overlap_high_half(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, high half match""" + q = setools.PortconQuery(compiled_policy, ports=(60205, 60211), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60200, 60210)] == ports + + def test_range_overlap_middle(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, middle match""" + q = setools.PortconQuery(compiled_policy, ports=(60305, 60308), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60300, 60310)] == ports + + def test_range_overlap_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, equal match""" + q = setools.PortconQuery(compiled_policy, ports=(60400, 60410), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60400, 60410)] == ports + + def test_range_overlap_superset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Portcon query with range overlap, superset match""" + q = setools.PortconQuery(compiled_policy, ports=(60500, 60510), ports_overlap=True) + + ports = sorted(p.ports for p in q.results()) + assert [setools.PortconRange(60501, 60509)] == ports diff --git a/tests/library/test_rbacrulequery.py b/tests/library/test_rbacrulequery.py new file mode 100644 index 00000000..b5b979e8 --- /dev/null +++ b/tests/library/test_rbacrulequery.py @@ -0,0 +1,134 @@ +"""RBAC rule query unit tests.""" +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +# pylint: disable=invalid-name,too-many-public-methods +import pytest +import setools +from setools import RBACRuleQuery +from setools import RBACRuletype as RRT +from setools.exception import RuleUseError, RuleNotConditional + +from . import util + + +@pytest.mark.obj_args("tests/library/rbacrulequery.conf") +class TestRBACRuleQuery: + + """RBAC rule query unit tests.""" + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with no criteria.""" + # query with no parameters gets all RBAC rules. + rules = sorted(compiled_policy.rbacrules()) + + q = RBACRuleQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_source_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with exact, direct, source match.""" + q = RBACRuleQuery( + compiled_policy, source="test1s", source_indirect=False, source_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + + util.validate_rule(r[0], RRT.allow, "test1s", "test1t") + util.validate_rule(r[1], RRT.role_transition, "test1s", "system", tclass="infoflow", + default="test1t") + + def test_source_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with regex, direct, source match.""" + q = RBACRuleQuery( + compiled_policy, source="test2s(1|2)", source_indirect=False, source_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RRT.allow, "test2s1", "test2t") + + def test_target_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with exact, direct, target match.""" + q = RBACRuleQuery( + compiled_policy, target="test10t", target_indirect=False, target_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RRT.allow, "test10s", "test10t") + + def test_target_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with regex, direct, target match.""" + q = RBACRuleQuery( + compiled_policy, target="test11t(1|3)", target_indirect=False, target_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RRT.allow, "test11s", "test11t1") + + def test_target_type(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with a type as target.""" + q = RBACRuleQuery(compiled_policy, target="test12t") + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RRT.role_transition, "test12s", "test12t", tclass="infoflow", + default="test12d") + + def test_class_list(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with object class list match.""" + q = RBACRuleQuery( + compiled_policy, tclass=["infoflow3", "infoflow4"], tclass_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RRT.role_transition, "test21", "system", tclass="infoflow3", + default="test21d3") + util.validate_rule(r[1], RRT.role_transition, "test21", "system", tclass="infoflow4", + default="test21d2") + + def test_class_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with object class regex match.""" + q = RBACRuleQuery(compiled_policy, tclass="infoflow(5|6)", tclass_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RRT.role_transition, "test22", "system", tclass="infoflow5", + default="test22d2") + util.validate_rule(r[1], RRT.role_transition, "test22", "system", tclass="infoflow6", + default="test22d3") + + def test_default(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with exact default match.""" + q = RBACRuleQuery( + compiled_policy, default="test30d", default_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], RRT.role_transition, "test30s", "system", tclass="infoflow", + default="test30d") + + def test_default_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with regex default match.""" + q = RBACRuleQuery( + compiled_policy, default="test31d(2|3)", default_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], RRT.role_transition, "test31s", "system", tclass="infoflow7", + default="test31d3") + util.validate_rule(r[1], RRT.role_transition, "test31s", "system", tclass="process", + default="test31d2") + + def test_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """RBAC rule query with rule type.""" + q = RBACRuleQuery(compiled_policy, ruletype=[RRT.allow]) + + num = 0 + for num, r in enumerate(sorted(q.results()), start=1): + assert r.ruletype == RRT.allow + + # this will have to be updated as number of + # role allows change in the test policy + assert num == 9 diff --git a/tests/library/test_rolequery.py b/tests/library/test_rolequery.py new file mode 100644 index 00000000..95c19b1c --- /dev/null +++ b/tests/library/test_rolequery.py @@ -0,0 +1,57 @@ +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/rolequery.conf") +class TestRoleQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role query with no criteria.""" + # query with no parameters gets all types. + roles = sorted(compiled_policy.roles()) + + q = setools.RoleQuery(compiled_policy) + q_roles = sorted(q.results()) + + assert roles == q_roles + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role query with exact name match.""" + q = setools.RoleQuery(compiled_policy, name="test1") + + roles = sorted(str(r) for r in q.results()) + assert ["test1"] == roles + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role query with regex name match.""" + q = setools.RoleQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + roles = sorted(str(r) for r in q.results()) + assert ["test2a", "test2b"] == roles + + def test_type_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role query with type set intersection.""" + q = setools.RoleQuery(compiled_policy, types=["test10a", "test10b"]) + + roles = sorted(str(r) for r in q.results()) + assert ["test10r1", "test10r2", "test10r3", + "test10r4", "test10r5", "test10r6"] == roles + + def test_type_equality(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role query with type set equality.""" + q = setools.RoleQuery(compiled_policy, types=["test11a", "test11b"], types_equal=True) + + roles = sorted(str(r) for r in q.results()) + assert ["test11r2"] == roles + + def test_type_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Role query with type set match.""" + q = setools.RoleQuery(compiled_policy, types="test12(a|b)", types_regex=True) + + roles = sorted(str(r) for r in q.results()) + assert ["test12r1", "test12r2", "test12r3", + "test12r4", "test12r5", "test12r6"] == roles diff --git a/tests/library/test_sensitivityquery.py b/tests/library/test_sensitivityquery.py new file mode 100644 index 00000000..b95fad16 --- /dev/null +++ b/tests/library/test_sensitivityquery.py @@ -0,0 +1,83 @@ +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/sensitivityquery.conf") +class TestSensitivityQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with no criteria.""" + # query with no parameters gets all sensitivities. + allsens = sorted(str(c) for c in compiled_policy.sensitivities()) + + q = setools.SensitivityQuery(compiled_policy) + qsens = sorted(str(c) for c in q.results()) + + assert allsens == qsens + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with exact name match.""" + q = setools.SensitivityQuery(compiled_policy, name="test1") + + sens = sorted(str(c) for c in q.results()) + assert ["test1"] == sens + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with regex name match.""" + q = setools.SensitivityQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + sens = sorted(str(c) for c in q.results()) + assert ["test2a", "test2b"] == sens + + def test_alias_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with exact alias match.""" + q = setools.SensitivityQuery(compiled_policy, alias="test10a") + + sens = sorted(str(t) for t in q.results()) + assert ["test10s1"] == sens + + def test_alias_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with regex alias match.""" + q = setools.SensitivityQuery(compiled_policy, alias="test11(a|b)", alias_regex=True) + + sens = sorted(str(t) for t in q.results()) + assert ["test11s1", "test11s2"] == sens + + def test_sens_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with sens equality.""" + q = setools.SensitivityQuery(compiled_policy, sens="test20") + + sens = sorted(str(u) for u in q.results()) + assert ["test20"] == sens + + def test_sens_dom1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with sens dominance.""" + q = setools.SensitivityQuery(compiled_policy, sens="test21crit", sens_dom=True) + + sens = sorted(str(u) for u in q.results()) + assert ["test21", "test21crit"] == sens + + def test_sens_dom2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with sens dominance (equal).""" + q = setools.SensitivityQuery(compiled_policy, sens="test21", sens_dom=True) + + sens = sorted(str(u) for u in q.results()) + assert ["test21"] == sens + + def test_sens_domby1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with sens dominated-by.""" + q = setools.SensitivityQuery(compiled_policy, sens="test22crit", sens_domby=True) + + sens = sorted(str(u) for u in q.results()) + assert ["test22", "test22crit"] == sens + + def test_sens_domby2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Sensitivity query with sens dominated-by (equal).""" + q = setools.SensitivityQuery(compiled_policy, sens="test22", sens_domby=True) + + sens = sorted(str(u) for u in q.results()) + assert ["test22"] == sens diff --git a/tests/library/test_terulequery.py b/tests/library/test_terulequery.py new file mode 100644 index 00000000..7b837aea --- /dev/null +++ b/tests/library/test_terulequery.py @@ -0,0 +1,464 @@ +"""Type enforcement rule query unit tests.""" +# Copyright 2014, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +# pylint: disable=invalid-name,too-many-public-methods +import pytest +import setools +from setools import TERuleQuery +from setools import TERuletype as TRT + +from . import util + + +@pytest.mark.obj_args("tests/library/terulequery.conf") +class TestTERuleQuery: + + """Type enforcement rule query unit tests.""" + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with no criteria.""" + # query with no parameters gets all TE rules. + rules = sorted(compiled_policy.terules()) + + q = TERuleQuery(compiled_policy) + q_rules = sorted(q.results()) + + assert rules == q_rules + + def test_source_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with exact, direct, source match.""" + q = TERuleQuery( + compiled_policy, source="test1a", source_indirect=False, source_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test1a", "test1t", tclass="infoflow", + perms=set(["hi_w"])) + + def test_source_indirect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with exact, indirect, source match.""" + q = TERuleQuery( + compiled_policy, source="test2s", source_indirect=True, source_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test2a", "test2t", tclass="infoflow", + perms=set(["hi_w"])) + + def test_source_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with regex, direct, source match.""" + q = TERuleQuery( + compiled_policy, source="test3a.*", source_indirect=False, source_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test3aS", "test3t", tclass="infoflow", + perms=set(["low_r"])) + + def test_source_indirect_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with regex, indirect, source match.""" + q = TERuleQuery( + compiled_policy, source="test4(s|t)", source_indirect=True, source_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test4a1", "test4a1", tclass="infoflow", + perms=set(["hi_w"])) + util.validate_rule(r[1], TRT.allow, "test4a2", "test4a2", tclass="infoflow", + perms=set(["low_r"])) + + def test_target_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with exact, direct, target match.""" + q = TERuleQuery( + compiled_policy, target="test5a", target_indirect=False, target_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test5s", "test5a", tclass="infoflow", + perms=set(["hi_w"])) + + def test_target_indirect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with exact, indirect, target match.""" + q = TERuleQuery( + compiled_policy, target="test6t", target_indirect=True, target_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test6s", "test6a", tclass="infoflow", + perms=set(["hi_w"])) + util.validate_rule(r[1], TRT.allow, "test6s", "test6t", tclass="infoflow", + perms=set(["low_r"])) + + def test_target_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with regex, direct, target match.""" + q = TERuleQuery( + compiled_policy, target="test7a.*", target_indirect=False, target_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test7s", "test7aPASS", tclass="infoflow", + perms=set(["low_r"])) + + def test_target_indirect_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with regex, indirect, target match.""" + q = TERuleQuery( + compiled_policy, target="test8(s|t)", target_indirect=True, target_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test8a1", "test8a1", tclass="infoflow", + perms=set(["hi_w"])) + util.validate_rule(r[1], TRT.allow, "test8a2", "test8a2", tclass="infoflow", + perms=set(["low_r"])) + + def test_class_list(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with object class list match.""" + q = TERuleQuery( + compiled_policy, tclass=["infoflow3", "infoflow4"], tclass_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test10", "test10", tclass="infoflow3", + perms=set(["null"])) + util.validate_rule(r[1], TRT.allow, "test10", "test10", tclass="infoflow4", + perms=set(["hi_w"])) + + def test_class_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with object class regex match.""" + q = TERuleQuery(compiled_policy, tclass="infoflow(5|6)", tclass_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test11", "test11", tclass="infoflow5", + perms=set(["low_w"])) + util.validate_rule(r[1], TRT.allow, "test11", "test11", tclass="infoflow6", + perms=set(["med_r"])) + + def test_perms_any(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with permission set intersection.""" + q = TERuleQuery(compiled_policy, perms=["super_r"], perms_equal=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test12a", "test12a", tclass="infoflow7", + perms=set(["super_r"])) + util.validate_rule(r[1], TRT.allow, "test12b", "test12b", tclass="infoflow7", + perms=set(["super_r", "super_none"])) + + def test_perms_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with permission set equality.""" + q = TERuleQuery( + compiled_policy, perms=["super_w", "super_none", "super_both"], perms_equal=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test13c", "test13c", tclass="infoflow7", + perms=set(["super_w", "super_none", "super_both"])) + + def test_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with rule type match.""" + q = TERuleQuery(compiled_policy, ruletype=["auditallow", "dontaudit"]) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.auditallow, "test14", "test14", tclass="infoflow7", + perms=set(["super_both"])) + util.validate_rule(r[1], TRT.dontaudit, "test14", "test14", tclass="infoflow7", + perms=set(["super_unmapped"])) + + def test_perms_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with permission subset.""" + q = TERuleQuery(compiled_policy, perms=["super_none", "super_both"], perms_subset=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test13c", "test13c", tclass="infoflow7", + perms=set(["super_w", "super_none", "super_both"])) + util.validate_rule(r[1], TRT.allow, "test13d", "test13d", tclass="infoflow7", + perms=set(["super_w", "super_none", "super_both", "super_unmapped"])) + + def test_perms_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with permission subset (equality).""" + q = TERuleQuery(compiled_policy, perms=["super_w", "super_none", "super_both", + "super_unmapped"], + perms_subset=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test13d", "test13d", tclass="infoflow7", + perms=set(["super_w", "super_none", "super_both", "super_unmapped"])) + + def test_default(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with default type exact match.""" + q = TERuleQuery(compiled_policy, default="test100d", default_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.type_transition, "test100", "test100", tclass="infoflow7", + default="test100d") + + def test_default_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with default type regex match.""" + q = TERuleQuery(compiled_policy, default="test101.", default_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.type_transition, "test101", "test101d", tclass="infoflow7", + default="test101e") + util.validate_rule(r[1], TRT.type_transition, "test101", "test101e", tclass="infoflow7", + default="test101d") + + def test_boolean_intersection(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with intersection Boolean set match.""" + q = TERuleQuery(compiled_policy, boolean=["test200"]) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test200t1", "test200t1", tclass="infoflow7", + perms=set(["super_w"]), cond="test200", cond_block=True) + util.validate_rule(r[1], TRT.allow, "test200t2", "test200t2", tclass="infoflow7", + perms=set(["super_w"]), cond="test200a && test200", cond_block=True) + + def test_boolean_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with equal Boolean set match.""" + q = TERuleQuery(compiled_policy, boolean=["test201a", "test201b"], boolean_equal=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allow, "test201t1", "test201t1", tclass="infoflow7", + perms=set(["super_unmapped"]), cond="test201b && test201a", + cond_block=True) + + def test_boolean_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with regex Boolean match.""" + q = TERuleQuery(compiled_policy, boolean="test202(a|b)", boolean_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allow, "test202t1", "test202t1", tclass="infoflow7", + perms=set(["super_none"]), cond="test202a", cond_block=True) + util.validate_rule(r[1], TRT.allow, "test202t2", "test202t2", tclass="infoflow7", + perms=set(["super_unmapped"]), cond="test202b || test202c", + cond_block=True) + + def test_issue111(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with attribute source criteria, indirect match.""" + # https://github.com/TresysTechnology/setools/issues/111 + q = TERuleQuery(compiled_policy, source="test300b", source_indirect=True) + + r = sorted(q.results()) + assert len(r) == 4 + util.validate_rule(r[0], TRT.allow, "test300a", "test300target", tclass="infoflow7", + perms=set(["hi_w"])) + util.validate_rule(r[1], TRT.allow, "test300b", "test300target", tclass="infoflow7", + perms=set(["super_w"])) + util.validate_rule(r[2], TRT.allow, "test300t1", "test300t1", tclass="infoflow7", + perms=set(["hi_r"])) + util.validate_rule(r[3], TRT.allow, "test300t2", "test300t2", tclass="infoflow7", + perms=set(["med_w"])) + + def test_issue111_2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with attribute target criteria, indirect match.""" + # https://github.com/TresysTechnology/setools/issues/111 + q = TERuleQuery(compiled_policy, target="test301b", target_indirect=True) + + r = sorted(q.results()) + assert len(r) == 4 + util.validate_rule(r[0], TRT.allow, "test301source", "test301a", tclass="infoflow7", + perms=set(["hi_w"])) + util.validate_rule(r[1], TRT.allow, "test301source", "test301b", tclass="infoflow7", + perms=set(["super_w"])) + util.validate_rule(r[2], TRT.allow, "test301t1", "test301t1", tclass="infoflow7", + perms=set(["hi_r"])) + util.validate_rule(r[3], TRT.allow, "test301t2", "test301t2", tclass="infoflow7", + perms=set(["med_w"])) + + def test_issue111_3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """TE rule query with attribute default type criteria.""" + # https://github.com/TresysTechnology/setools/issues/111 + q = TERuleQuery(compiled_policy, default="test302") + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.type_transition, "test302source", "test302t1", + tclass="infoflow7", default="test302t1") + util.validate_rule(r[1], TRT.type_transition, "test302source", "test302t2", + tclass="infoflow7", default="test302t2") + + +@pytest.mark.obj_args("tests/library/terulequery2.conf") +class TERuleQueryXperm: + + """TE Rule Query with extended permission rules.""" + + def test_source_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with exact, direct, source match.""" + q = TERuleQuery( + compiled_policy, source="test1a", source_indirect=False, source_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allowxperm, "test1a", "test1t", tclass="infoflow", + perms=setools.IoctlSet(range(0xebe0, 0xebff + 1)), xperm="ioctl") + + def test_source_indirect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with exact, indirect, source match.""" + q = TERuleQuery( + compiled_policy, source="test2s", source_indirect=True, source_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allowxperm, "test2a", "test2t", tclass="infoflow", + perms=setools.IoctlSet([0x5411, 0x5451]), xperm="ioctl") + + def test_source_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with regex, direct, source match.""" + q = TERuleQuery( + compiled_policy, source="test3a.*", source_indirect=False, source_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allowxperm, "test3aS", "test3t", tclass="infoflow", + perms=setools.IoctlSet([0x1111]), xperm="ioctl") + + def test_source_indirect_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with regex, indirect, source match.""" + q = TERuleQuery( + compiled_policy, source="test4(s|t)", source_indirect=True, source_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allowxperm, "test4a1", "test4a1", tclass="infoflow", + perms=setools.IoctlSet([0x9999]), xperm="ioctl") + util.validate_rule(r[1], TRT.allowxperm, "test4a2", "test4a2", tclass="infoflow", + perms=setools.IoctlSet([0x1111]), xperm="ioctl") + + def test_target_direct(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with exact, direct, target match.""" + q = TERuleQuery( + compiled_policy, target="test5a", target_indirect=False, target_regex=False) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allowxperm, "test5s", "test5a", tclass="infoflow", + perms=setools.IoctlSet([0x9999]), xperm="ioctl") + + def test_target_indirect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with exact, indirect, target match.""" + q = TERuleQuery( + compiled_policy, target="test6t", target_indirect=True, target_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allowxperm, "test6s", "test6a", tclass="infoflow", + perms=setools.IoctlSet([0x9999]), xperm="ioctl") + util.validate_rule(r[1], TRT.allowxperm, "test6s", "test6t", tclass="infoflow", + perms=setools.IoctlSet([0x1111]), xperm="ioctl") + + def test_target_direct_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with regex, direct, target match.""" + q = TERuleQuery( + compiled_policy, target="test7a.*", target_indirect=False, target_regex=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allowxperm, "test7s", "test7aPASS", tclass="infoflow", + perms=setools.IoctlSet([0x1111]), xperm="ioctl") + + def test_target_indirect_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with regex, indirect, target match.""" + q = TERuleQuery( + compiled_policy, target="test8(s|t)", target_indirect=True, target_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allowxperm, "test8a1", "test8a1", tclass="infoflow", + perms=setools.IoctlSet([0x9999]), xperm="ioctl") + util.validate_rule(r[1], TRT.allowxperm, "test8a2", "test8a2", tclass="infoflow", + perms=setools.IoctlSet([0x1111]), xperm="ioctl") + + def test_class_list(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with object class list match.""" + q = TERuleQuery( + compiled_policy, tclass=["infoflow3", "infoflow4"], tclass_regex=False) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allowxperm, "test10", "test10", tclass="infoflow3", + perms=setools.IoctlSet([0]), xperm="ioctl") + util.validate_rule(r[1], TRT.allowxperm, "test10", "test10", tclass="infoflow4", + perms=setools.IoctlSet([0x9999]), xperm="ioctl") + + def test_class_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with object class regex match.""" + q = TERuleQuery(compiled_policy, tclass="infoflow(5|6)", tclass_regex=True) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.allowxperm, "test11", "test11", tclass="infoflow5", + perms=setools.IoctlSet([0x1111]), xperm="ioctl") + util.validate_rule(r[1], TRT.allowxperm, "test11", "test11", tclass="infoflow6", + perms=setools.IoctlSet([0x5555]), xperm="ioctl") + + def test_ruletype(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query with rule type match.""" + q = TERuleQuery(compiled_policy, ruletype=["auditallowxperm", "dontauditxperm"]) + + r = sorted(q.results()) + assert len(r) == 2 + util.validate_rule(r[0], TRT.auditallowxperm, "test14", "test14", tclass="infoflow7", + perms=setools.IoctlSet([0x1234]), xperm="ioctl") + util.validate_rule(r[1], TRT.dontauditxperm, "test14", "test14", tclass="infoflow7", + perms=setools.IoctlSet([0x4321]), xperm="ioctl") + + def test_std_perm_any(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query match by standard permission.""" + q = TERuleQuery(compiled_policy, ruletype=["neverallow", "neverallowxperm"], + perms=set(["ioctl", "hi_w"]), perms_equal=False) + + r = sorted(q.results()) + assert len(r) == 0 + # changed after dropping source policy support + # assert len(r) == 2 + # util.validate_rule(r[0], TRT.neverallow, "test100", "system", "infoflow2", + # set(["ioctl", "hi_w"])) + # util.validate_rule(r[1], TRT.neverallowxperm, "test100", "test100", "infoflow2", + # setools.IoctlSet([0x1234]), xperm="ioctl") + + def test_std_perm_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query match by standard permission, equal perm set.""" + q = TERuleQuery(compiled_policy, ruletype=["neverallow", "neverallowxperm"], + perms=set(["ioctl", "hi_w"]), perms_equal=True) + + r = sorted(q.results()) + assert len(r) == 0 + # changed after dropping source policy support + # assert len(r) == 1 + # util.validate_rule(r[0], TRT.neverallow, "test100", "system", "infoflow2", + # set(["ioctl", "hi_w"])) + + def test_xperm_any(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query match any perm set.""" + q = TERuleQuery(compiled_policy, xperms=[(0x9011, 0x9013)], xperms_equal=False) + + r = sorted(q.results()) + assert len(r) == 4 + util.validate_rule(r[0], TRT.allowxperm, "test101a", "test101a", tclass="infoflow7", + perms=setools.IoctlSet([0x9011]), xperm="ioctl") + util.validate_rule(r[1], TRT.allowxperm, "test101b", "test101b", tclass="infoflow7", + perms=setools.IoctlSet([0x9011, 0x9012]), xperm="ioctl") + util.validate_rule(r[2], TRT.allowxperm, "test101c", "test101c", tclass="infoflow7", + perms=setools.IoctlSet([0x9011, 0x9012, 0x9013]), xperm="ioctl") + util.validate_rule(r[3], TRT.allowxperm, "test101d", "test101d", tclass="infoflow7", + perms=setools.IoctlSet([0x9011, 0x9012, 0x9013, 0x9014]), xperm="ioctl") + + def test_xperm_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Xperm rule query match equal perm set.""" + q = TERuleQuery(compiled_policy, xperms=[(0x9011, 0x9013)], xperms_equal=True) + + r = sorted(q.results()) + assert len(r) == 1 + util.validate_rule(r[0], TRT.allowxperm, "test101c", "test101c", tclass="infoflow7", + perms=setools.IoctlSet([0x9011, 0x9012, 0x9013]), xperm="ioctl") diff --git a/tests/library/test_typeattrquery.py b/tests/library/test_typeattrquery.py new file mode 100644 index 00000000..031a50f5 --- /dev/null +++ b/tests/library/test_typeattrquery.py @@ -0,0 +1,56 @@ +# Copyright 2014-2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/typeattrquery.conf") +class TestTypeAttributeQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type attribute query with no criteria.""" + # query with no parameters gets all attrs. + allattrs = sorted(compiled_policy.typeattributes()) + + q = setools.TypeAttributeQuery(compiled_policy) + qattrs = sorted(q.results()) + + assert allattrs == qattrs + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type attribute query with exact name match.""" + q = setools.TypeAttributeQuery(compiled_policy, name="test1") + + attrs = sorted(str(t) for t in q.results()) + assert ["test1"] == attrs + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type attribute query with regex name match.""" + q = setools.TypeAttributeQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + attrs = sorted(str(t) for t in q.results()) + assert ["test2a", "test2b"] == attrs + + def test_type_set_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type attribute query with type set intersection.""" + q = setools.TypeAttributeQuery(compiled_policy, types=["test10t1", "test10t7"]) + + attrs = sorted(str(t) for t in q.results()) + assert ["test10a", "test10c"] == attrs + + def test_type_set_equality(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type attribute query with type set equality.""" + q = setools.TypeAttributeQuery(compiled_policy, types=["test11t1", "test11t2", + "test11t3", "test11t5"], types_equal=True) + + attrs = sorted(str(t) for t in q.results()) + assert ["test11a"] == attrs + + def test_type_set_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type attribute query with type set regex match.""" + q = setools.TypeAttributeQuery(compiled_policy, types="test12t(1|2)", types_regex=True) + + attrs = sorted(str(t) for t in q.results()) + assert ["test12a", "test12b"] == attrs diff --git a/tests/library/test_typequery.py b/tests/library/test_typequery.py new file mode 100644 index 00000000..64c23cf5 --- /dev/null +++ b/tests/library/test_typequery.py @@ -0,0 +1,86 @@ +# Copyright 2014-2015, Tresys Technology, LLC +# Copyright 2019, Chris PeBenito +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/typequery.conf") +class TestTypeQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with no criteria.""" + # query with no parameters gets all types. + alltypes = sorted(compiled_policy.types()) + + q = setools.TypeQuery(compiled_policy) + qtypes = sorted(q.results()) + + assert alltypes == qtypes + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with exact name match.""" + q = setools.TypeQuery(compiled_policy, name="test1") + + types = sorted(str(t) for t in q.results()) + assert ["test1"] == types + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with regex name match.""" + q = setools.TypeQuery(compiled_policy, name="test2(a|b)", name_regex=True) + + types = sorted(str(t) for t in q.results()) + assert ["test2a", "test2b"] == types + + def test_attr_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with attribute set intersection.""" + q = setools.TypeQuery(compiled_policy, attrs=["test10a", "test10b"]) + + types = sorted(str(t) for t in q.results()) + assert ["test10t1", "test10t2", "test10t3", + "test10t4", "test10t5", "test10t6"] == types + + def test_attr_equality(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with attribute set equality.""" + q = setools.TypeQuery(compiled_policy, attrs=["test11a", "test11b"], attrs_equal=True) + + types = sorted(str(t) for t in q.results()) + assert ["test11t2"] == types + + def test_attr_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with attribute regex match.""" + q = setools.TypeQuery(compiled_policy, attrs="test12(a|b)", attrs_regex=True) + + types = sorted(str(t) for t in q.results()) + assert ["test12t1", "test12t2", "test12t3", + "test12t4", "test12t5", "test12t6"] == types + + def test_alias_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with exact alias match.""" + q = setools.TypeQuery(compiled_policy, alias="test20a") + + types = sorted(str(t) for t in q.results()) + assert ["test20t1"] == types + + def test_alias_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with regex alias match.""" + q = setools.TypeQuery(compiled_policy, alias="test21(a|b)", alias_regex=True) + + types = sorted(str(t) for t in q.results()) + assert ["test21t1", "test21t2"] == types + + def test_alias_dereference(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with alias dereference.""" + q = setools.TypeQuery(compiled_policy, name="test22alias", alias_deref=True) + + types = sorted(str(t) for t in q.results()) + assert ["test22"] == types + + def test_permissive(self, compiled_policy: setools.SELinuxPolicy) -> None: + """Type query with permissive match""" + q = setools.TypeQuery(compiled_policy, permissive=True) + + types = sorted(str(t) for t in q.results()) + assert ["test30"] == types diff --git a/tests/library/test_userquery.py b/tests/library/test_userquery.py new file mode 100644 index 00000000..c141317a --- /dev/null +++ b/tests/library/test_userquery.py @@ -0,0 +1,235 @@ +# Copyright 2014-2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +import pytest +import setools + + +@pytest.mark.obj_args("tests/library/userquery.conf") +class TestUserQuery: + + def test_unset(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with no criteria.""" + # query with no parameters gets all types. + allusers = sorted(compiled_policy.users()) + + q = setools.UserQuery(compiled_policy) + qusers = sorted(q.results()) + + assert allusers == qusers + + def test_name_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with exact name match.""" + q = setools.UserQuery(compiled_policy, name="test1_u") + + users = sorted(str(u) for u in q.results()) + assert ["test1_u"] == users + + def test_name_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with regex name match.""" + q = setools.UserQuery(compiled_policy, name="test2_u(1|2)", name_regex=True) + + users = sorted(str(u) for u in q.results()) + assert ["test2_u1", "test2_u2"] == users + + def test_role_intersect(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with role set intersection.""" + q = setools.UserQuery(compiled_policy, roles=["test10a_r", "test10b_r"]) + + users = sorted(str(u) for u in q.results()) + assert ["test10_u1", "test10_u2", "test10_u3", + "test10_u4", "test10_u5", "test10_u6"] == users + + def test_role_equality(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with role set equality.""" + q = setools.UserQuery( + compiled_policy, roles=["test11a_r", "test11b_r"], roles_equal=True) + + users = sorted(str(u) for u in q.results()) + assert ["test11_u2"] == users + + def test_role_regex(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with role regex match.""" + q = setools.UserQuery(compiled_policy, roles="test12(a|b)_r", roles_regex=True) + + users = sorted(str(u) for u in q.results()) + assert ["test12_u1", "test12_u2", "test12_u3", + "test12_u4", "test12_u5", "test12_u6"] == users + + def test_level_equal(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with default level equality.""" + q = setools.UserQuery(compiled_policy, level="s3:c0,c4") + + users = sorted(str(u) for u in q.results()) + assert ["test20"] == users + + def test_level_dom1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with default level dominance.""" + q = setools.UserQuery(compiled_policy, level="s2:c1,c2,c4", level_dom=True) + + users = sorted(str(u) for u in q.results()) + assert ["test21"] == users + + def test_level_dom2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with default level dominance (equal).""" + q = setools.UserQuery(compiled_policy, level="s2:c1,c4", level_dom=True) + + users = sorted(str(u) for u in q.results()) + assert ["test21"] == users + + def test_level_domby1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with default level dominated-by.""" + q = setools.UserQuery(compiled_policy, level="s3:c2", level_domby=True) + + users = sorted(str(u) for u in q.results()) + assert ["test22"] == users + + def test_level_domby2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with default level dominated-by (equal).""" + q = setools.UserQuery(compiled_policy, level="s3:c2,c4", level_domby=True) + + users = sorted(str(u) for u in q.results()) + assert ["test22"] == users + + def test_level_incomp(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with default level icomparable.""" + q = setools.UserQuery(compiled_policy, level="s5:c0.c5,c7", level_incomp=True) + + users = sorted(str(u) for u in q.results()) + assert ["test23"] == users + + def test_range_exact(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range exact match""" + q = setools.UserQuery(compiled_policy, range_="s0:c5 - s0:c0.c5") + + users = sorted(str(u) for u in q.results()) + assert ["test40"] == users + + def test_range_overlap1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range overlap match (equal)""" + q = setools.UserQuery(compiled_policy, range_="s1:c5 - s1:c1.c3,c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test41"] == users + + def test_range_overlap2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range overlap match (subset)""" + q = setools.UserQuery(compiled_policy, range_="s1:c2,c5 - s1:c2.c3,c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test41"] == users + + def test_range_overlap3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range overlap match (superset)""" + q = setools.UserQuery(compiled_policy, range_="s1 - s1:c0.c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test41"] == users + + def test_range_overlap4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range overlap match (overlap low level)""" + q = setools.UserQuery(compiled_policy, range_="s1:c5 - s1:c2,c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test41"] == users + + def test_range_overlap5(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range overlap match (overlap high level)""" + q = setools.UserQuery(compiled_policy, range_="s1:c5,c2 - s1:c1.c3,c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test41"] == users + + def test_range_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range subset match""" + q = setools.UserQuery(compiled_policy, range_="s2:c2,c5 - s2:c2.c3,c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test42"] == users + + def test_range_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range subset match (equal)""" + q = setools.UserQuery(compiled_policy, range_="s2:c5 - s2:c1.c3,c5", range_overlap=True) + + users = sorted(str(u) for u in q.results()) + assert ["test42"] == users + + def test_range_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range superset match""" + q = setools.UserQuery(compiled_policy, range_="s3 - s3:c0.c6", range_superset=True) + + users = sorted(str(u) for u in q.results()) + assert ["test43"] == users + + def test_range_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range superset match (equal)""" + q = setools.UserQuery(compiled_policy, range_="s3:c5 - s3:c1.c3,c5.c6", + range_superset=True) + + users = sorted(str(u) for u in q.results()) + assert ["test43"] == users + + def test_range_proper_subset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper subset match""" + q = setools.UserQuery(compiled_policy, range_="s4:c2,c5", range_subset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert ["test44"] == users + + def test_range_proper_subset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper subset match (equal)""" + q = setools.UserQuery(compiled_policy, range_="s4:c5 - s4:c1.c3,c5", range_subset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert [] == users + + def test_range_proper_subset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper subset match (equal low)""" + q = setools.UserQuery(compiled_policy, range_="s4:c5 - s4:c1.c2,c5", range_subset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert ["test44"] == users + + def test_range_proper_subset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper subset match (equal high)""" + q = setools.UserQuery(compiled_policy, range_="s4:c1,c5 - s4:c1.c3,c5", range_subset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert ["test44"] == users + + def test_range_proper_superset1(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper superset match""" + q = setools.UserQuery(compiled_policy, range_="s5 - s5:c0.c5", range_superset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert ["test45"] == users + + def test_range_proper_superset2(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper superset match (equal)""" + q = setools.UserQuery(compiled_policy, range_="s5:c5 - s5:c1.c3,c5", range_superset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert [] == users + + def test_range_proper_superset3(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper superset match (equal low)""" + q = setools.UserQuery(compiled_policy, range_="s5:c5 - s5:c1.c5", range_superset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert ["test45"] == users + + def test_range_proper_superset4(self, compiled_policy: setools.SELinuxPolicy) -> None: + """User query with range proper superset match (equal high)""" + q = setools.UserQuery(compiled_policy, range_="s5 - s5:c1.c3,c5", range_superset=True, + range_proper=True) + + users = sorted(str(u) for u in q.results()) + assert ["test45"] == users diff --git a/tests/typeattrquery.conf b/tests/library/typeattrquery.conf similarity index 100% rename from tests/typeattrquery.conf rename to tests/library/typeattrquery.conf diff --git a/tests/typequery.conf b/tests/library/typequery.conf similarity index 100% rename from tests/typequery.conf rename to tests/library/typequery.conf diff --git a/tests/userquery.conf b/tests/library/userquery.conf similarity index 100% rename from tests/userquery.conf rename to tests/library/userquery.conf diff --git a/tests/library/util.py b/tests/library/util.py new file mode 100644 index 00000000..78b2a3d2 --- /dev/null +++ b/tests/library/util.py @@ -0,0 +1,50 @@ +"""Unit test mixin classes.""" +# Copyright 2015, Tresys Technology, LLC +# +# SPDX-License-Identifier: GPL-2.0-only +# +# pylint: disable=too-few-public-methods +import pytest +import setools + + +def validate_rule(rule: setools.policyrep.PolicyRule, + ruletype: setools.policyrep.PolicyEnum | str, + source: setools.policyrep.PolicySymbol | str, + target: setools.policyrep.PolicySymbol | str, + /, *, + tclass: setools.ObjClass | str | None = None, + perms: set[str] | setools.IoctlSet | None = None, + default: setools.policyrep.PolicySymbol | str | None = None, + cond: str | None = None, + cond_block: bool | None = None, + xperm: str | None = None) -> None: + + """Validate a rule.""" + assert ruletype == rule.ruletype + assert source == rule.source + assert target == rule.target + + if tclass is not None: + assert tclass == rule.tclass + + if perms is not None: + assert perms == rule.perms + + elif default is not None: + assert default == rule.default + + if cond: + assert cond == rule.conditional + assert cond_block == rule.conditional_block + else: + with pytest.raises(setools.exception.RuleNotConditional): + rule.conditional + with pytest.raises(setools.exception.RuleNotConditional): + rule.conditional_block + + if xperm: + assert xperm == rule.xperm_type + assert rule.extended + else: + assert not rule.extended diff --git a/tests/mixins.py b/tests/mixins.py deleted file mode 100644 index 4b2a690d..00000000 --- a/tests/mixins.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Unit test mixin classes.""" -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# pylint: disable=too-few-public-methods -import unittest - -from setools.exception import RuleNotConditional, RuleUseError - - -class ValidateRule(unittest.TestCase): - - """Mixin for validating policy rules.""" - - def validate_rule(self, rule, ruletype, source, target, tclass, last_item, cond=None, - cond_block=None, xperm=None): - """Validate a rule.""" - self.assertEqual(ruletype, rule.ruletype) - self.assertEqual(source, rule.source) - self.assertEqual(target, rule.target) - self.assertEqual(tclass, rule.tclass) - - try: - # This is the common case. - self.assertSetEqual(last_item, rule.perms) - except (AttributeError, RuleUseError): - self.assertEqual(last_item, rule.default) - - if cond: - self.assertEqual(cond, rule.conditional) - else: - self.assertRaises(RuleNotConditional, getattr, rule, "conditional") - - if cond_block is not None: - self.assertEqual(cond_block, rule.conditional_block) - - if xperm: - self.assertEqual(xperm, rule.xperm_type) - self.assertTrue(rule.extended) - else: - self.assertRaises(AttributeError, getattr, rule, "xperm_type") - self.assertFalse(rule.extended) diff --git a/tests/policyrep/test_default.py b/tests/policyrep/test_default.py deleted file mode 100644 index cc67e870..00000000 --- a/tests/policyrep/test_default.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2016, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable -import unittest -from unittest.mock import Mock, patch - -from setools.exception import InvalidDefaultType, InvalidDefaultValue, \ - InvalidDefaultRange, NoDefaults - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.objclass.class_factory', lambda x, y: y) -class DefaultTest(unittest.TestCase): - - @staticmethod - def mock_default(objclass=None, user=None, role=None, type_=None, range_=None): - d = Mock(qpol_default_object_t) - d.object_class.return_value = objclass - d.user_default.return_value = user - d.role_default.return_value = role - d.type_default.return_value = type_ - d.range_default.return_value = range_ - return d - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_001_factory_user(self): - """Default: factory on qpol object with user default.""" - q = self.mock_default("test1", "source") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_user, d.ruletype) - self.assertEqual("test1", d.tclass) - self.assertEqual(DefaultValue.source, d.default) - - def test_002_factory_role(self): - """Default: factory on qpol object with role default.""" - q = self.mock_default("test2", role="target") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_role, d.ruletype) - self.assertEqual("test2", d.tclass) - self.assertEqual(DefaultValue.target, d.default) - - def test_003_factory_type(self): - """Default: factory on qpol object with type default.""" - q = self.mock_default("test3", type_="source") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_type, d.ruletype) - self.assertEqual("test3", d.tclass) - self.assertEqual(DefaultValue.source, d.default) - - def test_004_factory_range(self): - """Default: factory on qpol object with range default.""" - q = self.mock_default("test4", range_="target low_high") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_range, d.ruletype) - self.assertEqual("test4", d.tclass) - self.assertEqual(DefaultValue.target, d.default) - self.assertEqual(DefaultRangeValue.low_high, d.default_range) - - def test_005_factory_multiple(self): - """Default: factory on qpol object with mulitple defaults.""" - q = self.mock_default("test5", "source", "target", "source", "target low") - defaults = sorted(default_factory(self.p, q)) - self.assertEqual(4, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_range, d.ruletype) - self.assertEqual("test5", d.tclass) - - d = defaults[1] - self.assertEqual(DefaultRuletype.default_role, d.ruletype) - self.assertEqual("test5", d.tclass) - - d = defaults[2] - self.assertEqual(DefaultRuletype.default_type, d.ruletype) - self.assertEqual("test5", d.tclass) - - d = defaults[3] - self.assertEqual(DefaultRuletype.default_user, d.ruletype) - self.assertEqual("test5", d.tclass) - - def test_010_user(self): - """Default: default_user methods/attributes.""" - q = self.mock_default("test10", "target") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_user, d.ruletype) - self.assertEqual("test10", d.tclass) - self.assertEqual(DefaultValue.target, d.default) - self.assertEqual("default_user test10 target;", str(d)) - self.assertEqual(str(d), d.statement()) - - def test_011_role(self): - """Default: default_role methods/attributes.""" - q = self.mock_default("test11", role="source") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_role, d.ruletype) - self.assertEqual("test11", d.tclass) - self.assertEqual(DefaultValue.source, d.default) - self.assertEqual("default_role test11 source;", str(d)) - self.assertEqual(str(d), d.statement()) - - def test_012_type(self): - """Default: default_type methods/attributes.""" - q = self.mock_default("test12", type_="target") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_type, d.ruletype) - self.assertEqual("test12", d.tclass) - self.assertEqual(DefaultValue.target, d.default) - self.assertEqual("default_type test12 target;", str(d)) - self.assertEqual(str(d), d.statement()) - - def test_013_range(self): - """Default: default_range methods/attributes.""" - q = self.mock_default("test13", range_="source high") - defaults = list(default_factory(self.p, q)) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_range, d.ruletype) - self.assertEqual("test13", d.tclass) - self.assertEqual(DefaultValue.source, d.default) - self.assertEqual(DefaultRangeValue.high, d.default_range) - self.assertEqual("default_range test13 source high;", str(d)) - self.assertEqual(str(d), d.statement()) - - @unittest.skip("Default ruletype changed to an enumeration.") - def test_020_validate_ruletype(self): - """Default: validate rule type.""" - for r in ["default_user", "default_role", "default_type", "default_range"]: - self.assertEqual(r, validate_ruletype(r)) - - @unittest.skip("Default ruletype changed to an enumeration.") - def test_021_validate_ruletype_invalid(self): - """Default: invalid ruletype""" - with self.assertRaises(InvalidDefaultType): - validate_ruletype("INVALID") - - @unittest.skip("Default value changed to an enumeration.") - def test_030_validate_default(self): - """Default: validate default value.""" - for d in ["source", "target"]: - self.assertEqual(d, validate_default_value(d)) - - @unittest.skip("Default value changed to an enumeration.") - def test_031_validate_default_invalid(self): - """Default query: invalid default value""" - with self.assertRaises(InvalidDefaultValue): - validate_default_value("INVALID") - - @unittest.skip("Default range value changed to an enumeration.") - def test_040_validate_default_range(self): - """Default: validate default range.""" - for r in ["low", "high", "low_high"]: - self.assertEqual(r, validate_default_range(r)) - - @unittest.skip("Default range value changed to an enumeration.") - def test_041_validate_default_range_invalid(self): - """Default query: invalid default range""" - with self.assertRaises(InvalidDefaultRange): - validate_default_range("INVALID") diff --git a/tests/policyrep/test_initsid.py b/tests/policyrep/test_initsid.py deleted file mode 100644 index 14067528..00000000 --- a/tests/policyrep/test_initsid.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable,no-member -import unittest -from unittest.mock import Mock, patch - -from setools import SELinuxPolicy -from setools.exception import InvalidInitialSid - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.context.context_factory', lambda x, y: y) -class InitialSIDTest(unittest.TestCase): - - @staticmethod - def mock_sid(name): - sid = Mock(qpol.qpol_isid_t) - sid.name.return_value = name - sid.context.return_value = name + "_context" - return sid - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/initsid.conf") - - def test_001_factory(self): - """InitialSID: factory on qpol object.""" - q = self.mock_sid("test1") - sid = initialsid_factory(self.p.policy, q) - self.assertEqual("test1", sid.qpol_symbol.name(self.p.policy)) - - def test_002_factory_object(self): - """InitialSID: factory on InitialSID object.""" - q = self.mock_sid("test2") - sid1 = initialsid_factory(self.p.policy, q) - sid2 = initialsid_factory(self.p.policy, sid1) - self.assertIs(sid2, sid1) - - def test_003_factory_lookup(self): - """InitialSID: factory lookup.""" - sid = initialsid_factory(self.p.policy, "kernel") - self.assertEqual("kernel", sid.qpol_symbol.name(self.p.policy)) - - def test_004_factory_lookup_invalid(self): - """InitialSID: factory lookup.""" - with self.assertRaises(InvalidInitialSid): - initialsid_factory(self.p.policy, "INVALID") - - def test_010_string(self): - """InitialSID: basic string rendering.""" - q = self.mock_sid("test10") - sid = initialsid_factory(self.p.policy, q) - self.assertEqual("test10", str(sid)) - - def test_020_statement(self): - """InitialSID: context.""" - q = self.mock_sid("test20") - sid = initialsid_factory(self.p.policy, q) - self.assertEqual("test20_context", sid.context) - - def test_030_statement(self): - """InitialSID: statement.""" - q = self.mock_sid("test30") - sid = initialsid_factory(self.p.policy, q) - self.assertEqual("sid test30 test30_context", sid.statement()) diff --git a/tests/policyrep/test_mls.py b/tests/policyrep/test_mls.py deleted file mode 100644 index d22377bf..00000000 --- a/tests/policyrep/test_mls.py +++ /dev/null @@ -1,772 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable,no-member -import unittest -from unittest.mock import Mock - -from setools import SELinuxPolicy -from setools.exception import MLSDisabled, InvalidLevel, InvalidLevelDecl, InvalidRange, \ - InvalidSensitivity, InvalidCategory, NoStatement - - -@unittest.skip("Needs to be reworked for cython") -class SensitivityTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/mls.conf") - - def mock_sens_factory(self, sens, aliases=[]): - """Factory function for Sensitivity objects, using a mock qpol object.""" - mock_sens = Mock(qpol.qpol_level_t) - mock_sens.name.return_value = sens - mock_sens.isalias.return_value = False - mock_sens.value.return_value = int(sens[1:]) - mock_sens.alias_iter = lambda x: iter(aliases) - - return sensitivity_factory(self.p.policy, mock_sens) - - def test_000_mls_disabled(self): - """Sensitivity factory on MLS-disabled policy.""" - mock_p = Mock(qpol.qpol_policy_t) - mock_p.capability.return_value = False - self.assertRaises(MLSDisabled, sensitivity_factory, mock_p, None) - - def test_001_lookup(self): - """Sensitivity factory policy lookup.""" - sens = sensitivity_factory(self.p.policy, "s1") - self.assertEqual("s1", sens.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """Sensitivity factory policy invalid lookup.""" - with self.assertRaises(InvalidSensitivity): - sensitivity_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """Sensitivity factory policy lookup of Sensitivity object.""" - sens1 = sensitivity_factory(self.p.policy, "s1") - sens2 = sensitivity_factory(self.p.policy, sens1) - self.assertIs(sens2, sens1) - - def test_010_string(self): - """Sensitivity basic string rendering.""" - sens = self.mock_sens_factory("s0") - self.assertEqual("s0", str(sens)) - - def test_020_statement(self): - """Sensitivity basic statement rendering.""" - sens = self.mock_sens_factory("s0") - self.assertEqual("sensitivity s0;", sens.statement()) - - def test_021_statement_alias(self): - """Sensitivity one alias statement rendering.""" - sens = self.mock_sens_factory("s0", ["name1"]) - self.assertEqual("sensitivity s0 alias name1;", sens.statement()) - - def test_022_statement_alias(self): - """Sensitivity two alias statement rendering.""" - sens = self.mock_sens_factory("s0", ["name1", "name2"]) - self.assertEqual("sensitivity s0 alias { name1 name2 };", sens.statement()) - - def test_030_value(self): - """Sensitivity value.""" - sens = self.mock_sens_factory("s17") - self.assertEqual(17, sens._value) - - def test_031_equal(self): - """Sensitivity equal.""" - sens1 = self.mock_sens_factory("s0") - sens2 = self.mock_sens_factory("s0") - self.assertEqual(sens1, sens2) - - def test_032_equal_str(self): - """Sensitivity equal to string.""" - sens = self.mock_sens_factory("s17") - self.assertEqual("s17", sens) - - def test_033_not_equal(self): - """Sensitivity not equal.""" - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s23") - self.assertNotEqual(sens1, sens2) - - def test_034_not_equal_str(self): - """Sensitivity not equal to string.""" - sens = self.mock_sens_factory("s17") - self.assertNotEqual("s0", sens) - - def test_035_lt(self): - """Sensitivity less-than.""" - # less - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s23") - self.assertTrue(sens1 < sens2) - - # equal - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s17") - self.assertFalse(sens1 < sens2) - - # greater - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s0") - self.assertFalse(sens1 < sens2) - - def test_036_le(self): - """Sensitivity less-than-or-equal.""" - # less - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s23") - self.assertTrue(sens1 <= sens2) - - # equal - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s17") - self.assertTrue(sens1 <= sens2) - - # greater - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s0") - self.assertFalse(sens1 <= sens2) - - def test_037_ge(self): - """Sensitivity greater-than-or-equal.""" - # less - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s23") - self.assertFalse(sens1 >= sens2) - - # equal - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s17") - self.assertTrue(sens1 >= sens2) - - # greater - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s0") - self.assertTrue(sens1 >= sens2) - - def test_038_gt(self): - """Sensitivity greater-than.""" - # less - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s23") - self.assertFalse(sens1 > sens2) - - # equal - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s17") - self.assertFalse(sens1 > sens2) - - # greater - sens1 = self.mock_sens_factory("s17") - sens2 = self.mock_sens_factory("s0") - self.assertTrue(sens1 > sens2) - - -@unittest.skip("Needs to be reworked for cython") -class CategoryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/mls.conf") - - def mock_cat_factory(self, cat, aliases=[]): - """Factory function for Category objects, using a mock qpol object.""" - mock_cat = Mock(qpol.qpol_cat_t) - mock_cat.name.return_value = cat - mock_cat.isalias.return_value = False - mock_cat.value.return_value = int(cat[1:]) - mock_cat.alias_iter = lambda x: iter(aliases) - - return category_factory(self.p.policy, mock_cat) - - def test_000_mls_disabled(self): - """Category factory on MLS-disabled policy.""" - mock_p = Mock(qpol.qpol_policy_t) - mock_p.capability.return_value = False - self.assertRaises(MLSDisabled, category_factory, mock_p, None) - - def test_001_lookup(self): - """Category factory policy lookup.""" - cat = category_factory(self.p.policy, "c1") - self.assertEqual("c1", cat.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """Category factory policy invalid lookup.""" - with self.assertRaises(InvalidCategory): - category_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """Category factory policy lookup of Category object.""" - cat1 = category_factory(self.p.policy, "c1") - cat2 = category_factory(self.p.policy, cat1) - self.assertIs(cat2, cat1) - - def test_010_statement(self): - """Category basic string rendering.""" - cat = self.mock_cat_factory("c0") - self.assertEqual("c0", str(cat)) - - def test_020_statement(self): - """Category basic statement rendering.""" - cat = self.mock_cat_factory("c0") - self.assertEqual("category c0;", cat.statement()) - - def test_021_statement_alias(self): - """Category one alias statement rendering.""" - cat = self.mock_cat_factory("c0", ["name1"]) - self.assertEqual("category c0 alias name1;", cat.statement()) - - def test_022_statement_alias(self): - """Category two alias statement rendering.""" - cat = self.mock_cat_factory("c0", ["name1", "name2"]) - self.assertEqual("category c0 alias { name1 name2 };", cat.statement()) - - def test_030_value(self): - """Category value.""" - cat = self.mock_cat_factory("c17") - self.assertEqual(17, cat._value) - - -@unittest.skip("Needs to be reworked for cython") -class LevelDeclTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/mls.conf") - - def mock_decl_factory(self, sens, cats=[]): - """Factory function for LevelDecl objects, using a mock qpol object.""" - mock_decl = Mock(qpol.qpol_level_t) - mock_decl.name.return_value = sens - mock_decl.isalias.return_value = False - mock_decl.value.return_value = int(sens[1:]) - mock_decl.cat_iter = lambda x: iter(cats) - - return level_decl_factory(self.p.policy, mock_decl) - - def test_000_mls_disabled(self): - """Level declaration factory on MLS-disabled policy.""" - mock_p = Mock(qpol.qpol_policy_t) - mock_p.capability.return_value = False - self.assertRaises(MLSDisabled, level_decl_factory, mock_p, None) - - def test_001_lookup(self): - """Level declaration factory policy lookup.""" - decl = level_decl_factory(self.p.policy, "s1") - self.assertEqual("s1", decl.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """Level declaration factory policy invalid lookup.""" - with self.assertRaises(InvalidLevelDecl): - level_decl_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """Level declaration factory policy lookup of LevelDecl object.""" - level1 = level_decl_factory(self.p.policy, "s1") - level2 = level_decl_factory(self.p.policy, level1) - self.assertIs(level2, level1) - - def test_010_string(self): - """Level declaration basic string rendering.""" - decl = self.mock_decl_factory("s0") - self.assertEqual("s0", str(decl)) - - def test_011_string_single_cat(self): - """Level declaration string rendering with one category""" - decl = self.mock_decl_factory("s0", ["c0"]) - self.assertEqual("s0:c0", str(decl)) - - def test_012_string_multiple_cat(self): - """Level declaration string rendering with multiple categories""" - decl = self.mock_decl_factory("s0", ["c0", "c3"]) - self.assertEqual("s0:c0,c3", str(decl)) - - def test_013_string_cat_set(self): - """Level declaration string rendering with category set""" - decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3"]) - self.assertEqual("s0:c0.c3", str(decl)) - - def test_014_string_complex(self): - """Level declaration string rendering with complex category set""" - decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3", "c5", "c7", "c8", "c9"]) - self.assertEqual("s0:c0.c3,c5,c7.c9", str(decl)) - - def test_020_statement(self): - """Level declaration basic statement rendering.""" - decl = self.mock_decl_factory("s0") - self.assertEqual("level s0;", decl.statement()) - - def test_021_statement_single_cat(self): - """Level declaration statement rendering with one category""" - decl = self.mock_decl_factory("s0", ["c0"]) - self.assertEqual("level s0:c0;", decl.statement()) - - def test_022_statement_multiple_cat(self): - """Level declaration statement rendering with multiple categories""" - decl = self.mock_decl_factory("s0", ["c0", "c3"]) - self.assertEqual("level s0:c0,c3;", decl.statement()) - - def test_012_string_cat_set(self): - """Level declaration statement rendering with category set""" - decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3"]) - self.assertEqual("level s0:c0.c3;", decl.statement()) - - def test_013_statement_complex(self): - """Level declaration statement rendering with complex category set""" - decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3", "c5", "c7", "c8", "c9"]) - self.assertEqual("level s0:c0.c3,c5,c7.c9;", decl.statement()) - - def test_030_equal(self): - """Level declaration equal.""" - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertEqual(decl1, decl2) - - def test_031_equal_str(self): - """Level declaration equal to string.""" - decl = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertEqual("s17:c0.c3", decl) - - def test_032_not_equal(self): - """Level declaration not equal.""" - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s23") - self.assertNotEqual(decl1, decl2) - - def test_033_not_equal_str(self): - """Level declaration not equal to string.""" - decl = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertNotEqual("s0:c0.c2", decl) - - def test_034_lt(self): - """Level declaration less-than.""" - # less - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertTrue(decl1 < decl2) - - # equal - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertFalse(decl1 < decl2) - - # greater - decl1 = self.mock_decl_factory("s24") - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertFalse(decl1 < decl2) - - def test_035_le(self): - """Level declaration less-than-or-equal.""" - # less - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertTrue(decl1 <= decl2) - - # equal - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertTrue(decl1 <= decl2) - - # greater - decl1 = self.mock_decl_factory("s24") - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertFalse(decl1 <= decl2) - - def test_036_ge(self): - """Level declaration greater-than-or-equal.""" - # less - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertFalse(decl1 >= decl2) - - # equal - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertTrue(decl1 >= decl2) - - # greater - decl1 = self.mock_decl_factory("s24") - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertTrue(decl1 >= decl2) - - def test_037_gt(self): - """Level declaration greater-than.""" - # less - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertFalse(decl1 > decl2) - - # equal - decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"]) - self.assertFalse(decl1 > decl2) - - # greater - decl1 = self.mock_decl_factory("s24") - decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"]) - self.assertTrue(decl1 > decl2) - - -@unittest.skip("Needs to be reworked for cython") -class LevelTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/mls.conf") - - def mock_level_factory(self, sens, cats=[]): - """Factory function Level objects, using a mock qpol object.""" - mock_level = Mock(qpol.qpol_mls_level_t) - mock_level.sens_name.return_value = sens - mock_level.cat_iter = lambda x: iter(cats) - - return level_factory(self.p.policy, mock_level) - - def test_000_mls_disabled(self): - """Level factory on MLS-disabled policy.""" - mock_p = Mock(qpol.qpol_policy_t) - mock_p.capability.return_value = False - self.assertRaises(MLSDisabled, level_factory, mock_p, None) - - def test_001_lookup_no_cats(self): - """Level lookup with no categories.""" - levelobj = level_factory(self.p.policy, "s2") - self.assertEqual("s2", levelobj.qpol_symbol.sens_name(self.p.policy)) - self.assertEqual(str(levelobj), "s2") - - def test_002_lookup_cat_range(self): - """Level lookup with category range.""" - levelobj = level_factory(self.p.policy, "s1:c0.c13") - self.assertEqual(str(levelobj), "s1:c0.c13") - - def test_003_lookup_complex_cats(self): - """Level lookup with complex category set.""" - levelobj = level_factory(self.p.policy, "s2:c0.c5,c7,c9.c11,c13") - self.assertEqual(str(levelobj), "s2:c0.c5,c7,c9.c11,c13") - - def test_004_lookup_bad1(self): - """Level lookup with garbage.""" - self.assertRaises(InvalidLevel, level_factory, self.p.policy, "FAIL") - - def test_005_lookup_bad2(self): - """Level lookup with : in garbage.""" - self.assertRaises(InvalidLevel, level_factory, self.p.policy, "FAIL:BAD") - - def test_006_lookup_bad_cat(self): - """Level lookup with invalid category.""" - self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:FAIL") - - def test_007_lookup_bad_cat_range(self): - """Level lookup with backwards category range.""" - self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:c4.c0") - - def test_008_lookup_cat_range_error(self): - """Level lookup with category range parse error.""" - self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:c0.c2.c4") - - def test_009_lookup_cat_not_assoc(self): - """Level lookup with category not associated with sensitivity.""" - # c4 is not associated with s0. - self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:c0,c4") - - def test_00a_lookup_object(self): - """Level factory policy lookup of Level object.""" - level1 = level_factory(self.p.policy, "s0") - level2 = level_factory(self.p.policy, level1) - self.assertIs(level2, level1) - - def test_010_equal(self): - """Level equal.""" - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - self.assertEqual(level1, level2) - - def test_011_equal_str(self): - """Level equal to string.""" - level = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"]) - self.assertEqual("s2:c0.c3", level) - - def test_012_not_equal(self): - """Level not equal.""" - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s0") - self.assertNotEqual(level1, level2) - - def test_013_not_equal_str(self): - """Level not equal to string.""" - level = self.mock_level_factory("s0", ["c0", "c2"]) - self.assertNotEqual("s0:c0.c2", level) - - def test_014_dom(self): - """Level dominate (ge).""" - # equal - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 >= level2) - - # sens dominate - level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 >= level2) - - # cat set dominate - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 >= level2) - - # sens domby - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 >= level2) - - # cat set domby - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 >= level2) - - # incomp - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"]) - self.assertFalse(level1 >= level2) - - def test_015_domby(self): - """Level dominate-by (le).""" - # equal - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 <= level2) - - # sens dominate - level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 <= level2) - - # cat set dominate - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 <= level2) - - # sens domby - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 <= level2) - - # cat set domby - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 <= level2) - - # incomp - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"]) - self.assertFalse(level1 <= level2) - - def test_016_proper_dom(self): - """Level proper dominate (gt).""" - # equal - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 > level2) - - # sens dominate - level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 > level2) - - # cat set dominate - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 > level2) - - # sens domby - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 > level2) - - # cat set domby - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 > level2) - - # incomp - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"]) - self.assertFalse(level1 > level2) - - def test_017_proper_domby(self): - """Level proper dominate-by (lt).""" - # equal - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 < level2) - - # sens dominate - level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 < level2) - - # cat set dominate - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 < level2) - - # sens domby - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 < level2) - - # cat set domby - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertTrue(level1 < level2) - - # incomp - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"]) - self.assertFalse(level1 < level2) - - def test_018_incomp(self): - """Level incomparable (xor).""" - # equal - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 ^ level2) - - # sens dominate - level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 ^ level2) - - # cat set dominate - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 ^ level2) - - # sens domby - level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 ^ level2) - - # cat set domby - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"]) - self.assertFalse(level1 ^ level2) - - # incomp - level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"]) - level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"]) - self.assertTrue(level1 ^ level2) - - def test_020_level_statement(self): - """Level has no statement.""" - level = self.mock_level_factory("s1") - with self.assertRaises(NoStatement): - level.statement() - - -@unittest.skip("Needs to be reworked for cython") -class RangeTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/mls.conf") - - def test_000_mls_disabled(self): - """Range factory on MLS-disabled policy.""" - mock_p = Mock(qpol.qpol_policy_t) - mock_p.capability.return_value = False - self.assertRaises(MLSDisabled, range_factory, mock_p, None) - - def test_001_range_lookup_single_level(self): - """Range lookup with single-level range.""" - rangeobj = range_factory(self.p.policy, "s0") - self.assertEqual(str(rangeobj), "s0") - - def test_002_range_lookup_single_level_redundant(self): - """Range lookup with single-level range (same range listed twice).""" - rangeobj = range_factory(self.p.policy, "s1-s1") - self.assertEqual(str(rangeobj), "s1") - - def test_003_range_lookup_simple(self): - """Range lookup with simple range.""" - rangeobj = range_factory(self.p.policy, "s0-s1:c0.c10") - self.assertEqual(str(rangeobj), "s0 - s1:c0.c10") - - def test_004_range_lookup_no_cats(self): - """Range lookup with no categories.""" - rangeobj = range_factory(self.p.policy, "s0-s1") - self.assertEqual(str(rangeobj), "s0 - s1") - - def test_005_range_lookup_complex(self): - """Range lookup with complex category set.""" - rangeobj = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") - self.assertEqual(str(rangeobj), "s0:c0.c2 - s2:c0.c5,c7,c9.c11,c13") - - def test_006_range_lookup_non_dom(self): - """Range lookup with non-dominating high level.""" - self.assertRaises(InvalidRange, range_factory, self.p.policy, "s1-s0") - - def test_007_range_lookup_invalid_range_low(self): - """Range lookup with an invalid range (low).""" - # c13 is not associated with s0. - self.assertRaises(InvalidRange, range_factory, self.p.policy, "s0:c13-s2:c13") - - def test_008_range_lookup_invalid_range_high(self): - """Range lookup with an invalid range (high).""" - # c13 is not associated with s0. - self.assertRaises(InvalidRange, range_factory, self.p.policy, "s0-s0:c13") - - def test_009_lookup_object(self): - """Range factory policy lookup of Range object.""" - range1 = range_factory(self.p.policy, "s0") - range2 = range_factory(self.p.policy, range1) - self.assertIs(range2, range1) - - def test_020_equal(self): - """Range equality.""" - rangeobj1 = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") - rangeobj2 = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") - self.assertEqual(rangeobj1, rangeobj2) - - def test_021_equal(self): - """Range equal to string.""" - rangeobj = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13") - self.assertEqual("s0:c0.c2-s2:c0.c5,c7,c9.c11,c13", rangeobj) - self.assertEqual("s0:c0.c2- s2:c0.c5,c7,c9.c11,c13", rangeobj) - self.assertEqual("s0:c0.c2 -s2:c0.c5,c7,c9.c11,c13", rangeobj) - self.assertEqual("s0:c0.c2 - s2:c0.c5,c7,c9.c11,c13", rangeobj) - - def test_022_contains(self): - """Range contains a level.""" - rangeobj = range_factory(self.p.policy, "s0:c1-s2:c0.c10") - - # too low - level1 = level_factory(self.p.policy, "s0") - self.assertNotIn(level1, rangeobj) - - # low level - level2 = level_factory(self.p.policy, "s0:c1") - self.assertIn(level2, rangeobj) - - # mid - level3 = level_factory(self.p.policy, "s1:c1,c5") - self.assertIn(level3, rangeobj) - - # high level - level4 = level_factory(self.p.policy, "s2:c0.c10") - self.assertIn(level4, rangeobj) - - # too high - level5 = level_factory(self.p.policy, "s2:c0.c11") - self.assertNotIn(level5, rangeobj) - - def test_030_range_statement(self): - """Range has no statement.""" - rangeobj = range_factory(self.p.policy, "s0") - with self.assertRaises(NoStatement): - rangeobj.statement() diff --git a/tests/policyrep/test_mlsrule.py b/tests/policyrep/test_mlsrule.py deleted file mode 100644 index 7c8b1d3a..00000000 --- a/tests/policyrep/test_mlsrule.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable -import unittest -from unittest.mock import Mock, patch - -from setools import MLSRuletype as MRT -from setools.exception import InvalidMLSRuleType, RuleNotConditional - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.mls.range_factory', lambda x, y: y) -@patch('setools.policyrep.typeattr.type_or_attr_factory', lambda x, y: y) -@patch('setools.policyrep.objclass.class_factory', lambda x, y: y) -class MLSRuleTest(unittest.TestCase): - - def mock_rangetrans_factory(self, source, target, tclass, default): - mock_rule = Mock(qpol_range_trans_t) - mock_rule.rule_type.return_value = MRT.range_transition - mock_rule.source_type.return_value = source - mock_rule.target_type.return_value = target - mock_rule.object_class.return_value = tclass - mock_rule.range.return_value = default - - return mls_rule_factory(self.p, mock_rule) - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_000_factory(self): - """RangeTransition factory lookup.""" - with self.assertRaises(TypeError): - mls_rule_factory(self.p, "INVALID") - - def test_001_validate_ruletype(self): - """RangeTransition valid rule types.""" - self.assertEqual(MRT.range_transition, validate_ruletype("range_transition")) - - @unittest.skip("MLS ruletype changed to an enumeration.") - def test_002_validate_ruletype_invalid(self): - """RangeTransition valid rule types.""" - with self.assertRaises(InvalidMLSRuleType): - self.assertTrue(validate_ruletype("type_transition")) - - def test_010_ruletype(self): - """RangeTransition rule type""" - rule = self.mock_rangetrans_factory("a", "b", "c", "d") - self.assertEqual(MRT.range_transition, rule.ruletype) - - def test_020_source_type(self): - """RangeTransition source type""" - rule = self.mock_rangetrans_factory("source20", "b", "c", "d") - self.assertEqual("source20", rule.source) - - def test_030_target_type(self): - """RangeTransition target type""" - rule = self.mock_rangetrans_factory("a", "target30", "c", "d") - self.assertEqual("target30", rule.target) - - def test_040_object_class(self): - """RangeTransition object class""" - rule = self.mock_rangetrans_factory("a", "b", "class40", "d") - self.assertEqual("class40", rule.tclass) - - def test_050_default(self): - """RangeTransition default range""" - rule = self.mock_rangetrans_factory("a", "b", "c", "default50") - self.assertEqual("default50", rule.default) - - def test_060_conditional(self): - """RangeTransition conditional expression""" - rule = self.mock_rangetrans_factory("a", "b", "c", "d") - with self.assertRaises(RuleNotConditional): - rule.conditional - - def test_100_statement(self): - """RangeTransition statement.""" - rule = self.mock_rangetrans_factory("a", "b", "c", "d") - self.assertEqual("range_transition a b:c d;", rule.statement()) diff --git a/tests/policyrep/test_objclass.py b/tests/policyrep/test_objclass.py deleted file mode 100644 index b8a7b54d..00000000 --- a/tests/policyrep/test_objclass.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable,no-member -import unittest -from unittest.mock import Mock - -from setools import SELinuxPolicy -from setools.exception import InvalidCommon, InvalidClass - - -@unittest.skip("Needs to be reworked for cython") -class CommonTest(unittest.TestCase): - - @staticmethod - def mock_common(name, perms): - policy = Mock(qpol.qpol_policy_t) - com = Mock(qpol.qpol_common_t) - com.name.return_value = name - com.perm_iter = lambda x: iter(perms) - return common_factory(policy, com) - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/objclass.conf") - - def test_001_lookup(self): - """Common: factory policy lookup.""" - com = common_factory(self.p.policy, "com_a") - self.assertEqual("com_a", com.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """Common: factory policy invalid lookup.""" - with self.assertRaises(InvalidCommon): - common_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """Common: factory policy lookup of Common object.""" - com1 = common_factory(self.p.policy, "com_b") - com2 = common_factory(self.p.policy, com1) - self.assertIs(com2, com1) - - def test_010_string(self): - """Common: string representation""" - com = self.mock_common("test10", ["perm1", "perm2"]) - self.assertEqual("test10", str(com)) - - def test_020_perms(self): - """Common: permissions""" - com = self.mock_common("test20", ["perm1", "perm2"]) - self.assertEqual(set(["perm1", "perm2"]), com.perms) - - def test_030_statment(self): - """Common: statement.""" - com = self.mock_common("test30", ["perm1", "perm2"]) - self.assertRegex(com.statement(), "(" - "common test30\n{\n\tperm1\n\tperm2\n}" - "|" - "common test30\n{\n\tperm2\n\tperm1\n}" - ")") - - def test_040_contains(self): - """Common: contains""" - com = self.mock_common("test40", ["perm1", "perm2"]) - self.assertIn("perm1", com) - self.assertNotIn("perm3", com) - - -@unittest.skip("Needs to be reworked for cython") -class ObjClassTest(unittest.TestCase): - - @staticmethod - def mock_class(name, perms, com_perms=[]): - policy = Mock(qpol.qpol_policy_t) - - cls = Mock(qpol.qpol_class_t) - cls.name.return_value = name - cls.perm_iter = lambda x: iter(perms) - - if com_perms: - com = Mock(qpol.qpol_common_t) - com.name.return_value = name + "_common" - com.perm_iter = lambda x: iter(com_perms) - cls.common.return_value = com - else: - cls.common.side_effect = ValueError - - return class_factory(policy, cls) - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/objclass.conf") - - def test_001_lookup(self): - """ObjClass: factory policy lookup.""" - cls = class_factory(self.p.policy, "infoflow") - self.assertEqual("infoflow", cls.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """ObjClass: factory policy invalid lookup.""" - with self.assertRaises(InvalidClass): - class_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """ObjClass: factory policy lookup of ObjClass object.""" - cls1 = class_factory(self.p.policy, "infoflow4") - cls2 = class_factory(self.p.policy, cls1) - self.assertIs(cls2, cls1) - - def test_010_string(self): - """ObjClass: string representation""" - cls = self.mock_class("test10", ["perm1", "perm2"]) - self.assertEqual("test10", str(cls)) - - def test_020_perms(self): - """ObjClass: permissions""" - cls = self.mock_class("test20", ["perm1", "perm2"], com_perms=["perm3", "perm4"]) - self.assertEqual(set(["perm1", "perm2"]), cls.perms) - - def test_030_statment(self): - """ObjClass: statement, no common.""" - cls = self.mock_class("test30", ["perm1", "perm2"]) - self.assertRegex(cls.statement(), "(" - "class test30\n{\n\tperm1\n\tperm2\n}" - "|" - "class test30\n{\n\tperm2\n\tperm1\n}" - ")") - - def test_031_statment(self): - """ObjClass: statement, with common.""" - cls = self.mock_class("test31", ["perm1", "perm2"], com_perms=["perm3", "perm4"]) - self.assertRegex(cls.statement(), "(" - "class test31\ninherits test31_common\n{\n\tperm1\n\tperm2\n}" - "|" - "class test31\ninherits test31_common\n{\n\tperm2\n\tperm1\n}" - ")") - - def test_032_statment(self): - """ObjClass: statement, with common, no class perms.""" - cls = self.mock_class("test32", [], com_perms=["perm3", "perm4"]) - self.assertRegex(cls.statement(), "(" - "class test32\ninherits test32_common" - "|" - "class test32\ninherits test32_common" - ")") - - def test_040_contains(self): - """ObjClass: contains""" - cls = self.mock_class("test40", ["perm1", "perm2"]) - self.assertIn("perm1", cls) - self.assertNotIn("perm3", cls) - - def test_041_contains_common(self): - """ObjClass: contains, with common""" - cls = self.mock_class("test41", ["perm1", "perm2"], com_perms=["perm3", "perm4"]) - self.assertIn("perm1", cls) - self.assertIn("perm3", cls) - self.assertNotIn("perm5", cls) diff --git a/tests/policyrep/test_polcap.py b/tests/policyrep/test_polcap.py deleted file mode 100644 index c5ccc604..00000000 --- a/tests/policyrep/test_polcap.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable -import unittest -from unittest.mock import Mock - - -@unittest.skip("Needs to be reworked for cython") -class PolCapTest(unittest.TestCase): - - @staticmethod - def mock_cap(name): - cap = Mock(qpol.qpol_polcap_t) - cap.name.return_value = name - return cap - - def setUp(self): - self.p = Mock(qpol.qpol_policy_t) - - def test_001_factory(self): - """PolCap: factory on qpol object.""" - q = self.mock_cap("test1") - cap = polcap_factory(self.p, q) - self.assertEqual("test1", cap.qpol_symbol.name(self.p)) - - def test_002_factory_object(self): - """PolCap: factory on PolCap object.""" - q = self.mock_cap("test2") - cap1 = polcap_factory(self.p, q) - cap2 = polcap_factory(self.p, cap1) - self.assertIs(cap2, cap1) - - def test_003_factory_lookup(self): - """PolCap: factory lookup.""" - with self.assertRaises(TypeError): - polcap_factory(self.p, "open_perms") - - def test_010_string(self): - """PolCap: basic string rendering.""" - q = self.mock_cap("test10") - cap = polcap_factory(self.p, q) - self.assertEqual("test10", str(cap)) - - def test_020_statement(self): - """PolCap: statement.""" - q = self.mock_cap("test20") - cap = polcap_factory(self.p, q) - self.assertEqual("policycap test20;", cap.statement()) diff --git a/tests/policyrep/test_rbacrule.py b/tests/policyrep/test_rbacrule.py deleted file mode 100644 index cf2b01cc..00000000 --- a/tests/policyrep/test_rbacrule.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable -import unittest -from unittest.mock import Mock, patch - -from setools.exception import InvalidRBACRuleType, RuleNotConditional, RuleUseError - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.role.role_factory', lambda x, y: y) -class RoleAllowTest(unittest.TestCase): - - def mock_avrule_factory(self, source, target): - mock_rule = Mock(qpol_role_allow_t) - mock_rule.rule_type.return_value = RBACRuletype.allow - mock_rule.source_role.return_value = source - mock_rule.target_role.return_value = target - - return rbac_rule_factory(self.p, mock_rule) - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_000_factory(self): - """RoleAllow factory lookup.""" - with self.assertRaises(TypeError): - rbac_rule_factory(self.p, "INVALID") - - @unittest.skip("RBAC ruletype changed to an enumeration.") - def test_001_validate_ruletype(self): - """RoleAllow valid rule types.""" - # no return value means a return of None - self.assertEqual("allow", validate_ruletype("allow")) - - def test_002_validate_ruletype_invalid(self): - """RoleAllow valid rule types.""" - with self.assertRaises(InvalidRBACRuleType): - self.assertTrue(validate_ruletype("range_transition")) - - def test_010_ruletype(self): - """RoleAllow rule type""" - rule = self.mock_avrule_factory("a", "b") - self.assertEqual(RBACRuletype.allow, rule.ruletype) - - def test_020_source_role(self): - """RoleAllow source role""" - rule = self.mock_avrule_factory("source20", "b") - self.assertEqual("source20", rule.source) - - def test_030_target_role(self): - """RoleAllow target role""" - rule = self.mock_avrule_factory("a", "target30") - self.assertEqual("target30", rule.target) - - def test_040_object_class(self): - """RoleAllow object class""" - rule = self.mock_avrule_factory("a", "b") - with self.assertRaises(RuleUseError): - rule.tclass - - def test_060_conditional(self): - """RoleAllow conditional expression""" - rule = self.mock_avrule_factory("a", "b") - with self.assertRaises(RuleNotConditional): - rule.conditional - - def test_070_default(self): - """RoleAllow default role""" - rule = self.mock_avrule_factory("a", "b") - with self.assertRaises(RuleUseError): - rule.default - - def test_100_statement_one_perm(self): - """RoleAllow statement.""" - rule = self.mock_avrule_factory("a", "b") - self.assertEqual("allow a b;", rule.statement()) - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.role.role_factory', lambda x, y: y) -@patch('setools.policyrep.typeattr.type_or_attr_factory', lambda x, y: y) -@patch('setools.policyrep.objclass.class_factory', lambda x, y: y) -class RoleTransitionTest(unittest.TestCase): - - def mock_roletrans_factory(self, source, target, tclass, default): - mock_rule = Mock(qpol_role_trans_t) - mock_rule.rule_type.return_value = RBACRuletype.role_transition - mock_rule.source_role.return_value = source - mock_rule.target_type.return_value = target - mock_rule.object_class.return_value = tclass - mock_rule.default_role.return_value = default - - return rbac_rule_factory(self.p, mock_rule) - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_000_factory(self): - """RoleTransition factory lookup.""" - with self.assertRaises(TypeError): - rbac_rule_factory(self.p, "INVALID") - - def test_001_validate_ruletype(self): - """RoleTransition valid rule types.""" - self.assertEqual(RBACRuletype.role_transition, validate_ruletype("role_transition")) - - def test_002_validate_ruletype_invalid(self): - """RoleTransition valid rule types.""" - with self.assertRaises(InvalidRBACRuleType): - self.assertTrue(validate_ruletype("type_transition")) - - def test_010_ruletype(self): - """RoleTransition rule type""" - rule = self.mock_roletrans_factory("a", "b", "c", "d") - self.assertEqual(RBACRuletype.role_transition, rule.ruletype) - - def test_020_source_role(self): - """RoleTransition source role""" - rule = self.mock_roletrans_factory("source20", "b", "c", "d") - self.assertEqual("source20", rule.source) - - def test_030_target_type(self): - """RoleTransition target type""" - rule = self.mock_roletrans_factory("a", "target30", "c", "d") - self.assertEqual("target30", rule.target) - - def test_040_object_class(self): - """RoleTransition object class""" - rule = self.mock_roletrans_factory("a", "b", "class40", "d") - self.assertEqual("class40", rule.tclass) - - def test_050_default(self): - """RoleTransition default role""" - rule = self.mock_roletrans_factory("a", "b", "c", "default50") - self.assertEqual("default50", rule.default) - - def test_060_conditional(self): - """RoleTransition conditional expression""" - rule = self.mock_roletrans_factory("a", "b", "c", "d") - with self.assertRaises(RuleNotConditional): - rule.conditional - - def test_100_statement(self): - """RoleTransition statement.""" - rule = self.mock_roletrans_factory("a", "b", "c", "d") - self.assertEqual("role_transition a b:c d;", rule.statement()) diff --git a/tests/policyrep/test_role.py b/tests/policyrep/test_role.py deleted file mode 100644 index 75863a44..00000000 --- a/tests/policyrep/test_role.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable,no-member -import unittest -from unittest.mock import Mock - -from setools import SELinuxPolicy -from setools.exception import InvalidRole - - -@unittest.skip("Needs to be reworked for cython") -class RoleTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/role.conf") - - def mock_role_factory(self, name, types): - """Factory function for Role objects, using a mock qpol object.""" - mock_role = Mock(qpol.qpol_role_t) - mock_role.name.return_value = name - mock_role.type_iter = lambda x: iter(types) - - return role_factory(self.p.policy, mock_role) - - def test_001_lookup(self): - """Role factory policy lookup.""" - role = role_factory(self.p.policy, "role20_r") - self.assertEqual("role20_r", role.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """Role factory policy invalid lookup.""" - with self.assertRaises(InvalidRole): - role_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """Role factory policy lookup of Role object.""" - role1 = role_factory(self.p.policy, "role20_r") - role2 = role_factory(self.p.policy, role1) - self.assertIs(role2, role1) - - def test_010_string(self): - """Role basic string rendering.""" - role = self.mock_role_factory("rolename10", ['type1']) - self.assertEqual("rolename10", str(role)) - - def test_020_statement_type(self): - """Role statement, one type.""" - role = self.mock_role_factory("rolename20", ['type30']) - self.assertEqual("role rolename20 types type30;", role.statement()) - - def test_021_statement_two_types(self): - """Role statement, two types.""" - role = self.mock_role_factory("rolename21", ['type31a', 'type31b']) - self.assertEqual("role rolename21 types { type31a type31b };", role.statement()) - - def test_022_statement_decl(self): - """Role statement, no types.""" - # This is an unlikely corner case, where a role - # has been declared but has no types. - role = self.mock_role_factory("rolename22", []) - self.assertEqual("role rolename22;", role.statement()) - - def test_030_types(self): - """Role types generator.""" - role = self.mock_role_factory("rolename", ['type31b', 'type31c']) - self.assertEqual(['type31b', 'type31c'], sorted(role.types())) - - def test_040_expand(self): - """Role expansion""" - role = self.mock_role_factory("rolename", ['type31a', 'type31b', 'type31c']) - expanded = list(role.expand()) - self.assertEqual(1, len(expanded)) - self.assertIs(role, expanded[0]) diff --git a/tests/policyrep/test_selinuxpolicy.py b/tests/policyrep/test_selinuxpolicy.py deleted file mode 100644 index ddca49b9..00000000 --- a/tests/policyrep/test_selinuxpolicy.py +++ /dev/null @@ -1,231 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# - -import copy -import os -import sys -import unittest - -from setools import SELinuxPolicy, HandleUnknown -from setools.exception import InvalidPolicy - -from .util import compile_policy - - -class SELinuxPolicyTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/policyrep/selinuxpolicy.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - @unittest.skip("Retired for the SELinuxPolicyLoadError test suite.") - def test_001_open_policy_error(self): - """SELinuxPolicy: Invalid policy on open.""" - # source policies not supported - self.assertRaises(InvalidPolicy, SELinuxPolicy, "tests/policyrep/selinuxpolicy-bad.conf") - - def test_002_open_policy_non_existant(self): - """SELinuxPolicy: Non existant policy on open.""" - self.assertRaises(OSError, SELinuxPolicy, "tests/policyrep/DOES_NOT_EXIST") - - def test_003_deepcopy(self): - """SELinuxPolicy: Deep copy""" - p = copy.deepcopy(self.p) - self.assertIs(self.p, p) - - def test_010_handle_unknown(self): - """SELinuxPolicy: handle unknown setting.""" - self.assertEqual(self.p.handle_unknown, HandleUnknown.reject) - - def test_011_mls(self): - """SELinuxPolicy: MLS status.""" - self.assertTrue(self.p.mls) - - def test_012_version(self): - """SELinuxPolicy: version.""" - self.assertTrue(self.p.version) - - def test_100_allow_count(self): - """SELinuxPolicy: allow count""" - self.assertEqual(self.p.allow_count, 113) - - def test_101_auditallow_count(self): - """SELinuxPolicy: auditallow count""" - self.assertEqual(self.p.auditallow_count, 109) - - def test_102_boolean_count(self): - """SELinuxPolicy: Boolean count.""" - self.assertEqual(self.p.boolean_count, 127) - - # def test_103_bounds_count(self): - - def test_104_category_count(self): - """SELinuxPolicy: category count""" - self.assertEqual(self.p.category_count, 17) - - def test_105_class_count(self): - """SELinuxPolicy: object class count""" - self.assertEqual(self.p.class_count, 7) - - def test_106_common_count(self): - """SELinuxPolicy: common permisison set count""" - self.assertEqual(self.p.common_count, 3) - - def test_107_conditional_count(self): - """SELinuxPolicy: conditional (expression) count""" - self.assertEqual(self.p.conditional_count, 67) - - def test_108_constraint_count(self): - """SELinuxPolicy: standard constraint count""" - self.assertEqual(self.p.constraint_count, 19) - - # def test_109_default_count(self): - - def test_110_dontaudit_count(self): - """SELinuxPolicy: dontaudit rule count""" - self.assertEqual(self.p.dontaudit_count, 107) - - def test_111_fs_use_count(self): - """SELinuxPolicy: fs_use_* count""" - self.assertEqual(self.p.fs_use_count, 149) - - def test_112_genfscon_count(self): - """SELinuxPolicy: genfscon count""" - self.assertEqual(self.p.genfscon_count, 151) - - def test_113_initial_sid_count(self): - """SELinuxPolicy: initial sid count""" - self.assertEqual(self.p.initialsids_count, 11) - - def test_114_level_count(self): - """SELinuxPolicy: MLS level count""" - self.assertEqual(self.p.level_count, 13) - - def test_115_mls_constraint_count(self): - """SELinuxPolicy: MLS constraint count""" - self.assertEqual(self.p.mlsconstraint_count, 23) - - def test_116_mls_validatetrans_count(self): - """SELinuxPolicy: MLS validatetrans count""" - self.assertEqual(self.p.mlsvalidatetrans_count, 3) - - def test_117_netifcon_count(self): - """SELinuxPolicy: netifcon count""" - self.assertEqual(self.p.netifcon_count, 167) - - def test_118_neverallow_count(self): - """SELinuxPolicy: neverallow rule count""" - # changed after dropping source policy support - # self.assertEqual(self.p.neverallow_count, 103) - self.assertEqual(self.p.neverallow_count, 0) - - def test_119_nodecon_count(self): - """SELinuxPolicy: nodecon count""" - self.assertEqual(self.p.nodecon_count, 173) - - def test_120_permission_count(self): - """SELinuxPolicy: permission count""" - self.assertEqual(self.p.permission_count, 29) - - def test_121_permissive_types_count(self): - """SELinuxPolicy: permissive types count""" - self.assertEqual(self.p.permissives_count, 73) - - def test_122_polcap_count(self): - """SELinuxPolicy: policy capability count""" - self.assertEqual(self.p.polcap_count, 2) - - def test_123_portcon_count(self): - """SELinuxPolicy: portcon count""" - self.assertEqual(self.p.portcon_count, 163) - - def test_124_range_transition_count(self): - """SELinuxPolicy: range_transition count""" - self.assertEqual(self.p.range_transition_count, 71) - - def test_125_role_count(self): - """SELinuxPolicy: role count""" - self.assertEqual(self.p.role_count, 131) - - # def test_126_role_attribute_count(self): - - def test_127_role_allow_count(self): - """SELinuxPolicy: (role) allow count""" - self.assertEqual(self.p.role_allow_count, 83) - - def test_128_role_transition_count(self): - """SELinuxPolicy: role_transition count""" - self.assertEqual(self.p.role_transition_count, 79) - - def test_129_type_count(self): - """SELinuxPolicy: type count""" - self.assertEqual(self.p.type_count, 137) - - def test_130_type_attribute_count(self): - """SELinuxPolicy: type attribute count""" - self.assertEqual(self.p.type_attribute_count, 157) - - def test_131_type_change_count(self): - """SELinuxPolicy: type_change rule count""" - self.assertEqual(self.p.type_change_count, 89) - - def test_132_type_member_count(self): - """SELinuxPolicy: type_member rule count""" - self.assertEqual(self.p.type_member_count, 61) - - def test_133_type_transition_count(self): - """SELinuxPolicy: type_transition rule count""" - self.assertEqual(self.p.type_transition_count, 97) - - def test_134_user_count(self): - """SELinuxPolicy: user count""" - self.assertEqual(self.p.user_count, 101) - - def test_135_validatetrans_count(self): - """SELinuxPolicy: validatetrans count""" - self.assertEqual(self.p.validatetrans_count, 5) - - def test_136_allowxperm_count(self): - """SELinuxPolicy: allowxperm rount""" - self.assertEqual(self.p.allowxperm_count, 179) - - def test_137_allowxperm_count(self): - """SELinuxPolicy: auditallowxperm rount""" - self.assertEqual(self.p.auditallowxperm_count, 181) - - def test_138_neverallowxperm_count(self): - """SELinuxPolicy: neverallowxperm rount""" - # changed after dropping source policy support - # self.assertEqual(self.p.neverallowxperm_count, 191) - self.assertEqual(self.p.neverallowxperm_count, 0) - - def test_139_allowxperm_count(self): - """SELinuxPolicy: dontauditxperm rount""" - self.assertEqual(self.p.dontauditxperm_count, 193) - - -@unittest.skip("No longer necessary since source policy support was dropped.") -class SELinuxPolicyLoadError(unittest.TestCase): - - """Test attempted loading of non-compiling policies.""" - - def _load_policy(self, policy): - self.assertRaises(InvalidPolicy, SELinuxPolicy, - "tests/policyrep/invalid_policies/" + policy) - - def test_nodecon_invalid_range(self): - """SELinuxPolicy: invalid nodecon range (category not associated) error.""" - self._load_policy("nodecon-invalid-range.conf") - sys.stderr.write("The \"category can not be associated\" error above is expected.") - - # this is not fixed yet. See issue #72 - @unittest.expectedFailure - def test_user_level_not_in_range(self): - """SELinuxPolicy: error for user's default level isn't within the range.""" - self._load_policy("user-level-not-in-range.conf") diff --git a/tests/policyrep/test_symbol.py b/tests/policyrep/test_symbol.py deleted file mode 100644 index 86c765b0..00000000 --- a/tests/policyrep/test_symbol.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable -import copy -import unittest -from unittest.mock import Mock, patch - -from setools import SELinuxPolicy - - -@unittest.skip("Needs to be reworked for cython") -class PolicySymbolTest(unittest.TestCase): - - """Tests for base symbol class methods.""" - - def mock_symbol_factory(self, name): - """Factory function for Role objects, using a mock qpol object.""" - mock_role = Mock(qpol.qpol_role_t) - mock_role.name.return_value = name - mock_role.this = name - - mock_policy = Mock(qpol.qpol_policy_t) - return PolicySymbol(mock_policy, mock_role) - - def test_001_string(self): - """Symbol: string representation""" - sym = self.mock_symbol_factory("test1") - self.assertEqual("test1", str(sym)) - - def test_010_hash(self): - """Symbol: hash""" - sym = self.mock_symbol_factory("test10") - self.assertEqual(hash("test10"), hash(sym)) - - def test_020_eq(self): - """Symbol: equality""" - sym1 = self.mock_symbol_factory("test20") - sym2 = self.mock_symbol_factory("test20") - self.assertEqual(sym1, sym2) - - def test_021_eq(self): - """Symbol: equality with string""" - sym = self.mock_symbol_factory("test21") - self.assertEqual("test21", sym) - - def test_030_ne(self): - """Symbol: inequality""" - sym1 = self.mock_symbol_factory("test30a") - sym2 = self.mock_symbol_factory("test30b") - self.assertNotEqual(sym1, sym2) - - def test_031_ne(self): - """Symbol: inequality with string""" - sym = self.mock_symbol_factory("test31a") - self.assertNotEqual("test31b", sym) - - def test_040_lt(self): - """Symbol: less-than""" - sym1 = self.mock_symbol_factory("test40a") - sym2 = self.mock_symbol_factory("test40b") - self.assertTrue(sym1 < sym2) - - sym1 = self.mock_symbol_factory("test40") - sym2 = self.mock_symbol_factory("test40") - self.assertFalse(sym1 < sym2) - - sym1 = self.mock_symbol_factory("test40b") - sym2 = self.mock_symbol_factory("test40a") - self.assertFalse(sym1 < sym2) - - def test_050_deepcopy(self): - """Symbol: deep copy""" - sym1 = self.mock_symbol_factory("test50") - sym2 = copy.deepcopy(sym1) - self.assertIs(sym1.policy, sym2.policy) - self.assertIs(sym1.qpol_symbol, sym2.qpol_symbol) diff --git a/tests/policyrep/test_terule.py b/tests/policyrep/test_terule.py deleted file mode 100644 index 4603f330..00000000 --- a/tests/policyrep/test_terule.py +++ /dev/null @@ -1,405 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable -import unittest -from unittest.mock import Mock, patch - -from setools import SELinuxPolicy -from setools.exception import InvalidTERuleType, RuleNotConditional, RuleUseError, \ - TERuleNoFilename - -from .util import compile_policy - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.boolcond.condexpr_factory', lambda x, y: y) -@patch('setools.policyrep.typeattr.type_or_attr_factory', lambda x, y: y) -@patch('setools.policyrep.objclass.class_factory', lambda x, y: y) -class AVRuleTest(unittest.TestCase): - - def mock_avrule_factory(self, ruletype, source, target, tclass, perms, cond=None): - mock_rule = Mock(qpol_avrule_t) - mock_rule.is_extended.return_value = False - mock_rule.rule_type.return_value = TERuletype.lookup(ruletype) - mock_rule.source_type.return_value = source - mock_rule.target_type.return_value = target - mock_rule.object_class.return_value = tclass - mock_rule.perm_iter = lambda x: iter(perms) - - if cond: - mock_rule.cond.return_value = cond - else: - # this actually comes out of condexpr_factory - # but it's simpler to have here - mock_rule.cond.side_effect = AttributeError - - return te_rule_factory(self.p, mock_rule) - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_000_factory(self): - """AVRule factory lookup.""" - with self.assertRaises(TypeError): - te_rule_factory(self.p, "INVALID") - - @unittest.skip("TE ruletype changed to an enumeration.") - def test_001_validate_ruletype(self): - """AVRule valid rule types.""" - for r in ["allow", "neverallow", "auditallow", "dontaudit"]: - self.assertEqual(r, validate_ruletype(r)) - - def test_002_validate_ruletype_invalid(self): - """AVRule valid rule types.""" - with self.assertRaises(InvalidTERuleType): - self.assertTrue(validate_ruletype("role_transition")) - - def test_010_ruletype(self): - """AVRule rule type""" - rule = self.mock_avrule_factory("neverallow", "a", "b", "c", ['d']) - self.assertEqual(TERuletype.neverallow, rule.ruletype) - - def test_020_source_type(self): - """AVRule source type""" - rule = self.mock_avrule_factory("allow", "source20", "b", "c", ['d']) - self.assertEqual("source20", rule.source) - - def test_030_target_type(self): - """AVRule target type""" - rule = self.mock_avrule_factory("allow", "a", "target30", "c", ['d']) - self.assertEqual("target30", rule.target) - - def test_040_object_class(self): - """AVRule object class""" - rule = self.mock_avrule_factory("allow", "a", "b", "class40", ['d']) - self.assertEqual("class40", rule.tclass) - - def test_050_permissions(self): - """AVRule permissions""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['perm50a', 'perm50b']) - self.assertSetEqual(set(['perm50a', 'perm50b']), rule.perms) - - def test_060_conditional(self): - """AVRule conditional expression""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d'], cond="cond60") - self.assertEqual("cond60", rule.conditional) - - def test_061_unconditional(self): - """AVRule conditional expression (none)""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d']) - with self.assertRaises(RuleNotConditional): - rule.conditional - - def test_070_default(self): - """AVRule default type""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d']) - with self.assertRaises(RuleUseError): - rule.default - - def test_080_filename(self): - """AVRule filename (none)""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d']) - with self.assertRaises(RuleUseError): - rule.filename - - def test_100_statement_one_perm(self): - """AVRule statement, one permission.""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d']) - self.assertEqual("allow a b:c d;", rule.statement()) - - def test_101_statement_two_perms(self): - """AVRule statement, two permissions.""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d1', 'd2']) - - # permissions are stored in a set, so the order may vary - self.assertRegex(rule.statement(), "(" - "allow a b:c { d1 d2 };" - "|" - "allow a b:c { d2 d1 };" - ")") - - def test_102_statement_one_perm_cond(self): - """AVRule statement, one permission, conditional.""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d'], cond="cond102") - self.assertEqual("allow a b:c d; [ cond102 ]:True", rule.statement()) - - def test_103_statement_two_perms_cond(self): - """AVRule statement, two permissions, conditional.""" - rule = self.mock_avrule_factory("allow", "a", "b", "c", ['d1', 'd2'], cond="cond103") - - # permissions are stored in a set, so the order may vary - self.assertRegex(rule.statement(), "(" - r"allow a b:c { d1 d2 }; \[ cond103 ]" # noqa - "|" - r"allow a b:c { d2 d1 }; \[ cond103 ]" - ")") - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.boolcond.condexpr_factory', lambda x, y: y) -@patch('setools.policyrep.typeattr.type_or_attr_factory', lambda x, y: y) -@patch('setools.policyrep.objclass.class_factory', lambda x, y: y) -class AVRuleXpermTest(unittest.TestCase): - - def mock_avrule_factory(self, ruletype, source, target, tclass, xperm, perms): - mock_rule = Mock(qpol_avrule_t) - mock_rule.is_extended.return_value = True - mock_rule.rule_type.return_value = TERuletype.lookup(ruletype) - mock_rule.source_type.return_value = source - mock_rule.target_type.return_value = target - mock_rule.object_class.return_value = tclass - mock_rule.xperm_type.return_value = xperm - mock_rule.xperm_iter = lambda x: iter(perms) - - # this actually comes out of condexpr_factory - # but it's simpler to have here - mock_rule.cond.side_effect = AttributeError - - return te_rule_factory(self.p, mock_rule) - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_000_factory(self): - """AVRuleXperm factory lookup.""" - with self.assertRaises(TypeError): - te_rule_factory(self.p, "INVALID") - - @unittest.skip("TE ruletype changed to an enumeration.") - def test_001_validate_ruletype(self): - """AVRuleXperm valid rule types.""" - for r in ["allowxperm", "neverallowxperm", "auditallowxperm", "dontauditxperm"]: - self.assertEqual(r, validate_ruletype(r)) - - def test_010_ruletype(self): - """AVRuleXperm rule type""" - rule = self.mock_avrule_factory("neverallowxperm", "a", "b", "c", "d", [0x0001]) - self.assertEqual(TERuletype.neverallowxperm, rule.ruletype) - - def test_020_source_type(self): - """AVRuleXperm source type""" - rule = self.mock_avrule_factory("allowxperm", "source20", "b", "c", "d", [0x0001]) - self.assertEqual("source20", rule.source) - - def test_030_target_type(self): - """AVRuleXperm target type""" - rule = self.mock_avrule_factory("allowxperm", "a", "target30", "c", "d", [0x0001]) - self.assertEqual("target30", rule.target) - - def test_040_object_class(self): - """AVRuleXperm object class""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "class40", "d", [0x0001]) - self.assertEqual("class40", rule.tclass) - - def test_050_permissions(self): - """AVRuleXperm permissions""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", [0x0001, 0x0002, 0x0003]) - self.assertSetEqual(set([0x0001, 0x0002, 0x0003]), rule.perms) - - def test_060_xperm_type(self): - """AVRuleXperm xperm type""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "xperm60", [0x0001]) - self.assertEqual("xperm60", rule.xperm_type) - - def test_070_unconditional(self): - """AVRuleXperm conditional expression (none)""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", [0x0001]) - with self.assertRaises(RuleNotConditional): - rule.conditional - - def test_080_default(self): - """AVRuleXperm default type""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", [0x0001]) - with self.assertRaises(RuleUseError): - rule.default - - def test_090_filename(self): - """AVRuleXperm filename (none)""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", [0x0001]) - with self.assertRaises(RuleUseError): - rule.filename - - def test_100_statement_one_perm(self): - """AVRuleXperm statement, one permission.""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", [0x0001]) - self.assertEqual("allowxperm a b:c d 0x0001;", rule.statement()) - - def test_101_statement_two_perms(self): - """AVRuleXperm statement, two permissions.""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", [0x0001, 0x0003]) - self.assertEqual(rule.statement(), "allowxperm a b:c d { 0x0001 0x0003 };") - - def test_102_statement_range_perms(self): - """AVRuleXperm statement, range of permissions.""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", - list(range(0x0010, 0x0015))) - self.assertEqual(rule.statement(), "allowxperm a b:c d 0x0010-0x0014;") - - def test_103_statement_single_perm_range_perms(self): - """AVRuleXperm statement, single perm with range of permissions.""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", - [0x0001, 0x0003, 0x0004, 0x0005]) - self.assertEqual(rule.statement(), "allowxperm a b:c d { 0x0001 0x0003-0x0005 };") - - def test_104_statement_two_range_perms(self): - """AVRuleXperm statement, two ranges of permissions.""" - rule = self.mock_avrule_factory("allowxperm", "a", "b", "c", "d", - [0x0003, 0x0004, 0x0005, 0x0007, 0x0008, 0x0009]) - self.assertEqual(rule.statement(), "allowxperm a b:c d { 0x0003-0x0005 0x0007-0x0009 };") - - -class AVRuleXpermTestIssue74(unittest.TestCase): - - """ - Regression test for xperm ranges starting with 0x00 not being loaded. - https://github.com/SELinuxProject/setools/issues/74 - """ - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/policyrep/terule_issue74.conf") - - def test_issue74_regression(self): - """Regression test for GitHub issue 74.""" - rules = sorted(self.p.terules()) - print(rules) - self.assertEqual(2, len(rules)) - - # expect 2 rules: - # allowxperm init_type_t init_type_t : unix_dgram_socket ioctl { 0x8910 }; - # allowxperm init_type_t init_type_t : unix_dgram_socket ioctl { 0x0-0xff }; - self.assertSetEqual(set(range(0x100)), rules[0].perms) - self.assertSetEqual(set([0x8910]), rules[1].perms) - - -@unittest.skip("Needs to be reworked for cython") -@patch('setools.policyrep.boolcond.condexpr_factory', lambda x, y: y) -@patch('setools.policyrep.typeattr.type_factory', lambda x, y: y) -@patch('setools.policyrep.typeattr.type_or_attr_factory', lambda x, y: y) -@patch('setools.policyrep.objclass.class_factory', lambda x, y: y) -class TERuleTest(unittest.TestCase): - - def mock_terule_factory(self, ruletype, source, target, tclass, default, cond=None, - filename=None): - - if filename: - assert not cond - mock_rule = Mock(qpol_filename_trans_t) - mock_rule.filename.return_value = filename - - else: - mock_rule = Mock(qpol_terule_t) - - if cond: - mock_rule.cond.return_value = cond - else: - # this actually comes out of condexpr_factory - # but it's simpler to have here - mock_rule.cond.side_effect = AttributeError - - mock_rule.rule_type.return_value = TERuletype.lookup(ruletype) - mock_rule.source_type.return_value = source - mock_rule.target_type.return_value = target - mock_rule.object_class.return_value = tclass - mock_rule.default_type.return_value = default - - return te_rule_factory(self.p, mock_rule) - - def setUp(self): - self.p = Mock(qpol_policy_t) - - def test_000_factory(self): - """TERule factory lookup.""" - with self.assertRaises(TypeError): - te_rule_factory(self.p, "INVALID") - - @unittest.skip("TE ruletype changed to an enumeration.") - def test_001_validate_ruletype(self): - """TERule valid rule types.""" - for r in ["type_transition", "type_change", "type_member"]: - self.assertEqual(r, validate_ruletype(r)) - - @unittest.skip("TE ruletype changed to an enumeration.") - def test_002_validate_ruletype_invalid(self): - """TERule valid rule types.""" - with self.assertRaises(InvalidTERuleType): - self.assertTrue(validate_ruletype("role_transition")) - - def test_010_ruletype(self): - """TERule rule type""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d") - self.assertEqual(TERuletype.type_transition, rule.ruletype) - - def test_020_source_type(self): - """TERule source type""" - rule = self.mock_terule_factory("type_transition", "source20", "b", "c", "d") - self.assertEqual("source20", rule.source) - - def test_030_target_type(self): - """TERule target type""" - rule = self.mock_terule_factory("type_transition", "a", "target30", "c", "d") - self.assertEqual("target30", rule.target) - - def test_040_object_class(self): - """TERule object class""" - rule = self.mock_terule_factory("type_transition", "a", "b", "class40", "d") - self.assertEqual("class40", rule.tclass) - - def test_050_permissions(self): - """TERule permissions""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d") - with self.assertRaises(RuleUseError): - rule.perms - - def test_060_conditional(self): - """TERule conditional expression""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d", cond="cond60") - self.assertEqual("cond60", rule.conditional) - - def test_061_unconditional(self): - """TERule conditional expression (none)""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d") - with self.assertRaises(RuleNotConditional): - rule.conditional - - def test_070_default(self): - """TERule default type""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "default70") - self.assertEqual("default70", rule.default) - - def test_080_filename(self): - """TERule filename""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d", filename="name80") - self.assertEqual("name80", rule.filename) - - def test_081_filename_none(self): - """TERule filename (none)""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d") - with self.assertRaises(TERuleNoFilename): - rule.filename - - def test_082_filename_wrong_ruletype(self): - """TERule filename on wrong ruletype""" - rule = self.mock_terule_factory("type_change", "a", "b", "c", "d") - with self.assertRaises(RuleUseError): - rule.filename - - def test_100_statement(self): - """TERule statement.""" - rule1 = self.mock_terule_factory("type_transition", "a", "b", "c", "d") - rule2 = self.mock_terule_factory("type_change", "a", "b", "c", "d") - self.assertEqual("type_transition a b:c d;", rule1.statement()) - self.assertEqual("type_change a b:c d;", rule2.statement()) - - def test_102_statement_cond(self): - """TERule statement, conditional.""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d", cond="cond102") - self.assertEqual("type_transition a b:c d; [ cond102 ]:True", rule.statement()) - - def test_103_statement_filename(self): - """TERule statement, two permissions, conditional.""" - rule = self.mock_terule_factory("type_transition", "a", "b", "c", "d", filename="name103") - self.assertEqual("type_transition a b:c d \"name103\";", rule.statement()) diff --git a/tests/policyrep/test_typeattr.py b/tests/policyrep/test_typeattr.py deleted file mode 100644 index b16bc979..00000000 --- a/tests/policyrep/test_typeattr.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable,no-member -import unittest -from unittest.mock import Mock, patch - -from setools import SELinuxPolicy -from setools.exception import InvalidType, SymbolUseError - - -@unittest.skip("Needs to be reworked for cython") -class TypeTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/typeattr.conf") - - def mock_type_factory(self, name, attrs=[], alias=[], perm=False): - """Factory function for Type objects, using a mock qpol object.""" - mock_type = Mock(qpol.qpol_type_t) - mock_type.name.return_value = name - mock_type.type_iter.side_effect = AssertionError("Type iterator used") - mock_type.attr_iter = lambda x: iter(attrs) - mock_type.alias_iter = lambda x: iter(alias) - mock_type.ispermissive.return_value = perm - mock_type.isattr.return_value = False - mock_type.isalias.return_value = False - - return type_factory(self.p.policy, mock_type) - - def test_001_lookup(self): - """Type factory policy lookup.""" - type_ = type_factory(self.p.policy, "system") - self.assertEqual("system", type_.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """Type factory policy invalid lookup.""" - with self.assertRaises(InvalidType): - type_factory(self.p.policy, "INVALID") - - def test_003_lookup_alias(self): - """Type factory policy lookup alias.""" - type_ = type_factory(self.p.policy, "sysalias", deref=True) - self.assertEqual("system", type_.qpol_symbol.name(self.p.policy)) - - def test_004_lookup_alias_no_deref(self): - """Type factory policy lookup alias (no dereference).""" - with self.assertRaises(TypeError): - type_ = type_factory(self.p.policy, "sysalias") - - def test_005_lookup_attr(self): - """Type factory policy lookup atribute.""" - with self.assertRaises(TypeError): - type_ = type_factory(self.p.policy, "attr1") - - def test_006_lookup2(self): - """Type factory policy lookup (type_or_attr_factory).""" - type_ = type_or_attr_factory(self.p.policy, "system") - self.assertEqual("system", type_.qpol_symbol.name(self.p.policy)) - - def test_007_lookup2_invalid(self): - """Type factory policy invalid lookup (type_or_attr_factory).""" - with self.assertRaises(InvalidType): - type_or_attr_factory(self.p.policy, "INVALID") - - def test_008_lookup2_alias(self): - """Type factory policy lookup alias (type_or_attr_factory).""" - type_ = type_or_attr_factory(self.p.policy, "sysalias", deref=True) - self.assertEqual("system", type_.qpol_symbol.name(self.p.policy)) - - def test_009_lookup2_alias_no_deref(self): - """Type factory policy lookup alias (no dereference, type_or_attr_factory).""" - with self.assertRaises(TypeError): - type_ = type_or_attr_factory(self.p.policy, "sysalias") - - def test_00a_lookup_object(self): - """Type factory policy lookup of Type object.""" - type1 = type_factory(self.p.policy, "system") - type2 = type_factory(self.p.policy, type1) - self.assertIs(type2, type1) - - def test_00b_lookup2_object(self): - """Type factory policy lookup of Type object (type_or_attr_factory).""" - type1 = type_or_attr_factory(self.p.policy, "system") - type2 = type_or_attr_factory(self.p.policy, type1) - self.assertIs(type2, type1) - - def test_010_string(self): - """Type basic string rendering.""" - type_ = self.mock_type_factory("name10") - self.assertEqual("name10", str(type_)) - - def test_020_attrs(self): - """Type attributes""" - type_ = self.mock_type_factory("name20", attrs=['attr1', 'attr2', 'attr3']) - self.assertEqual(['attr1', 'attr2', 'attr3'], sorted(type_.attributes())) - - def test_030_aliases(self): - """Type aliases""" - type_ = self.mock_type_factory("name30", alias=['alias1', 'alias2', 'alias3']) - self.assertEqual(['alias1', 'alias2', 'alias3'], sorted(type_.aliases())) - - def test_040_expand(self): - """Type expansion""" - type_ = self.mock_type_factory("name40") - expanded = list(type_.expand()) - self.assertEqual(1, len(expanded)) - self.assertIs(type_, expanded[0]) - - def test_050_permissive(self): - """Type is permissive""" - type_ = self.mock_type_factory("name50a") - permtype = self.mock_type_factory("name50b", perm=True) - self.assertFalse(type_.ispermissive) - self.assertTrue(permtype.ispermissive) - - def test_060_statement(self): - """Type basic statement""" - type_ = self.mock_type_factory("name60") - self.assertEqual("type name60;", type_.statement()) - - def test_061_statement_one_attr(self): - """Type statement, one attribute""" - type_ = self.mock_type_factory("name61", attrs=['attr1']) - self.assertEqual("type name61, attr1;", type_.statement()) - - def test_062_statement_two_attr(self): - """Type statement, two attributes""" - type_ = self.mock_type_factory("name62", attrs=['attr1', 'attr2']) - self.assertEqual("type name62, attr1, attr2;", type_.statement()) - - def test_063_statement_one_alias(self): - """Type statement, one alias""" - type_ = self.mock_type_factory("name63", alias=['alias1']) - self.assertEqual("type name63 alias alias1;", type_.statement()) - - def test_064_statement_two_alias(self): - """Type statement, two aliases""" - type_ = self.mock_type_factory("name64", alias=['alias1', 'alias2']) - self.assertEqual("type name64 alias { alias1 alias2 };", type_.statement()) - - def test_065_statement_one_attr_one_alias(self): - """Type statement, one attribute, one alias""" - type_ = self.mock_type_factory("name65", attrs=['attr1'], alias=['alias1']) - self.assertEqual("type name65 alias alias1, attr1;", type_.statement()) - - def test_066_statement_two_attr_one_alias(self): - """Type statement, two attributes, one alias""" - type_ = self.mock_type_factory("name66", attrs=['attr1', 'attr2'], alias=['alias1']) - self.assertEqual("type name66 alias alias1, attr1, attr2;", type_.statement()) - - def test_067_statement_one_attr_two_alias(self): - """Type statement, one attribute, two aliases""" - type_ = self.mock_type_factory("name67", attrs=['attr2'], alias=['alias3', 'alias4']) - self.assertEqual("type name67 alias { alias3 alias4 }, attr2;", type_.statement()) - - def test_068_statement_two_attr_two_alias(self): - """Type statement, two attributes, two aliases""" - type_ = self.mock_type_factory("name68", attrs=['attr2', 'attr3'], - alias=['alias2', 'alias4']) - self.assertEqual("type name68 alias { alias2 alias4 }, attr2, attr3;", type_.statement()) - - -@unittest.skip("Needs to be reworked for cython") -class TypeAttributeTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/typeattr.conf") - - def mock_attr_factory(self, name, types=[]): - """Factory function for TypeAttribute objects, using a mock qpol object.""" - mock_type = Mock(qpol.qpol_type_t) - mock_type.name.return_value = name - mock_type.type_iter = lambda x: iter(types) - mock_type.attr_iter.side_effect = AssertionError("Attr iter used") - mock_type.alias_iter.side_effect = AssertionError("Alias iter used") - mock_type.ispermissive.side_effect = AssertionError("Permissive used") - mock_type.isattr.return_value = True - mock_type.isalias.side_effect = AssertionError("Alias used") - - return attribute_factory(self.p.policy, mock_type) - - def test_001_lookup(self): - """TypeAttribute factory policy lookup.""" - attr = attribute_factory(self.p.policy, "attr1") - self.assertEqual("attr1", attr.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """TypeAttribute factory policy invalid lookup.""" - with self.assertRaises(InvalidType): - attribute_factory(self.p.policy, "INVALID") - - def test_006_lookup2(self): - """TypeAttribute factory policy lookup (type_or_attr_factory).""" - attr = type_or_attr_factory(self.p.policy, "attr1") - self.assertEqual("attr1", attr.qpol_symbol.name(self.p.policy)) - - def test_007_lookup2_invalid(self): - """TypeAttribute factory policy invalid lookup (type_or_attr_factory).""" - with self.assertRaises(InvalidType): - type_or_attr_factory(self.p.policy, "INVALID") - - def test_008_lookup_object(self): - """TypeAttribute factory policy lookup of TypeAttribute object.""" - attr1 = attribute_factory(self.p.policy, "attr1") - attr2 = attribute_factory(self.p.policy, attr1) - self.assertIs(attr2, attr1) - - def test_009_lookup2_object(self): - """TypeAttribute factory policy lookup of TypeAttribute object (type_or_attr_factory).""" - attr1 = type_or_attr_factory(self.p.policy, "attr2") - attr2 = type_or_attr_factory(self.p.policy, attr1) - self.assertIs(attr2, attr1) - - def test_010_string(self): - """TypeAttribute basic string rendering.""" - attr = self.mock_attr_factory("name10") - self.assertEqual("name10", str(attr)) - - def test_020_attrs(self): - """TypeAttribute attributes""" - attr = self.mock_attr_factory("name20") - with self.assertRaises(SymbolUseError): - attr.attributes() - - def test_030_aliases(self): - """TypeAttribute aliases""" - attr = self.mock_attr_factory("name30") - with self.assertRaises(SymbolUseError): - attr.aliases() - - def test_040_expand(self): - """TypeAttribute expansion""" - attr = self.mock_attr_factory("name40", types=['type31a', 'type31b', 'type31c']) - self.assertEqual(['type31a', 'type31b', 'type31c'], sorted(attr.expand())) - - def test_050_permissive(self): - with self.assertRaises(SymbolUseError): - attr = self.mock_attr_factory("name20") - attr.ispermissive - - def test_060_statement(self): - """TypeAttribute basic statement""" - attr = self.mock_attr_factory("name60") - self.assertEqual("attribute name60;", attr.statement()) - - def test_070_contains(self): - """TypeAttribute: contains""" - attr = self.mock_attr_factory("name70", types=['type31a', 'type31b', 'type31c']) - self.assertIn("type31b", attr) - self.assertNotIn("type30", attr) diff --git a/tests/policyrep/test_user.py b/tests/policyrep/test_user.py deleted file mode 100644 index 1ed7983b..00000000 --- a/tests/policyrep/test_user.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# Until this is fixed for cython: -# pylint: disable=undefined-variable,no-member -import unittest -from unittest.mock import Mock, patch - -from setools import SELinuxPolicy -from setools.exception import MLSDisabled, InvalidUser - - -@unittest.skip("Needs to be reworked for cython") -class UserTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = SELinuxPolicy("tests/policyrep/user.conf") - - def mock_user_factory(self, name, roles, level=None, range_=None): - """Factory function for User objects, using a mock qpol object.""" - assert (level and range_) or (not level and not range_) - - # inject object_r, like the compiler does - roles_with_objr = roles - roles_with_objr.append('object_r') - - mock_user = Mock(qpol.qpol_user_t) - mock_user.name.return_value = name - mock_user.role_iter = lambda x: iter(roles_with_objr) - mock_user.dfltlevel.return_value = level - mock_user.range.return_value = range_ - - return user_factory(self.p.policy, mock_user) - - def test_001_lookup(self): - """User factory policy lookup.""" - user = user_factory(self.p.policy, "user10") - self.assertEqual("user10", user.qpol_symbol.name(self.p.policy)) - - def test_002_lookup_invalid(self): - """User factory policy invalid lookup.""" - with self.assertRaises(InvalidUser): - user_factory(self.p.policy, "INVALID") - - def test_003_lookup_object(self): - """User factory policy lookup of User object.""" - user1 = user_factory(self.p.policy, "user10") - user2 = user_factory(self.p.policy, user1) - self.assertIs(user2, user1) - - def test_010_string(self): - """User basic string rendering.""" - user = self.mock_user_factory("username", ['role1']) - self.assertEqual("username", str(user)) - - def test_020_statement_role(self): - """User statement, one role.""" - with patch('setools.policyrep.mls.enabled', return_value=False): - user = self.mock_user_factory("username", ['role20_r']) - self.assertEqual("user username roles role20_r;", user.statement()) - - def test_021_statement_two_roles(self): - """User statement, two roles.""" - with patch('setools.policyrep.mls.enabled', return_value=False): - user = self.mock_user_factory("username", ['role20_r', 'role21a_r']) - # roles are stored in a set, so the role order may vary - self.assertRegex(user.statement(), "(" - "user username roles { role20_r role21a_r };" - "|" - "user username roles { role21a_r role20_r };" - ")") - - def test_022_statement_one_role_mls(self): - """User statement, one role, MLS.""" - user = self.mock_user_factory("username", ['role20_r'], level="s0", range_="s0-s2") - self.assertEqual("user username roles role20_r level s0 range s0 - s2;", user.statement()) - - def test_023_statement_two_roles_mls(self): - """User statement, two roles, MLS.""" - user = self.mock_user_factory("username", ['role20_r', 'role21a_r'], - level="s0", range_="s0 - s2") - # roles are stored in a set, so the role order may vary - self.assertRegex( - user.statement(), "(" - "user username roles { role20_r role21a_r } level s0 range s0 - s2;" - "|" - "user username roles { role21a_r role20_r } level s0 range s0 - s2;" - ")") - - def test_030_roles(self): - """User roles.""" - user = self.mock_user_factory("username", ['role20_r', 'role21a_r']) - self.assertSetEqual(user.roles, set(['role20_r', 'role21a_r'])) - - def test_040_level(self): - """User level.""" - user = self.mock_user_factory("username", ['role20_r', 'role21a_r'], - level="s0", range_="s0-s2") - self.assertEqual("s0", user.mls_level) - - def test_041_level_non_mls(self): - """User level, MLS disabled.""" - user = self.mock_user_factory("username", ['role20_r', 'role21a_r']) - with patch('setools.policyrep.mls.enabled', return_value=False): - with self.assertRaises(MLSDisabled): - user.mls_level - - def test_050_range(self): - """User level.""" - user = self.mock_user_factory("username", ['role20_r', 'role21a_r'], - level="s0", range_="s0-s2") - self.assertEqual("s0 - s2", user.mls_range) - - def test_051_range_non_mls(self): - """User level, MLS disabled.""" - user = self.mock_user_factory("username", ['role20_r', 'role21a_r'], - level="s0", range_="s0-s2") - with patch('setools.policyrep.mls.enabled', return_value=False): - with self.assertRaises(MLSDisabled): - user.mls_range diff --git a/tests/policyrep/util.py b/tests/policyrep/util.py deleted file mode 100644 index 3124cda6..00000000 --- a/tests/policyrep/util.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# Copyright 2018, Chris PeBenito -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import subprocess -import tempfile - -from setools import SELinuxPolicy - - -def compile_policy(source_file, mls=True, xen=False): - """ - Compile the specified source policy. Checkpolicy is - assumed to be /usr/bin/checkpolicy. Otherwise the path - must be specified in the CHECKPOLICY environment variable. - - Return: - A SELinuxPolicy object. - """ - # create a temp file for the binary policy - # and then have checkpolicy overwrite it. - fd, policy_path = tempfile.mkstemp() - os.close(fd) - - if "USERSPACE_SRC" in os.environ: - command = [os.environ['USERSPACE_SRC'] + "/checkpolicy/checkpolicy"] - elif "CHECKPOLICY" in os.environ: - command = [os.environ['CHECKPOLICY']] - else: - command = ["/usr/bin/checkpolicy"] - - if mls: - command.append("-M") - - if xen: - command.extend(["-t", "xen", "-c", "30"]) - - command.extend(["-o", policy_path, "-U", "reject", source_file]) - - with open(os.devnull, "w") as null: - subprocess.check_call(command, stdout=null, shell=False, close_fds=True) - - try: - policy = SELinuxPolicy(policy_path) - except Exception: - # This should never be hit, since this policy - # successfully compiled with checkpolicy above. - # If we do, clean up the binary policy since - # tearDownClass() does not run. - os.unlink(policy_path) - raise - - return policy diff --git a/tests/terulequery.py b/tests/terulequery.py deleted file mode 100644 index 61b619b3..00000000 --- a/tests/terulequery.py +++ /dev/null @@ -1,463 +0,0 @@ -"""Type enforcement rule query unit tests.""" -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# pylint: disable=invalid-name,too-many-public-methods -import os -import unittest - -from setools import TERuleQuery -from setools import TERuletype as TRT - -from . import mixins -from .policyrep.util import compile_policy - - -class TERuleQueryTest(mixins.ValidateRule, unittest.TestCase): - - """Type enforcement rule query unit tests.""" - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/terulequery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """TE rule query with no criteria.""" - # query with no parameters gets all TE rules. - rules = sorted(self.p.terules()) - - q = TERuleQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_001_source_direct(self): - """TE rule query with exact, direct, source match.""" - q = TERuleQuery( - self.p, source="test1a", source_indirect=False, source_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test1a", "test1t", "infoflow", set(["hi_w"])) - - def test_002_source_indirect(self): - """TE rule query with exact, indirect, source match.""" - q = TERuleQuery( - self.p, source="test2s", source_indirect=True, source_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test2a", "test2t", "infoflow", set(["hi_w"])) - - def test_003_source_direct_regex(self): - """TE rule query with regex, direct, source match.""" - q = TERuleQuery( - self.p, source="test3a.*", source_indirect=False, source_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test3aS", "test3t", "infoflow", set(["low_r"])) - - def test_004_source_indirect_regex(self): - """TE rule query with regex, indirect, source match.""" - q = TERuleQuery( - self.p, source="test4(s|t)", source_indirect=True, source_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test4a1", "test4a1", "infoflow", set(["hi_w"])) - self.validate_rule(r[1], TRT.allow, "test4a2", "test4a2", "infoflow", set(["low_r"])) - - def test_005_target_direct(self): - """TE rule query with exact, direct, target match.""" - q = TERuleQuery( - self.p, target="test5a", target_indirect=False, target_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test5s", "test5a", "infoflow", set(["hi_w"])) - - def test_006_target_indirect(self): - """TE rule query with exact, indirect, target match.""" - q = TERuleQuery( - self.p, target="test6t", target_indirect=True, target_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test6s", "test6a", "infoflow", set(["hi_w"])) - self.validate_rule(r[1], TRT.allow, "test6s", "test6t", "infoflow", set(["low_r"])) - - def test_007_target_direct_regex(self): - """TE rule query with regex, direct, target match.""" - q = TERuleQuery( - self.p, target="test7a.*", target_indirect=False, target_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test7s", "test7aPASS", "infoflow", set(["low_r"])) - - def test_008_target_indirect_regex(self): - """TE rule query with regex, indirect, target match.""" - q = TERuleQuery( - self.p, target="test8(s|t)", target_indirect=True, target_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test8a1", "test8a1", "infoflow", set(["hi_w"])) - self.validate_rule(r[1], TRT.allow, "test8a2", "test8a2", "infoflow", set(["low_r"])) - - @unittest.skip("Setting tclass to a string is no longer supported.") - def test_009_class(self): - """TE rule query with exact object class match.""" - q = TERuleQuery(self.p, tclass="infoflow2", tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test9", "test9", "infoflow2", set(["super_w"])) - - def test_010_class_list(self): - """TE rule query with object class list match.""" - q = TERuleQuery( - self.p, tclass=["infoflow3", "infoflow4"], tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test10", "test10", "infoflow3", set(["null"])) - self.validate_rule(r[1], TRT.allow, "test10", "test10", "infoflow4", set(["hi_w"])) - - def test_011_class_regex(self): - """TE rule query with object class regex match.""" - q = TERuleQuery(self.p, tclass="infoflow(5|6)", tclass_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test11", "test11", "infoflow5", set(["low_w"])) - self.validate_rule(r[1], TRT.allow, "test11", "test11", "infoflow6", set(["med_r"])) - - def test_012_perms_any(self): - """TE rule query with permission set intersection.""" - q = TERuleQuery(self.p, perms=["super_r"], perms_equal=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test12a", "test12a", "infoflow7", set(["super_r"])) - self.validate_rule(r[1], TRT.allow, "test12b", "test12b", "infoflow7", - set(["super_r", "super_none"])) - - def test_013_perms_equal(self): - """TE rule query with permission set equality.""" - q = TERuleQuery( - self.p, perms=["super_w", "super_none", "super_both"], perms_equal=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test13c", "test13c", "infoflow7", - set(["super_w", "super_none", "super_both"])) - - def test_014_ruletype(self): - """TE rule query with rule type match.""" - q = TERuleQuery(self.p, ruletype=["auditallow", "dontaudit"]) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.auditallow, "test14", "test14", "infoflow7", - set(["super_both"])) - self.validate_rule(r[1], TRT.dontaudit, "test14", "test14", "infoflow7", - set(["super_unmapped"])) - - def test_052_perms_subset1(self): - """TE rule query with permission subset.""" - q = TERuleQuery(self.p, perms=["super_none", "super_both"], perms_subset=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test13c", "test13c", "infoflow7", - set(["super_w", "super_none", "super_both"])) - self.validate_rule(r[1], TRT.allow, "test13d", "test13d", "infoflow7", - set(["super_w", "super_none", "super_both", "super_unmapped"])) - - def test_052_perms_subset2(self): - """TE rule query with permission subset (equality).""" - q = TERuleQuery(self.p, perms=["super_w", "super_none", "super_both", "super_unmapped"], - perms_subset=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test13d", "test13d", "infoflow7", - set(["super_w", "super_none", "super_both", "super_unmapped"])) - - def test_100_default(self): - """TE rule query with default type exact match.""" - q = TERuleQuery(self.p, default="test100d", default_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.type_transition, "test100", "test100", "infoflow7", "test100d") - - def test_101_default_regex(self): - """TE rule query with default type regex match.""" - q = TERuleQuery(self.p, default="test101.", default_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.type_transition, "test101", "test101d", "infoflow7", - "test101e") - self.validate_rule(r[1], TRT.type_transition, "test101", "test101e", "infoflow7", - "test101d") - - def test_200_boolean_intersection(self): - """TE rule query with intersection Boolean set match.""" - q = TERuleQuery(self.p, boolean=["test200"]) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test200t1", "test200t1", "infoflow7", - set(["super_w"]), cond="test200") - self.validate_rule(r[1], TRT.allow, "test200t2", "test200t2", "infoflow7", - set(["super_w"]), cond="test200a && test200") - - def test_201_boolean_equal(self): - """TE rule query with equal Boolean set match.""" - q = TERuleQuery(self.p, boolean=["test201a", "test201b"], boolean_equal=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allow, "test201t1", "test201t1", "infoflow7", - set(["super_unmapped"]), cond="test201b && test201a") - - def test_202_boolean_regex(self): - """TE rule query with regex Boolean match.""" - q = TERuleQuery(self.p, boolean="test202(a|b)", boolean_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allow, "test202t1", "test202t1", "infoflow7", - set(["super_none"]), cond="test202a") - self.validate_rule(r[1], TRT.allow, "test202t2", "test202t2", "infoflow7", - set(["super_unmapped"]), cond="test202b || test202c") - - def test_300_issue111(self): - """TE rule query with attribute source criteria, indirect match.""" - # https://github.com/TresysTechnology/setools/issues/111 - q = TERuleQuery(self.p, source="test300b", source_indirect=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 4) - self.validate_rule(r[0], TRT.allow, "test300a", "test300target", "infoflow7", set(["hi_w"])) - self.validate_rule(r[1], TRT.allow, "test300b", "test300target", "infoflow7", - set(["super_w"])) - self.validate_rule(r[2], TRT.allow, "test300t1", "test300t1", "infoflow7", set(["hi_r"])) - self.validate_rule(r[3], TRT.allow, "test300t2", "test300t2", "infoflow7", set(["med_w"])) - - def test_301_issue111(self): - """TE rule query with attribute target criteria, indirect match.""" - # https://github.com/TresysTechnology/setools/issues/111 - q = TERuleQuery(self.p, target="test301b", target_indirect=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 4) - self.validate_rule(r[0], TRT.allow, "test301source", "test301a", "infoflow7", set(["hi_w"])) - self.validate_rule(r[1], TRT.allow, "test301source", "test301b", "infoflow7", - set(["super_w"])) - self.validate_rule(r[2], TRT.allow, "test301t1", "test301t1", "infoflow7", set(["hi_r"])) - self.validate_rule(r[3], TRT.allow, "test301t2", "test301t2", "infoflow7", set(["med_w"])) - - def test_302_issue111(self): - """TE rule query with attribute default type criteria.""" - # https://github.com/TresysTechnology/setools/issues/111 - q = TERuleQuery(self.p, default="test302") - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.type_transition, "test302source", "test302t1", "infoflow7", - "test302t1") - self.validate_rule(r[1], TRT.type_transition, "test302source", "test302t2", "infoflow7", - "test302t2") - - -class TERuleQueryXperm(mixins.ValidateRule, unittest.TestCase): - - """TE Rule Query with extended permission rules.""" - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/terulequery2.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_001_source_direct(self): - """Xperm rule query with exact, direct, source match.""" - q = TERuleQuery( - self.p, source="test1a", source_indirect=False, source_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allowxperm, "test1a", "test1t", "infoflow", - set(range(0xebe0, 0xebff + 1)), xperm="ioctl") - - def test_002_source_indirect(self): - """Xperm rule query with exact, indirect, source match.""" - q = TERuleQuery( - self.p, source="test2s", source_indirect=True, source_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allowxperm, "test2a", "test2t", "infoflow", - set([0x5411, 0x5451]), xperm="ioctl") - - def test_003_source_direct_regex(self): - """Xperm rule query with regex, direct, source match.""" - q = TERuleQuery( - self.p, source="test3a.*", source_indirect=False, source_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allowxperm, "test3aS", "test3t", "infoflow", - set([0x1111]), xperm="ioctl") - - def test_004_source_indirect_regex(self): - """Xperm rule query with regex, indirect, source match.""" - q = TERuleQuery( - self.p, source="test4(s|t)", source_indirect=True, source_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allowxperm, "test4a1", "test4a1", "infoflow", - set([0x9999]), xperm="ioctl") - self.validate_rule(r[1], TRT.allowxperm, "test4a2", "test4a2", "infoflow", - set([0x1111]), xperm="ioctl") - - def test_005_target_direct(self): - """Xperm rule query with exact, direct, target match.""" - q = TERuleQuery( - self.p, target="test5a", target_indirect=False, target_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allowxperm, "test5s", "test5a", "infoflow", set([0x9999]), - xperm="ioctl") - - def test_006_target_indirect(self): - """Xperm rule query with exact, indirect, target match.""" - q = TERuleQuery( - self.p, target="test6t", target_indirect=True, target_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allowxperm, "test6s", "test6a", "infoflow", set([0x9999]), - xperm="ioctl") - self.validate_rule(r[1], TRT.allowxperm, "test6s", "test6t", "infoflow", set([0x1111]), - xperm="ioctl") - - def test_007_target_direct_regex(self): - """Xperm rule query with regex, direct, target match.""" - q = TERuleQuery( - self.p, target="test7a.*", target_indirect=False, target_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allowxperm, "test7s", "test7aPASS", "infoflow", set([0x1111]), - xperm="ioctl") - - def test_008_target_indirect_regex(self): - """Xperm rule query with regex, indirect, target match.""" - q = TERuleQuery( - self.p, target="test8(s|t)", target_indirect=True, target_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allowxperm, "test8a1", "test8a1", "infoflow", set([0x9999]), - xperm="ioctl") - self.validate_rule(r[1], TRT.allowxperm, "test8a2", "test8a2", "infoflow", set([0x1111]), - xperm="ioctl") - - def test_010_class_list(self): - """Xperm rule query with object class list match.""" - q = TERuleQuery( - self.p, tclass=["infoflow3", "infoflow4"], tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allowxperm, "test10", "test10", "infoflow3", set([0]), - xperm="ioctl") - self.validate_rule(r[1], TRT.allowxperm, "test10", "test10", "infoflow4", set([0x9999]), - xperm="ioctl") - - def test_011_class_regex(self): - """Xperm rule query with object class regex match.""" - q = TERuleQuery(self.p, tclass="infoflow(5|6)", tclass_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.allowxperm, "test11", "test11", "infoflow5", set([0x1111]), - xperm="ioctl") - self.validate_rule(r[1], TRT.allowxperm, "test11", "test11", "infoflow6", set([0x5555]), - xperm="ioctl") - - def test_014_ruletype(self): - """Xperm rule query with rule type match.""" - q = TERuleQuery(self.p, ruletype=["auditallowxperm", "dontauditxperm"]) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TRT.auditallowxperm, "test14", "test14", "infoflow7", - set([0x1234]), xperm="ioctl") - self.validate_rule(r[1], TRT.dontauditxperm, "test14", "test14", "infoflow7", - set([0x4321]), xperm="ioctl") - - def test_100_std_perm_any(self): - """Xperm rule query match by standard permission.""" - q = TERuleQuery(self.p, ruletype=["neverallow", "neverallowxperm"], - perms=set(["ioctl", "hi_w"]), perms_equal=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 0) - # changed after dropping source policy support - # self.assertEqual(len(r), 2) - # self.validate_rule(r[0], TRT.neverallow, "test100", "system", "infoflow2", - # set(["ioctl", "hi_w"])) - # self.validate_rule(r[1], TRT.neverallowxperm, "test100", "test100", "infoflow2", - # set([0x1234]), xperm="ioctl") - - def test_100_std_perm_equal(self): - """Xperm rule query match by standard permission, equal perm set.""" - q = TERuleQuery(self.p, ruletype=["neverallow", "neverallowxperm"], - perms=set(["ioctl", "hi_w"]), perms_equal=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 0) - # changed after dropping source policy support - # self.assertEqual(len(r), 1) - # self.validate_rule(r[0], TRT.neverallow, "test100", "system", "infoflow2", - # set(["ioctl", "hi_w"])) - - def test_101_xperm_any(self): - """Xperm rule query match any perm set.""" - q = TERuleQuery(self.p, xperms=[(0x9011, 0x9013)], xperms_equal=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 4) - self.validate_rule(r[0], TRT.allowxperm, "test101a", "test101a", "infoflow7", - set([0x9011]), xperm="ioctl") - self.validate_rule(r[1], TRT.allowxperm, "test101b", "test101b", "infoflow7", - set([0x9011, 0x9012]), xperm="ioctl") - self.validate_rule(r[2], TRT.allowxperm, "test101c", "test101c", "infoflow7", - set([0x9011, 0x9012, 0x9013]), xperm="ioctl") - self.validate_rule(r[3], TRT.allowxperm, "test101d", "test101d", "infoflow7", - set([0x9011, 0x9012, 0x9013, 0x9014]), xperm="ioctl") - - def test_101_xperm_equal(self): - """Xperm rule query match equal perm set.""" - q = TERuleQuery(self.p, xperms=[(0x9011, 0x9013)], xperms_equal=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TRT.allowxperm, "test101c", "test101c", "infoflow7", - set([0x9011, 0x9012, 0x9013]), xperm="ioctl") diff --git a/tests/test_boolquery.py b/tests/test_boolquery.py deleted file mode 100644 index 5d083b90..00000000 --- a/tests/test_boolquery.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import BoolQuery - -from .policyrep.util import compile_policy - - -class BoolQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/boolquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Boolean query with no criteria.""" - # query with no parameters gets all Booleans. - allbools = sorted(str(b) for b in self.p.bools()) - - q = BoolQuery(self.p) - qbools = sorted(str(b) for b in q.results()) - - self.assertListEqual(allbools, qbools) - - def test_001_name_exact(self): - """Boolean query with exact match""" - q = BoolQuery(self.p, name="test1") - - bools = sorted(str(b) for b in q.results()) - self.assertListEqual(["test1"], bools) - - def test_002_name_regex(self): - """Boolean query with regex match.""" - q = BoolQuery(self.p, name="test2(a|b)", name_regex=True) - - bools = sorted(str(b) for b in q.results()) - self.assertListEqual(["test2a", "test2b"], bools) - - def test_010_default(self): - """Boolean query with default state match.""" - q = BoolQuery(self.p, default=False) - - bools = sorted(str(b) for b in q.results()) - self.assertListEqual(["test10a", "test10b"], bools) diff --git a/tests/test_boundsquery.py b/tests/test_boundsquery.py deleted file mode 100644 index f1be083a..00000000 --- a/tests/test_boundsquery.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2016, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import BoundsQuery, BoundsRuletype - -from .policyrep.util import compile_policy - - -class BoundsQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/boundsquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Bounds query with no criteria.""" - # query with no parameters gets all bounds. - allbounds = sorted(self.p.bounds()) - - q = BoundsQuery(self.p) - qbounds = sorted(q.results()) - - self.assertListEqual(allbounds, qbounds) - - def test_001_parent_exact(self): - """Bounds query with exact parent match.""" - q = BoundsQuery(self.p, parent="test1_parent", parent_regex=False) - qbounds = sorted(q.results()) - self.assertEqual(1, len(qbounds)) - - b = qbounds[0] - self.assertEqual(BoundsRuletype.typebounds, b.ruletype) - self.assertEqual("test1_parent", b.parent) - self.assertEqual("test1_child", b.child) - - def test_002_parent_regex(self): - """Bounds query with regex parent match.""" - q = BoundsQuery(self.p, parent="test2_parent?", parent_regex=True) - qbounds = sorted(q.results()) - self.assertEqual(2, len(qbounds)) - - b = qbounds[0] - self.assertEqual(BoundsRuletype.typebounds, b.ruletype) - self.assertEqual("test2_parent1", b.parent) - self.assertEqual("test2_child2", b.child) - - b = qbounds[1] - self.assertEqual(BoundsRuletype.typebounds, b.ruletype) - self.assertEqual("test2_parent2", b.parent) - self.assertEqual("test2_child1", b.child) - - def test_010_child_exact(self): - """Bounds query with exact child match.""" - q = BoundsQuery(self.p, child="test10_child", child_regex=False) - qbounds = sorted(q.results()) - self.assertEqual(1, len(qbounds)) - - b = qbounds[0] - self.assertEqual(BoundsRuletype.typebounds, b.ruletype) - self.assertEqual("test10_parent", b.parent) - self.assertEqual("test10_child", b.child) - - def test_011_child_regex(self): - """Bounds query with regex child match.""" - q = BoundsQuery(self.p, child="test11_child?", child_regex=True) - qbounds = sorted(q.results()) - self.assertEqual(2, len(qbounds)) - - b = qbounds[0] - self.assertEqual(BoundsRuletype.typebounds, b.ruletype) - self.assertEqual("test11_parent1", b.parent) - self.assertEqual("test11_child2", b.child) - - b = qbounds[1] - self.assertEqual(BoundsRuletype.typebounds, b.ruletype) - self.assertEqual("test11_parent2", b.parent) - self.assertEqual("test11_child1", b.child) diff --git a/tests/test_categoryquery.py b/tests/test_categoryquery.py deleted file mode 100644 index ba9a7004..00000000 --- a/tests/test_categoryquery.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import CategoryQuery - -from .policyrep.util import compile_policy - - -class CategoryQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/categoryquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """MLS category query with no criteria.""" - # query with no parameters gets all categories. - allcats = sorted(str(c) for c in self.p.categories()) - - q = CategoryQuery(self.p) - qcats = sorted(str(c) for c in q.results()) - - self.assertListEqual(allcats, qcats) - - def test_001_name_exact(self): - """MLS category query with exact name match.""" - q = CategoryQuery(self.p, name="test1") - - cats = sorted(str(c) for c in q.results()) - self.assertListEqual(["test1"], cats) - - def test_002_name_regex(self): - """MLS category query with regex name match.""" - q = CategoryQuery(self.p, name="test2(a|b)", name_regex=True) - - cats = sorted(str(c) for c in q.results()) - self.assertListEqual(["test2a", "test2b"], cats) - - def test_010_alias_exact(self): - """MLS category query with exact alias match.""" - q = CategoryQuery(self.p, alias="test10a") - - cats = sorted(str(t) for t in q.results()) - self.assertListEqual(["test10c1"], cats) - - def test_011_alias_regex(self): - """MLS category query with regex alias match.""" - q = CategoryQuery(self.p, alias="test11(a|b)", alias_regex=True) - - cats = sorted(str(t) for t in q.results()) - self.assertListEqual(["test11c1", "test11c2"], cats) diff --git a/tests/test_commonquery.py b/tests/test_commonquery.py deleted file mode 100644 index ae031850..00000000 --- a/tests/test_commonquery.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import CommonQuery - -from .policyrep.util import compile_policy - - -class CommonQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/commonquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Common query with no criteria.""" - # query with no parameters gets all types. - commons = sorted(self.p.commons()) - - q = CommonQuery(self.p) - q_commons = sorted(q.results()) - - self.assertListEqual(commons, q_commons) - - def test_001_name_exact(self): - """Common query with exact name match.""" - q = CommonQuery(self.p, name="test1") - - commons = sorted(str(c) for c in q.results()) - self.assertListEqual(["test1"], commons) - - def test_002_name_regex(self): - """Common query with regex name match.""" - q = CommonQuery(self.p, name="test2(a|b)", name_regex=True) - - commons = sorted(str(c) for c in q.results()) - self.assertListEqual(["test2a", "test2b"], commons) - - def test_010_perm_indirect_intersect(self): - """Common query with intersect permission name patch.""" - q = CommonQuery(self.p, perms=set(["null"]), perms_equal=False) - - commons = sorted(str(c) for c in q.results()) - self.assertListEqual(["test10a", "test10b"], commons) - - def test_011_perm_indirect_equal(self): - """Common query with equal permission name patch.""" - q = CommonQuery(self.p, perms=set(["read", "write"]), perms_equal=True) - - commons = sorted(str(c) for c in q.results()) - self.assertListEqual(["test11a"], commons) - - def test_012_perm_indirect_regex(self): - """Common query with regex permission name patch.""" - q = CommonQuery(self.p, perms="sig.+", perms_regex=True) - - commons = sorted(str(c) for c in q.results()) - self.assertListEqual(["test12a", "test12b"], commons) diff --git a/tests/test_conditionalinfoflow.py b/tests/test_conditionalinfoflow.py deleted file mode 100644 index 71bdf8f2..00000000 --- a/tests/test_conditionalinfoflow.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright 2014-2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import InfoFlowAnalysis -from setools import TERuletype as TERT -from setools.exception import InvalidType -from setools.permmap import PermissionMap -from setools.policyrep import Type - -from . import mixins -from .policyrep.util import compile_policy - - -# Note: the testing for having correct rules on every edge is only -# performed once on the full graph, since it is assumed that NetworkX's -# Digraph.subgraph() function correctly copies the edge attributes into -# the subgraph. - - -class ConditionalInfoFlowAnalysisTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/conditionalinfoflow.conf", mls=False) - cls.m = PermissionMap("tests/perm_map") - cls.a = InfoFlowAnalysis(cls.p, cls.m) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_001_keep_conditional_rules(self): - """Keep all conditional rules.""" - self.a.booleans = None - self.a._rebuildgraph = True - self.a._build_subgraph() - - source = self.p.lookup_type("src") - target = self.p.lookup_type("tgt") - flow_true = self.p.lookup_type("flow_true") - flow_false = self.p.lookup_type("flow_false") - - r = self.a.G.edges[source, flow_true]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[flow_true, target]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[source, flow_false]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[flow_false, target]["rules"] - self.assertEqual(len(r), 1) - - def test_002_default_conditional_rules(self): - """Keep only default conditional rules.""" - self.a.booleans = {} - self.a._rebuildgraph = True - self.a._build_subgraph() - - source = self.p.lookup_type("src") - target = self.p.lookup_type("tgt") - flow_true = self.p.lookup_type("flow_true") - flow_false = self.p.lookup_type("flow_false") - - r = self.a.G.edges[source, flow_true]["rules"] - self.assertEqual(len(r), 0) - r = self.a.G.edges[flow_true, target]["rules"] - self.assertEqual(len(r), 0) - r = self.a.G.edges[source, flow_false]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[flow_false, target]["rules"] - self.assertEqual(len(r), 1) - - def test_003_user_conditional_true(self): - """Keep only conditional rules selected by user specified booleans (True Case.)""" - self.a.booleans = {"condition": True} - self.a.rebuildgraph = True - self.a._build_subgraph() - - source = self.p.lookup_type("src") - target = self.p.lookup_type("tgt") - flow_true = self.p.lookup_type("flow_true") - flow_false = self.p.lookup_type("flow_false") - - r = self.a.G.edges[source, flow_true]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[flow_true, target]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[source, flow_false]["rules"] - self.assertEqual(len(r), 0) - r = self.a.G.edges[flow_false, target]["rules"] - self.assertEqual(len(r), 0) - - def test_004_user_conditional_false(self): - """Keep only conditional rules selected by user specified booleans (False Case.)""" - self.a.booleans = {"condition": False} - self.a.rebuildgraph = True - self.a._build_subgraph() - - source = self.p.lookup_type("src") - target = self.p.lookup_type("tgt") - flow_true = self.p.lookup_type("flow_true") - flow_false = self.p.lookup_type("flow_false") - - r = self.a.G.edges[source, flow_true]["rules"] - self.assertEqual(len(r), 0) - r = self.a.G.edges[flow_true, target]["rules"] - self.assertEqual(len(r), 0) - r = self.a.G.edges[source, flow_false]["rules"] - self.assertEqual(len(r), 1) - r = self.a.G.edges[flow_false, target]["rules"] - self.assertEqual(len(r), 1) - - def test_005_remaining_edges(self): - """Keep edges when rules are deleted, but there are still remaining rules on the edge.""" - self.a.booleans = {} - self.a.rebuildgraph = True - self.a._build_subgraph() - - source = self.p.lookup_type("src_remain") - target = self.p.lookup_type("tgt_remain") - flow = self.p.lookup_type("flow_remain") - - r = self.a.G.edges[source, flow]["rules"] - self.assertEqual(len(r), 1) - self.assertEqual(str(r[0]), 'allow src_remain flow_remain:infoflow hi_w;') - r = self.a.G.edges[flow, target]["rules"] - self.assertEqual(len(r), 1) - self.assertEqual(str(r[0]), 'allow tgt_remain flow_remain:infoflow hi_r;') diff --git a/tests/test_constraintquery.py b/tests/test_constraintquery.py deleted file mode 100644 index 97055317..00000000 --- a/tests/test_constraintquery.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import ConstraintQuery - -from .policyrep.util import compile_policy - - -class ConstraintQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/constraintquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Constraint query with no criteria.""" - allconstraint = sorted(c.tclass for c in self.p.constraints()) - - q = ConstraintQuery(self.p) - qconstraint = sorted(c.tclass for c in q.results()) - - self.assertListEqual(allconstraint, qconstraint) - - def test_001_ruletype(self): - """Constraint query with rule type match.""" - q = ConstraintQuery(self.p, ruletype=["mlsconstrain"]) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test1"], constraint) - - @unittest.skip("Setting tclass to a string is no longer supported.") - def test_010_class_exact(self): - """Constraint query with exact object class match.""" - q = ConstraintQuery(self.p, tclass="test10") - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test10"], constraint) - - def test_011_class_list(self): - """Constraint query with object class list match.""" - q = ConstraintQuery(self.p, tclass=["test11a", "test11b"]) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test11a", "test11b"], constraint) - - def test_012_class_regex(self): - """Constraint query with object class regex match.""" - q = ConstraintQuery(self.p, tclass="test12(a|c)", tclass_regex=True) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test12a", "test12c"], constraint) - - def test_020_perms_any(self): - """Constraint query with permission set intersection match.""" - q = ConstraintQuery(self.p, perms=["test20ap", "test20bp"]) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test20a", "test20b"], constraint) - - def test_021_perms_equal(self): - """Constraint query with permission set equality match.""" - q = ConstraintQuery(self.p, perms=["test21ap", "test21bp"], perms_equal=True) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test21c"], constraint) - - def test_030_role_match_single(self): - """Constraint query with role match.""" - q = ConstraintQuery(self.p, role="test30r") - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test30"], constraint) - - def test_031_role_match_regex(self): - """Constraint query with regex role match.""" - q = ConstraintQuery(self.p, role="test31r.", role_regex=True) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test31a", "test31b"], constraint) - - def test_040_type_match_single(self): - """Constraint query with type match.""" - q = ConstraintQuery(self.p, type_="test40t") - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test40"], constraint) - - def test_041_type_match_regex(self): - """Constraint query with regex type match.""" - q = ConstraintQuery(self.p, type_="test41t.", type_regex=True) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test41a", "test41b"], constraint) - - def test_050_user_match_single(self): - """Constraint query with user match.""" - q = ConstraintQuery(self.p, user="test50u") - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test50"], constraint) - - def test_051_user_match_regex(self): - """Constraint query with regex user match.""" - q = ConstraintQuery(self.p, user="test51u.", user_regex=True) - - constraint = sorted(c.tclass for c in q.results()) - self.assertListEqual(["test51a", "test51b"], constraint) diff --git a/tests/test_defaultquery.py b/tests/test_defaultquery.py deleted file mode 100644 index 9e673ebb..00000000 --- a/tests/test_defaultquery.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2016, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import DefaultQuery, DefaultRuletype, DefaultValue -from setools.exception import InvalidClass - -from .policyrep.util import compile_policy - - -class DefaultQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/defaultquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Default query: no criteria.""" - # query with no parameters gets all defaults - alldefaults = sorted(self.p.defaults()) - - q = DefaultQuery(self.p) - qdefaults = sorted(q.results()) - - self.assertListEqual(alldefaults, qdefaults) - - def test_001_ruletype(self): - """Default query: ruletype criterion.""" - q = DefaultQuery(self.p, ruletype=["default_user"]) - defaults = list(q.results()) - self.assertEqual(1, len(defaults)) - - d = defaults[0] - self.assertEqual(DefaultRuletype.default_user, d.ruletype) - self.assertEqual("infoflow", d.tclass) - self.assertEqual(DefaultValue.target, d.default) - - def test_010_class_list(self): - """Default query: object class list match.""" - q = DefaultQuery(self.p, tclass=["infoflow3", "infoflow4"]) - - defaults = sorted(d.tclass for d in q.results()) - self.assertListEqual(["infoflow3", "infoflow4"], defaults) - - def test_011_class_regex(self): - """Default query: object class regex match.""" - q = DefaultQuery(self.p, tclass="infoflow(3|5)", tclass_regex=True) - - defaults = sorted(c.tclass for c in q.results()) - self.assertListEqual(["infoflow3", "infoflow5"], defaults) - - def test_020_default(self): - """Default query: default setting.""" - q = DefaultQuery(self.p, default="source") - - defaults = sorted(c.tclass for c in q.results()) - self.assertListEqual(["infoflow", "infoflow3"], defaults) - - def test_030_default_range(self): - """Default query: default_range setting.""" - q = DefaultQuery(self.p, default_range="high") - - defaults = sorted(c.tclass for c in q.results()) - self.assertListEqual(["infoflow7"], defaults) - - def test_900_invalid_ruletype(self): - """Default query: invalid ruletype""" - with self.assertRaises(KeyError): - q = DefaultQuery(self.p, ruletype=["INVALID"]) - - def test_901_invalid_class(self): - """Default query: invalid object class""" - with self.assertRaises(InvalidClass): - q = DefaultQuery(self.p, tclass=["INVALID"]) - - def test_902_invalid_default_value(self): - """Default query: invalid default value""" - with self.assertRaises(KeyError): - q = DefaultQuery(self.p, default="INVALID") - - def test_903_invalid_default_range(self): - """Default query: invalid default range""" - with self.assertRaises(KeyError): - q = DefaultQuery(self.p, default_range="INVALID") diff --git a/tests/test_devicetreeconquery.py b/tests/test_devicetreeconquery.py deleted file mode 100644 index 470356cf..00000000 --- a/tests/test_devicetreeconquery.py +++ /dev/null @@ -1,206 +0,0 @@ -# Derived from tests/portconquery.py -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import DevicetreeconQuery - -from .policyrep.util import compile_policy - - -class DevicetreeconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/devicetreeconquery.conf", xen=True) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Devicetreecon query with no criteria""" - # query with no parameters gets all PCI paths. - rules = sorted(self.p.devicetreecons()) - - q = DevicetreeconQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_010_user_exact(self): - """Devicetreecon query with context user exact match""" - q = DevicetreeconQuery(self.p, user="user10", user_regex=False) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree10")], path) - - def test_011_user_regex(self): - """Devicetreecon query with context user regex match""" - q = DevicetreeconQuery(self.p, user="user11(a|b)", user_regex=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree11"), ("/dev/tree11000")], path) - - def test_020_role_exact(self): - """Devicetreecon query with context role exact match""" - q = DevicetreeconQuery(self.p, role="role20_r", role_regex=False) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree20")], path) - - def test_021_role_regex(self): - """Devicetreecon query with context role regex match""" - q = DevicetreeconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree21"), ("/dev/tree21001")], path) - - def test_030_type_exact(self): - """Devicetreecon query with context type exact match""" - q = DevicetreeconQuery(self.p, type_="type30", type_regex=False) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree30")], path) - - def test_031_type_regex(self): - """Devicetreecon query with context type regex match""" - q = DevicetreeconQuery(self.p, type_="type31(b|c)", type_regex=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree31000"), ("/dev/tree31001")], path) - - def test_040_range_exact(self): - """Devicetreecon query with context range exact match""" - q = DevicetreeconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree40")], path) - - def test_041_range_overlap1(self): - """Devicetreecon query with context range overlap match (equal)""" - q = DevicetreeconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree41")], path) - - def test_041_range_overlap2(self): - """Devicetreecon query with context range overlap match (subset)""" - q = DevicetreeconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree41")], path) - - def test_041_range_overlap3(self): - """Devicetreecon query with context range overlap match (superset)""" - q = DevicetreeconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree41")], path) - - def test_041_range_overlap4(self): - """Devicetreecon query with context range overlap match (overlap low level)""" - q = DevicetreeconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree41")], path) - - def test_041_range_overlap5(self): - """Devicetreecon query with context range overlap match (overlap high level)""" - q = DevicetreeconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree41")], path) - - def test_042_range_subset1(self): - """Devicetreecon query with context range subset match""" - q = DevicetreeconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree42")], path) - - def test_042_range_subset2(self): - """Devicetreecon query with context range subset match (equal)""" - q = DevicetreeconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree42")], path) - - def test_043_range_superset1(self): - """Devicetreecon query with context range superset match""" - q = DevicetreeconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree43")], path) - - def test_043_range_superset2(self): - """Devicetreecon query with context range superset match (equal)""" - q = DevicetreeconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree43")], path) - - def test_044_range_proper_subset1(self): - """Devicetreecon query with context range proper subset match""" - q = DevicetreeconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree44")], path) - - def test_044_range_proper_subset2(self): - """Devicetreecon query with context range proper subset match (equal)""" - q = DevicetreeconQuery(self.p, - range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([], path) - - def test_044_range_proper_subset3(self): - """Devicetreecon query with context range proper subset match (equal low only)""" - q = DevicetreeconQuery(self.p, - range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree44")], path) - - def test_044_range_proper_subset4(self): - """Devicetreecon query with context range proper subset match (equal high only)""" - q = DevicetreeconQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree44")], path) - - def test_045_range_proper_superset1(self): - """Devicetreecon query with context range proper superset match""" - q = DevicetreeconQuery(self.p, - range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree45")], path) - - def test_045_range_proper_superset2(self): - """Devicetreecon query with context range proper superset match (equal)""" - q = DevicetreeconQuery(self.p, - range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([], path) - - def test_045_range_proper_superset3(self): - """Devicetreecon query with context range proper superset match (equal low)""" - q = DevicetreeconQuery(self.p, - range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree45")], path) - - def test_045_range_proper_superset4(self): - """Devicetreecon query with context range proper superset match (equal high)""" - q = DevicetreeconQuery(self.p, - range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - path = sorted(p.path for p in q.results()) - self.assertListEqual([("/dev/tree45")], path) diff --git a/tests/test_diff.py b/tests/test_diff.py deleted file mode 100644 index 986c8cc7..00000000 --- a/tests/test_diff.py +++ /dev/null @@ -1,2945 +0,0 @@ -# Copyright 2015-2016, Tresys Technology, LLC -# Copyright 2016, 2017, Chris PeBenito -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest -from dataclasses import astuple -from ipaddress import IPv6Address, IPv4Network, IPv6Network - -from setools import PolicyDifference, PortconProtocol, PortconRange -from setools import BoundsRuletype as BRT -from setools import ConstraintRuletype as CRT -from setools import DefaultRuletype as DRT -from setools import DefaultRangeValue as DRV -from setools import DefaultValue as DV -from setools import FSUseRuletype as FSURT -from setools import MLSRuletype as MRT -from setools import RBACRuletype as RRT -from setools import TERuletype as TRT - -from .mixins import ValidateRule -from .policyrep.util import compile_policy - - -class PolicyDifferenceTest(ValidateRule, unittest.TestCase): - - """Policy difference tests.""" - - @classmethod - def setUpClass(cls): - cls.p_left = compile_policy("tests/diff_left.conf") - cls.p_right = compile_policy("tests/diff_right.conf") - cls.diff = PolicyDifference(cls.p_left, cls.p_right) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p_left.path) - os.unlink(cls.p_right.path) - - # - # Types - # - def test_added_types(self): - """Diff: added type""" - self.assertSetEqual(set(["added_type"]), self.diff.added_types) - - def test_removed_types(self): - """Diff: modified type""" - self.assertSetEqual(set(["removed_type"]), self.diff.removed_types) - - def test_modified_types_count(self): - """Diff: total modified types""" - self.assertEqual(6, len(self.diff.modified_types)) - - def test_modified_types_remove_attr(self): - """Diff: modified type with removed attribute.""" - # modified_remove_attr - self.diff.modified_types.sort() - type_ = self.diff.modified_types[4] - self.assertSetEqual(set(["an_attr"]), type_.removed_attributes) - self.assertFalse(type_.added_attributes) - self.assertFalse(type_.matched_attributes) - self.assertFalse(type_.modified_permissive) - self.assertFalse(type_.permissive) - self.assertFalse(type_.added_aliases) - self.assertFalse(type_.removed_aliases) - self.assertFalse(type_.matched_aliases) - - def test_modified_types_remove_alias(self): - """Diff: modified type with removed alias.""" - # modified_remove_alias - self.diff.modified_types.sort() - type_ = self.diff.modified_types[3] - self.assertSetEqual(set(["an_alias"]), type_.removed_aliases) - self.assertFalse(type_.added_attributes) - self.assertFalse(type_.removed_attributes) - self.assertFalse(type_.matched_attributes) - self.assertFalse(type_.modified_permissive) - self.assertFalse(type_.permissive) - self.assertFalse(type_.added_aliases) - self.assertFalse(type_.matched_aliases) - - def test_modified_types_remove_permissive(self): - """Diff: modified type with removed permissve.""" - # modified_remove_permissive - self.diff.modified_types.sort() - type_ = self.diff.modified_types[5] - self.assertFalse(type_.added_attributes) - self.assertFalse(type_.removed_attributes) - self.assertFalse(type_.matched_attributes) - self.assertTrue(type_.modified_permissive) - self.assertTrue(type_.permissive) - self.assertFalse(type_.added_aliases) - self.assertFalse(type_.removed_aliases) - self.assertFalse(type_.matched_aliases) - - def test_modified_types_add_attr(self): - """Diff: modified type with added attribute.""" - # modified_add_attr - self.diff.modified_types.sort() - type_ = self.diff.modified_types[1] - self.assertSetEqual(set(["an_attr"]), type_.added_attributes) - self.assertFalse(type_.removed_attributes) - self.assertFalse(type_.matched_attributes) - self.assertFalse(type_.modified_permissive) - self.assertFalse(type_.permissive) - self.assertFalse(type_.added_aliases) - self.assertFalse(type_.removed_aliases) - self.assertFalse(type_.matched_aliases) - - def test_modified_types_add_alias(self): - """Diff: modified type with added alias.""" - # modified_add_alias - self.diff.modified_types.sort() - type_ = self.diff.modified_types[0] - self.assertSetEqual(set(["an_alias"]), type_.added_aliases) - self.assertFalse(type_.added_attributes) - self.assertFalse(type_.removed_attributes) - self.assertFalse(type_.matched_attributes) - self.assertFalse(type_.modified_permissive) - self.assertFalse(type_.permissive) - self.assertFalse(type_.removed_aliases) - self.assertFalse(type_.matched_aliases) - - def test_modified_types_add_permissive(self): - """Diff: modified type with added permissive.""" - # modified_add_permissive - self.diff.modified_types.sort() - type_ = self.diff.modified_types[2] - self.assertFalse(type_.added_attributes) - self.assertFalse(type_.removed_attributes) - self.assertFalse(type_.matched_attributes) - self.assertTrue(type_.modified_permissive) - self.assertFalse(type_.permissive) - self.assertFalse(type_.added_aliases) - self.assertFalse(type_.removed_aliases) - self.assertFalse(type_.matched_aliases) - - # - # Roles - # - def test_added_role(self): - """Diff: added role.""" - self.assertSetEqual(set(["added_role"]), self.diff.added_roles) - - def test_removed_role(self): - """Diff: removed role.""" - self.assertSetEqual(set(["removed_role"]), self.diff.removed_roles) - - def test_modified_role_count(self): - """Diff: modified role.""" - self.assertEqual(2, len(self.diff.modified_roles)) - - def test_modified_role_add_type(self): - """Diff: modified role with added type.""" - # modified_add_type - self.diff.modified_roles.sort() - self.assertSetEqual(set(["system"]), - self.diff.modified_roles[0].added_types) - self.assertFalse(self.diff.modified_roles[0].removed_types) - - def test_modified_role_remove_type(self): - """Diff: modified role with removed type.""" - # modified_remove_type - self.diff.modified_roles.sort() - self.assertSetEqual(set(["system"]), - self.diff.modified_roles[1].removed_types) - self.assertFalse(self.diff.modified_roles[1].added_types) - - # - # Commons - # - def test_added_common(self): - """Diff: added common.""" - self.assertSetEqual(set(["added_common"]), self.diff.added_commons) - - def test_removed_common(self): - """Diff: removed common.""" - self.assertSetEqual(set(["removed_common"]), self.diff.removed_commons) - - def test_modified_common_count(self): - """Diff: modified common count.""" - self.assertEqual(2, len(self.diff.modified_commons)) - - def test_modified_common_add_perm(self): - """Diff: modified common with added perm.""" - # modified_add_perm - self.diff.modified_commons.sort() - self.assertSetEqual(set(["added_perm"]), - self.diff.modified_commons[0].added_perms) - self.assertFalse(self.diff.modified_commons[0].removed_perms) - - def test_modified_common_remove_perm(self): - """Diff: modified common with removed perm.""" - # modified_remove_perm - self.diff.modified_commons.sort() - self.assertSetEqual(set(["removed_perm"]), - self.diff.modified_commons[1].removed_perms) - self.assertFalse(self.diff.modified_commons[1].added_perms) - - # - # Classes - # - def test_added_class(self): - """Diff: added class.""" - self.assertSetEqual(set(["added_class"]), self.diff.added_classes) - - def test_removed_class(self): - """Diff: removed class.""" - self.assertSetEqual(set(["removed_class"]), self.diff.removed_classes) - - def test_modified_class_count(self): - """Diff: modified class count.""" - self.assertEqual(3, len(self.diff.modified_classes)) - - def test_modified_class_add_perm(self): - """Diff: modified class with added perm.""" - # modified_add_perm - self.diff.modified_classes.sort() - self.assertSetEqual(set(["added_perm"]), - self.diff.modified_classes[0].added_perms) - self.assertFalse(self.diff.modified_classes[0].removed_perms) - - def test_modified_class_remove_perm(self): - """Diff: modified class with removed perm.""" - # modified_remove_perm - self.diff.modified_classes.sort() - self.assertSetEqual(set(["removed_perm"]), - self.diff.modified_classes[2].removed_perms) - self.assertFalse(self.diff.modified_classes[2].added_perms) - - def test_modified_class_change_common(self): - """Diff: modified class due to modified common.""" - # modified_change_common - self.diff.modified_classes.sort() - self.assertSetEqual(set(["old_com"]), - self.diff.modified_classes[1].removed_perms) - self.assertSetEqual(set(["new_com"]), - self.diff.modified_classes[1].added_perms) - - # - # Allow rules - # - def test_added_allow_rules(self): - """Diff: added allow rules.""" - rules = sorted(self.diff.added_allows) - self.assertEqual(5, len(rules)) - - # added rule with existing types - self.validate_rule(rules[0], TRT.allow, "added_rule_source", "added_rule_target", - "infoflow", set(["med_w"])) - - # added rule with new type - self.validate_rule(rules[1], TRT.allow, "added_type", "added_type", "infoflow2", - set(["med_w"])) - - # rule moved out of a conditional - self.validate_rule(rules[2], TRT.allow, "move_from_bool", "move_from_bool", "infoflow4", - set(["hi_r"])) - - # rule moved into a conditional - self.validate_rule(rules[3], TRT.allow, "move_to_bool", "move_to_bool", "infoflow4", - set(["hi_w"]), cond="move_to_bool_b", cond_block=True) - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[4], TRT.allow, "system", "switch_block", "infoflow6", - set(["hi_r"]), cond="switch_block_b", cond_block=False) - - def test_removed_allow_rules(self): - """Diff: removed allow rules.""" - rules = sorted(self.diff.removed_allows) - self.assertEqual(5, len(rules)) - - # rule moved out of a conditional - self.validate_rule(rules[0], TRT.allow, "move_from_bool", "move_from_bool", "infoflow4", - set(["hi_r"]), cond="move_from_bool_b", cond_block=True) - - # rule moved into a conditional - self.validate_rule(rules[1], TRT.allow, "move_to_bool", "move_to_bool", "infoflow4", - set(["hi_w"])) - - # removed rule with existing types - self.validate_rule(rules[2], TRT.allow, "removed_rule_source", "removed_rule_target", - "infoflow", set(["hi_r"])) - - # removed rule with new type - self.validate_rule(rules[3], TRT.allow, "removed_type", "removed_type", "infoflow3", - set(["null"])) - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[4], TRT.allow, "system", "switch_block", "infoflow6", - set(["hi_r"]), cond="switch_block_b", cond_block=True) - - def test_modified_allow_rules(self): - """Diff: modified allow rules.""" - lst = sorted(self.diff.modified_allows, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # add permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) - self.assertEqual(TRT.allow, rule.ruletype) - self.assertEqual("modified_rule_add_perms", rule.source) - self.assertEqual("modified_rule_add_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertSetEqual(set(["hi_w"]), added_perms) - self.assertFalse(removed_perms) - self.assertSetEqual(set(["hi_r"]), matched_perms) - - # add and remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) - self.assertEqual(TRT.allow, rule.ruletype) - self.assertEqual("modified_rule_add_remove_perms", rule.source) - self.assertEqual("modified_rule_add_remove_perms", rule.target) - self.assertEqual("infoflow2", rule.tclass) - self.assertSetEqual(set(["super_r"]), added_perms) - self.assertSetEqual(set(["super_w"]), removed_perms) - self.assertSetEqual(set(["low_w"]), matched_perms) - - # remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) - self.assertEqual(TRT.allow, rule.ruletype) - self.assertEqual("modified_rule_remove_perms", rule.source) - self.assertEqual("modified_rule_remove_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertFalse(added_perms) - self.assertSetEqual(set(["low_r"]), removed_perms) - self.assertSetEqual(set(["low_w"]), matched_perms) - - # - # Auditallow rules - # - def test_added_auditallow_rules(self): - """Diff: added auditallow rules.""" - rules = sorted(self.diff.added_auditallows) - self.assertEqual(5, len(rules)) - - # added rule with existing types - self.validate_rule(rules[0], TRT.auditallow, "aa_added_rule_source", "aa_added_rule_target", - "infoflow", set(["med_w"])) - - # rule moved out of a conditional - self.validate_rule(rules[1], TRT.auditallow, "aa_move_from_bool", "aa_move_from_bool", - "infoflow4", set(["hi_r"])) - - # rule moved into a conditional - self.validate_rule(rules[2], TRT.auditallow, "aa_move_to_bool", "aa_move_to_bool", - "infoflow4", set(["hi_w"]), cond="aa_move_to_bool_b", cond_block=True) - - # added rule with new type - self.validate_rule(rules[3], TRT.auditallow, "added_type", "added_type", "infoflow7", - set(["super_none"])) - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[4], TRT.auditallow, "system", "aa_switch_block", "infoflow6", - set(["hi_r"]), cond="aa_switch_block_b", cond_block=False) - - def test_removed_auditallow_rules(self): - """Diff: removed auditallow rules.""" - rules = sorted(self.diff.removed_auditallows) - self.assertEqual(5, len(rules)) - - # rule moved out of a conditional - self.validate_rule(rules[0], TRT.auditallow, "aa_move_from_bool", "aa_move_from_bool", - "infoflow4", set(["hi_r"]), cond="aa_move_from_bool_b", cond_block=True) - - # rule moved into a conditional - self.validate_rule(rules[1], TRT.auditallow, "aa_move_to_bool", "aa_move_to_bool", - "infoflow4", set(["hi_w"])) - - # removed rule with existing types - self.validate_rule(rules[2], TRT.auditallow, "aa_removed_rule_source", - "aa_removed_rule_target", "infoflow", set(["hi_r"])) - - # removed rule with new type - self.validate_rule(rules[3], TRT.auditallow, "removed_type", "removed_type", "infoflow7", - set(["super_unmapped"])) - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[4], TRT.auditallow, "system", "aa_switch_block", "infoflow6", - set(["hi_r"]), cond="aa_switch_block_b", cond_block=True) - - def test_modified_auditallow_rules(self): - """Diff: modified auditallow rules.""" - lst = sorted(self.diff.modified_auditallows, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # add permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) - self.assertEqual(TRT.auditallow, rule.ruletype) - self.assertEqual("aa_modified_rule_add_perms", rule.source) - self.assertEqual("aa_modified_rule_add_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertSetEqual(set(["hi_w"]), added_perms) - self.assertFalse(removed_perms) - self.assertSetEqual(set(["hi_r"]), matched_perms) - - # add and remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) - self.assertEqual(TRT.auditallow, rule.ruletype) - self.assertEqual("aa_modified_rule_add_remove_perms", rule.source) - self.assertEqual("aa_modified_rule_add_remove_perms", rule.target) - self.assertEqual("infoflow2", rule.tclass) - self.assertSetEqual(set(["super_r"]), added_perms) - self.assertSetEqual(set(["super_w"]), removed_perms) - self.assertSetEqual(set(["low_w"]), matched_perms) - - # remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) - self.assertEqual(TRT.auditallow, rule.ruletype) - self.assertEqual("aa_modified_rule_remove_perms", rule.source) - self.assertEqual("aa_modified_rule_remove_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertFalse(added_perms) - self.assertSetEqual(set(["low_r"]), removed_perms) - self.assertSetEqual(set(["low_w"]), matched_perms) - - # - # Dontaudit rules - # - def test_added_dontaudit_rules(self): - """Diff: added dontaudit rules.""" - rules = sorted(self.diff.added_dontaudits) - self.assertEqual(5, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], TRT.dontaudit, "added_type", "added_type", "infoflow7", - set(["super_none"])) - - # added rule with existing types - self.validate_rule(rules[1], TRT.dontaudit, "da_added_rule_source", "da_added_rule_target", - "infoflow", set(["med_w"])) - - # rule moved out of a conditional - self.validate_rule(rules[2], TRT.dontaudit, "da_move_from_bool", "da_move_from_bool", - "infoflow4", set(["hi_r"])) - - # rule moved into a conditional - self.validate_rule(rules[3], TRT.dontaudit, "da_move_to_bool", "da_move_to_bool", - "infoflow4", set(["hi_w"]), cond="da_move_to_bool_b", cond_block=True) - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[4], TRT.dontaudit, "system", "da_switch_block", "infoflow6", - set(["hi_r"]), cond="da_switch_block_b", cond_block=False) - - def test_removed_dontaudit_rules(self): - """Diff: removed dontaudit rules.""" - rules = sorted(self.diff.removed_dontaudits) - self.assertEqual(5, len(rules)) - - # rule moved out of a conditional - self.validate_rule(rules[0], TRT.dontaudit, "da_move_from_bool", "da_move_from_bool", - "infoflow4", set(["hi_r"]), cond="da_move_from_bool_b", cond_block=True) - - # rule moved into a conditional - self.validate_rule(rules[1], TRT.dontaudit, "da_move_to_bool", "da_move_to_bool", - "infoflow4", set(["hi_w"])) - - # removed rule with existing types - self.validate_rule(rules[2], TRT.dontaudit, "da_removed_rule_source", - "da_removed_rule_target", "infoflow", set(["hi_r"])) - - # removed rule with new type - self.validate_rule(rules[3], TRT.dontaudit, "removed_type", "removed_type", "infoflow7", - set(["super_both"])) - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[4], TRT.dontaudit, "system", "da_switch_block", "infoflow6", - set(["hi_r"]), cond="da_switch_block_b", cond_block=True) - - def test_modified_dontaudit_rules(self): - """Diff: modified dontaudit rules.""" - lst = sorted(self.diff.modified_dontaudits, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # add permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) - self.assertEqual(TRT.dontaudit, rule.ruletype) - self.assertEqual("da_modified_rule_add_perms", rule.source) - self.assertEqual("da_modified_rule_add_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertSetEqual(set(["hi_w"]), added_perms) - self.assertFalse(removed_perms) - self.assertSetEqual(set(["hi_r"]), matched_perms) - - # add and remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) - self.assertEqual(TRT.dontaudit, rule.ruletype) - self.assertEqual("da_modified_rule_add_remove_perms", rule.source) - self.assertEqual("da_modified_rule_add_remove_perms", rule.target) - self.assertEqual("infoflow2", rule.tclass) - self.assertSetEqual(set(["super_r"]), added_perms) - self.assertSetEqual(set(["super_w"]), removed_perms) - self.assertSetEqual(set(["low_w"]), matched_perms) - - # remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) - self.assertEqual(TRT.dontaudit, rule.ruletype) - self.assertEqual("da_modified_rule_remove_perms", rule.source) - self.assertEqual("da_modified_rule_remove_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertFalse(added_perms) - self.assertSetEqual(set(["low_r"]), removed_perms) - self.assertSetEqual(set(["low_w"]), matched_perms) - - # - # Neverallow rules - # - def test_added_neverallow_rules(self): - """Diff: added neverallow rules.""" - self.assertFalse(self.diff.added_neverallows) - # changed after dropping source policy support - - # rules = sorted(self.diff.added_neverallows) - # self.assertEqual(2, len(rules)) - - # added rule with new type - # self.validate_rule(rules[0], TRT.neverallow, "added_type", "added_type", "added_class", - # set(["new_class_perm"])) - - # added rule with existing types - # self.validate_rule(rules[1], TRT.neverallow, "na_added_rule_source", - # "na_added_rule_target", "infoflow", set(["med_w"])) - - def test_removed_neverallow_rules(self): - """Diff: removed neverallow rules.""" - self.assertFalse(self.diff.removed_neverallows) - # changed after dropping source policy support - # rules = sorted(self.diff.removed_neverallows) - # self.assertEqual(2, len(rules)) - - # removed rule with existing types - # self.validate_rule(rules[0], TRT.neverallow, "na_removed_rule_source", - # "na_removed_rule_target", "infoflow", set(["hi_r"])) - - # removed rule with new type - # self.validate_rule(rules[1], TRT.neverallow, "removed_type", "removed_type", - # "removed_class", set(["null_perm"])) - - def test_modified_neverallow_rules(self): - """Diff: modified neverallow rules.""" - # changed after dropping source policy support - self.assertFalse(self.diff.modified_neverallows) - # l = sorted(self.diff.modified_neverallows, key=lambda x: x.rule) - # self.assertEqual(3, len(l)) - # - # # add permissions - # rule, added_perms, removed_perms, matched_perms = l[0] - # self.assertEqual(TRT.neverallow, rule.ruletype) - # self.assertEqual("na_modified_rule_add_perms", rule.source) - # self.assertEqual("na_modified_rule_add_perms", rule.target) - # self.assertEqual("infoflow", rule.tclass) - # self.assertSetEqual(set(["hi_w"]), added_perms) - # self.assertFalse(removed_perms) - # self.assertSetEqual(set(["hi_r"]), matched_perms) - # - # # add and remove permissions - # rule, added_perms, removed_perms, matched_perms = l[1] - # self.assertEqual(TRT.neverallow, rule.ruletype) - # self.assertEqual("na_modified_rule_add_remove_perms", rule.source) - # self.assertEqual("na_modified_rule_add_remove_perms", rule.target) - # self.assertEqual("infoflow2", rule.tclass) - # self.assertSetEqual(set(["super_r"]), added_perms) - # self.assertSetEqual(set(["super_w"]), removed_perms) - # self.assertSetEqual(set(["low_w"]), matched_perms) - # - # # remove permissions - # rule, added_perms, removed_perms, matched_perms = l[2] - # self.assertEqual(TRT.neverallow, rule.ruletype) - # self.assertEqual("na_modified_rule_remove_perms", rule.source) - # self.assertEqual("na_modified_rule_remove_perms", rule.target) - # self.assertEqual("infoflow", rule.tclass) - # self.assertFalse(added_perms) - # self.assertSetEqual(set(["low_r"]), removed_perms) - # self.assertSetEqual(set(["low_w"]), matched_perms) - - # - # Type_transition rules - # - def test_added_type_transition_rules(self): - """Diff: added type_transition rules.""" - rules = sorted(self.diff.added_type_transitions) - self.assertEqual(5, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], TRT.type_transition, "added_type", "system", "infoflow4", - "system") - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[1], TRT.type_transition, "system", "tt_switch_block", "infoflow6", - "system", cond="tt_switch_block_b", cond_block=False) - - # added rule with existing types - self.validate_rule(rules[2], TRT.type_transition, "tt_added_rule_source", - "tt_added_rule_target", "infoflow", "system") - - # rule moved out of a conditional - self.validate_rule(rules[3], TRT.type_transition, "tt_move_from_bool", "system", - "infoflow4", "system") - - # rule moved into a conditional - self.validate_rule(rules[4], TRT.type_transition, "tt_move_to_bool", "system", - "infoflow3", "system", cond="tt_move_to_bool_b", cond_block=True) - - def test_removed_type_transition_rules(self): - """Diff: removed type_transition rules.""" - rules = sorted(self.diff.removed_type_transitions) - self.assertEqual(5, len(rules)) - - # removed rule with new type - self.validate_rule(rules[0], TRT.type_transition, "removed_type", "system", "infoflow4", - "system") - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[1], TRT.type_transition, "system", "tt_switch_block", "infoflow6", - "system", cond="tt_switch_block_b", cond_block=True) - - # rule moved out of a conditional - self.validate_rule(rules[2], TRT.type_transition, "tt_move_from_bool", "system", - "infoflow4", "system", cond="tt_move_from_bool_b", cond_block=True) - - # rule moved into a conditional - self.validate_rule(rules[3], TRT.type_transition, "tt_move_to_bool", "system", - "infoflow3", "system") - - # removed rule with existing types - self.validate_rule(rules[4], TRT.type_transition, "tt_removed_rule_source", - "tt_removed_rule_target", "infoflow", "system") - - def test_modified_type_transition_rules(self): - """Diff: modified type_transition rules.""" - lst = sorted(self.diff.modified_type_transitions, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_default, removed_default = astuple(lst[0]) - self.assertEqual(TRT.type_transition, rule.ruletype) - self.assertEqual("tt_matched_source", rule.source) - self.assertEqual("system", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertEqual("tt_new_type", added_default) - self.assertEqual("tt_old_type", removed_default) - - # - # Type_change rules - # - def test_added_type_change_rules(self): - """Diff: added type_change rules.""" - rules = sorted(self.diff.added_type_changes) - self.assertEqual(5, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], TRT.type_change, "added_type", "system", "infoflow4", - "system") - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[1], TRT.type_change, "system", "tc_switch_block", "infoflow6", - "system", cond="tc_switch_block_b", cond_block=False) - - # added rule with existing types - self.validate_rule(rules[2], TRT.type_change, "tc_added_rule_source", - "tc_added_rule_target", "infoflow", "system") - - # rule moved out of a conditional - self.validate_rule(rules[3], TRT.type_change, "tc_move_from_bool", "system", - "infoflow4", "system") - - # rule moved into a conditional - self.validate_rule(rules[4], TRT.type_change, "tc_move_to_bool", "system", - "infoflow3", "system", cond="tc_move_to_bool_b", cond_block=True) - - def test_removed_type_change_rules(self): - """Diff: removed type_change rules.""" - rules = sorted(self.diff.removed_type_changes) - self.assertEqual(5, len(rules)) - - # removed rule with new type - self.validate_rule(rules[0], TRT.type_change, "removed_type", "system", "infoflow4", - "system") - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[1], TRT.type_change, "system", "tc_switch_block", "infoflow6", - "system", cond="tc_switch_block_b", cond_block=True) - - # rule moved out of a conditional - self.validate_rule(rules[2], TRT.type_change, "tc_move_from_bool", "system", - "infoflow4", "system", cond="tc_move_from_bool_b", cond_block=True) - - # rule moved into a conditional - self.validate_rule(rules[3], TRT.type_change, "tc_move_to_bool", "system", - "infoflow3", "system") - - # removed rule with existing types - self.validate_rule(rules[4], TRT.type_change, "tc_removed_rule_source", - "tc_removed_rule_target", "infoflow", "system") - - def test_modified_type_change_rules(self): - """Diff: modified type_change rules.""" - lst = sorted(self.diff.modified_type_changes, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_default, removed_default = astuple(lst[0]) - self.assertEqual(TRT.type_change, rule.ruletype) - self.assertEqual("tc_matched_source", rule.source) - self.assertEqual("system", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertEqual("tc_new_type", added_default) - self.assertEqual("tc_old_type", removed_default) - - # - # Type_member rules - # - def test_added_type_member_rules(self): - """Diff: added type_member rules.""" - rules = sorted(self.diff.added_type_members) - self.assertEqual(5, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], TRT.type_member, "added_type", "system", "infoflow4", - "system") - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[1], TRT.type_member, "system", "tm_switch_block", "infoflow6", - "system", cond="tm_switch_block_b", cond_block=False) - - # added rule with existing types - self.validate_rule(rules[2], TRT.type_member, "tm_added_rule_source", - "tm_added_rule_target", "infoflow", "system") - - # rule moved out of a conditional - self.validate_rule(rules[3], TRT.type_member, "tm_move_from_bool", "system", - "infoflow4", "system") - - # rule moved into a conditional - self.validate_rule(rules[4], TRT.type_member, "tm_move_to_bool", "system", - "infoflow3", "system", cond="tm_move_to_bool_b", cond_block=True) - - def test_removed_type_member_rules(self): - """Diff: removed type_member rules.""" - rules = sorted(self.diff.removed_type_members) - self.assertEqual(5, len(rules)) - - # removed rule with new type - self.validate_rule(rules[0], TRT.type_member, "removed_type", "system", "infoflow4", - "system") - - # rule moved from one conditional block to another (true to false) - self.validate_rule(rules[1], TRT.type_member, "system", "tm_switch_block", "infoflow6", - "system", cond="tm_switch_block_b", cond_block=True) - - # rule moved out of a conditional - self.validate_rule(rules[2], TRT.type_member, "tm_move_from_bool", "system", - "infoflow4", "system", cond="tm_move_from_bool_b", cond_block=True) - - # rule moved into a conditional - self.validate_rule(rules[3], TRT.type_member, "tm_move_to_bool", "system", - "infoflow3", "system") - - # removed rule with existing types - self.validate_rule(rules[4], TRT.type_member, "tm_removed_rule_source", - "tm_removed_rule_target", "infoflow", "system") - - def test_modified_type_member_rules(self): - """Diff: modified type_member rules.""" - lst = sorted(self.diff.modified_type_members, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_default, removed_default = astuple(lst[0]) - self.assertEqual(TRT.type_member, rule.ruletype) - self.assertEqual("tm_matched_source", rule.source) - self.assertEqual("system", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertEqual("tm_new_type", added_default) - self.assertEqual("tm_old_type", removed_default) - - # - # Range_transition rules - # - def test_added_range_transition_rules(self): - """Diff: added range_transition rules.""" - rules = sorted(self.diff.added_range_transitions) - self.assertEqual(2, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], MRT.range_transition, "added_type", "system", "infoflow4", - "s3") - - # added rule with existing types - self.validate_rule(rules[1], MRT.range_transition, "rt_added_rule_source", - "rt_added_rule_target", "infoflow", "s3") - - def test_removed_range_transition_rules(self): - """Diff: removed range_transition rules.""" - rules = sorted(self.diff.removed_range_transitions) - self.assertEqual(2, len(rules)) - - # removed rule with new type - self.validate_rule(rules[0], MRT.range_transition, "removed_type", "system", "infoflow4", - "s1") - - # removed rule with existing types - self.validate_rule(rules[1], MRT.range_transition, "rt_removed_rule_source", - "rt_removed_rule_target", "infoflow", "s1") - - def test_modified_range_transition_rules(self): - """Diff: modified range_transition rules.""" - lst = sorted(self.diff.modified_range_transitions, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_default, removed_default = astuple(lst[0]) - self.assertEqual(MRT.range_transition, rule.ruletype) - self.assertEqual("rt_matched_source", rule.source) - self.assertEqual("system", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertEqual("s0:c0,c4 - s1:c0.c2,c4", added_default) - self.assertEqual("s2:c0 - s3:c0.c2", removed_default) - - # - # Role allow rules - # - def test_added_role_allow_rules(self): - """Diff: added role_allow rules.""" - rules = sorted(self.diff.added_role_allows) - self.assertEqual(2, len(rules)) - - # added rule with existing roles - self.assertEqual(RRT.allow, rules[0].ruletype) - self.assertEqual("added_role", rules[0].source) - self.assertEqual("system", rules[0].target) - - # added rule with new roles - self.assertEqual(RRT.allow, rules[1].ruletype) - self.assertEqual("added_rule_source_r", rules[1].source) - self.assertEqual("added_rule_target_r", rules[1].target) - - def test_removed_role_allow_rules(self): - """Diff: removed role_allow rules.""" - rules = sorted(self.diff.removed_role_allows) - self.assertEqual(2, len(rules)) - - # removed rule with removed role - self.assertEqual(RRT.allow, rules[0].ruletype) - self.assertEqual("removed_role", rules[0].source) - self.assertEqual("system", rules[0].target) - - # removed rule with existing roles - self.assertEqual(RRT.allow, rules[1].ruletype) - self.assertEqual("removed_rule_source_r", rules[1].source) - self.assertEqual("removed_rule_target_r", rules[1].target) - - # - # Role_transition rules - # - def test_added_role_transition_rules(self): - """Diff: added role_transition rules.""" - rules = sorted(self.diff.added_role_transitions) - self.assertEqual(2, len(rules)) - - # added rule with new role - self.validate_rule(rules[0], RRT.role_transition, "added_role", "system", "infoflow4", - "system") - - # added rule with existing roles - self.validate_rule(rules[1], RRT.role_transition, "role_tr_added_rule_source", - "role_tr_added_rule_target", "infoflow6", "system") - - def test_removed_role_transition_rules(self): - """Diff: removed role_transition rules.""" - rules = sorted(self.diff.removed_role_transitions) - self.assertEqual(2, len(rules)) - - # removed rule with new role - self.validate_rule(rules[0], RRT.role_transition, "removed_role", "system", "infoflow4", - "system") - - # removed rule with existing roles - self.validate_rule(rules[1], RRT.role_transition, "role_tr_removed_rule_source", - "role_tr_removed_rule_target", "infoflow5", "system") - - def test_modified_role_transition_rules(self): - """Diff: modified role_transition rules.""" - lst = sorted(self.diff.modified_role_transitions, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_default, removed_default = astuple(lst[0]) - self.assertEqual(RRT.role_transition, rule.ruletype) - self.assertEqual("role_tr_matched_source", rule.source) - self.assertEqual("role_tr_matched_target", rule.target) - self.assertEqual("infoflow3", rule.tclass) - self.assertEqual("role_tr_new_role", added_default) - self.assertEqual("role_tr_old_role", removed_default) - - # - # Users - # - def test_added_user(self): - """Diff: added user.""" - self.assertSetEqual(set(["added_user"]), self.diff.added_users) - - def test_removed_user(self): - """Diff: removed user.""" - self.assertSetEqual(set(["removed_user"]), self.diff.removed_users) - - def test_modified_user_count(self): - """Diff: modified user count.""" - self.assertEqual(4, len(self.diff.modified_users)) - - def test_modified_user_add_role(self): - """Diff: modified user with added role.""" - # modified_add_role - self.diff.modified_users.sort() - self.assertSetEqual(set(["added_role"]), - self.diff.modified_users[0].added_roles) - self.assertFalse(self.diff.modified_users[0].removed_roles) - - def test_modified_user_remove_role(self): - """Diff: modified user with removed role.""" - # modified_remove_role - self.diff.modified_users.sort() - self.assertSetEqual(set(["removed_role"]), - self.diff.modified_users[3].removed_roles) - self.assertFalse(self.diff.modified_users[3].added_roles) - - def test_modified_user_change_level(self): - """Diff: modified user due to modified default level.""" - # modified_change_level - self.diff.modified_users.sort() - self.assertEqual("s2:c0", self.diff.modified_users[1].removed_level) - self.assertEqual("s2:c1", self.diff.modified_users[1].added_level) - - def test_modified_user_change_range(self): - """Diff: modified user due to modified range.""" - # modified_change_range - self.diff.modified_users.sort() - self.assertEqual("s3:c1 - s3:c1.c3", - self.diff.modified_users[2].removed_range) - self.assertEqual("s3:c1 - s3:c1.c4", - self.diff.modified_users[2].added_range) - - # - # Type attributes - # - def test_added_type_attribute(self): - """Diff: added type attribute.""" - self.assertSetEqual(set(["added_attr"]), self.diff.added_type_attributes) - - def test_removed_type_attribute(self): - """Diff: removed type attribute.""" - self.assertSetEqual(set(["removed_attr"]), self.diff.removed_type_attributes) - - def test_modified_type_attribute(self): - """Diff: modified type attribute.""" - self.assertEqual(1, len(self.diff.modified_type_attributes)) - self.assertSetEqual(set(["modified_add_attr"]), - self.diff.modified_type_attributes[0].added_types) - self.assertSetEqual(set(["modified_remove_attr"]), - self.diff.modified_type_attributes[0].removed_types) - - # - # Booleans - # - def test_added_boolean(self): - """Diff: added boolean.""" - self.assertSetEqual(set(["added_bool"]), self.diff.added_booleans) - - def test_removed_boolean(self): - """Diff: removed boolean.""" - self.assertSetEqual(set(["removed_bool"]), self.diff.removed_booleans) - - def test_modified_boolean(self): - """Diff: modified boolean.""" - self.assertEqual(1, len(self.diff.modified_booleans)) - self.assertTrue(self.diff.modified_booleans[0].added_state) - self.assertFalse(self.diff.modified_booleans[0].removed_state) - - # - # Categories - # - def test_added_category(self): - """Diff: added category.""" - self.assertSetEqual(set(["c6"]), self.diff.added_categories) - - def test_removed_category(self): - """Diff: removed category.""" - self.assertSetEqual(set(["c5"]), self.diff.removed_categories) - - def test_modified_category(self): - """Diff: modified categories.""" - self.assertEqual(2, len(self.diff.modified_categories)) - self.diff.modified_categories.sort() - - # add alias on c1 - self.assertEqual(set(["foo"]), self.diff.modified_categories[1].added_aliases) - self.assertFalse(self.diff.modified_categories[1].removed_aliases) - - # remove alias on c0 - self.assertFalse(self.diff.modified_categories[0].added_aliases) - self.assertEqual(set(["eggs"]), self.diff.modified_categories[0].removed_aliases) - - # - # Sensitivity - # - def test_added_sensitivities(self): - """Diff: added sensitivities.""" - self.assertSetEqual(set(["s46"]), self.diff.added_sensitivities) - - def test_removed_sensitivities(self): - """Diff: removed sensitivities.""" - self.assertSetEqual(set(["s47"]), self.diff.removed_sensitivities) - - def test_modified_sensitivities(self): - """Diff: modified sensitivities.""" - self.assertEqual(2, len(self.diff.modified_sensitivities)) - self.diff.modified_sensitivities.sort() - - # add alias to s1 - self.assertSetEqual(set(["al4"]), self.diff.modified_sensitivities[1].added_aliases) - self.assertFalse(self.diff.modified_sensitivities[1].removed_aliases) - - # remove alias from s0 - self.assertFalse(self.diff.modified_sensitivities[0].added_aliases) - self.assertSetEqual(set(["al2"]), self.diff.modified_sensitivities[0].removed_aliases) - - # - # Initial SIDs - # - def test_added_initialsids(self): - """Diff: added initialsids.""" - self.assertSetEqual(set(["file_labels"]), self.diff.added_initialsids) - - @unittest.skip("Moved to PolicyDifferenceRmIsidTest.") - def test_removed_initialsids(self): - """Diff: removed initialsids.""" - self.assertSetEqual(set(["removed_sid"]), self.diff.removed_initialsids) - - def test_modified_initialsids(self): - """Diff: modified initialsids.""" - self.assertEqual(1, len(self.diff.modified_initialsids)) - self.assertEqual("system:system:system:s0", - self.diff.modified_initialsids[0].added_context) - self.assertEqual("removed_user:system:system:s0", - self.diff.modified_initialsids[0].removed_context) - - # - # fs_use_* - # - def test_added_fs_uses(self): - """Diff: added fs_uses.""" - lst = sorted(self.diff.added_fs_uses) - self.assertEqual(1, len(lst)) - - rule = lst[0] - self.assertEqual(FSURT.fs_use_xattr, rule.ruletype) - self.assertEqual("added_fsuse", rule.fs) - self.assertEqual("system:object_r:system:s0", rule.context) - - def test_removed_fs_uses(self): - """Diff: removed fs_uses.""" - lst = sorted(self.diff.removed_fs_uses) - self.assertEqual(1, len(lst)) - - rule = lst[0] - self.assertEqual(FSURT.fs_use_task, rule.ruletype) - self.assertEqual("removed_fsuse", rule.fs) - self.assertEqual("system:object_r:system:s0", rule.context) - - def test_modified_fs_uses(self): - """Diff: modified fs_uses.""" - lst = sorted(self.diff.modified_fs_uses, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_context, removed_context = astuple(lst[0]) - self.assertEqual(FSURT.fs_use_trans, rule.ruletype) - self.assertEqual("modified_fsuse", rule.fs) - self.assertEqual("added_user:object_r:system:s1", added_context) - self.assertEqual("removed_user:object_r:system:s0", removed_context) - - # - # genfscon - # - def test_added_genfscons(self): - """Diff: added genfscons.""" - lst = sorted(self.diff.added_genfscons) - self.assertEqual(2, len(lst)) - - rule = lst[0] - self.assertEqual("added_genfs", rule.fs) - self.assertEqual("/", rule.path) - self.assertEqual("added_user:object_r:system:s0", rule.context) - - rule = lst[1] - self.assertEqual("change_path", rule.fs) - self.assertEqual("/new", rule.path) - self.assertEqual("system:object_r:system:s0", rule.context) - - def test_removed_genfscons(self): - """Diff: removed genfscons.""" - lst = sorted(self.diff.removed_genfscons) - self.assertEqual(2, len(lst)) - - rule = lst[0] - self.assertEqual("change_path", rule.fs) - self.assertEqual("/old", rule.path) - self.assertEqual("system:object_r:system:s0", rule.context) - - rule = lst[1] - self.assertEqual("removed_genfs", rule.fs) - self.assertEqual("/", rule.path) - self.assertEqual("system:object_r:system:s0", rule.context) - - def test_modified_genfscons(self): - """Diff: modified genfscons.""" - lst = sorted(self.diff.modified_genfscons, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - rule, added_context, removed_context = astuple(lst[0]) - self.assertEqual("modified_genfs", rule.fs) - self.assertEqual("/", rule.path) - self.assertEqual("added_user:object_r:system:s0", added_context) - self.assertEqual("removed_user:object_r:system:s0", removed_context) - - # - # level decl - # - def test_added_levels(self): - """Diff: added levels.""" - lst = sorted(self.diff.added_levels) - self.assertEqual(1, len(lst)) - self.assertEqual("s46:c0.c4", lst[0]) - - def test_removed_levels(self): - """Diff: removed levels.""" - lst = sorted(self.diff.removed_levels) - self.assertEqual(1, len(lst)) - self.assertEqual("s47:c0.c4", lst[0]) - - def test_modified_levels(self): - """Diff: modified levels.""" - lst = sorted(self.diff.modified_levels) - self.assertEqual(2, len(lst)) - - level = lst[0] - self.assertEqual("s40", level.level.sensitivity) - self.assertSetEqual(set(["c3"]), level.added_categories) - self.assertFalse(level.removed_categories) - - level = lst[1] - self.assertEqual("s41", level.level.sensitivity) - self.assertFalse(level.added_categories) - self.assertSetEqual(set(["c4"]), level.removed_categories) - - # - # netifcon - # - def test_added_netifcons(self): - """Diff: added netifcons.""" - lst = sorted(self.diff.added_netifcons) - self.assertEqual(1, len(lst)) - - rule = lst[0] - self.assertEqual("added_netif", rule.netif) - self.assertEqual("system:object_r:system:s0", rule.context) - self.assertEqual("system:object_r:system:s0", rule.packet) - - def test_removed_netifcons(self): - """Diff: removed netifcons.""" - lst = sorted(self.diff.removed_netifcons) - self.assertEqual(1, len(lst)) - - rule = lst[0] - self.assertEqual("removed_netif", rule.netif) - self.assertEqual("system:object_r:system:s0", rule.context) - self.assertEqual("system:object_r:system:s0", rule.packet) - - def test_modified_netifcons(self): - """Diff: modified netifcons.""" - lst = sorted(self.diff.modified_netifcons, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # modified both contexts - rule, added_context, removed_context, added_packet, removed_packet = astuple(lst[0]) - self.assertEqual("mod_both_netif", rule.netif) - self.assertEqual("added_user:object_r:system:s0", added_context) - self.assertEqual("removed_user:object_r:system:s0", removed_context) - self.assertEqual("added_user:object_r:system:s0", added_packet) - self.assertEqual("removed_user:object_r:system:s0", removed_packet) - - # modified context - rule, added_context, removed_context, added_packet, removed_packet = astuple(lst[1]) - self.assertEqual("mod_ctx_netif", rule.netif) - self.assertEqual("added_user:object_r:system:s0", added_context) - self.assertEqual("removed_user:object_r:system:s0", removed_context) - self.assertIsNone(added_packet) - self.assertIsNone(removed_packet) - - # modified packet context - rule, added_context, removed_context, added_packet, removed_packet = astuple(lst[2]) - self.assertEqual("mod_pkt_netif", rule.netif) - self.assertIsNone(added_context) - self.assertIsNone(removed_context) - self.assertEqual("added_user:object_r:system:s0", added_packet) - self.assertEqual("removed_user:object_r:system:s0", removed_packet) - - # - # nodecons - # - def test_added_nodecons(self): - """Diff: added nodecons.""" - lst = sorted(self.diff.added_nodecons) - self.assertEqual(4, len(lst)) - - # new IPv4 - nodecon = lst[0] - self.assertEqual(IPv4Network("124.0.0.0/8"), nodecon.network) - - # changed IPv4 netmask - nodecon = lst[1] - self.assertEqual(IPv4Network("125.0.0.0/16"), nodecon.network) - - # new IPv6 - nodecon = lst[2] - self.assertEqual(IPv6Network("ff04::/62"), nodecon.network) - - # changed IPv6 netmask - nodecon = lst[3] - self.assertEqual(IPv6Network("ff05::/60"), nodecon.network) - - def test_removed_nodecons(self): - """Diff: removed nodecons.""" - lst = sorted(self.diff.removed_nodecons) - self.assertEqual(4, len(lst)) - - # new IPv4 - nodecon = lst[0] - self.assertEqual(IPv4Network("122.0.0.0/8"), nodecon.network) - - # changed IPv4 netmask - nodecon = lst[1] - self.assertEqual(IPv4Network("125.0.0.0/8"), nodecon.network) - - # new IPv6 - nodecon = lst[2] - self.assertEqual(IPv6Network("ff02::/62"), nodecon.network) - - # changed IPv6 netmask - nodecon = lst[3] - self.assertEqual(IPv6Network("ff05::/62"), nodecon.network) - - def test_modified_nodecons(self): - """Diff: modified nodecons.""" - lst = sorted(self.diff.modified_nodecons, key=lambda x: x.rule) - self.assertEqual(2, len(lst)) - - # changed IPv4 - nodecon, added_context, removed_context = astuple(lst[0]) - self.assertEqual(IPv4Network("123.0.0.0/8"), nodecon.network) - self.assertEqual("modified_change_level:object_r:system:s2:c0", added_context) - self.assertEqual("modified_change_level:object_r:system:s2:c1", removed_context) - - # changed IPv6 - nodecon, added_context, removed_context = astuple(lst[1]) - self.assertEqual(IPv6Network("ff03::/62"), nodecon.network) - self.assertEqual("modified_change_level:object_r:system:s2:c1", added_context) - self.assertEqual("modified_change_level:object_r:system:s2:c0.c1", removed_context) - - # - # Policy capabilities - # - def test_added_polcaps(self): - """Diff: added polcaps.""" - self.assertSetEqual(set(["always_check_network"]), self.diff.added_polcaps) - - def test_removed_polcaps(self): - """Diff: removed polcaps.""" - self.assertSetEqual(set(["network_peer_controls"]), self.diff.removed_polcaps) - - # - # portcons - # - def test_added_portcons(self): - """Diff: added portcons.""" - lst = sorted(self.diff.added_portcons) - self.assertEqual(2, len(lst)) - - portcon = lst[0] - self.assertEqual(PortconProtocol.tcp, portcon.protocol) - self.assertEqual(PortconRange(2024, 2026), portcon.ports) - - portcon = lst[1] - self.assertEqual(PortconProtocol.udp, portcon.protocol) - self.assertEqual(PortconRange(2024, 2024), portcon.ports) - - def test_removed_portcons(self): - """Diff: removed portcons.""" - lst = sorted(self.diff.removed_portcons) - self.assertEqual(2, len(lst)) - - portcon = lst[0] - self.assertEqual(PortconProtocol.tcp, portcon.protocol) - self.assertEqual(PortconRange(1024, 1026), portcon.ports) - - portcon = lst[1] - self.assertEqual(PortconProtocol.udp, portcon.protocol) - self.assertEqual(PortconRange(1024, 1024), portcon.ports) - - def test_modified_portcons(self): - """Diff: modified portcons.""" - lst = sorted(self.diff.modified_portcons, key=lambda x: x.rule) - self.assertEqual(2, len(lst)) - - portcon, added_context, removed_context = astuple(lst[0]) - self.assertEqual(PortconProtocol.tcp, portcon.protocol) - self.assertEqual(PortconRange(3024, 3026), portcon.ports) - self.assertEqual("added_user:object_r:system:s1", added_context) - self.assertEqual("removed_user:object_r:system:s0", removed_context) - - portcon, added_context, removed_context = astuple(lst[1]) - self.assertEqual(PortconProtocol.udp, portcon.protocol) - self.assertEqual(PortconRange(3024, 3024), portcon.ports) - self.assertEqual("added_user:object_r:system:s1", added_context) - self.assertEqual("removed_user:object_r:system:s0", removed_context) - - # - # defaults - # - def test_added_defaults(self): - """Diff: added defaults.""" - lst = sorted(self.diff.added_defaults) - self.assertEqual(2, len(lst)) - - default = lst[0] - self.assertEqual(DRT.default_range, default.ruletype) - self.assertEqual("infoflow2", default.tclass) - - default = lst[1] - self.assertEqual(DRT.default_user, default.ruletype) - self.assertEqual("infoflow2", default.tclass) - - def test_removed_defaults(self): - """Diff: removed defaults.""" - lst = sorted(self.diff.removed_defaults) - self.assertEqual(2, len(lst)) - - default = lst[0] - self.assertEqual(DRT.default_range, default.ruletype) - self.assertEqual("infoflow3", default.tclass) - - default = lst[1] - self.assertEqual(DRT.default_role, default.ruletype) - self.assertEqual("infoflow3", default.tclass) - - def test_modified_defaults(self): - """Diff: modified defaults.""" - lst = sorted(self.diff.modified_defaults, key=lambda x: x.rule) - self.assertEqual(4, len(lst)) - - default, added_default, removed_default, added_range, removed_range = astuple(lst[0]) - self.assertEqual(DRT.default_range, default.ruletype) - self.assertEqual("infoflow4", default.tclass) - self.assertEqual(DV.target, added_default) - self.assertEqual(DV.source, removed_default) - self.assertIsNone(added_range) - self.assertIsNone(removed_range) - - default, added_default, removed_default, added_range, removed_range = astuple(lst[1]) - self.assertEqual(DRT.default_range, default.ruletype) - self.assertEqual("infoflow5", default.tclass) - self.assertIsNone(added_default) - self.assertIsNone(removed_default) - self.assertEqual(DRV.high, added_range) - self.assertEqual(DRV.low, removed_range) - - default, added_default, removed_default, added_range, removed_range = astuple(lst[2]) - self.assertEqual(DRT.default_range, default.ruletype) - self.assertEqual("infoflow6", default.tclass) - self.assertEqual(DV.target, added_default) - self.assertEqual(DV.source, removed_default) - self.assertEqual(DRV.low, added_range) - self.assertEqual(DRV.high, removed_range) - - default, added_default, removed_default, added_range, removed_range = astuple(lst[3]) - self.assertEqual(DRT.default_type, default.ruletype) - self.assertEqual("infoflow4", default.tclass) - self.assertEqual(DV.target, added_default) - self.assertEqual(DV.source, removed_default) - self.assertIsNone(added_range) - self.assertIsNone(removed_range) - - # - # constrains - # - def test_added_constrains(self): - """Diff: added constrains.""" - lst = sorted(self.diff.added_constrains) - self.assertEqual(2, len(lst)) - - constrain = lst[0] - self.assertEqual(CRT.constrain, constrain.ruletype) - self.assertEqual("infoflow3", constrain.tclass) - self.assertSetEqual(set(["null"]), constrain.perms) - self.assertEqual(["u1", "u2", "!="], constrain.expression) - - constrain = lst[1] - self.assertEqual(CRT.constrain, constrain.ruletype) - self.assertEqual("infoflow5", constrain.tclass) - self.assertSetEqual(set(["hi_r"]), constrain.perms) - self.assertEqual( - ['u1', 'u2', '==', 'r1', 'r2', '==', 'and', 't1', set(["system"]), '!=', 'or'], - constrain.expression) - - def test_removed_constrains(self): - """Diff: removed constrains.""" - lst = sorted(self.diff.removed_constrains) - self.assertEqual(2, len(lst)) - - constrain = lst[0] - self.assertEqual(CRT.constrain, constrain.ruletype) - self.assertEqual("infoflow4", constrain.tclass) - self.assertSetEqual(set(["hi_w"]), constrain.perms) - self.assertEqual(["u1", "u2", "!="], constrain.expression) - - constrain = lst[1] - self.assertEqual(CRT.constrain, constrain.ruletype) - self.assertEqual("infoflow5", constrain.tclass) - self.assertSetEqual(set(["hi_r"]), constrain.perms) - self.assertEqual( - ['u1', 'u2', '==', 'r1', 'r2', '==', 'and', 't1', set(["system"]), '==', 'or'], - constrain.expression) - - # - # mlsconstrains - # - def test_added_mlsconstrains(self): - """Diff: added mlsconstrains.""" - lst = sorted(self.diff.added_mlsconstrains) - self.assertEqual(2, len(lst)) - - mlsconstrain = lst[0] - self.assertEqual(CRT.mlsconstrain, mlsconstrain.ruletype) - self.assertEqual("infoflow3", mlsconstrain.tclass) - self.assertSetEqual(set(["null"]), mlsconstrain.perms) - self.assertEqual( - ['l1', 'l2', 'domby', 'h1', 'h2', 'domby', 'and', - 't1', set(["mls_exempt"]), '!=', 'or'], - mlsconstrain.expression) - - mlsconstrain = lst[1] - self.assertEqual(CRT.mlsconstrain, mlsconstrain.ruletype) - self.assertEqual("infoflow5", mlsconstrain.tclass) - self.assertSetEqual(set(["hi_r"]), mlsconstrain.perms) - self.assertEqual( - ['l1', 'l2', 'domby', 'h1', 'h2', 'incomp', - 'and', 't1', set(["mls_exempt"]), '==', 'or'], - mlsconstrain.expression) - - def test_removed_mlsconstrains(self): - """Diff: removed mlsconstrains.""" - lst = sorted(self.diff.removed_mlsconstrains) - self.assertEqual(2, len(lst)) - - mlsconstrain = lst[0] - self.assertEqual(CRT.mlsconstrain, mlsconstrain.ruletype) - self.assertEqual("infoflow4", mlsconstrain.tclass) - self.assertSetEqual(set(["hi_w"]), mlsconstrain.perms) - self.assertEqual( - ['l1', 'l2', 'domby', 'h1', 'h2', 'domby', 'and', - 't1', set(["mls_exempt"]), '==', 'or'], - mlsconstrain.expression) - - mlsconstrain = lst[1] - self.assertEqual(CRT.mlsconstrain, mlsconstrain.ruletype) - self.assertEqual("infoflow5", mlsconstrain.tclass) - self.assertSetEqual(set(["hi_r"]), mlsconstrain.perms) - self.assertEqual( - ['l1', 'l2', 'domby', 'h1', 'h2', 'dom', 'and', 't1', set(["mls_exempt"]), '==', 'or'], - mlsconstrain.expression) - - # - # validatetrans - # - def test_added_validatetrans(self): - """Diff: added validatetrans.""" - lst = sorted(self.diff.added_validatetrans) - self.assertEqual(2, len(lst)) - - validatetrans = lst[0] - self.assertEqual(CRT.validatetrans, validatetrans.ruletype) - self.assertEqual("infoflow3", validatetrans.tclass) - self.assertEqual( - ['t1', 't2', '==', 't3', set(["system"]), '==', 'or'], - validatetrans.expression) - - validatetrans = lst[1] - self.assertEqual(CRT.validatetrans, validatetrans.ruletype) - self.assertEqual("infoflow5", validatetrans.tclass) - self.assertEqual( - ['u1', 'u2', '!=', 'r1', 'r2', '==', 'and', 't3', set(["system"]), '==', 'or'], - validatetrans.expression) - - def test_removed_validatetrans(self): - """Diff: removed validatetrans.""" - lst = sorted(self.diff.removed_validatetrans) - self.assertEqual(2, len(lst)) - - validatetrans = lst[0] - self.assertEqual(CRT.validatetrans, validatetrans.ruletype) - self.assertEqual("infoflow4", validatetrans.tclass) - self.assertEqual( - ['u1', 'u2', '==', 't3', set(["system"]), '==', 'or'], - validatetrans.expression) - - validatetrans = lst[1] - self.assertEqual(CRT.validatetrans, validatetrans.ruletype) - self.assertEqual("infoflow5", validatetrans.tclass) - self.assertEqual( - ['u1', 'u2', '==', 'r1', 'r2', '!=', 'and', 't3', set(["system"]), '==', 'or'], - validatetrans.expression) - - # - # mlsvalidatetrans - # - def test_added_mlsvalidatetrans(self): - """Diff: added mlsvalidatetrans.""" - lst = sorted(self.diff.added_mlsvalidatetrans) - self.assertEqual(2, len(lst)) - - mlsvalidatetrans = lst[0] - self.assertEqual(CRT.mlsvalidatetrans, mlsvalidatetrans.ruletype) - self.assertEqual("infoflow3", mlsvalidatetrans.tclass) - self.assertEqual( - ['l1', 'l2', '==', 'h1', 'h2', '==', 'and', 't3', set(["mls_exempt"]), '==', 'or'], - mlsvalidatetrans.expression) - - mlsvalidatetrans = lst[1] - self.assertEqual(CRT.mlsvalidatetrans, mlsvalidatetrans.ruletype) - self.assertEqual("infoflow5", mlsvalidatetrans.tclass) - self.assertEqual( - ['l1', 'l2', 'incomp', 'h1', 'h2', 'domby', - 'and', 't3', set(["mls_exempt"]), '==', 'or'], - mlsvalidatetrans.expression) - - def test_removed_mlsvalidatetrans(self): - """Diff: removed mlsvalidatetrans.""" - lst = sorted(self.diff.removed_mlsvalidatetrans) - self.assertEqual(2, len(lst)) - - mlsvalidatetrans = lst[0] - self.assertEqual(CRT.mlsvalidatetrans, mlsvalidatetrans.ruletype) - self.assertEqual("infoflow4", mlsvalidatetrans.tclass) - self.assertEqual( - ['l1', 'l2', '==', 'h1', 'h2', '==', 'and', 't3', set(["mls_exempt"]), '==', 'or'], - mlsvalidatetrans.expression) - - mlsvalidatetrans = lst[1] - self.assertEqual(CRT.mlsvalidatetrans, mlsvalidatetrans.ruletype) - self.assertEqual("infoflow5", mlsvalidatetrans.tclass) - self.assertEqual( - ['l1', 'l2', 'dom', 'h1', 'h2', 'dom', 'and', 't3', set(["mls_exempt"]), '==', 'or'], - mlsvalidatetrans.expression) - - # - # typebounds - # - def test_added_typebounds(self): - """Diff: added typebounds.""" - lst = sorted(self.diff.added_typebounds) - self.assertEqual(1, len(lst)) - - bounds = lst[0] - self.assertEqual(BRT.typebounds, bounds.ruletype) - self.assertEqual("added_parent", bounds.parent) - self.assertEqual("added_child", bounds.child) - - def test_removed_typebounds(self): - """Diff: removed typebounds.""" - lst = sorted(self.diff.removed_typebounds) - self.assertEqual(1, len(lst)) - - bounds = lst[0] - self.assertEqual(BRT.typebounds, bounds.ruletype) - self.assertEqual("removed_parent", bounds.parent) - self.assertEqual("removed_child", bounds.child) - - def test_modified_typebounds(self): - """Diff: modified typebounds.""" - lst = sorted(self.diff.modified_typebounds, key=lambda x: x.rule) - self.assertEqual(1, len(lst)) - - bounds, added_bound, removed_bound = astuple(lst[0]) - self.assertEqual(BRT.typebounds, bounds.ruletype) - self.assertEqual("mod_child", bounds.child) - self.assertEqual("mod_parent_added", added_bound) - self.assertEqual("mod_parent_removed", removed_bound) - - # - # Allowxperm rules - # - def test_added_allowxperm_rules(self): - """Diff: added allowxperm rules.""" - rules = sorted(self.diff.added_allowxperms) - self.assertEqual(2, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], TRT.allowxperm, "added_type", "added_type", "infoflow7", - set([0x0009]), xperm="ioctl") - - # added rule with existing types - self.validate_rule(rules[1], TRT.allowxperm, "ax_added_rule_source", "ax_added_rule_target", - "infoflow", set([0x0002]), xperm="ioctl") - - def test_removed_allowxperm_rules(self): - """Diff: removed allowxperm rules.""" - rules = sorted(self.diff.removed_allowxperms) - self.assertEqual(2, len(rules)) - - # removed rule with existing types - self.validate_rule(rules[0], TRT.allowxperm, "ax_removed_rule_source", - "ax_removed_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - - # removed rule with new type - self.validate_rule(rules[1], TRT.allowxperm, "removed_type", "removed_type", "infoflow7", - set([0x0009]), xperm="ioctl") - - def test_modified_allowxperm_rules(self): - """Diff: modified allowxperm rules.""" - lst = sorted(self.diff.modified_allowxperms, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # add permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) - self.assertEqual(TRT.allowxperm, rule.ruletype) - self.assertEqual("ax_modified_rule_add_perms", rule.source) - self.assertEqual("ax_modified_rule_add_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertSetEqual(set([0x000f]), added_perms) - self.assertFalse(removed_perms) - self.assertSetEqual(set([0x0004]), matched_perms) - - # add and remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) - self.assertEqual(TRT.allowxperm, rule.ruletype) - self.assertEqual("ax_modified_rule_add_remove_perms", rule.source) - self.assertEqual("ax_modified_rule_add_remove_perms", rule.target) - self.assertEqual("infoflow2", rule.tclass) - self.assertSetEqual(set([0x0006]), added_perms) - self.assertSetEqual(set([0x0007]), removed_perms) - self.assertSetEqual(set([0x0008]), matched_perms) - - # remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) - self.assertEqual(TRT.allowxperm, rule.ruletype) - self.assertEqual("ax_modified_rule_remove_perms", rule.source) - self.assertEqual("ax_modified_rule_remove_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertFalse(added_perms) - self.assertSetEqual(set([0x0006]), removed_perms) - self.assertSetEqual(set([0x0005]), matched_perms) - - # - # Auditallowxperm rules - # - def test_added_auditallowxperm_rules(self): - """Diff: added auditallowxperm rules.""" - rules = sorted(self.diff.added_auditallowxperms) - self.assertEqual(2, len(rules)) - - # added rule with existing types - self.validate_rule(rules[0], TRT.auditallowxperm, "aax_added_rule_source", - "aax_added_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - - # added rule with new type - self.validate_rule(rules[1], TRT.auditallowxperm, "added_type", "added_type", "infoflow7", - set([0x0009]), xperm="ioctl") - - def test_removed_auditallowxperm_rules(self): - """Diff: removed auditallowxperm rules.""" - rules = sorted(self.diff.removed_auditallowxperms) - self.assertEqual(2, len(rules)) - - # removed rule with existing types - self.validate_rule(rules[0], TRT.auditallowxperm, "aax_removed_rule_source", - "aax_removed_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - - # removed rule with new type - self.validate_rule(rules[1], TRT.auditallowxperm, "removed_type", "removed_type", - "infoflow7", set([0x0009]), xperm="ioctl") - - def test_modified_auditallowxperm_rules(self): - """Diff: modified auditallowxperm rules.""" - lst = sorted(self.diff.modified_auditallowxperms, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # add permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) - self.assertEqual(TRT.auditallowxperm, rule.ruletype) - self.assertEqual("aax_modified_rule_add_perms", rule.source) - self.assertEqual("aax_modified_rule_add_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertSetEqual(set([0x000f]), added_perms) - self.assertFalse(removed_perms) - self.assertSetEqual(set([0x0004]), matched_perms) - - # add and remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) - self.assertEqual(TRT.auditallowxperm, rule.ruletype) - self.assertEqual("aax_modified_rule_add_remove_perms", rule.source) - self.assertEqual("aax_modified_rule_add_remove_perms", rule.target) - self.assertEqual("infoflow2", rule.tclass) - self.assertSetEqual(set([0x0006]), added_perms) - self.assertSetEqual(set([0x0007]), removed_perms) - self.assertSetEqual(set([0x0008]), matched_perms) - - # remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) - self.assertEqual(TRT.auditallowxperm, rule.ruletype) - self.assertEqual("aax_modified_rule_remove_perms", rule.source) - self.assertEqual("aax_modified_rule_remove_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertFalse(added_perms) - self.assertSetEqual(set([0x0006]), removed_perms) - self.assertSetEqual(set([0x0005]), matched_perms) - - # - # Neverallowxperm rules - # - def test_added_neverallowxperm_rules(self): - """Diff: added neverallowxperm rules.""" - self.assertFalse(self.diff.added_neverallowxperms) - # changed after dropping source policy support - # rules = sorted(self.diff.added_neverallowxperms) - # self.assertEqual(2, len(rules)) - # - # # added rule with new type - # self.validate_rule(rules[0], TRT.neverallowxperm, "added_type", "added_type", "infoflow7", - # set([0x0009]), xperm="ioctl") - # - # # added rule with existing types - # self.validate_rule(rules[1], TRT.neverallowxperm, "nax_added_rule_source", - # "nax_added_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - - def test_removed_neverallowxperm_rules(self): - """Diff: removed neverallowxperm rules.""" - self.assertFalse(self.diff.removed_neverallowxperms) - # changed after dropping source policy support - # rules = sorted(self.diff.removed_neverallowxperms) - # self.assertEqual(2, len(rules)) - # - # # removed rule with existing types - # self.validate_rule(rules[0], TRT.neverallowxperm, "nax_removed_rule_source", - # "nax_removed_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - # - # # removed rule with new type - # self.validate_rule(rules[1], TRT.neverallowxperm, "removed_type", "removed_type", - # "infoflow7", set([0x0009]), xperm="ioctl") - - def test_modified_neverallowxperm_rules(self): - """Diff: modified neverallowxperm rules.""" - self.assertFalse(self.diff.modified_neverallowxperms) - # changed after dropping source policy support - # l = sorted(self.diff.modified_neverallowxperms, key=lambda x: x.rule) - # self.assertEqual(3, len(l)) - # - # # add permissions - # rule, added_perms, removed_perms, matched_perms = l[0] - # self.assertEqual(TRT.neverallowxperm, rule.ruletype) - # self.assertEqual("nax_modified_rule_add_perms", rule.source) - # self.assertEqual("nax_modified_rule_add_perms", rule.target) - # self.assertEqual("infoflow", rule.tclass) - # self.assertSetEqual(set([0x000f]), added_perms) - # self.assertFalse(removed_perms) - # self.assertSetEqual(set([0x0004]), matched_perms) - # - # # add and remove permissions - # rule, added_perms, removed_perms, matched_perms = l[1] - # self.assertEqual(TRT.neverallowxperm, rule.ruletype) - # self.assertEqual("nax_modified_rule_add_remove_perms", rule.source) - # self.assertEqual("nax_modified_rule_add_remove_perms", rule.target) - # self.assertEqual("infoflow2", rule.tclass) - # self.assertSetEqual(set([0x0006]), added_perms) - # self.assertSetEqual(set([0x0007]), removed_perms) - # self.assertSetEqual(set([0x0008]), matched_perms) - # - # # remove permissions - # rule, added_perms, removed_perms, matched_perms = l[2] - # self.assertEqual(TRT.neverallowxperm, rule.ruletype) - # self.assertEqual("nax_modified_rule_remove_perms", rule.source) - # self.assertEqual("nax_modified_rule_remove_perms", rule.target) - # self.assertEqual("infoflow", rule.tclass) - # self.assertFalse(added_perms) - # self.assertSetEqual(set([0x0006]), removed_perms) - # self.assertSetEqual(set([0x0005]), matched_perms) - - # - # Dontauditxperm rules - # - def test_added_dontauditxperm_rules(self): - """Diff: added dontauditxperm rules.""" - rules = sorted(self.diff.added_dontauditxperms) - self.assertEqual(2, len(rules)) - - # added rule with new type - self.validate_rule(rules[0], TRT.dontauditxperm, "added_type", "added_type", "infoflow7", - set([0x0009]), xperm="ioctl") - - # added rule with existing types - self.validate_rule(rules[1], TRT.dontauditxperm, "dax_added_rule_source", - "dax_added_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - - def test_removed_dontauditxperm_rules(self): - """Diff: removed dontauditxperm rules.""" - rules = sorted(self.diff.removed_dontauditxperms) - self.assertEqual(2, len(rules)) - - # removed rule with existing types - self.validate_rule(rules[0], TRT.dontauditxperm, "dax_removed_rule_source", - "dax_removed_rule_target", "infoflow", set([0x0002]), xperm="ioctl") - - # removed rule with new type - self.validate_rule(rules[1], TRT.dontauditxperm, "removed_type", "removed_type", - "infoflow7", set([0x0009]), xperm="ioctl") - - def test_modified_dontauditxperm_rules(self): - """Diff: modified dontauditxperm rules.""" - lst = sorted(self.diff.modified_dontauditxperms, key=lambda x: x.rule) - self.assertEqual(3, len(lst)) - - # add permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[0]) - self.assertEqual(TRT.dontauditxperm, rule.ruletype) - self.assertEqual("dax_modified_rule_add_perms", rule.source) - self.assertEqual("dax_modified_rule_add_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertSetEqual(set([0x000f]), added_perms) - self.assertFalse(removed_perms) - self.assertSetEqual(set([0x0004]), matched_perms) - - # add and remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[1]) - self.assertEqual(TRT.dontauditxperm, rule.ruletype) - self.assertEqual("dax_modified_rule_add_remove_perms", rule.source) - self.assertEqual("dax_modified_rule_add_remove_perms", rule.target) - self.assertEqual("infoflow2", rule.tclass) - self.assertSetEqual(set([0x0006]), added_perms) - self.assertSetEqual(set([0x0007]), removed_perms) - self.assertSetEqual(set([0x0008]), matched_perms) - - # remove permissions - rule, added_perms, removed_perms, matched_perms = astuple(lst[2]) - self.assertEqual(TRT.dontauditxperm, rule.ruletype) - self.assertEqual("dax_modified_rule_remove_perms", rule.source) - self.assertEqual("dax_modified_rule_remove_perms", rule.target) - self.assertEqual("infoflow", rule.tclass) - self.assertFalse(added_perms) - self.assertSetEqual(set([0x0006]), removed_perms) - self.assertSetEqual(set([0x0005]), matched_perms) - - # - # Ibendportcon statements - # - def test_added_ibendportcons(self): - """Diff: added ibendportcon statements.""" - rules = sorted(self.diff.added_ibendportcons) - self.assertEqual(1, len(rules)) - self.assertEqual("add", rules[0].name) - self.assertEqual(23, rules[0].port) - self.assertEqual("system:system:system:s0", rules[0].context) - - def test_removed_ibendportcons(self): - """Diff: removed ibendportcon statements.""" - rules = sorted(self.diff.removed_ibendportcons) - self.assertEqual(1, len(rules)) - self.assertEqual("removed", rules[0].name) - self.assertEqual(7, rules[0].port) - self.assertEqual("system:system:system:s0", rules[0].context) - - def test_modified_ibendportcons(self): - """Diff: modified ibendportcon statements""" - rules = sorted(self.diff.modified_ibendportcons) - self.assertEqual(1, len(rules)) - - rule, added, removed = astuple(rules[0]) - self.assertEqual("modified", rule.name) - self.assertEqual(13, rule.port) - self.assertEqual("modified_change_level:object_r:system:s2", added) - self.assertEqual("modified_change_level:object_r:system:s2:c0.c1", removed) - - # - # Ibpkeycon statements - # - def test_added_ibpkeycons(self): - """Diff: added ibpkeycon statements.""" - rules = sorted(self.diff.added_ibpkeycons) - self.assertEqual(2, len(rules)) - - rule = rules[0] - self.assertEqual(IPv6Address("beef::"), rule.subnet_prefix) - self.assertEqual(0xe, rule.pkeys.low) - self.assertEqual(0xe, rule.pkeys.high) - self.assertEqual("system:system:system:s0", rule.context) - - rule = rules[1] - self.assertEqual(IPv6Address("dead::"), rule.subnet_prefix) - self.assertEqual(0xbeef, rule.pkeys.low) - self.assertEqual(0xdead, rule.pkeys.high) - self.assertEqual("system:system:system:s0", rule.context) - - def test_removed_ibpkeycons(self): - """Diff: removed ibpkeycon statements.""" - rules = sorted(self.diff.removed_ibpkeycons) - self.assertEqual(2, len(rules)) - - rule = rules[0] - self.assertEqual(IPv6Address("dccc::"), rule.subnet_prefix) - self.assertEqual(0xc, rule.pkeys.low) - self.assertEqual(0xc, rule.pkeys.high) - self.assertEqual("system:system:system:s0", rule.context) - - rule = rules[1] - self.assertEqual(IPv6Address("feee::"), rule.subnet_prefix) - self.assertEqual(0xaaaa, rule.pkeys.low) - self.assertEqual(0xbbbb, rule.pkeys.high) - self.assertEqual("system:system:system:s0", rule.context) - - def test_modified_ibpkeycons(self): - """Diff: modified ibpkeycon statements""" - rules = sorted(self.diff.modified_ibpkeycons) - self.assertEqual(2, len(rules)) - - rule, added, removed = astuple(rules[0]) - self.assertEqual(IPv6Address("aaaa::"), rule.subnet_prefix) - self.assertEqual(0xcccc, rule.pkeys.low) - self.assertEqual(0xdddd, rule.pkeys.high) - self.assertEqual("modified_change_level:object_r:system:s2:c0", added) - self.assertEqual("modified_change_level:object_r:system:s2:c1", removed) - - rule, added, removed = astuple(rules[1]) - self.assertEqual(IPv6Address("bbbb::"), rule.subnet_prefix) - self.assertEqual(0xf, rule.pkeys.low) - self.assertEqual(0xf, rule.pkeys.high) - self.assertEqual("modified_change_level:object_r:system:s2:c1", added) - self.assertEqual("modified_change_level:object_r:system:s2:c0.c1", removed) - - -class PolicyDifferenceRmIsidTest(unittest.TestCase): - - """ - Policy difference test for removed initial SID. - - Since initial SID names are fixed (they don't exist in the binary policy) - this cannot be in the above test suite. - """ - - @classmethod - def setUpClass(cls): - cls.p_left = compile_policy("tests/diff_left.conf") - cls.p_right = compile_policy("tests/diff_right_rmisid.conf") - cls.diff = PolicyDifference(cls.p_left, cls.p_right) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p_left.path) - os.unlink(cls.p_right.path) - - def test_removed_initialsids(self): - """Diff: removed initialsids.""" - self.assertSetEqual(set(["file"]), self.diff.removed_initialsids) - - -class PolicyDifferenceTestNoDiff(unittest.TestCase): - - """Policy difference test with no policy differences.""" - - @classmethod - def setUpClass(cls): - cls.p_left = compile_policy("tests/diff_left.conf") - cls.p_right = compile_policy("tests/diff_left.conf") - cls.diff = PolicyDifference(cls.p_left, cls.p_right) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p_left.path) - os.unlink(cls.p_right.path) - - def test_added_types(self): - """NoDiff: no added types""" - self.assertFalse(self.diff.added_types) - - def test_removed_types(self): - """NoDiff: no removed types""" - self.assertFalse(self.diff.removed_types) - - def test_modified_types(self): - """NoDiff: no modified types""" - self.assertFalse(self.diff.modified_types) - - def test_added_roles(self): - """NoDiff: no added roles.""" - self.assertFalse(self.diff.added_roles) - - def test_removed_roles(self): - """NoDiff: no removed roles.""" - self.assertFalse(self.diff.removed_roles) - - def test_modified_roles(self): - """NoDiff: no modified roles.""" - self.assertFalse(self.diff.modified_roles) - - def test_added_commons(self): - """NoDiff: no added commons.""" - self.assertFalse(self.diff.added_commons) - - def test_removed_commons(self): - """NoDiff: no removed commons.""" - self.assertFalse(self.diff.removed_commons) - - def test_modified_commons(self): - """NoDiff: no modified commons.""" - self.assertFalse(self.diff.modified_commons) - - def test_added_classes(self): - """NoDiff: no added classes.""" - self.assertFalse(self.diff.added_classes) - - def test_removed_classes(self): - """NoDiff: no removed classes.""" - self.assertFalse(self.diff.removed_classes) - - def test_modified_classes(self): - """NoDiff: no modified classes.""" - self.assertFalse(self.diff.modified_classes) - - def test_added_allows(self): - """NoDiff: no added allow rules.""" - self.assertFalse(self.diff.added_allows) - - def test_removed_allows(self): - """NoDiff: no removed allow rules.""" - self.assertFalse(self.diff.removed_allows) - - def test_modified_allows(self): - """NoDiff: no modified allow rules.""" - self.assertFalse(self.diff.modified_allows) - - def test_added_auditallows(self): - """NoDiff: no added auditallow rules.""" - self.assertFalse(self.diff.added_auditallows) - - def test_removed_auditallows(self): - """NoDiff: no removed auditallow rules.""" - self.assertFalse(self.diff.removed_auditallows) - - def test_modified_auditallows(self): - """NoDiff: no modified auditallow rules.""" - self.assertFalse(self.diff.modified_auditallows) - - def test_added_neverallows(self): - """NoDiff: no added neverallow rules.""" - self.assertFalse(self.diff.added_neverallows) - - def test_removed_neverallows(self): - """NoDiff: no removed neverallow rules.""" - self.assertFalse(self.diff.removed_neverallows) - - def test_modified_neverallows(self): - """NoDiff: no modified neverallow rules.""" - self.assertFalse(self.diff.modified_neverallows) - - def test_added_dontaudits(self): - """NoDiff: no added dontaudit rules.""" - self.assertFalse(self.diff.added_dontaudits) - - def test_removed_dontaudits(self): - """NoDiff: no removed dontaudit rules.""" - self.assertFalse(self.diff.removed_dontaudits) - - def test_modified_dontaudits(self): - """NoDiff: no modified dontaudit rules.""" - self.assertFalse(self.diff.modified_dontaudits) - - def test_added_type_transitions(self): - """NoDiff: no added type_transition rules.""" - self.assertFalse(self.diff.added_type_transitions) - - def test_removed_type_transitions(self): - """NoDiff: no removed type_transition rules.""" - self.assertFalse(self.diff.removed_type_transitions) - - def test_modified_type_transitions(self): - """NoDiff: no modified type_transition rules.""" - self.assertFalse(self.diff.modified_type_transitions) - - def test_added_type_changes(self): - """NoDiff: no added type_change rules.""" - self.assertFalse(self.diff.added_type_changes) - - def test_removed_type_changes(self): - """NoDiff: no removed type_change rules.""" - self.assertFalse(self.diff.removed_type_changes) - - def test_modified_type_changes(self): - """NoDiff: no modified type_change rules.""" - self.assertFalse(self.diff.modified_type_changes) - - def test_added_type_members(self): - """NoDiff: no added type_member rules.""" - self.assertFalse(self.diff.added_type_members) - - def test_removed_type_members(self): - """NoDiff: no removed type_member rules.""" - self.assertFalse(self.diff.removed_type_members) - - def test_modified_type_members(self): - """NoDiff: no modified type_member rules.""" - self.assertFalse(self.diff.modified_type_members) - - def test_added_range_transitions(self): - """NoDiff: no added range_transition rules.""" - self.assertFalse(self.diff.added_range_transitions) - - def test_removed_range_transitions(self): - """NoDiff: no removed range_transition rules.""" - self.assertFalse(self.diff.removed_range_transitions) - - def test_modified_range_transitions(self): - """NoDiff: no modified range_transition rules.""" - self.assertFalse(self.diff.modified_range_transitions) - - def test_added_role_allows(self): - """NoDiff: no added role_allow rules.""" - self.assertFalse(self.diff.added_role_allows) - - def test_removed_role_allows(self): - """NoDiff: no removed role_allow rules.""" - self.assertFalse(self.diff.removed_role_allows) - - def test_added_role_transitions(self): - """NoDiff: no added role_transition rules.""" - self.assertFalse(self.diff.added_role_transitions) - - def test_removed_role_transitions(self): - """NoDiff: no removed role_transition rules.""" - self.assertFalse(self.diff.removed_role_transitions) - - def test_modified_role_transitions(self): - """NoDiff: no modified role_transition rules.""" - self.assertFalse(self.diff.modified_role_transitions) - - def test_added_users(self): - """NoDiff: no added users.""" - self.assertFalse(self.diff.added_users) - - def test_removed_users(self): - """NoDiff: no removed users.""" - self.assertFalse(self.diff.removed_users) - - def test_modified_users(self): - """NoDiff: no modified user rules.""" - self.assertFalse(self.diff.modified_users) - - def test_added_type_attributes(self): - """NoDiff: no added type attribute.""" - self.assertFalse(self.diff.added_type_attributes) - - def test_removed_type_attributes(self): - """NoDiff: no removed type attributes.""" - self.assertFalse(self.diff.removed_type_attributes) - - def test_modified_type_attributes(self): - """NoDiff: no modified type attributes.""" - self.assertFalse(self.diff.modified_type_attributes) - - def test_added_booleans(self): - """NoDiff: no added booleans.""" - self.assertFalse(self.diff.added_booleans) - - def test_removed_booleans(self): - """NoDiff: no removed booleans.""" - self.assertFalse(self.diff.removed_booleans) - - def test_modified_booleans(self): - """NoDiff: no modified booleans.""" - self.assertFalse(self.diff.modified_booleans) - - def test_added_categories(self): - """NoDiff: no added categories.""" - self.assertFalse(self.diff.added_categories) - - def test_removed_categories(self): - """NoDiff: no removed categories.""" - self.assertFalse(self.diff.removed_categories) - - def test_modified_categories(self): - """NoDiff: no modified categories.""" - self.assertFalse(self.diff.modified_categories) - - def test_added_sensitivities(self): - """NoDiff: no added sensitivities.""" - self.assertFalse(self.diff.added_sensitivities) - - def test_removed_sensitivities(self): - """NoDiff: no removed sensitivities.""" - self.assertFalse(self.diff.removed_sensitivities) - - def test_modified_sensitivities(self): - """NoDiff: no modified sensitivities.""" - self.assertFalse(self.diff.modified_sensitivities) - - def test_added_initialsids(self): - """NoDiff: no added initialsids.""" - self.assertFalse(self.diff.added_initialsids) - - def test_removed_initialsids(self): - """NoDiff: no removed initialsids.""" - self.assertFalse(self.diff.removed_initialsids) - - def test_modified_initialsids(self): - """NoDiff: no modified initialsids.""" - self.assertFalse(self.diff.modified_initialsids) - - def test_added_fs_uses(self): - """NoDiff: no added fs_uses.""" - self.assertFalse(self.diff.added_fs_uses) - - def test_removed_fs_uses(self): - """NoDiff: no removed fs_uses.""" - self.assertFalse(self.diff.removed_fs_uses) - - def test_modified_fs_uses(self): - """NoDiff: no modified fs_uses.""" - self.assertFalse(self.diff.modified_fs_uses) - - def test_added_genfscons(self): - """NoDiff: no added genfscons.""" - self.assertFalse(self.diff.added_genfscons) - - def test_removed_genfscons(self): - """NoDiff: no removed genfscons.""" - self.assertFalse(self.diff.removed_genfscons) - - def test_modified_genfscons(self): - """NoDiff: no modified genfscons.""" - self.assertFalse(self.diff.modified_genfscons) - - def test_added_levels(self): - """NoDiff: no added levels.""" - self.assertFalse(self.diff.added_levels) - - def test_removed_levels(self): - """NoDiff: no removed levels.""" - self.assertFalse(self.diff.removed_levels) - - def test_modified_levels(self): - """NoDiff: no modified levels.""" - self.assertFalse(self.diff.modified_levels) - - def test_added_netifcons(self): - """NoDiff: no added netifcons.""" - self.assertFalse(self.diff.added_netifcons) - - def test_removed_netifcons(self): - """NoDiff: no removed netifcons.""" - self.assertFalse(self.diff.removed_netifcons) - - def test_modified_netifcons(self): - """NoDiff: no modified netifcons.""" - self.assertFalse(self.diff.modified_netifcons) - - def test_added_nodecons(self): - """NoDiff: no added nodecons.""" - self.assertFalse(self.diff.added_nodecons) - - def test_removed_nodecons(self): - """NoDiff: no removed nodecons.""" - self.assertFalse(self.diff.removed_nodecons) - - def test_modified_nodecons(self): - """NoDiff: no modified nodecons.""" - self.assertFalse(self.diff.modified_nodecons) - - def test_added_polcaps(self): - """NoDiff: no added polcaps.""" - self.assertFalse(self.diff.added_polcaps) - - def test_removed_polcaps(self): - """NoDiff: no removed polcaps.""" - self.assertFalse(self.diff.removed_polcaps) - - def test_added_portcons(self): - """NoDiff: no added portcons.""" - self.assertFalse(self.diff.added_portcons) - - def test_removed_portcons(self): - """NoDiff: no removed portcons.""" - self.assertFalse(self.diff.removed_portcons) - - def test_modified_portcons(self): - """NoDiff: no modified portcons.""" - self.assertFalse(self.diff.modified_portcons) - - def test_modified_properties(self): - """NoDiff: no modified properties.""" - self.assertFalse(self.diff.modified_properties) - - def test_added_defaults(self): - """NoDiff: no added defaults.""" - self.assertFalse(self.diff.added_defaults) - - def test_removed_defaults(self): - """NoDiff: no removed defaults.""" - self.assertFalse(self.diff.removed_defaults) - - def test_modified_defaults(self): - """NoDiff: no modified defaults.""" - self.assertFalse(self.diff.modified_defaults) - - def test_added_constrains(self): - """NoDiff: no added constrains.""" - self.assertFalse(self.diff.added_constrains) - - def test_removed_constrains(self): - """NoDiff: no removed constrains.""" - self.assertFalse(self.diff.removed_constrains) - - def test_added_mlsconstrains(self): - """NoDiff: no added mlsconstrains.""" - self.assertFalse(self.diff.added_mlsconstrains) - - def test_removed_mlsconstrains(self): - """NoDiff: no removed mlsconstrains.""" - self.assertFalse(self.diff.removed_mlsconstrains) - - def test_added_validatetrans(self): - """NoDiff: no added validatetrans.""" - self.assertFalse(self.diff.added_validatetrans) - - def test_removed_validatetrans(self): - """NoDiff: no removed validatetrans.""" - self.assertFalse(self.diff.removed_validatetrans) - - def test_added_mlsvalidatetrans(self): - """NoDiff: no added mlsvalidatetrans.""" - self.assertFalse(self.diff.added_mlsvalidatetrans) - - def test_removed_mlsvalidatetrans(self): - """NoDiff: no removed mlsvalidatetrans.""" - self.assertFalse(self.diff.removed_mlsvalidatetrans) - - def test_added_typebounds(self): - """NoDiff: no added typebounds.""" - self.assertFalse(self.diff.added_typebounds) - - def test_removed_typebounds(self): - """NoDiff: no removed typebounds.""" - self.assertFalse(self.diff.removed_typebounds) - - def test_modified_typebounds(self): - """NoDiff: no modified typebounds.""" - self.assertFalse(self.diff.modified_typebounds) - - def test_added_allowxperms(self): - """NoDiff: no added allowxperm rules.""" - self.assertFalse(self.diff.added_allowxperms) - - def test_removed_allowxperms(self): - """NoDiff: no removed allowxperm rules.""" - self.assertFalse(self.diff.removed_allowxperms) - - def test_modified_allowxperms(self): - """NoDiff: no modified allowxperm rules.""" - self.assertFalse(self.diff.modified_allowxperms) - - def test_added_auditallowxperms(self): - """NoDiff: no added auditallowxperm rules.""" - self.assertFalse(self.diff.added_auditallowxperms) - - def test_removed_auditallowxperms(self): - """NoDiff: no removed auditallowxperm rules.""" - self.assertFalse(self.diff.removed_auditallowxperms) - - def test_modified_auditallowxperms(self): - """NoDiff: no modified auditallowxperm rules.""" - self.assertFalse(self.diff.modified_auditallowxperms) - - def test_added_neverallowxperms(self): - """NoDiff: no added neverallowxperm rules.""" - self.assertFalse(self.diff.added_neverallowxperms) - - def test_removed_neverallowxperms(self): - """NoDiff: no removed neverallowxperm rules.""" - self.assertFalse(self.diff.removed_neverallowxperms) - - def test_modified_neverallowxperms(self): - """NoDiff: no modified neverallowxperm rules.""" - self.assertFalse(self.diff.modified_neverallowxperms) - - def test_added_dontauditxperms(self): - """NoDiff: no added dontauditxperm rules.""" - self.assertFalse(self.diff.added_dontauditxperms) - - def test_removed_dontauditxperms(self): - """NoDiff: no removed dontauditxperm rules.""" - self.assertFalse(self.diff.removed_dontauditxperms) - - def test_modified_dontauditxperms(self): - """NoDiff: no modified dontauditxperm rules.""" - self.assertFalse(self.diff.modified_dontauditxperms) - - def test_added_ibendportcons(self): - """NoDiff: no added ibendportcon rules.""" - self.assertFalse(self.diff.added_ibendportcons) - - def test_removed_ibendportcons(self): - """NoDiff: no removed ibendportcon rules.""" - self.assertFalse(self.diff.removed_ibendportcons) - - def test_modified_ibendportcons(self): - """NoDiff: no modified ibendportcon rules.""" - self.assertFalse(self.diff.modified_ibendportcons) - - def test_added_ibpkeycons(self): - """NoDiff: no added ibpkeycon rules.""" - self.assertFalse(self.diff.added_ibpkeycons) - - def test_removed_ibpkeycons(self): - """NoDiff: no removed ibpkeycon rules.""" - self.assertFalse(self.diff.removed_ibpkeycons) - - def test_modified_ibpkeycons(self): - """NoDiff: no modified ibpkeycon rules.""" - self.assertFalse(self.diff.modified_ibpkeycons) - - -class PolicyDifferenceTestMLStoStandard(unittest.TestCase): - - """ - Policy difference test between MLS and standard (non-MLS) policy. - - The left policy is an MLS policy. The right policy is identical to the - left policy, except with MLS disabled. - """ - - @classmethod - def setUpClass(cls): - cls.p_left = compile_policy("tests/diff_left.conf") - cls.p_right = compile_policy("tests/diff_left_standard.conf", mls=False) - cls.diff = PolicyDifference(cls.p_left, cls.p_right) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p_left.path) - os.unlink(cls.p_right.path) - - def test_added_types(self): - """MLSvsStandardDiff: no added types""" - self.assertFalse(self.diff.added_types) - - def test_removed_types(self): - """MLSvsStandardDiff: no removed types""" - self.assertFalse(self.diff.removed_types) - - def test_modified_types(self): - """MLSvsStandardDiff: no modified types""" - self.assertFalse(self.diff.modified_types) - - def test_added_roles(self): - """MLSvsStandardDiff: no added roles.""" - self.assertFalse(self.diff.added_roles) - - def test_removed_roles(self): - """MLSvsStandardDiff: no removed roles.""" - self.assertFalse(self.diff.removed_roles) - - def test_modified_roles(self): - """MLSvsStandardDiff: no modified roles.""" - self.assertFalse(self.diff.modified_roles) - - def test_added_commons(self): - """MLSvsStandardDiff: no added commons.""" - self.assertFalse(self.diff.added_commons) - - def test_removed_commons(self): - """MLSvsStandardDiff: no removed commons.""" - self.assertFalse(self.diff.removed_commons) - - def test_modified_commons(self): - """MLSvsStandardDiff: no modified commons.""" - self.assertFalse(self.diff.modified_commons) - - def test_added_classes(self): - """MLSvsStandardDiff: no added classes.""" - self.assertFalse(self.diff.added_classes) - - def test_removed_classes(self): - """MLSvsStandardDiff: no removed classes.""" - self.assertFalse(self.diff.removed_classes) - - def test_modified_classes(self): - """MLSvsStandardDiff: no modified classes.""" - self.assertFalse(self.diff.modified_classes) - - def test_added_allows(self): - """MLSvsStandardDiff: no added allow rules.""" - self.assertFalse(self.diff.added_allows) - - def test_removed_allows(self): - """MLSvsStandardDiff: no removed allow rules.""" - self.assertFalse(self.diff.removed_allows) - - def test_modified_allows(self): - """MLSvsStandardDiff: no modified allow rules.""" - self.assertFalse(self.diff.modified_allows) - - def test_added_auditallows(self): - """MLSvsStandardDiff: no added auditallow rules.""" - self.assertFalse(self.diff.added_auditallows) - - def test_removed_auditallows(self): - """MLSvsStandardDiff: no removed auditallow rules.""" - self.assertFalse(self.diff.removed_auditallows) - - def test_modified_auditallows(self): - """MLSvsStandardDiff: no modified auditallow rules.""" - self.assertFalse(self.diff.modified_auditallows) - - def test_added_neverallows(self): - """MLSvsStandardDiff: no added neverallow rules.""" - self.assertFalse(self.diff.added_neverallows) - - def test_removed_neverallows(self): - """MLSvsStandardDiff: no removed neverallow rules.""" - self.assertFalse(self.diff.removed_neverallows) - - def test_modified_neverallows(self): - """MLSvsStandardDiff: no modified neverallow rules.""" - self.assertFalse(self.diff.modified_neverallows) - - def test_added_dontaudits(self): - """MLSvsStandardDiff: no added dontaudit rules.""" - self.assertFalse(self.diff.added_dontaudits) - - def test_removed_dontaudits(self): - """MLSvsStandardDiff: no removed dontaudit rules.""" - self.assertFalse(self.diff.removed_dontaudits) - - def test_modified_dontaudits(self): - """MLSvsStandardDiff: no modified dontaudit rules.""" - self.assertFalse(self.diff.modified_dontaudits) - - def test_added_type_transitions(self): - """MLSvsStandardDiff: no added type_transition rules.""" - self.assertFalse(self.diff.added_type_transitions) - - def test_removed_type_transitions(self): - """MLSvsStandardDiff: no removed type_transition rules.""" - self.assertFalse(self.diff.removed_type_transitions) - - def test_modified_type_transitions(self): - """MLSvsStandardDiff: no modified type_transition rules.""" - self.assertFalse(self.diff.modified_type_transitions) - - def test_added_type_changes(self): - """MLSvsStandardDiff: no added type_change rules.""" - self.assertFalse(self.diff.added_type_changes) - - def test_removed_type_changes(self): - """MLSvsStandardDiff: no removed type_change rules.""" - self.assertFalse(self.diff.removed_type_changes) - - def test_modified_type_changes(self): - """MLSvsStandardDiff: no modified type_change rules.""" - self.assertFalse(self.diff.modified_type_changes) - - def test_added_type_members(self): - """MLSvsStandardDiff: no added type_member rules.""" - self.assertFalse(self.diff.added_type_members) - - def test_removed_type_members(self): - """MLSvsStandardDiff: no removed type_member rules.""" - self.assertFalse(self.diff.removed_type_members) - - def test_modified_type_members(self): - """MLSvsStandardDiff: no modified type_member rules.""" - self.assertFalse(self.diff.modified_type_members) - - def test_added_range_transitions(self): - """MLSvsStandardDiff: no added range_transition rules.""" - self.assertFalse(self.diff.added_range_transitions) - - def test_removed_range_transitions(self): - """MLSvsStandardDiff: all range_transition rules removed.""" - self.assertEqual(self.diff.left_policy.range_transition_count, - len(self.diff.removed_range_transitions)) - - def test_modified_range_transitions(self): - """MLSvsStandardDiff: no modified range_transition rules.""" - self.assertFalse(self.diff.modified_range_transitions) - - def test_added_role_allows(self): - """MLSvsStandardDiff: no added role_allow rules.""" - self.assertFalse(self.diff.added_role_allows) - - def test_removed_role_allows(self): - """MLSvsStandardDiff: no removed role_allow rules.""" - self.assertFalse(self.diff.removed_role_allows) - - def test_added_role_transitions(self): - """MLSvsStandardDiff: no added role_transition rules.""" - self.assertFalse(self.diff.added_role_transitions) - - def test_removed_role_transitions(self): - """MLSvsStandardDiff: no removed role_transition rules.""" - self.assertFalse(self.diff.removed_role_transitions) - - def test_modified_role_transitions(self): - """MLSvsStandardDiff: no modified role_transition rules.""" - self.assertFalse(self.diff.modified_role_transitions) - - def test_added_users(self): - """MLSvsStandardDiff: no added users.""" - self.assertFalse(self.diff.added_users) - - def test_removed_users(self): - """MLSvsStandardDiff: no removed users.""" - self.assertFalse(self.diff.removed_users) - - def test_modified_users(self): - """MLSvsStandardDiff: all users modified.""" - self.assertEqual(self.diff.left_policy.user_count, len(self.diff.modified_users)) - - def test_added_type_attributes(self): - """MLSvsStandardDiff: no added type attribute.""" - self.assertFalse(self.diff.added_type_attributes) - - def test_removed_type_attributes(self): - """MLSvsStandardDiff: no removed type attributes.""" - self.assertFalse(self.diff.removed_type_attributes) - - def test_modified_type_attributes(self): - """MLSvsStandardDiff: no modified type attributes.""" - self.assertFalse(self.diff.modified_type_attributes) - - def test_added_booleans(self): - """MLSvsStandardDiff: no added booleans.""" - self.assertFalse(self.diff.added_booleans) - - def test_removed_booleans(self): - """MLSvsStandardDiff: no removed booleans.""" - self.assertFalse(self.diff.removed_booleans) - - def test_modified_booleans(self): - """MLSvsStandardDiff: no modified booleans.""" - self.assertFalse(self.diff.modified_booleans) - - def test_added_categories(self): - """MLSvsStandardDiff: no added categories.""" - self.assertFalse(self.diff.added_categories) - - def test_removed_categories(self): - """MLSvsStandardDiff: all categories removed.""" - self.assertEqual(self.diff.left_policy.category_count, len(self.diff.removed_categories)) - - def test_modified_categories(self): - """MLSvsStandardDiff: no modified categories.""" - self.assertFalse(self.diff.modified_categories) - - def test_added_sensitivities(self): - """MLSvsStandardDiff: no added sensitivities.""" - self.assertFalse(self.diff.added_sensitivities) - - def test_removed_sensitivities(self): - """MLSvsStandardDiff: all sensitivities removed.""" - self.assertEqual(self.diff.left_policy.level_count, len(self.diff.removed_sensitivities)) - - def test_modified_sensitivities(self): - """MLSvsStandardDiff: no modified sensitivities.""" - self.assertFalse(self.diff.modified_sensitivities) - - def test_added_initialsids(self): - """MLSvsStandardDiff: no added initialsids.""" - self.assertFalse(self.diff.added_initialsids) - - def test_removed_initialsids(self): - """MLSvsStandardDiff: no removed initialsids.""" - self.assertFalse(self.diff.removed_initialsids) - - def test_modified_initialsids(self): - """MLSvsStandardDiff: all initialsids modified.""" - self.assertEqual(self.diff.left_policy.initialsids_count, - len(self.diff.modified_initialsids)) - - def test_added_fs_uses(self): - """MLSvsStandardDiff: no added fs_uses.""" - self.assertFalse(self.diff.added_fs_uses) - - def test_removed_fs_uses(self): - """MLSvsStandardDiff: no removed fs_uses.""" - self.assertFalse(self.diff.removed_fs_uses) - - def test_modified_fs_uses(self): - """MLSvsStandardDiff: all fs_uses modified.""" - self.assertEqual(self.diff.left_policy.fs_use_count, len(self.diff.modified_fs_uses)) - - def test_added_genfscons(self): - """MLSvsStandardDiff: no added genfscons.""" - self.assertFalse(self.diff.added_genfscons) - - def test_removed_genfscons(self): - """MLSvsStandardDiff: no removed genfscons.""" - self.assertFalse(self.diff.removed_genfscons) - - def test_modified_genfscons(self): - """MLSvsStandardDiff: all genfscons modified.""" - self.assertEqual(self.diff.left_policy.genfscon_count, len(self.diff.modified_genfscons)) - - def test_added_levels(self): - """MLSvsStandardDiff: no added levels.""" - self.assertFalse(self.diff.added_levels) - - def test_removed_levels(self): - """MLSvsStandardDiff: all levels removed.""" - self.assertEqual(self.diff.left_policy.level_count, len(self.diff.removed_levels)) - - def test_modified_levels(self): - """MLSvsStandardDiff: no modified levels.""" - self.assertFalse(self.diff.modified_levels) - - def test_added_netifcons(self): - """MLSvsStandardDiff: no added netifcons.""" - self.assertFalse(self.diff.added_netifcons) - - def test_removed_netifcons(self): - """MLSvsStandardDiff: no removed netifcons.""" - self.assertFalse(self.diff.removed_netifcons) - - def test_modified_netifcons(self): - """MLSvsStandardDiff: all netifcons modified.""" - self.assertEqual(self.diff.left_policy.netifcon_count, len(self.diff.modified_netifcons)) - - def test_added_nodecons(self): - """MLSvsStandardDiff: no added nodecons.""" - self.assertFalse(self.diff.added_nodecons) - - def test_removed_nodecons(self): - """MLSvsStandardDiff: no removed nodecons.""" - self.assertFalse(self.diff.removed_nodecons) - - def test_modified_nodecons(self): - """MLSvsStandardDiff: all nodecons modified.""" - self.assertEqual(self.diff.left_policy.nodecon_count, len(self.diff.modified_nodecons)) - - def test_added_polcaps(self): - """MLSvsStandardDiff: no added polcaps.""" - self.assertFalse(self.diff.added_polcaps) - - def test_removed_polcaps(self): - """MLSvsStandardDiff: no removed polcaps.""" - self.assertFalse(self.diff.removed_polcaps) - - def test_added_portcons(self): - """MLSvsStandardDiff: no added portcons.""" - self.assertFalse(self.diff.added_portcons) - - def test_removed_portcons(self): - """MLSvsStandardDiff: no removed portcons.""" - self.assertFalse(self.diff.removed_portcons) - - def test_modified_portcons(self): - """MLSvsStandardDiff: all portcons modified.""" - self.assertEqual(self.diff.left_policy.portcon_count, len(self.diff.modified_portcons)) - - def test_modified_properties(self): - """MLSvsStandardDiff: MLS property modified only.""" - self.assertEqual(1, len(self.diff.modified_properties)) - - name, added, removed = astuple(self.diff.modified_properties[0]) - self.assertEqual("MLS", name) - self.assertIs(False, added) - self.assertIs(True, removed) - - def test_added_defaults(self): - """MLSvsStandardDiff: no added defaults.""" - self.assertFalse(self.diff.added_defaults) - - def test_removed_defaults(self): - """MLSvsStandardDiff: all default_range removed.""" - self.assertEqual( - sum(1 for d in self.diff.left_policy.defaults() if d.ruletype == DRT.default_range), - len(self.diff.removed_defaults)) - - def test_modified_defaults(self): - """MLSvsStandardDiff: no defaults modified.""" - self.assertFalse(self.diff.modified_defaults) - - def test_added_constraints(self): - """MLSvsStandardDiff: no added constraints.""" - self.assertFalse(self.diff.added_constrains) - - def test_removed_constraints(self): - """MLSvsStandardDiff: no removed constraints.""" - self.assertFalse(self.diff.removed_constrains) - - def test_added_validatetrans(self): - """MLSvsStandardDiff: no added validatetrans.""" - self.assertFalse(self.diff.added_validatetrans) - - def test_removed_validatetrans(self): - """MLSvsStandardDiff: no removed validatetrans.""" - self.assertFalse(self.diff.removed_validatetrans) - - def test_added_mlsconstraints(self): - """MLSvsStandardDiff: no added mlsconstraints.""" - self.assertFalse(self.diff.added_mlsconstrains) - - def test_removed_mlsconstraints(self): - """MLSvsStandardDiff: all mlsconstraints removed.""" - self.assertEqual( - sum(1 for m in self.diff.left_policy.constraints() if m.ruletype == CRT.mlsconstrain), - len(self.diff.removed_mlsconstrains)) - - def test_added_mlsvalidatetrans(self): - """MLSvsStandardDiff: no added mlsvalidatetrans.""" - self.assertFalse(self.diff.added_mlsvalidatetrans) - - def test_removed_mlsvalidatetrans(self): - """MLSvsStandardDiff: all mlsvalidatetrans removed.""" - self.assertEqual( - sum(1 for m in self.diff.left_policy.constraints() - if m.ruletype == CRT.mlsvalidatetrans), - len(self.diff.removed_mlsvalidatetrans)) - - def test_added_typebounds(self): - """MLSvsStandardDiff: no added typebounds.""" - self.assertFalse(self.diff.added_typebounds) - - def test_removed_typebounds(self): - """MLSvsStandardDiff: no removed typebounds.""" - self.assertFalse(self.diff.removed_typebounds) - - def test_modified_typebounds(self): - """MLSvsStandardDiff: no modified typebounds.""" - self.assertFalse(self.diff.modified_typebounds) - - def test_added_allowxperms(self): - """NoDiff: no added allowxperm rules.""" - self.assertFalse(self.diff.added_allowxperms) - - def test_removed_allowxperms(self): - """NoDiff: no removed allowxperm rules.""" - self.assertFalse(self.diff.removed_allowxperms) - - def test_modified_allowxperms(self): - """NoDiff: no modified allowxperm rules.""" - self.assertFalse(self.diff.modified_allowxperms) - - def test_added_auditallowxperms(self): - """NoDiff: no added auditallowxperm rules.""" - self.assertFalse(self.diff.added_auditallowxperms) - - def test_removed_auditallowxperms(self): - """NoDiff: no removed auditallowxperm rules.""" - self.assertFalse(self.diff.removed_auditallowxperms) - - def test_modified_auditallowxperms(self): - """NoDiff: no modified auditallowxperm rules.""" - self.assertFalse(self.diff.modified_auditallowxperms) - - def test_added_neverallowxperms(self): - """NoDiff: no added neverallowxperm rules.""" - self.assertFalse(self.diff.added_neverallowxperms) - - def test_removed_neverallowxperms(self): - """NoDiff: no removed neverallowxperm rules.""" - self.assertFalse(self.diff.removed_neverallowxperms) - - def test_modified_neverallowxperms(self): - """NoDiff: no modified neverallowxperm rules.""" - self.assertFalse(self.diff.modified_neverallowxperms) - - def test_added_dontauditxperms(self): - """NoDiff: no added dontauditxperm rules.""" - self.assertFalse(self.diff.added_dontauditxperms) - - def test_removed_dontauditxperms(self): - """NoDiff: no removed dontauditxperm rules.""" - self.assertFalse(self.diff.removed_dontauditxperms) - - def test_modified_dontauditxperms(self): - """NoDiff: no modified dontauditxperm rules.""" - self.assertFalse(self.diff.modified_dontauditxperms) - - def test_added_ibpkeycons(self): - """NoDiff: no added ibpkeycon rules.""" - self.assertFalse(self.diff.added_ibpkeycons) - - def test_removed_ibpkeycons(self): - """NoDiff: no removed ibpkeycon rules.""" - self.assertFalse(self.diff.removed_ibpkeycons) - - def test_modified_ibpkeycons(self): - """NoDiff: no modified ibpkeycon rules.""" - self.assertEqual(self.diff.left_policy.ibpkeycon_count, - len(self.diff.modified_ibpkeycons)) - - def test_added_ibendportcons(self): - """NoDiff: no added ibendportcon rules.""" - self.assertFalse(self.diff.added_ibendportcons) - - def test_removed_ibendportcons(self): - """NoDiff: no removed ibendportcon rules.""" - self.assertFalse(self.diff.removed_ibendportcons) - - def test_modified_ibendportcons(self): - """NoDiff: no modified ibendportcon rules.""" - self.assertEqual(self.diff.left_policy.ibendportcon_count, - len(self.diff.modified_ibendportcons)) - - -class PolicyDifferenceTestRedundant(unittest.TestCase): - - """ - Policy difference test with redundant rules. - There should be no policy differences. - """ - - @classmethod - def setUpClass(cls): - cls.p_left = compile_policy("tests/diff_left.conf") - cls.p_right = compile_policy("tests/diff_left_redundant.conf") - cls.diff = PolicyDifference(cls.p_left, cls.p_right) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p_left.path) - os.unlink(cls.p_right.path) - - def test_added_allows(self): - """Redundant: no added allow rules.""" - self.assertFalse(self.diff.added_allows) - - def test_removed_allows(self): - """Redundant: no removed allow rules.""" - self.assertFalse(self.diff.removed_allows) - - def test_modified_allows(self): - """Redundant: no modified allow rules.""" - self.assertFalse(self.diff.modified_allows) diff --git a/tests/test_dta.py b/tests/test_dta.py deleted file mode 100644 index 2398b3f8..00000000 --- a/tests/test_dta.py +++ /dev/null @@ -1,882 +0,0 @@ -# Copyright 2014-2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import DomainTransitionAnalysis -from setools import TERuletype as TERT -from setools.exception import InvalidType -from setools.policyrep import Type - -from . import mixins -from .policyrep.util import compile_policy - - -class DomainTransitionAnalysisTest(mixins.ValidateRule, unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/dta.conf") - cls.a = DomainTransitionAnalysis(cls.p) - cls.a._build_graph() - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_graph_structure(self): - """DTA: verify graph structure.""" - # don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - start = self.p.lookup_type("start") - trans1 = self.p.lookup_type("trans1") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.G.out_edges()) - self.assertSetEqual(set([(dyntrans100, bothtrans200), - (start, dyntrans100), - (start, trans1), - (trans1, trans2), - (trans2, trans3), - (trans3, trans5)]), edges) - - def test_001_bothtrans(self): - """DTA: type_transition, setexeccon(), and setcon() transitions.""" - - s = self.p.lookup_type("dyntrans100") - t = self.p.lookup_type("bothtrans200") - e = self.p.lookup_type("bothtrans200_exec") - - # regular transition - r = self.a.G.edges[s, t]["transition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition", "dyntransition"])) - - # setexec perms - r = self.a.G.edges[s, t]["setexec"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec", "setcurrent"])) - - # exec perms - k = sorted(self.a.G.edges[s, t]["execute"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["execute"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) - - # entrypoint perms - k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["entrypoint"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) - - # type_transition - k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["type_transition"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.type_transition, s, e, "process", t) - - # dynamic transition - r = self.a.G.edges[s, t]["dyntransition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition", "dyntransition"])) - - # setcurrent - r = self.a.G.edges[s, t]["setcurrent"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec", "setcurrent"])) - - def test_010_dyntrans(self): - """DTA: setcon() transition.""" - - s = self.p.lookup_type("start") - t = self.p.lookup_type("dyntrans100") - - # regular transition - r = self.a.G.edges[s, t]["transition"] - self.assertEqual(len(r), 0) - - # setexec perms - r = self.a.G.edges[s, t]["setexec"] - self.assertEqual(len(r), 0) - - # exec perms - k = sorted(self.a.G.edges[s, t]["execute"].keys()) - self.assertEqual(len(k), 0) - - # entrypoint perms - k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) - self.assertEqual(len(k), 0) - - # type_transition - k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) - self.assertEqual(len(k), 0) - - # dynamic transition - r = self.a.G.edges[s, t]["dyntransition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["dyntransition"])) - - # setcurrent - r = self.a.G.edges[s, t]["setcurrent"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setcurrent"])) - - def test_020_trans(self): - """DTA: type_transition transition.""" - - s = self.p.lookup_type("start") - t = self.p.lookup_type("trans1") - e = self.p.lookup_type("trans1_exec") - - # regular transition - r = self.a.G.edges[s, t]["transition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) - - # setexec perms - r = self.a.G.edges[s, t]["setexec"] - self.assertEqual(len(r), 0) - - # exec perms - k = sorted(self.a.G.edges[s, t]["execute"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["execute"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) - - # entrypoint perms - k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["entrypoint"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) - - # type_transition - k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["type_transition"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.type_transition, s, e, "process", t) - - # dynamic transition - r = self.a.G.edges[s, t]["dyntransition"] - self.assertEqual(len(r), 0) - - # setcurrent - r = self.a.G.edges[s, t]["setcurrent"] - self.assertEqual(len(r), 0) - - def test_030_setexec(self): - """DTA: setexec() transition.""" - - s = self.p.lookup_type("trans1") - t = self.p.lookup_type("trans2") - e = self.p.lookup_type("trans2_exec") - - # regular transition - r = self.a.G.edges[s, t]["transition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) - - # setexec perms - r = self.a.G.edges[s, t]["setexec"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec"])) - - # exec perms - k = sorted(self.a.G.edges[s, t]["execute"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["execute"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) - - # entrypoint perms - k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["entrypoint"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) - - # type_transition - k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) - self.assertEqual(len(k), 0) - - # dynamic transition - r = self.a.G.edges[s, t]["dyntransition"] - self.assertEqual(len(r), 0) - - # setcurrent - r = self.a.G.edges[s, t]["setcurrent"] - self.assertEqual(len(r), 0) - - def test_040_two_entrypoint(self): - """DTA: 2 entrypoints, only one by type_transition.""" - - s = self.p.lookup_type("trans2") - t = self.p.lookup_type("trans3") - e = [self.p.lookup_type("trans3_exec1"), self.p.lookup_type("trans3_exec2")] - - # regular transition - r = self.a.G.edges[s, t]["transition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) - - # setexec perms - r = self.a.G.edges[s, t]["setexec"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, s, "process", set(["setexec"])) - - # exec perms - k = sorted(self.a.G.edges[s, t]["execute"].keys()) - self.assertEqual(k, e) - - r = self.a.G.edges[s, t]["execute"][e[0]] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, e[0], "file", set(["execute"])) - - r = self.a.G.edges[s, t]["execute"][e[1]] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, e[1], "file", set(["execute"])) - - # entrypoint perms - k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) - self.assertEqual(k, e) - - r = self.a.G.edges[s, t]["entrypoint"][e[0]] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, t, e[0], "file", set(["entrypoint"])) - - r = self.a.G.edges[s, t]["entrypoint"][e[1]] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, t, e[1], "file", set(["entrypoint"])) - - # type_transition - k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) - self.assertEqual(k, [e[0]]) - - r = self.a.G.edges[s, t]["type_transition"][e[0]] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.type_transition, s, e[0], "process", t) - - # dynamic transition - r = self.a.G.edges[s, t]["dyntransition"] - self.assertEqual(len(r), 0) - - # setcurrent - r = self.a.G.edges[s, t]["setcurrent"] - self.assertEqual(len(r), 0) - - def test_050_cond_type_trans(self): - """DTA: conditional type_transition.""" - - s = self.p.lookup_type("trans3") - t = self.p.lookup_type("trans5") - e = self.p.lookup_type("trans5_exec") - - # regular transition - r = self.a.G.edges[s, t]["transition"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, t, "process", set(["transition"])) - - # setexec perms - r = self.a.G.edges[s, t]["setexec"] - self.assertEqual(len(r), 0) - - # exec perms - k = sorted(self.a.G.edges[s, t]["execute"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["execute"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, s, e, "file", set(["execute"])) - - # entrypoint perms - k = sorted(self.a.G.edges[s, t]["entrypoint"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["entrypoint"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, t, e, "file", set(["entrypoint"])) - - # type_transition - k = sorted(self.a.G.edges[s, t]["type_transition"].keys()) - self.assertEqual(k, [e]) - - r = self.a.G.edges[s, t]["type_transition"][e] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.type_transition, s, e, "process", t, cond="trans5") - - # dynamic transition - r = self.a.G.edges[s, t]["dyntransition"] - self.assertEqual(len(r), 0) - - # setcurrent - r = self.a.G.edges[s, t]["setcurrent"] - self.assertEqual(len(r), 0) - - def test_100_forward_subgraph_structure(self): - """DTA: verify forward subgraph structure.""" - # The purpose is to ensure the subgraph is reversed - # only when the reverse option is set, not that - # graph reversal is correct (assumed that NetworkX - # does it correctly). - # Don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - self.a.reverse = False - self.a._build_subgraph() - - start = self.p.lookup_type("start") - trans1 = self.p.lookup_type("trans1") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(dyntrans100, bothtrans200), - (start, dyntrans100), - (start, trans1), - (trans1, trans2), - (trans2, trans3), - (trans3, trans5)]), edges) - - def test_101_reverse_subgraph_structure(self): - """DTA: verify reverse subgraph structure.""" - # The purpose is to ensure the subgraph is reversed - # only when the reverse option is set, not that - # graph reversal is correct (assumed that NetworkX - # does it correctly). - # Don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - self.a.reverse = True - self.a._build_subgraph() - - start = self.p.lookup_type("start") - trans1 = self.p.lookup_type("trans1") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(bothtrans200, dyntrans100), - (dyntrans100, start), - (trans1, start), - (trans2, trans1), - (trans3, trans2), - (trans5, trans3)]), edges) - - def test_200_exclude_domain(self): - """DTA: exclude domain type.""" - # Don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - self.a.reverse = False - self.a.exclude = ["trans1"] - self.a._build_subgraph() - - start = self.p.lookup_type("start") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(dyntrans100, bothtrans200), - (start, dyntrans100), - (trans2, trans3), - (trans3, trans5)]), edges) - - def test_201_exclude_entryoint_with_2entrypoints(self): - """DTA: exclude entrypoint type without transition deletion (other entrypoints).""" - # Don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - self.a.reverse = False - self.a.exclude = ["trans3_exec1"] - self.a._build_subgraph() - - start = self.p.lookup_type("start") - trans1 = self.p.lookup_type("trans1") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(dyntrans100, bothtrans200), - (start, dyntrans100), - (start, trans1), - (trans1, trans2), - (trans2, trans3), - (trans3, trans5)]), edges) - - def test_202_exclude_entryoint_with_dyntrans(self): - """DTA: exclude entrypoint type without transition deletion (dyntrans).""" - # Don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - self.a.reverse = False - self.a.exclude = ["bothtrans200_exec"] - self.a._build_subgraph() - - start = self.p.lookup_type("start") - trans1 = self.p.lookup_type("trans1") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(dyntrans100, bothtrans200), - (start, dyntrans100), - (start, trans1), - (trans1, trans2), - (trans2, trans3), - (trans3, trans5)]), edges) - - def test_203_exclude_entryoint_delete_transition(self): - """DTA: exclude entrypoint type with transition deletion.""" - # Don't check node list since the disconnected nodes are not - # removed after removing invalid domain transitions - - self.a.reverse = False - self.a.exclude = ["trans2_exec"] - self.a._build_subgraph() - - start = self.p.lookup_type("start") - trans1 = self.p.lookup_type("trans1") - trans2 = self.p.lookup_type("trans2") - trans3 = self.p.lookup_type("trans3") - trans5 = self.p.lookup_type("trans5") - dyntrans100 = self.p.lookup_type("dyntrans100") - bothtrans200 = self.p.lookup_type("bothtrans200") - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(dyntrans100, bothtrans200), - (start, dyntrans100), - (start, trans1), - (trans2, trans3), - (trans3, trans5)]), edges) - - def test_300_all_paths(self): - """DTA: all paths output""" - self.a.reverse = False - self.a.exclude = None - self.a.source = "start" - self.a.target = "bothtrans200" - self.a.depth_limit = 3 - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - - expected_path = ["start", "dyntrans100", "bothtrans200"] - - paths = list(self.a.results()) - self.assertEqual(1, len(paths)) - - for path in paths: - for stepnum, step in enumerate(path): - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(expected_path[stepnum], step.source) - self.assertEqual(expected_path[stepnum + 1], step.target) - - for r in step.transition: - self.assertIn("transition", r.perms) - - for e in step.entrypoints: - self.assertIsInstance(e.name, Type) - - for r in e.entrypoint: - self.assertIn("entrypoint", r.perms) - - for r in e.execute: - self.assertIn("execute", r.perms) - - for r in e.type_transition: - self.assertEqual(TERT.type_transition, r.ruletype) - - for r in step.setexec: - self.assertIn("setexec", r.perms) - - for r in step.dyntransition: - self.assertIn("dyntransition", r.perms) - - for r in step.setcurrent: - self.assertIn("setcurrent", r.perms) - - def test_301_all_shortest_paths(self): - """DTA: all shortest paths output""" - self.a.reverse = False - self.a.exclude = None - self.a.source = "start" - self.a.target = "bothtrans200" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - - expected_path = ["start", "dyntrans100", "bothtrans200"] - - paths = list(self.a.results()) - self.assertEqual(1, len(paths)) - - for path in paths: - for stepnum, step in enumerate(path): - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(expected_path[stepnum], step.source) - self.assertEqual(expected_path[stepnum + 1], step.target) - - for r in step.transition: - self.assertIn("transition", r.perms) - - for e in step.entrypoints: - self.assertIsInstance(e.name, Type) - - for r in e.entrypoint: - self.assertIn("entrypoint", r.perms) - - for r in e.execute: - self.assertIn("execute", r.perms) - - for r in e.type_transition: - self.assertEqual(TERT.type_transition, r.ruletype) - - for r in step.setexec: - self.assertIn("setexec", r.perms) - - for r in step.dyntransition: - self.assertIn("dyntransition", r.perms) - - for r in step.setcurrent: - self.assertIn("setcurrent", r.perms) - - def test_303_transitions(self): - """DTA: transitions output""" - self.a.reverse = False - self.a.exclude = None - self.a.source = "start" - self.a.depth_limit = 1 - self.a.mode = DomainTransitionAnalysis.Mode.TransitionsOut - - transitions = list(self.a.results()) - self.assertEqual(2, len(transitions)) - - for step in transitions: - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual("start", step.source) - - for r in step.transition: - self.assertIn("transition", r.perms) - - for e in step.entrypoints: - self.assertIsInstance(e.name, Type) - - for r in e.entrypoint: - self.assertIn("entrypoint", r.perms) - - for r in e.execute: - self.assertIn("execute", r.perms) - - for r in e.type_transition: - self.assertEqual(TERT.type_transition, r.ruletype) - - for r in step.setexec: - self.assertIn("setexec", r.perms) - - for r in step.dyntransition: - self.assertIn("dyntransition", r.perms) - - for r in step.setcurrent: - self.assertIn("setcurrent", r.perms) - - def test_310_all_paths_reversed(self): - """DTA: all paths output reverse DTA""" - self.a.reverse = True - self.a.exclude = None - self.a.source = "bothtrans200" - self.a.target = "start" - self.a.depth_limit = 3 - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - - expected_path = ["bothtrans200", "dyntrans100", "start"] - - paths = list(self.a.results()) - self.assertEqual(1, len(paths)) - - for path in paths: - for stepnum, step in enumerate(path): - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(step.source, expected_path[stepnum + 1]) - self.assertEqual(step.target, expected_path[stepnum]) - - for r in step.transition: - self.assertIn("transition", r.perms) - - for e in step.entrypoints: - self.assertIsInstance(e.name, Type) - - for r in e.entrypoint: - self.assertIn("entrypoint", r.perms) - - for r in e.execute: - self.assertIn("execute", r.perms) - - for r in e.type_transition: - self.assertEqual(TERT.type_transition, r.ruletype) - - for r in step.setexec: - self.assertIn("setexec", r.perms) - - for r in step.dyntransition: - self.assertIn("dyntransition", r.perms) - - for r in step.setcurrent: - self.assertIn("setcurrent", r.perms) - - def test_311_all_shortest_paths_reversed(self): - """DTA: all shortest paths output reverse DTA""" - self.a.reverse = True - self.a.exclude = None - self.a.source = "bothtrans200" - self.a.target = "start" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - - expected_path = ["bothtrans200", "dyntrans100", "start"] - - paths = list(self.a.results()) - self.assertEqual(1, len(paths)) - - for path in paths: - for stepnum, step in enumerate(path): - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(step.source, expected_path[stepnum + 1]) - self.assertEqual(step.target, expected_path[stepnum]) - - for r in step.transition: - self.assertIn("transition", r.perms) - - for e in step.entrypoints: - self.assertIsInstance(e.name, Type) - - for r in e.entrypoint: - self.assertIn("entrypoint", r.perms) - - for r in e.execute: - self.assertIn("execute", r.perms) - - for r in e.type_transition: - self.assertEqual(TERT.type_transition, r.ruletype) - - for r in step.setexec: - self.assertIn("setexec", r.perms) - - for r in step.dyntransition: - self.assertIn("dyntransition", r.perms) - - for r in step.setcurrent: - self.assertIn("setcurrent", r.perms) - - def test_313_transitions_reversed(self): - """DTA: transitions output reverse DTA""" - self.a.reverse = False - self.a.exclude = None - self.a.target = "bothtrans200" - self.a.depth_limit = 1 - self.a.mode = DomainTransitionAnalysis.Mode.TransitionsIn - - transitions = list(self.a.results()) - self.assertEqual(1, len(transitions)) - - for step in transitions: - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual("bothtrans200", step.target) - - for r in step.transition: - self.assertIn("transition", r.perms) - - for e in step.entrypoints: - self.assertIsInstance(e.name, Type) - - for r in e.entrypoint: - self.assertIn("entrypoint", r.perms) - - for r in e.execute: - self.assertIn("execute", r.perms) - - for r in e.type_transition: - self.assertEqual(TERT.type_transition, r.ruletype) - - for r in step.setexec: - self.assertIn("setexec", r.perms) - - for r in step.dyntransition: - self.assertIn("dyntransition", r.perms) - - for r in step.setcurrent: - self.assertIn("setcurrent", r.perms) - - def test_900_set_exclude_invalid_type(self): - """DTA: set invalid excluded type.""" - self.a.reverse = False - self.a.exclude = None - with self.assertRaises(InvalidType): - self.a.exclude = ["trans1", "invalid_type"] - - def test_910_all_paths_invalid_source(self): - """DTA: all paths with invalid source type.""" - self.a.reverse = False - self.a.exclude = None - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - with self.assertRaises(InvalidType): - self.a.source = "invalid_type" - - def test_911_all_paths_invalid_target(self): - """DTA: all paths with invalid target type.""" - self.a.reverse = False - self.a.exclude = None - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - with self.assertRaises(InvalidType): - self.a.target = "invalid_type" - - def test_912_all_paths_invalid_maxlen(self): - """DTA: all paths with invalid max path length.""" - self.a.reverse = False - self.a.exclude = None - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - with self.assertRaises(ValueError): - self.a.depth_limit = -2 - - def test_913_all_paths_source_excluded(self): - """DTA: all paths with excluded source type.""" - self.a.reverse = False - self.a.exclude = ["trans1"] - self.a.source = "trans1" - self.a.target = "trans2" - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_914_all_paths_target_excluded(self): - """DTA: all paths with excluded target type.""" - self.a.reverse = False - self.a.exclude = ["trans2"] - self.a.source = "trans1" - self.a.target = "trans2" - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_915_all_paths_source_disconnected(self): - """DTA: all paths with disconnected source type.""" - self.a.reverse = False - self.a.exclude = None - self.a.source = "trans5" - self.a.target = "trans2" - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_916_all_paths_target_disconnected(self): - """DTA: all paths with disconnected target type.""" - self.a.reverse = False - self.a.exclude = ["trans3"] - self.a.source = "trans2" - self.a.target = "trans5" - self.a.mode = DomainTransitionAnalysis.Mode.AllPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_925_shortest_path_target_disconnected(self): - """DTA: shortest path with disconnected target type.""" - self.a.reverse = False - self.a.exclude = ["trans3"] - self.a.source = "trans2" - self.a.target = "trans5" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_932_all_shortest_paths_source_excluded(self): - """DTA: all shortest paths with excluded source type.""" - self.a.reverse = False - self.a.exclude = ["trans1"] - self.a.source = "trans1" - self.a.target = "trans2" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_933_all_shortest_paths_target_excluded(self): - """DTA: all shortest paths with excluded target type.""" - self.a.reverse = False - self.a.exclude = ["trans2"] - self.a.source = "trans1" - self.a.target = "trans2" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_934_all_shortest_paths_source_disconnected(self): - """DTA: all shortest paths with disconnected source type.""" - self.a.reverse = False - self.a.exclude = None - self.a.source = "trans5" - self.a.target = "trans2" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_935_all_shortest_paths_target_disconnected(self): - """DTA: all shortest paths with disconnected target type.""" - self.a.reverse = False - self.a.exclude = ["trans3"] - self.a.source = "trans2" - self.a.target = "trans5" - self.a.mode = DomainTransitionAnalysis.Mode.ShortestPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_941_transitions_source_excluded(self): - """DTA: transitions with excluded source type.""" - self.a.reverse = False - self.a.exclude = ["trans1"] - self.a.mode = DomainTransitionAnalysis.Mode.TransitionsOut - self.a.source = "trans1" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_942_transitions_source_disconnected(self): - """DTA: transitions with disconnected source type.""" - self.a.reverse = False - self.a.exclude = ["trans3"] - self.a.source = "trans5" - self.a.mode = DomainTransitionAnalysis.Mode.TransitionsOut - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) diff --git a/tests/test_fsusequery.py b/tests/test_fsusequery.py deleted file mode 100644 index 4b5be832..00000000 --- a/tests/test_fsusequery.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import FSUseQuery - -from .policyrep.util import compile_policy - - -class FSUseQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/fsusequery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """fs_use_* query with no criteria""" - # query with no parameters gets all fs_use_*. - fsu = sorted(self.p.fs_uses()) - - q = FSUseQuery(self.p) - q_fsu = sorted(q.results()) - - self.assertListEqual(fsu, q_fsu) - - def test_001_fs_exact(self): - """fs_use_* query with exact fs match""" - q = FSUseQuery(self.p, fs="test1", fs_regex=False) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test1"], fsu) - - def test_002_fs_regex(self): - """fs_use_* query with regex fs match""" - q = FSUseQuery(self.p, fs="test2(a|b)", fs_regex=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test2a", "test2b"], fsu) - - def test_010_ruletype(self): - """fs_use_* query with ruletype match""" - q = FSUseQuery(self.p, ruletype=['fs_use_trans', 'fs_use_task']) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test10a", "test10b"], fsu) - - def test_020_user_exact(self): - """fs_use_* query with context user exact match""" - q = FSUseQuery(self.p, user="user20", user_regex=False) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test20"], fsu) - - def test_021_user_regex(self): - """fs_use_* query with context user regex match""" - q = FSUseQuery(self.p, user="user21(a|b)", user_regex=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test21a", "test21b"], fsu) - - def test_030_role_exact(self): - """fs_use_* query with context role exact match""" - q = FSUseQuery(self.p, role="role30_r", role_regex=False) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test30"], fsu) - - def test_031_role_regex(self): - """fs_use_* query with context role regex match""" - q = FSUseQuery(self.p, role="role31(a|c)_r", role_regex=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test31a", "test31c"], fsu) - - def test_040_type_exact(self): - """fs_use_* query with context type exact match""" - q = FSUseQuery(self.p, type_="type40", type_regex=False) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test40"], fsu) - - def test_041_type_regex(self): - """fs_use_* query with context type regex match""" - q = FSUseQuery(self.p, type_="type41(b|c)", type_regex=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test41b", "test41c"], fsu) - - def test_050_range_exact(self): - """fs_use_* query with context range exact match""" - q = FSUseQuery(self.p, range_="s0:c1 - s0:c0.c4") - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test50"], fsu) - - def test_051_range_overlap1(self): - """fs_use_* query with context range overlap match (equal)""" - q = FSUseQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test51"], fsu) - - def test_051_range_overlap2(self): - """fs_use_* query with context range overlap match (subset)""" - q = FSUseQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test51"], fsu) - - def test_051_range_overlap3(self): - """fs_use_* query with context range overlap match (superset)""" - q = FSUseQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test51"], fsu) - - def test_051_range_overlap4(self): - """fs_use_* query with context range overlap match (overlap low level)""" - q = FSUseQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test51"], fsu) - - def test_051_range_overlap5(self): - """fs_use_* query with context range overlap match (overlap high level)""" - q = FSUseQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test51"], fsu) - - def test_052_range_subset1(self): - """fs_use_* query with context range subset match""" - q = FSUseQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test52"], fsu) - - def test_052_range_subset2(self): - """fs_use_* query with context range subset match (equal)""" - q = FSUseQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test52"], fsu) - - def test_053_range_superset1(self): - """fs_use_* query with context range superset match""" - q = FSUseQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test53"], fsu) - - def test_053_range_superset2(self): - """fs_use_* query with context range superset match (equal)""" - q = FSUseQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test53"], fsu) - - def test_054_range_proper_subset1(self): - """fs_use_* query with context range proper subset match""" - q = FSUseQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test54"], fsu) - - def test_054_range_proper_subset2(self): - """fs_use_* query with context range proper subset match (equal)""" - q = FSUseQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual([], fsu) - - def test_054_range_proper_subset3(self): - """fs_use_* query with context range proper subset match (equal low only)""" - q = FSUseQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test54"], fsu) - - def test_054_range_proper_subset4(self): - """fs_use_* query with context range proper subset match (equal high only)""" - q = FSUseQuery(self.p, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test54"], fsu) - - def test_055_range_proper_superset1(self): - """fs_use_* query with context range proper superset match""" - q = FSUseQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test55"], fsu) - - def test_055_range_proper_superset2(self): - """fs_use_* query with context range proper superset match (equal)""" - q = FSUseQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual([], fsu) - - def test_055_range_proper_superset3(self): - """fs_use_* query with context range proper superset match (equal low)""" - q = FSUseQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test55"], fsu) - - def test_055_range_proper_superset4(self): - """fs_use_* query with context range proper superset match (equal high)""" - q = FSUseQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - fsu = sorted(s.fs for s in q.results()) - self.assertListEqual(["test55"], fsu) diff --git a/tests/test_genfsconquery.py b/tests/test_genfsconquery.py deleted file mode 100644 index 472fcde0..00000000 --- a/tests/test_genfsconquery.py +++ /dev/null @@ -1,236 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest -import stat - -from setools import GenfsconQuery - -from .policyrep.util import compile_policy - - -class GenfsconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/genfsconquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Genfscon query with no criteria""" - # query with no parameters gets all genfs. - genfs = sorted(self.p.genfscons()) - - q = GenfsconQuery(self.p) - q_genfs = sorted(q.results()) - - self.assertListEqual(genfs, q_genfs) - - def test_001_fs_exact(self): - """Genfscon query with exact fs match""" - q = GenfsconQuery(self.p, fs="test1", fs_regex=False) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test1"], genfs) - - def test_002_fs_regex(self): - """Genfscon query with regex fs match""" - q = GenfsconQuery(self.p, fs="test2(a|b)", fs_regex=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test2a", "test2b"], genfs) - - def test_010_path_exact(self): - """Genfscon query with exact path match""" - q = GenfsconQuery(self.p, path="/sys", path_regex=False) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test10"], genfs) - - def test_011_path_regex(self): - """Genfscon query with regex path match""" - q = GenfsconQuery(self.p, path="/(spam|eggs)", path_regex=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test11a", "test11b"], genfs) - - def test_020_user_exact(self): - """Genfscon query with context user exact match""" - q = GenfsconQuery(self.p, user="user20", user_regex=False) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test20"], genfs) - - def test_021_user_regex(self): - """Genfscon query with context user regex match""" - q = GenfsconQuery(self.p, user="user21(a|b)", user_regex=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test21a", "test21b"], genfs) - - def test_030_role_exact(self): - """Genfscon query with context role exact match""" - q = GenfsconQuery(self.p, role="role30_r", role_regex=False) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test30"], genfs) - - def test_031_role_regex(self): - """Genfscon query with context role regex match""" - q = GenfsconQuery(self.p, role="role31(a|c)_r", role_regex=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test31a", "test31c"], genfs) - - def test_040_type_exact(self): - """Genfscon query with context type exact match""" - q = GenfsconQuery(self.p, type_="type40", type_regex=False) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test40"], genfs) - - def test_041_type_regex(self): - """Genfscon query with context type regex match""" - q = GenfsconQuery(self.p, type_="type41(b|c)", type_regex=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test41b", "test41c"], genfs) - - def test_050_file_type(self): - """Genfscon query with file type match""" - q = GenfsconQuery(self.p, filetype=stat.S_IFBLK) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test50b"], genfs) - - def test_060_range_exact(self): - """Genfscon query with context range exact match""" - q = GenfsconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test60"], genfs) - - def test_061_range_overlap1(self): - """Genfscon query with context range overlap match (equal)""" - q = GenfsconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test61"], genfs) - - def test_061_range_overlap2(self): - """Genfscon query with context range overlap match (subset)""" - q = GenfsconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test61"], genfs) - - def test_061_range_overlap3(self): - """Genfscon query with context range overlap match (superset)""" - q = GenfsconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test61"], genfs) - - def test_061_range_overlap4(self): - """Genfscon query with context range overlap match (overlap low level)""" - q = GenfsconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test61"], genfs) - - def test_061_range_overlap5(self): - """Genfscon query with context range overlap match (overlap high level)""" - q = GenfsconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test61"], genfs) - - def test_062_range_subset1(self): - """Genfscon query with context range subset match""" - q = GenfsconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test62"], genfs) - - def test_062_range_subset2(self): - """Genfscon query with context range subset match (equal)""" - q = GenfsconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test62"], genfs) - - def test_063_range_superset1(self): - """Genfscon query with context range superset match""" - q = GenfsconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test63"], genfs) - - def test_063_range_superset2(self): - """Genfscon query with context range superset match (equal)""" - q = GenfsconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test63"], genfs) - - def test_064_range_proper_subset1(self): - """Genfscon query with context range proper subset match""" - q = GenfsconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test64"], genfs) - - def test_064_range_proper_subset2(self): - """Genfscon query with context range proper subset match (equal)""" - q = GenfsconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual([], genfs) - - def test_064_range_proper_subset3(self): - """Genfscon query with context range proper subset match (equal low only)""" - q = GenfsconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test64"], genfs) - - def test_064_range_proper_subset4(self): - """Genfscon query with context range proper subset match (equal high only)""" - q = GenfsconQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test64"], genfs) - - def test_065_range_proper_superset1(self): - """Genfscon query with context range proper superset match""" - q = GenfsconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test65"], genfs) - - def test_065_range_proper_superset2(self): - """Genfscon query with context range proper superset match (equal)""" - q = GenfsconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual([], genfs) - - def test_065_range_proper_superset3(self): - """Genfscon query with context range proper superset match (equal low)""" - q = GenfsconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test65"], genfs) - - def test_065_range_proper_superset4(self): - """Genfscon query with context range proper superset match (equal high)""" - q = GenfsconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - genfs = sorted(s.fs for s in q.results()) - self.assertListEqual(["test65"], genfs) diff --git a/tests/test_ibendportconquery.py b/tests/test_ibendportconquery.py deleted file mode 100644 index 14fd2480..00000000 --- a/tests/test_ibendportconquery.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2018, Chris PeBenito -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import IbendportconQuery - -from .policyrep.util import compile_policy - - -class IbendportconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/ibendportconquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Ibendportcon query with no criteria""" - # query with no parameters gets all ibendportcons. - ibendportcons = sorted(self.p.ibendportcons()) - - q = IbendportconQuery(self.p) - q_ibendportcons = sorted(q.results()) - - self.assertListEqual(ibendportcons, q_ibendportcons) - - def test_001_name_exact(self): - """Ibendportcon query with exact name match.""" - q = IbendportconQuery(self.p, name="test1", name_regex=False) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test1"], ibendportcons) - - def test_002_name_regext(self): - """Ibendportcon query with regex name match.""" - q = IbendportconQuery(self.p, name="test2(a|b)", name_regex=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test2a", "test2b"], ibendportcons) - - def test_010_port(self): - """Ibendportcon query with port match.""" - q = IbendportconQuery(self.p, port=10) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test10"], ibendportcons) - - def test_020_user_exact(self): - """Ibendportcon query with context user exact match""" - q = IbendportconQuery(self.p, user="user20", user_regex=False) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test20"], ibendportcons) - - def test_021_user_regex(self): - """Ibendportcon query with context user regex match""" - q = IbendportconQuery(self.p, user="user21(a|b)", user_regex=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test21a", "test21b"], ibendportcons) - - def test_030_role_exact(self): - """Ibendportcon query with context role exact match""" - q = IbendportconQuery(self.p, role="role30_r", role_regex=False) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test30"], ibendportcons) - - def test_031_role_regex(self): - """Ibendportcon query with context role regex match""" - q = IbendportconQuery(self.p, role="role31(a|c)_r", role_regex=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test31a", "test31c"], ibendportcons) - - def test_040_type_exact(self): - """Ibendportcon query with context type exact match""" - q = IbendportconQuery(self.p, type_="type40", type_regex=False) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test40"], ibendportcons) - - def test_041_type_regex(self): - """Ibendportcon query with context type regex match""" - q = IbendportconQuery(self.p, type_="type41(b|c)", type_regex=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test41b", "test41c"], ibendportcons) - - def test_050_range_exact(self): - """Ibendportcon query with context range exact match""" - q = IbendportconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test50"], ibendportcons) - - def test_051_range_overlap1(self): - """Ibendportcon query with context range overlap match (equal)""" - q = IbendportconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test51"], ibendportcons) - - def test_051_range_overlap2(self): - """Ibendportcon query with context range overlap match (subset)""" - q = IbendportconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test51"], ibendportcons) - - def test_051_range_overlap3(self): - """Ibendportcon query with context range overlap match (superset)""" - q = IbendportconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test51"], ibendportcons) - - def test_051_range_overlap4(self): - """Ibendportcon query with context range overlap match (overlap low level)""" - q = IbendportconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test51"], ibendportcons) - - def test_051_range_overlap5(self): - """Ibendportcon query with context range overlap match (overlap high level)""" - q = IbendportconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test51"], ibendportcons) - - def test_052_range_subset1(self): - """Ibendportcon query with context range subset match""" - q = IbendportconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test52"], ibendportcons) - - def test_052_range_subset2(self): - """Ibendportcon query with context range subset match (equal)""" - q = IbendportconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test52"], ibendportcons) - - def test_053_range_superset1(self): - """Ibendportcon query with context range superset match""" - q = IbendportconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test53"], ibendportcons) - - def test_053_range_superset2(self): - """Ibendportcon query with context range superset match (equal)""" - q = IbendportconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test53"], ibendportcons) - - def test_054_range_proper_subset1(self): - """Ibendportcon query with context range proper subset match""" - q = IbendportconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test54"], ibendportcons) - - def test_054_range_proper_subset2(self): - """Ibendportcon query with context range proper subset match (equal)""" - q = IbendportconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual([], ibendportcons) - - def test_054_range_proper_subset3(self): - """Ibendportcon query with context range proper subset match (equal low only)""" - q = IbendportconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test54"], ibendportcons) - - def test_054_range_proper_subset4(self): - """Ibendportcon query with context range proper subset match (equal high only)""" - q = IbendportconQuery(self.p, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test54"], ibendportcons) - - def test_055_range_proper_superset1(self): - """Ibendportcon query with context range proper superset match""" - q = IbendportconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test55"], ibendportcons) - - def test_055_range_proper_superset2(self): - """Ibendportcon query with context range proper superset match (equal)""" - q = IbendportconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual([], ibendportcons) - - def test_055_range_proper_superset3(self): - """Ibendportcon query with context range proper superset match (equal low)""" - q = IbendportconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test55"], ibendportcons) - - def test_055_range_proper_superset4(self): - """Ibendportcon query with context range proper superset match (equal high)""" - q = IbendportconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, - range_proper=True) - - ibendportcons = sorted(n.name for n in q.results()) - self.assertListEqual(["test55"], ibendportcons) diff --git a/tests/test_ibpkeyconquery.py b/tests/test_ibpkeyconquery.py deleted file mode 100644 index 6a1fa465..00000000 --- a/tests/test_ibpkeyconquery.py +++ /dev/null @@ -1,273 +0,0 @@ -# Copyright 2018, Chris PeBenito -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import IbpkeyconQuery, IbpkeyconRange - -from .policyrep.util import compile_policy - - -class IbpkeyconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/ibpkeyconquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """ibpkeycon query with no criteria""" - # query with no parameters gets all ibpkeycons. - ibpkeycons = sorted(self.p.ibpkeycons()) - - q = IbpkeyconQuery(self.p) - q_ibpkeycons = sorted(q.results()) - - self.assertListEqual(ibpkeycons, q_ibpkeycons) - - def test_001_subnet_mask(self): - """Ibpkeycon query with subnet mask match.""" - q = IbpkeyconQuery(self.p, subnet_prefix="fe81::") - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(1, 1)], ibpkeycons) - - def test_010_pkey_exact(self): - """Ibpkeycon query with exact pkey match.""" - q = IbpkeyconQuery(self.p, pkeys=(0x10c, 0x10e)) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(0x10c, 0x10e)], ibpkeycons) - - def test_020_user_exact(self): - """ibpkeycon query with context user exact match""" - q = IbpkeyconQuery(self.p, user="user20", user_regex=False) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(20, 20)], ibpkeycons) - - def test_021_user_regex(self): - """ibpkeycon query with context user regex match""" - q = IbpkeyconQuery(self.p, user="user21(a|b)", user_regex=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(0x21a, 0x21a), - IbpkeyconRange(0x21b, 0x21b)], ibpkeycons) - - def test_030_role_exact(self): - """ibpkeycon query with context role exact match""" - q = IbpkeyconQuery(self.p, role="role30_r", role_regex=False) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(30, 30)], ibpkeycons) - - def test_031_role_regex(self): - """ibpkeycon query with context role regex match""" - q = IbpkeyconQuery(self.p, role="role31(a|c)_r", role_regex=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(0x31a, 0x31a), - IbpkeyconRange(0x31c, 0x31c)], ibpkeycons) - - def test_040_type_exact(self): - """ibpkeycon query with context type exact match""" - q = IbpkeyconQuery(self.p, type_="type40", type_regex=False) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(40, 40)], ibpkeycons) - - def test_041_type_regex(self): - """ibpkeycon query with context type regex match""" - q = IbpkeyconQuery(self.p, type_="type41(b|c)", type_regex=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(0x41b, 0x41b), - IbpkeyconRange(0x41c, 0x41c)], ibpkeycons) - - def test_050_range_exact(self): - """ibpkeycon query with context range exact match""" - q = IbpkeyconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(50, 50)], ibpkeycons) - - def test_051_range_overlap1(self): - """ibpkeycon query with context range overlap match (equal)""" - q = IbpkeyconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(51, 51)], ibpkeycons) - - def test_051_range_overlap2(self): - """ibpkeycon query with context range overlap match (subset)""" - q = IbpkeyconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(51, 51)], ibpkeycons) - - def test_051_range_overlap3(self): - """ibpkeycon query with context range overlap match (superset)""" - q = IbpkeyconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(51, 51)], ibpkeycons) - - def test_051_range_overlap4(self): - """ibpkeycon query with context range overlap match (overlap low level)""" - q = IbpkeyconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(51, 51)], ibpkeycons) - - def test_051_range_overlap5(self): - """ibpkeycon query with context range overlap match (overlap high level)""" - q = IbpkeyconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(51, 51)], ibpkeycons) - - def test_052_range_subset1(self): - """ibpkeycon query with context range subset match""" - q = IbpkeyconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(52, 52)], ibpkeycons) - - def test_052_range_subset2(self): - """ibpkeycon query with context range subset match (equal)""" - q = IbpkeyconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(52, 52)], ibpkeycons) - - def test_053_range_superset1(self): - """ibpkeycon query with context range superset match""" - q = IbpkeyconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(53, 53)], ibpkeycons) - - def test_053_range_superset2(self): - """ibpkeycon query with context range superset match (equal)""" - q = IbpkeyconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(53, 53)], ibpkeycons) - - def test_054_range_proper_subset1(self): - """ibpkeycon query with context range proper subset match""" - q = IbpkeyconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(54, 54)], ibpkeycons) - - def test_054_range_proper_subset2(self): - """ibpkeycon query with context range proper subset match (equal)""" - q = IbpkeyconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([], ibpkeycons) - - def test_054_range_proper_subset3(self): - """ibpkeycon query with context range proper subset match (equal low only)""" - q = IbpkeyconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(54, 54)], ibpkeycons) - - def test_054_range_proper_subset4(self): - """ibpkeycon query with context range proper subset match (equal high only)""" - q = IbpkeyconQuery(self.p, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, - range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(54, 54)], ibpkeycons) - - def test_055_range_proper_superset1(self): - """ibpkeycon query with context range proper superset match""" - q = IbpkeyconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(55, 55)], ibpkeycons) - - def test_055_range_proper_superset2(self): - """ibpkeycon query with context range proper superset match (equal)""" - q = IbpkeyconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, - range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([], ibpkeycons) - - def test_055_range_proper_superset3(self): - """ibpkeycon query with context range proper superset match (equal low)""" - q = IbpkeyconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, - range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(55, 55)], ibpkeycons) - - def test_055_range_proper_superset4(self): - """ibpkeycon query with context range proper superset match (equal high)""" - q = IbpkeyconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, - range_proper=True) - - ibpkeycons = sorted(n.pkeys for n in q.results()) - self.assertListEqual([IbpkeyconRange(55, 55)], ibpkeycons) - - def test_900_invalid_subnet_prefix(self): - """Ibpkeycon query with invalid subnet prefix""" - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, subnet_prefix="INVALID") - - def test_910_invalid_pkey_negative(self): - """Ibpkeycon query with negative pkey""" - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(-1, -1)) - - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(1, -1)) - - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(-1, 1)) - - def test_911_invalid_pkey_zero(self): - """Ibpkeycon query with 0 pkey""" - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(0, 0)) - - def test_912_invalid_pkey_over_max(self): - """Ibpkeycon query with pkey over maximum value""" - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(1, 0xfffff)) - - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(0xfffff, 1)) - - with self.assertRaises(ValueError): - IbpkeyconQuery(self.p, pkeys=(0xfffff, 0xfffff)) - - def test_913_invalid_pkey_not_a_number(self): - """Ibpkeycon query with pkey is not a number""" - with self.assertRaises(TypeError): - IbpkeyconQuery(self.p, pkeys=(1, "INVALID")) - - with self.assertRaises(TypeError): - IbpkeyconQuery(self.p, pkeys=("INVALID", 2)) - - def test_914_invalid_pkey_not_tuple(self): - """Ibpkeycon query with pkey is not a tuple""" - with self.assertRaises(TypeError): - IbpkeyconQuery(self.p, pkeys=1) - - def test_915_invalid_pkey_wrong_tuple_length(self): - """Ibpkeycon query with pkey is not correct tuple size""" - with self.assertRaises(TypeError): - IbpkeyconQuery(self.p, pkeys=(1,)) - - with self.assertRaises(TypeError): - IbpkeyconQuery(self.p, pkeys=(1, 2, 3)) diff --git a/tests/test_infoflow.py b/tests/test_infoflow.py deleted file mode 100644 index ba2983f6..00000000 --- a/tests/test_infoflow.py +++ /dev/null @@ -1,422 +0,0 @@ -# Copyright 2014-2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import InfoFlowAnalysis -from setools import TERuletype as TERT -from setools.exception import InvalidType -from setools.permmap import PermissionMap -from setools.policyrep import Type - -from . import mixins -from .policyrep.util import compile_policy - - -# Note: the testing for having correct rules on every edge is only -# performed once on the full graph, since it is assumed that NetworkX's -# Digraph.subgraph() function correctly copies the edge attributes into -# the subgraph. - - -class InfoFlowAnalysisTest(mixins.ValidateRule, unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/infoflow.conf") - cls.m = PermissionMap("tests/perm_map") - cls.a = InfoFlowAnalysis(cls.p, cls.m) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_001_full_graph(self): - """Information flow analysis full graph.""" - - self.a._build_graph() - - disconnected1 = self.p.lookup_type("disconnected1") - disconnected2 = self.p.lookup_type("disconnected2") - node1 = self.p.lookup_type("node1") - node2 = self.p.lookup_type("node2") - node3 = self.p.lookup_type("node3") - node4 = self.p.lookup_type("node4") - node5 = self.p.lookup_type("node5") - node6 = self.p.lookup_type("node6") - node7 = self.p.lookup_type("node7") - node8 = self.p.lookup_type("node8") - node9 = self.p.lookup_type("node9") - - nodes = set(self.a.G.nodes()) - self.assertSetEqual(set([disconnected1, disconnected2, node1, - node2, node3, node4, node5, - node6, node7, node8, node9]), nodes) - - edges = set(self.a.G.out_edges()) - self.assertSetEqual(set([(disconnected1, disconnected2), - (disconnected2, disconnected1), - (node1, node2), - (node1, node3), - (node2, node4), - (node3, node5), - (node4, node6), - (node5, node8), - (node6, node5), - (node6, node7), - (node8, node9), - (node9, node8)]), edges) - - r = self.a.G.edges[disconnected1, disconnected2]["rules"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "disconnected1", "disconnected2", "infoflow2", - set(["super"])) - - r = self.a.G.edges[disconnected2, disconnected1]["rules"] - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "disconnected1", "disconnected2", "infoflow2", - set(["super"])) - - r = sorted(self.a.G.edges[node1, node2]["rules"]) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], TERT.allow, "node1", "node2", "infoflow", set(["med_w"])) - self.validate_rule(r[1], TERT.allow, "node2", "node1", "infoflow", set(["hi_r"])) - - r = sorted(self.a.G.edges[node1, node3]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node3", "node1", "infoflow", set(["low_r", "med_r"])) - - r = sorted(self.a.G.edges[node2, node4]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node2", "node4", "infoflow", set(["hi_w"])) - - r = sorted(self.a.G.edges[node3, node5]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node5", "node3", "infoflow", set(["low_r"])) - - r = sorted(self.a.G.edges[node4, node6]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node4", "node6", "infoflow2", set(["hi_w"])) - - r = sorted(self.a.G.edges[node5, node8]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node5", "node8", "infoflow2", set(["hi_w"])) - - r = sorted(self.a.G.edges[node6, node5]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node5", "node6", "infoflow", set(["med_r"])) - - r = sorted(self.a.G.edges[node6, node7]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node6", "node7", "infoflow", set(["hi_w"])) - - r = sorted(self.a.G.edges[node8, node9]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node8", "node9", "infoflow2", set(["super"])) - - r = sorted(self.a.G.edges[node9, node8]["rules"]) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], TERT.allow, "node8", "node9", "infoflow2", set(["super"])) - - def test_100_minimum_3(self): - """Information flow analysis with minimum weight 3.""" - - self.a.exclude = None - self.a.min_weight = 3 - self.a._build_subgraph() - - disconnected1 = self.p.lookup_type("disconnected1") - disconnected2 = self.p.lookup_type("disconnected2") - node1 = self.p.lookup_type("node1") - node2 = self.p.lookup_type("node2") - node3 = self.p.lookup_type("node3") - node4 = self.p.lookup_type("node4") - node5 = self.p.lookup_type("node5") - node6 = self.p.lookup_type("node6") - node7 = self.p.lookup_type("node7") - node8 = self.p.lookup_type("node8") - node9 = self.p.lookup_type("node9") - - # don't test nodes list, as disconnected nodes - # are not removed by subgraph generation. we - # assume NetworkX copies into the subgraph - # correctly. - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(disconnected1, disconnected2), - (disconnected2, disconnected1), - (node1, node2), - (node1, node3), - (node2, node4), - (node4, node6), - (node5, node8), - (node6, node5), - (node6, node7), - (node8, node9), - (node9, node8)]), edges) - - def test_200_minimum_8(self): - """Information flow analysis with minimum weight 8.""" - - self.a.exclude = None - self.a.min_weight = 8 - self.a._build_subgraph() - - disconnected1 = self.p.lookup_type("disconnected1") - disconnected2 = self.p.lookup_type("disconnected2") - node1 = self.p.lookup_type("node1") - node2 = self.p.lookup_type("node2") - node4 = self.p.lookup_type("node4") - node5 = self.p.lookup_type("node5") - node6 = self.p.lookup_type("node6") - node7 = self.p.lookup_type("node7") - node8 = self.p.lookup_type("node8") - node9 = self.p.lookup_type("node9") - - # don't test nodes list, as disconnected nodes - # are not removed by subgraph generation. we - # assume NetworkX copies into the subgraph - # correctly. - - edges = set(self.a.subG.out_edges()) - self.assertSetEqual(set([(disconnected1, disconnected2), - (disconnected2, disconnected1), - (node1, node2), - (node2, node4), - (node4, node6), - (node5, node8), - (node6, node7), - (node8, node9), - (node9, node8)]), edges) - - def test_300_all_paths(self): - """Information flow analysis: all paths output""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.source = "node1" - self.a.target = "node4" - self.a.mode = InfoFlowAnalysis.Mode.AllPaths - self.a.depth_limit = 3 - - paths = list(self.a.results()) - self.assertEqual(1, len(paths)) - - steps = list(paths[0]) - self.assertEqual(2, len(steps)) - - step = steps[0] - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(step.source, "node1") - self.assertEqual(step.target, "node2") - for r in steps[0].rules: - self.assertEqual(TERT.allow, r.ruletype) - - step = steps[1] - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(step.source, "node2") - self.assertEqual(step.target, "node4") - for r in step.rules: - self.assertEqual(TERT.allow, r.ruletype) - - def test_301_all_shortest_paths(self): - """Information flow analysis: all shortest paths output""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.source = "node1" - self.a.target = "node4" - self.a.mode = InfoFlowAnalysis.Mode.ShortestPaths - - paths = list(self.a.results()) - self.assertEqual(1, len(paths)) - - steps = list(paths[0]) - self.assertEqual(2, len(steps)) - - step = steps[0] - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(step.source, "node1") - self.assertEqual(step.target, "node2") - for r in steps[0].rules: - self.assertEqual(TERT.allow, r.ruletype) - - step = steps[1] - self.assertIsInstance(step.source, Type) - self.assertIsInstance(step.target, Type) - self.assertEqual(step.source, "node2") - self.assertEqual(step.target, "node4") - for r in step.rules: - self.assertEqual(TERT.allow, r.ruletype) - - def test_303_infoflows_out(self): - """Information flow analysis: flows out of a type""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.FlowsOut - self.a.depth_limit = 1 - self.a.source = "node6" - - for flow in self.a.results(): - self.assertIsInstance(flow.source, Type) - self.assertIsInstance(flow.target, Type) - self.assertEqual(flow.source, "node6") - for r in flow.rules: - self.assertEqual(TERT.allow, r.ruletype) - - def test_304_infoflows_in(self): - """Information flow analysis: flows in to a type""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.FlowsIn - self.a.depth_limit = 1 - self.a.target = "node8" - - for flow in self.a.results(): - self.assertIsInstance(flow.source, Type) - self.assertIsInstance(flow.target, Type) - self.assertEqual(flow.target, "node8") - for r in flow.rules: - self.assertEqual(TERT.allow, r.ruletype) - - def test_900_set_exclude_invalid_type(self): - """Information flow analysis: set invalid excluded type.""" - with self.assertRaises(InvalidType): - self.a.exclude = ["node1", "invalid_type"] - - def test_901_set_small_min_weight(self): - """Information flow analysis: set too small weight.""" - - with self.assertRaises(ValueError): - self.a.min_weight = 0 - - with self.assertRaises(ValueError): - self.a.min_weight = -3 - - def test_902_set_large_min_weight(self): - """Information flow analysis: set too big weight.""" - with self.assertRaises(ValueError): - self.a.min_weight = 11 - - with self.assertRaises(ValueError): - self.a.min_weight = 50 - - def test_910_invalid_source(self): - """Information flow analysis: invalid source type.""" - with self.assertRaises(InvalidType): - self.a.source = "invalid_type" - - def test_911_invalid_target(self): - """Information flow analysis: invalid target type.""" - with self.assertRaises(InvalidType): - self.a.target = "invalid_type" - - def test_912_all_paths_invalid_maxlen(self): - """Information flow analysis: all paths with invalid max path length.""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.AllPaths - - with self.assertRaises(ValueError): - self.a.depth_limit = -2 - - def test_913_all_paths_source_excluded(self): - """Information flow analysis: all paths with excluded source type.""" - self.a.exclude = ["node1"] - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.AllPaths - self.a.source = "node1" - self.a.target = "node2" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_914_all_paths_target_excluded(self): - """Information flow analysis: all paths with excluded target type.""" - self.a.exclude = ["node2"] - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.AllPaths - self.a.source = "node1" - self.a.target = "node2" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_915_all_paths_source_disconnected(self): - """Information flow analysis: all paths with disconnected source type.""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.AllPaths - self.a.source = "disconnected1" - self.a.target = "node2" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_916_all_paths_target_disconnected(self): - """Information flow analysis: all paths with disconnected target type.""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.source = "node2" - self.a.target = "disconnected1" - self.a.mode = InfoFlowAnalysis.Mode.AllPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_932_all_shortest_paths_source_excluded(self): - """Information flow analysis: all shortest paths with excluded source type.""" - self.a.exclude = ["node1"] - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.ShortestPaths - self.a.source = "node1" - self.a.target = "node2" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_933_all_shortest_paths_target_excluded(self): - """Information flow analysis: all shortest paths with excluded target type.""" - self.a.exclude = ["node2"] - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.ShortestPaths - self.a.source = "node1" - self.a.target = "node2" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_934_all_shortest_paths_source_disconnected(self): - """Information flow analysis: all shortest paths with disconnected source type.""" - self.a.exclude = None - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.ShortestPaths - self.a.source = "disconnected1" - self.a.target = "node2" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_935_all_shortest_paths_target_disconnected(self): - """Information flow analysis: all shortest paths with disconnected target type.""" - self.a.exclude = None - self.a.min_weight = 1 - self.source = "node2" - self.target = "disconnected1" - self.a.mode = InfoFlowAnalysis.Mode.ShortestPaths - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_941_infoflows_source_excluded(self): - """Information flow analysis: infoflows with excluded source type.""" - self.a.exclude = ["node1"] - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.FlowsOut - self.a.source = "node1" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) - - def test_942_infoflows_source_disconnected(self): - """Information flow analysis: infoflows with disconnected source type.""" - self.a.exclude = ["disconnected2"] - self.a.min_weight = 1 - self.a.mode = InfoFlowAnalysis.Mode.FlowsOut - self.a.source = "disconnected1" - paths = list(self.a.results()) - self.assertEqual(0, len(paths)) diff --git a/tests/test_initsidquery.py b/tests/test_initsidquery.py deleted file mode 100644 index cf79555d..00000000 --- a/tests/test_initsidquery.py +++ /dev/null @@ -1,216 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import InitialSIDQuery - -from .policyrep.util import compile_policy - - -class InitialSIDQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/initsidquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Initial SID query with no criteria""" - # query with no parameters gets all SIDs. - sids = sorted(self.p.initialsids()) - - q = InitialSIDQuery(self.p) - q_sids = sorted(q.results()) - - self.assertListEqual(sids, q_sids) - - def test_001_name_exact(self): - """Initial SID query with exact match""" - q = InitialSIDQuery(self.p, name="kernel", name_regex=False) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["kernel"], sids) - - def test_002_name_regex(self): - """Initial SID query with regex match""" - q = InitialSIDQuery(self.p, name="(security|unlabeled)", name_regex=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["security", "unlabeled"], sids) - - def test_010_user_exact(self): - """Initial SID query with context user exact match""" - q = InitialSIDQuery(self.p, user="user10", user_regex=False) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["fs"], sids) - - def test_011_user_regex(self): - """Initial SID query with context user regex match""" - q = InitialSIDQuery(self.p, user="user11(a|b)", user_regex=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["file", "file_labels"], sids) - - def test_020_role_exact(self): - """Initial SID query with context role exact match""" - q = InitialSIDQuery(self.p, role="role20_r", role_regex=False) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["any_socket"], sids) - - def test_021_role_regex(self): - """Initial SID query with context role regex match""" - q = InitialSIDQuery(self.p, role="role21(a|c)_r", role_regex=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["netmsg", "port"], sids) - - def test_030_type_exact(self): - """Initial SID query with context type exact match""" - q = InitialSIDQuery(self.p, type_="type30", type_regex=False) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["node"], sids) - - def test_031_type_regex(self): - """Initial SID query with context type regex match""" - q = InitialSIDQuery(self.p, type_="type31(b|c)", type_regex=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["icmp_socket", "tcp_socket"], sids) - - def test_040_range_exact(self): - """Initial SID query with context range exact match""" - q = InitialSIDQuery(self.p, range_="s0:c1 - s0:c0.c4") - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_modprobe"], sids) - - def test_041_range_overlap1(self): - """Initial SID query with context range overlap match (equal)""" - q = InitialSIDQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl"], sids) - - def test_041_range_overlap2(self): - """Initial SID query with context range overlap match (subset)""" - q = InitialSIDQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl"], sids) - - def test_041_range_overlap3(self): - """Initial SID query with context range overlap match (superset)""" - q = InitialSIDQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl"], sids) - - def test_041_range_overlap4(self): - """Initial SID query with context range overlap match (overlap low level)""" - q = InitialSIDQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl"], sids) - - def test_041_range_overlap5(self): - """Initial SID query with context range overlap match (overlap high level)""" - q = InitialSIDQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl"], sids) - - def test_042_range_subset1(self): - """Initial SID query with context range subset match""" - q = InitialSIDQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_fs"], sids) - - def test_042_range_subset2(self): - """Initial SID query with context range subset match (equal)""" - q = InitialSIDQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_fs"], sids) - - def test_043_range_superset1(self): - """Initial SID query with context range superset match""" - q = InitialSIDQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_kernel"], sids) - - def test_043_range_superset2(self): - """Initial SID query with context range superset match (equal)""" - q = InitialSIDQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_kernel"], sids) - - def test_044_range_proper_subset1(self): - """Initial SID query with context range proper subset match""" - q = InitialSIDQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_net"], sids) - - def test_044_range_proper_subset2(self): - """Initial SID query with context range proper subset match (equal)""" - q = InitialSIDQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual([], sids) - - def test_044_range_proper_subset3(self): - """Initial SID query with context range proper subset match (equal low only)""" - q = InitialSIDQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_net"], sids) - - def test_044_range_proper_subset4(self): - """Initial SID query with context range proper subset match (equal high only)""" - q = InitialSIDQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_net"], sids) - - def test_045_range_proper_superset1(self): - """Initial SID query with context range proper superset match""" - q = InitialSIDQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_net_unix"], sids) - - def test_045_range_proper_superset2(self): - """Initial SID query with context range proper superset match (equal)""" - q = InitialSIDQuery(self.p, - range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual([], sids) - - def test_045_range_proper_superset3(self): - """Initial SID query with context range proper superset match (equal low)""" - q = InitialSIDQuery(self.p, - range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_net_unix"], sids) - - def test_045_range_proper_superset4(self): - """Initial SID query with context range proper superset match (equal high)""" - q = InitialSIDQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - sids = sorted(str(s) for s in q.results()) - self.assertListEqual(["sysctl_net_unix"], sids) diff --git a/tests/test_iomemconquery.py b/tests/test_iomemconquery.py deleted file mode 100644 index 03b33f45..00000000 --- a/tests/test_iomemconquery.py +++ /dev/null @@ -1,430 +0,0 @@ -# Derived from tests/portconquery.py -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import IomemconQuery, IomemconRange - -from .policyrep.util import compile_policy - - -class IomemconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/iomemconquery.conf", xen=True) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Iomemcon query with no criteria""" - # query with no parameters gets all addr. - rules = sorted(self.p.iomemcons()) - - q = IomemconQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_010_user_exact(self): - """Iomemcon query with context user exact match""" - q = IomemconQuery(self.p, user="user10", user_regex=False) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(10, 10)], addr) - - def test_011_user_regex(self): - """Iomemcon query with context user regex match""" - q = IomemconQuery(self.p, user="user11(a|b)", user_regex=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(11, 11), IomemconRange(11000, 11000)], addr) - - def test_020_role_exact(self): - """Iomemcon query with context role exact match""" - q = IomemconQuery(self.p, role="role20_r", role_regex=False) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(20, 20)], addr) - - def test_021_role_regex(self): - """Iomemcon query with context role regex match""" - q = IomemconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(21, 21), IomemconRange(21001, 21001)], addr) - - def test_030_type_exact(self): - """Iomemcon query with context type exact match""" - q = IomemconQuery(self.p, type_="type30", type_regex=False) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(30, 30)], addr) - - def test_031_type_regex(self): - """Iomemcon query with context type regex match""" - q = IomemconQuery(self.p, type_="type31(b|c)", type_regex=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(31000, 31000), IomemconRange(31001, 31001)], addr) - - def test_040_range_exact(self): - """Iomemcon query with context range exact match""" - q = IomemconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(40, 40)], addr) - - def test_041_range_overlap1(self): - """Iomemcon query with context range overlap match (equal)""" - q = IomemconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(41, 41)], addr) - - def test_041_range_overlap2(self): - """Iomemcon query with context range overlap match (subset)""" - q = IomemconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(41, 41)], addr) - - def test_041_range_overlap3(self): - """Iomemcon query with context range overlap match (superset)""" - q = IomemconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(41, 41)], addr) - - def test_041_range_overlap4(self): - """Iomemcon query with context range overlap match (overlap low level)""" - q = IomemconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(41, 41)], addr) - - def test_041_range_overlap5(self): - """Iomemcon query with context range overlap match (overlap high level)""" - q = IomemconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(41, 41)], addr) - - def test_042_range_subset1(self): - """Iomemcon query with context range subset match""" - q = IomemconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(42, 42)], addr) - - def test_042_range_subset2(self): - """Iomemcon query with context range subset match (equal)""" - q = IomemconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(42, 42)], addr) - - def test_043_range_superset1(self): - """Iomemcon query with context range superset match""" - q = IomemconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(43, 43)], addr) - - def test_043_range_superset2(self): - """Iomemcon query with context range superset match (equal)""" - q = IomemconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(43, 43)], addr) - - def test_044_range_proper_subset1(self): - """Iomemcon query with context range proper subset match""" - q = IomemconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(44, 44)], addr) - - def test_044_range_proper_subset2(self): - """Iomemcon query with context range proper subset match (equal)""" - q = IomemconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([], addr) - - def test_044_range_proper_subset3(self): - """Iomemcon query with context range proper subset match (equal low only)""" - q = IomemconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(44, 44)], addr) - - def test_044_range_proper_subset4(self): - """Iomemcon query with context range proper subset match (equal high only)""" - q = IomemconQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(44, 44)], addr) - - def test_045_range_proper_superset1(self): - """Iomemcon query with context range proper superset match""" - q = IomemconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(45, 45)], addr) - - def test_045_range_proper_superset2(self): - """Iomemcon query with context range proper superset match (equal)""" - q = IomemconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([], addr) - - def test_045_range_proper_superset3(self): - """Iomemcon query with context range proper superset match (equal low)""" - q = IomemconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(45, 45)], addr) - - def test_045_range_proper_superset4(self): - """Iomemcon query with context range proper superset match (equal high)""" - q = IomemconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(45, 45)], addr) - - def test_050_single_equal(self): - """Iomemcon query with single mem addr exact match""" - q = IomemconQuery(self.p, addr=(50, 50)) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50, 50)], addr) - - def test_051_range_equal(self): - """Iomemcon query with mem addr range exact match""" - q = IomemconQuery(self.p, addr=(50100, 50110)) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50100, 50110)], addr) - - def test_052_single_subset(self): - """Iomemcon query with single mem addr subset""" - q = IomemconQuery(self.p, addr=(50200, 50200), addr_subset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50200, 50200)], addr) - - def test_053_range_subset(self): - """Iomemcon query with range subset""" - q = IomemconQuery(self.p, addr=(50301, 50309), addr_subset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50300, 50310)], addr) - - def test_053_range_subset_edge1(self): - """Iomemcon query with range subset, equal edge case""" - q = IomemconQuery(self.p, addr=(50300, 50310), addr_subset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50300, 50310)], addr) - - def test_054_single_proper_subset(self): - """Iomemcon query with single mem addr proper subset""" - q = IomemconQuery( - self.p, addr=(50400, 50400), addr_subset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([], addr) - - def test_055_range_proper_subset(self): - """Iomemcon query with range proper subset""" - q = IomemconQuery( - self.p, addr=(50501, 50509), addr_subset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50500, 50510)], addr) - - def test_055_range_proper_subset_edge1(self): - """Iomemcon query with range proper subset, equal edge case""" - q = IomemconQuery( - self.p, addr=(50500, 50510), addr_subset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([], addr) - - def test_055_range_proper_subset_edge2(self): - """Iomemcon query with range proper subset, low equal edge case""" - q = IomemconQuery( - self.p, addr=(50500, 50509), addr_subset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50500, 50510)], addr) - - def test_055_range_proper_subset_edge3(self): - """Iomemcon query with range proper subset, high equal edge case""" - q = IomemconQuery( - self.p, addr=(50501, 50510), addr_subset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50500, 50510)], addr) - - def test_056_single_superset(self): - """Iomemcon query with single mem addr superset""" - q = IomemconQuery(self.p, addr=(50600, 50602), addr_superset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50601, 50601)], addr) - - def test_056_single_superset_edge1(self): - """Iomemcon query with single mem addr superset, equal edge case""" - q = IomemconQuery(self.p, addr=(50601, 50601), addr_superset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50601, 50601)], addr) - - def test_057_range_superset(self): - """Iomemcon query with range superset""" - q = IomemconQuery(self.p, addr=(50700, 50711), addr_superset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50700, 50710)], addr) - - def test_057_range_superset_edge1(self): - """Iomemcon query with range superset, equal edge case""" - q = IomemconQuery(self.p, addr=(50700, 50710), addr_superset=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50700, 50710)], addr) - - def test_058_single_proper_superset(self): - """Iomemcon query with single mem addr proper superset""" - q = IomemconQuery( - self.p, addr=(50800, 50802), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50801, 50801)], addr) - - def test_058_single_proper_superset_edge1(self): - """Iomemcon query with single mem addr proper superset, equal edge case""" - q = IomemconQuery( - self.p, addr=(50801, 50801), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([], addr) - - def test_058_single_proper_superset_edge2(self): - """Iomemcon query with single mem addr proper superset, low equal edge case""" - q = IomemconQuery( - self.p, addr=(50801, 50802), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50801, 50801)], addr) - - def test_058_single_proper_superset_edge3(self): - """Iomemcon query with single mem addr proper superset, high equal edge case""" - q = IomemconQuery( - self.p, addr=(50800, 50801), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50801, 50801)], addr) - - def test_059_range_proper_superset(self): - """Iomemcon query with range proper superset""" - q = IomemconQuery( - self.p, addr=(50900, 50911), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50901, 50910)], addr) - - def test_059_range_proper_superset_edge1(self): - """Iomemcon query with range proper superset, equal edge case""" - q = IomemconQuery( - self.p, addr=(50901, 50910), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([], addr) - - def test_059_range_proper_superset_edge2(self): - """Iomemcon query with range proper superset, equal high mem addr edge case""" - q = IomemconQuery( - self.p, addr=(50900, 50910), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50901, 50910)], addr) - - def test_059_range_proper_superset_edge3(self): - """Iomemcon query with range proper superset, equal low mem addr edge case""" - q = IomemconQuery( - self.p, addr=(50901, 50911), addr_superset=True, addr_proper=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(50901, 50910)], addr) - - def test_060_single_overlap(self): - """Iomemcon query with single overlap""" - q = IomemconQuery(self.p, addr=(60001, 60001), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60001, 60001)], addr) - - def test_060_single_overlap_edge1(self): - """Iomemcon query with single overlap, range match low""" - q = IomemconQuery(self.p, addr=(60001, 60002), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60001, 60001)], addr) - - def test_060_single_overlap_edge2(self): - """Iomemcon query with single overlap, range match high""" - q = IomemconQuery(self.p, addr=(60000, 60001), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60001, 60001)], addr) - - def test_060_single_overlap_edge3(self): - """Iomemcon query with single overlap, range match proper superset""" - q = IomemconQuery(self.p, addr=(60000, 60002), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60001, 60001)], addr) - - def test_061_range_overlap_low_half(self): - """Iomemcon query with range overlap, low half match""" - q = IomemconQuery(self.p, addr=(60100, 60105), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60101, 60110)], addr) - - def test_062_range_overlap_high_half(self): - """Iomemcon query with range overlap, high half match""" - q = IomemconQuery(self.p, addr=(60205, 60211), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60200, 60210)], addr) - - def test_063_range_overlap_middle(self): - """Iomemcon query with range overlap, middle match""" - q = IomemconQuery(self.p, addr=(60305, 60308), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60300, 60310)], addr) - - def test_064_range_overlap_equal(self): - """Iomemcon query with range overlap, equal match""" - q = IomemconQuery(self.p, addr=(60400, 60410), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60400, 60410)], addr) - - def test_065_range_overlap_superset(self): - """Iomemcon query with range overlap, superset match""" - q = IomemconQuery(self.p, addr=(60500, 60510), addr_overlap=True) - - addr = sorted(p.addr for p in q.results()) - self.assertListEqual([IomemconRange(60501, 60509)], addr) diff --git a/tests/test_ioportconquery.py b/tests/test_ioportconquery.py deleted file mode 100644 index d472c55a..00000000 --- a/tests/test_ioportconquery.py +++ /dev/null @@ -1,432 +0,0 @@ -# Derived from tests/portconquery.py -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import IoportconQuery, IoportconRange - -from .policyrep.util import compile_policy - - -class IoportconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/ioportconquery.conf", xen=True) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Ioportcon query with no criteria""" - # query with no parameters gets all ports. - rules = sorted(self.p.ioportcons()) - - q = IoportconQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_010_user_exact(self): - """Portcon query with context user exact match""" - q = IoportconQuery(self.p, user="user10", user_regex=False) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(10, 10)], ports) - - def test_011_user_regex(self): - """Portcon query with context user regex match""" - q = IoportconQuery(self.p, user="user11(a|b)", user_regex=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(11, 11), IoportconRange(11000, 11000)], ports) - - def test_020_role_exact(self): - """Portcon query with context role exact match""" - q = IoportconQuery(self.p, role="role20_r", role_regex=False) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(20, 20)], ports) - - def test_021_role_regex(self): - """Portcon query with context role regex match""" - q = IoportconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(21, 21), IoportconRange(21001, 21001)], ports) - - def test_030_type_exact(self): - """Portcon query with context type exact match""" - q = IoportconQuery(self.p, type_="type30", type_regex=False) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(30, 30)], ports) - - def test_031_type_regex(self): - """Portcon query with context type regex match""" - q = IoportconQuery(self.p, type_="type31(b|c)", type_regex=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(31000, 31000), IoportconRange(31001, 31001)], ports) - - def test_040_range_exact(self): - """Portcon query with context range exact match""" - q = IoportconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(40, 40)], ports) - - def test_041_range_overlap1(self): - """Portcon query with context range overlap match (equal)""" - q = IoportconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(41, 41)], ports) - - def test_041_range_overlap2(self): - """Portcon query with context range overlap match (subset)""" - q = IoportconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(41, 41)], ports) - - def test_041_range_overlap3(self): - """Portcon query with context range overlap match (superset)""" - q = IoportconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(41, 41)], ports) - - def test_041_range_overlap4(self): - """Portcon query with context range overlap match (overlap low level)""" - q = IoportconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(41, 41)], ports) - - def test_041_range_overlap5(self): - """Portcon query with context range overlap match (overlap high level)""" - q = IoportconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(41, 41)], ports) - - def test_042_range_subset1(self): - """Portcon query with context range subset match""" - q = IoportconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(42, 42)], ports) - - def test_042_range_subset2(self): - """Portcon query with context range subset match (equal)""" - q = IoportconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(42, 42)], ports) - - def test_043_range_superset1(self): - """Portcon query with context range superset match""" - q = IoportconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(43, 43)], ports) - - def test_043_range_superset2(self): - """Portcon query with context range superset match (equal)""" - q = IoportconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(43, 43)], ports) - - def test_044_range_proper_subset1(self): - """Portcon query with context range proper subset match""" - q = IoportconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(44, 44)], ports) - - def test_044_range_proper_subset2(self): - """Portcon query with context range proper subset match (equal)""" - q = IoportconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_044_range_proper_subset3(self): - """Portcon query with context range proper subset match (equal low only)""" - q = IoportconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(44, 44)], ports) - - def test_044_range_proper_subset4(self): - """Portcon query with context range proper subset match (equal high only)""" - q = IoportconQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(44, 44)], ports) - - def test_045_range_proper_superset1(self): - """Portcon query with context range proper superset match""" - q = IoportconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(45, 45)], ports) - - def test_045_range_proper_superset2(self): - """Portcon query with context range proper superset match (equal)""" - q = IoportconQuery(self.p, - range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_045_range_proper_superset3(self): - """Portcon query with context range proper superset match (equal low)""" - q = IoportconQuery(self.p, - range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(45, 45)], ports) - - def test_045_range_proper_superset4(self): - """Portcon query with context range proper superset match (equal high)""" - q = IoportconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(45, 45)], ports) - - def test_050_single_equal(self): - """Portcon query with single port exact match""" - q = IoportconQuery(self.p, ports=(50, 50)) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50, 50)], ports) - - def test_051_range_equal(self): - """Portcon query with port range exact match""" - q = IoportconQuery(self.p, ports=(50100, 50110)) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50100, 50110)], ports) - - def test_052_single_subset(self): - """Portcon query with single port subset""" - q = IoportconQuery(self.p, ports=(50200, 50200), ports_subset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50200, 50200)], ports) - - def test_053_range_subset(self): - """Portcon query with range subset""" - q = IoportconQuery(self.p, ports=(50301, 50309), ports_subset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50300, 50310)], ports) - - def test_053_range_subset_edge1(self): - """Portcon query with range subset, equal edge case""" - q = IoportconQuery(self.p, ports=(50300, 50310), ports_subset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50300, 50310)], ports) - - def test_054_single_proper_subset(self): - """Portcon query with single port proper subset""" - q = IoportconQuery( - self.p, ports=(50400, 50400), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_055_range_proper_subset(self): - """Portcon query with range proper subset""" - q = IoportconQuery( - self.p, ports=(50501, 50509), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50500, 50510)], ports) - - def test_055_range_proper_subset_edge1(self): - """Portcon query with range proper subset, equal edge case""" - q = IoportconQuery( - self.p, ports=(50500, 50510), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_055_range_proper_subset_edge2(self): - """Portcon query with range proper subset, low equal edge case""" - q = IoportconQuery( - self.p, ports=(50500, 50509), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50500, 50510)], ports) - - def test_055_range_proper_subset_edge3(self): - """Portcon query with range proper subset, high equal edge case""" - q = IoportconQuery( - self.p, ports=(50501, 50510), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50500, 50510)], ports) - - def test_056_single_superset(self): - """Portcon query with single port superset""" - q = IoportconQuery(self.p, ports=(50600, 50602), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50601, 50601)], ports) - - def test_056_single_superset_edge1(self): - """Portcon query with single port superset, equal edge case""" - q = IoportconQuery(self.p, ports=(50601, 50601), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50601, 50601)], ports) - - def test_057_range_superset(self): - """Portcon query with range superset""" - q = IoportconQuery(self.p, ports=(50700, 50711), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50700, 50710)], ports) - - def test_057_range_superset_edge1(self): - """Portcon query with range superset, equal edge case""" - q = IoportconQuery(self.p, ports=(50700, 50710), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50700, 50710)], ports) - - def test_058_single_proper_superset(self): - """Portcon query with single port proper superset""" - q = IoportconQuery( - self.p, ports=(50800, 50802), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50801, 50801)], ports) - - def test_058_single_proper_superset_edge1(self): - """Portcon query with single port proper superset, equal edge case""" - q = IoportconQuery( - self.p, ports=(50801, 50801), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_058_single_proper_superset_edge2(self): - """Portcon query with single port proper superset, low equal edge case""" - q = IoportconQuery( - self.p, ports=(50801, 50802), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50801, 50801)], ports) - - def test_058_single_proper_superset_edge3(self): - """Portcon query with single port proper superset, high equal edge case""" - q = IoportconQuery( - self.p, ports=(50800, 50801), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50801, 50801)], ports) - - def test_059_range_proper_superset(self): - """Portcon query with range proper superset""" - q = IoportconQuery( - self.p, ports=(50900, 50911), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50901, 50910)], ports) - - def test_059_range_proper_superset_edge1(self): - """Portcon query with range proper superset, equal edge case""" - q = IoportconQuery( - self.p, ports=(50901, 50910), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_059_range_proper_superset_edge2(self): - """Portcon query with range proper superset, equal high port edge case""" - q = IoportconQuery( - self.p, ports=(50900, 50910), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50901, 50910)], ports) - - def test_059_range_proper_superset_edge3(self): - """Portcon query with range proper superset, equal low port edge case""" - q = IoportconQuery( - self.p, ports=(50901, 50911), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(50901, 50910)], ports) - - def test_060_single_overlap(self): - """Portcon query with single overlap""" - q = IoportconQuery(self.p, ports=(60001, 60001), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60001, 60001)], ports) - - def test_060_single_overlap_edge1(self): - """Portcon query with single overlap, range match low""" - q = IoportconQuery(self.p, ports=(60001, 60002), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60001, 60001)], ports) - - def test_060_single_overlap_edge2(self): - """Portcon query with single overlap, range match high""" - q = IoportconQuery(self.p, ports=(60000, 60001), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60001, 60001)], ports) - - def test_060_single_overlap_edge3(self): - """Portcon query with single overlap, range match proper superset""" - q = IoportconQuery(self.p, ports=(60000, 60002), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60001, 60001)], ports) - - def test_061_range_overlap_low_half(self): - """Portcon query with range overlap, low half match""" - q = IoportconQuery(self.p, ports=(60100, 60105), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60101, 60110)], ports) - - def test_062_range_overlap_high_half(self): - """Portcon query with range overlap, high half match""" - q = IoportconQuery(self.p, ports=(60205, 60211), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60200, 60210)], ports) - - def test_063_range_overlap_middle(self): - """Portcon query with range overlap, middle match""" - q = IoportconQuery(self.p, ports=(60305, 60308), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60300, 60310)], ports) - - def test_064_range_overlap_equal(self): - """Portcon query with range overlap, equal match""" - q = IoportconQuery(self.p, ports=(60400, 60410), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60400, 60410)], ports) - - def test_065_range_overlap_superset(self): - """Portcon query with range overlap, superset match""" - q = IoportconQuery(self.p, ports=(60500, 60510), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([IoportconRange(60501, 60509)], ports) diff --git a/tests/test_mlsrulequery.py b/tests/test_mlsrulequery.py deleted file mode 100644 index 4d9fb2ae..00000000 --- a/tests/test_mlsrulequery.py +++ /dev/null @@ -1,295 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import MLSRuleQuery -from setools import MLSRuletype as RT - -from . import mixins -from .policyrep.util import compile_policy - -# Note: the test policy has been written assuming range_transition -# statements could have attributes. However, range_transition -# statements are always expanded, so the below unit tests -# have been adjusted to this fact (hence a "FAIL" in one of the -# expected type names) - - -class MLSRuleQueryTest(mixins.ValidateRule, unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/mlsrulequery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """MLS rule query with no criteria.""" - # query with no parameters gets all MLS rules. - rules = sorted(self.p.mlsrules()) - - q = MLSRuleQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_001_source_direct(self): - """MLS rule query with exact, direct, source match.""" - q = MLSRuleQuery( - self.p, source="test1s", source_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test1s", "test1t", "infoflow", "s0") - - def test_003_source_direct_regex(self): - """MLS rule query with regex, direct, source match.""" - q = MLSRuleQuery( - self.p, source="test3(s|aS)", source_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RT.range_transition, "test3s", "test3t", "infoflow", "s1") - self.validate_rule(r[1], RT.range_transition, "test3s", "test3t", "infoflow2", "s2") - - def test_005_issue111(self): - """MLS rule query with attribute source criteria, indirect match.""" - # https://github.com/TresysTechnology/setools/issues/111 - q = MLSRuleQuery(self.p, source="test5b", source_indirect=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RT.range_transition, "test5t1", "test5target", "infoflow", "s1") - self.validate_rule(r[1], RT.range_transition, "test5t2", "test5target", "infoflow7", "s2") - - def test_010_target_direct(self): - """MLS rule query with exact, direct, target match.""" - q = MLSRuleQuery( - self.p, target="test10t", target_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RT.range_transition, "test10s", "test10t", "infoflow", "s0") - self.validate_rule(r[1], RT.range_transition, "test10s", "test10t", "infoflow2", "s1") - - def test_012_target_direct_regex(self): - """MLS rule query with regex, direct, target match.""" - q = MLSRuleQuery( - self.p, target="test12a.*", target_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test12s", "test12aFAIL", "infoflow", "s2") - - def test_014_issue111(self): - """MLS rule query with attribute target criteria, indirect match.""" - # https://github.com/TresysTechnology/setools/issues/111 - q = MLSRuleQuery(self.p, target="test14b", target_indirect=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RT.range_transition, "test14source", "test14t1", "infoflow", "s1") - self.validate_rule(r[1], RT.range_transition, "test14source", "test14t2", "infoflow7", "s2") - - @unittest.skip("Setting tclass to a string is no longer supported.") - def test_020_class(self): - """MLS rule query with exact object class match.""" - q = MLSRuleQuery(self.p, tclass="infoflow7", tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test20", "test20", "infoflow7", "s1") - - def test_021_class_list(self): - """MLS rule query with object class list match.""" - q = MLSRuleQuery( - self.p, tclass=["infoflow3", "infoflow4"], tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RT.range_transition, "test21", "test21", "infoflow3", "s2") - self.validate_rule(r[1], RT.range_transition, "test21", "test21", "infoflow4", "s1") - - def test_022_class_regex(self): - """MLS rule query with object class regex match.""" - q = MLSRuleQuery(self.p, tclass="infoflow(5|6)", tclass_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RT.range_transition, "test22", "test22", "infoflow5", "s1") - self.validate_rule(r[1], RT.range_transition, "test22", "test22", "infoflow6", "s2") - - def test_040_range_exact(self): - """MLS rule query with context range exact match""" - q = MLSRuleQuery(self.p, default="s40:c1 - s40:c0.c4") - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test40", "test40", "infoflow", - "s40:c1 - s40:c0.c4") - - def test_041_range_overlap1(self): - """MLS rule query with context range overlap match (equal)""" - q = MLSRuleQuery(self.p, default="s41:c1 - s41:c0.c4", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test41", "test41", "infoflow", - "s41:c1 - s41:c1.c3") - - def test_041_range_overlap2(self): - """MLS rule query with context range overlap match (subset)""" - q = MLSRuleQuery(self.p, default="s41:c1,c2 - s41:c0.c3", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test41", "test41", "infoflow", - "s41:c1 - s41:c1.c3") - - def test_041_range_overlap3(self): - """MLS rule query with context range overlap match (superset)""" - q = MLSRuleQuery(self.p, default="s41 - s41:c0.c4", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test41", "test41", "infoflow", - "s41:c1 - s41:c1.c3") - - def test_041_range_overlap4(self): - """MLS rule query with context range overlap match (overlap low level)""" - q = MLSRuleQuery(self.p, default="s41 - s41:c1,c2", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test41", "test41", "infoflow", - "s41:c1 - s41:c1.c3") - - def test_041_range_overlap5(self): - """MLS rule query with context range overlap match (overlap high level)""" - q = MLSRuleQuery(self.p, default="s41:c1,c2 - s41:c0.c4", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test41", "test41", "infoflow", - "s41:c1 - s41:c1.c3") - - def test_042_range_subset1(self): - """MLS rule query with context range subset match""" - q = MLSRuleQuery(self.p, default="s42:c1,c2 - s42:c0.c3", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test42", "test42", "infoflow", - "s42:c1 - s42:c1.c3") - - def test_042_range_subset2(self): - """MLS rule query with context range subset match (equal)""" - q = MLSRuleQuery(self.p, default="s42:c1 - s42:c1.c3", default_overlap=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test42", "test42", "infoflow", - "s42:c1 - s42:c1.c3") - - def test_043_range_superset1(self): - """MLS rule query with context range superset match""" - q = MLSRuleQuery(self.p, default="s43 - s43:c0.c4", default_superset=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test43", "test43", "infoflow", - "s43:c1 - s43:c1.c3") - - def test_043_range_superset2(self): - """MLS rule query with context range superset match (equal)""" - q = MLSRuleQuery(self.p, default="s43:c1 - s43:c1.c3", default_superset=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test43", "test43", "infoflow", - "s43:c1 - s43:c1.c3") - - def test_044_range_proper_subset1(self): - """MLS rule query with context range proper subset match""" - q = MLSRuleQuery(self.p, default="s44:c1,c2", default_subset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test44", "test44", "infoflow", - "s44:c1 - s44:c1.c3") - - def test_044_range_proper_subset2(self): - """MLS rule query with context range proper subset match (equal)""" - q = MLSRuleQuery(self.p, - default="s44:c1 - s44:c1.c3", default_subset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 0) - - def test_044_range_proper_subset3(self): - """MLS rule query with context range proper subset match (equal low only)""" - q = MLSRuleQuery(self.p, - default="s44:c1 - s44:c1.c2", default_subset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test44", "test44", "infoflow", - "s44:c1 - s44:c1.c3") - - def test_044_range_proper_subset4(self): - """MLS rule query with context range proper subset match (equal high only)""" - q = MLSRuleQuery(self.p, - default="s44:c1,c2 - s44:c1.c3", default_subset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test44", "test44", "infoflow", - "s44:c1 - s44:c1.c3") - - def test_045_range_proper_superset1(self): - """MLS rule query with context range proper superset match""" - q = MLSRuleQuery(self.p, - default="s45 - s45:c0.c4", default_superset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test45", "test45", "infoflow", - "s45:c1 - s45:c1.c3") - - def test_045_range_proper_superset2(self): - """MLS rule query with context range proper superset match (equal)""" - q = MLSRuleQuery(self.p, - default="s45:c1 - s45:c1.c3", default_superset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 0) - - def test_045_range_proper_superset3(self): - """MLS rule query with context range proper superset match (equal low)""" - q = MLSRuleQuery(self.p, - default="s45:c1 - s45:c1.c4", default_superset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test45", "test45", "infoflow", - "s45:c1 - s45:c1.c3") - - def test_045_range_proper_superset4(self): - """MLS rule query with context range proper superset match (equal high)""" - q = MLSRuleQuery(self.p, - default="s45 - s45:c1.c3", default_superset=True, default_proper=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RT.range_transition, "test45", "test45", "infoflow", - "s45:c1 - s45:c1.c3") - - def test_900_invalid_ruletype(self): - """MLS rule query with invalid rule type.""" - with self.assertRaises(KeyError): - q = MLSRuleQuery(self.p, ruletype=["type_transition"]) diff --git a/tests/test_netifconquery.py b/tests/test_netifconquery.py deleted file mode 100644 index 4cdb9390..00000000 --- a/tests/test_netifconquery.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import NetifconQuery - -from .policyrep.util import compile_policy - - -class NetifconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/netifconquery.conf") - - def test_000_unset(self): - """Netifcon query with no criteria""" - # query with no parameters gets all netifs. - netifs = sorted(self.p.netifcons()) - - q = NetifconQuery(self.p) - q_netifs = sorted(q.results()) - - self.assertListEqual(netifs, q_netifs) - - def test_001_name_exact(self): - """Netifcon query with exact match""" - q = NetifconQuery(self.p, name="test1", name_regex=False) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test1"], netifs) - - def test_002_name_regex(self): - """Netifcon query with regex match""" - q = NetifconQuery(self.p, name="test2(a|b)", name_regex=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test2a", "test2b"], netifs) - - def test_010_user_exact(self): - """Netifcon query with context user exact match""" - q = NetifconQuery(self.p, user="user10", user_regex=False) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test10"], netifs) - - def test_011_user_regex(self): - """Netifcon query with context user regex match""" - q = NetifconQuery(self.p, user="user11(a|b)", user_regex=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test11a", "test11b"], netifs) - - def test_020_role_exact(self): - """Netifcon query with context role exact match""" - q = NetifconQuery(self.p, role="role20_r", role_regex=False) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test20"], netifs) - - def test_021_role_regex(self): - """Netifcon query with context role regex match""" - q = NetifconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test21a", "test21c"], netifs) - - def test_030_type_exact(self): - """Netifcon query with context type exact match""" - q = NetifconQuery(self.p, type_="type30", type_regex=False) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test30"], netifs) - - def test_031_type_regex(self): - """Netifcon query with context type regex match""" - q = NetifconQuery(self.p, type_="type31(b|c)", type_regex=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test31b", "test31c"], netifs) - - def test_040_range_exact(self): - """Netifcon query with context range exact match""" - q = NetifconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test40"], netifs) - - def test_041_range_overlap1(self): - """Netifcon query with context range overlap match (equal)""" - q = NetifconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test41"], netifs) - - def test_041_range_overlap2(self): - """Netifcon query with context range overlap match (subset)""" - q = NetifconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test41"], netifs) - - def test_041_range_overlap3(self): - """Netifcon query with context range overlap match (superset)""" - q = NetifconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test41"], netifs) - - def test_041_range_overlap4(self): - """Netifcon query with context range overlap match (overlap low level)""" - q = NetifconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test41"], netifs) - - def test_041_range_overlap5(self): - """Netifcon query with context range overlap match (overlap high level)""" - q = NetifconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test41"], netifs) - - def test_042_range_subset1(self): - """Netifcon query with context range subset match""" - q = NetifconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test42"], netifs) - - def test_042_range_subset2(self): - """Netifcon query with context range subset match (equal)""" - q = NetifconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test42"], netifs) - - def test_043_range_superset1(self): - """Netifcon query with context range superset match""" - q = NetifconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test43"], netifs) - - def test_043_range_superset2(self): - """Netifcon query with context range superset match (equal)""" - q = NetifconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test43"], netifs) - - def test_044_range_proper_subset1(self): - """Netifcon query with context range proper subset match""" - q = NetifconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test44"], netifs) - - def test_044_range_proper_subset2(self): - """Netifcon query with context range proper subset match (equal)""" - q = NetifconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual([], netifs) - - def test_044_range_proper_subset3(self): - """Netifcon query with context range proper subset match (equal low only)""" - q = NetifconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test44"], netifs) - - def test_044_range_proper_subset4(self): - """Netifcon query with context range proper subset match (equal high only)""" - q = NetifconQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test44"], netifs) - - def test_045_range_proper_superset1(self): - """Netifcon query with context range proper superset match""" - q = NetifconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test45"], netifs) - - def test_045_range_proper_superset2(self): - """Netifcon query with context range proper superset match (equal)""" - q = NetifconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual([], netifs) - - def test_045_range_proper_superset3(self): - """Netifcon query with context range proper superset match (equal low)""" - q = NetifconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test45"], netifs) - - def test_045_range_proper_superset4(self): - """Netifcon query with context range proper superset match (equal high)""" - q = NetifconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - netifs = sorted(s.netif for s in q.results()) - self.assertListEqual(["test45"], netifs) diff --git a/tests/test_nodeconquery.py b/tests/test_nodeconquery.py deleted file mode 100644 index 7c0f40d6..00000000 --- a/tests/test_nodeconquery.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# Copyright 2017, Chris PeBenito -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest -from socket import AF_INET6 -from ipaddress import IPv4Network, IPv6Network - -from setools import NodeconQuery - -from .policyrep.util import compile_policy - - -class NodeconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/nodeconquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Nodecon query with no criteria""" - # query with no parameters gets all nodecons. - nodecons = sorted(self.p.nodecons()) - - q = NodeconQuery(self.p) - q_nodecons = sorted(q.results()) - - self.assertListEqual(nodecons, q_nodecons) - - def test_001_ip_version(self): - """Nodecon query with IP version match.""" - q = NodeconQuery(self.p, ip_version=AF_INET6) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv6Network("1100::/16"), IPv6Network("1110::/16")], nodecons) - - def test_020_user_exact(self): - """Nodecon query with context user exact match""" - q = NodeconQuery(self.p, user="user20", user_regex=False) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.20.1/32")], nodecons) - - def test_021_user_regex(self): - """Nodecon query with context user regex match""" - q = NodeconQuery(self.p, user="user21(a|b)", user_regex=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.21.1/32"), IPv4Network("10.1.21.2/32")], nodecons) - - def test_030_role_exact(self): - """Nodecon query with context role exact match""" - q = NodeconQuery(self.p, role="role30_r", role_regex=False) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.30.1/32")], nodecons) - - def test_031_role_regex(self): - """Nodecon query with context role regex match""" - q = NodeconQuery(self.p, role="role31(a|c)_r", role_regex=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.31.1/32"), IPv4Network("10.1.31.3/32")], nodecons) - - def test_040_type_exact(self): - """Nodecon query with context type exact match""" - q = NodeconQuery(self.p, type_="type40", type_regex=False) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.40.1/32")], nodecons) - - def test_041_type_regex(self): - """Nodecon query with context type regex match""" - q = NodeconQuery(self.p, type_="type41(b|c)", type_regex=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.41.2/32"), IPv4Network("10.1.41.3/32")], nodecons) - - def test_050_range_exact(self): - """Nodecon query with context range exact match""" - q = NodeconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.50.1/32")], nodecons) - - def test_051_range_overlap1(self): - """Nodecon query with context range overlap match (equal)""" - q = NodeconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.51.1/32")], nodecons) - - def test_051_range_overlap2(self): - """Nodecon query with context range overlap match (subset)""" - q = NodeconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.51.1/32")], nodecons) - - def test_051_range_overlap3(self): - """Nodecon query with context range overlap match (superset)""" - q = NodeconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.51.1/32")], nodecons) - - def test_051_range_overlap4(self): - """Nodecon query with context range overlap match (overlap low level)""" - q = NodeconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.51.1/32")], nodecons) - - def test_051_range_overlap5(self): - """Nodecon query with context range overlap match (overlap high level)""" - q = NodeconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.51.1/32")], nodecons) - - def test_052_range_subset1(self): - """Nodecon query with context range subset match""" - q = NodeconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.52.1/32")], nodecons) - - def test_052_range_subset2(self): - """Nodecon query with context range subset match (equal)""" - q = NodeconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.52.1/32")], nodecons) - - def test_053_range_superset1(self): - """Nodecon query with context range superset match""" - q = NodeconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.53.1/32")], nodecons) - - def test_053_range_superset2(self): - """Nodecon query with context range superset match (equal)""" - q = NodeconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.53.1/32")], nodecons) - - def test_054_range_proper_subset1(self): - """Nodecon query with context range proper subset match""" - q = NodeconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.54.1/32")], nodecons) - - def test_054_range_proper_subset2(self): - """Nodecon query with context range proper subset match (equal)""" - q = NodeconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([], nodecons) - - def test_054_range_proper_subset3(self): - """Nodecon query with context range proper subset match (equal low only)""" - q = NodeconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.54.1/32")], nodecons) - - def test_054_range_proper_subset4(self): - """Nodecon query with context range proper subset match (equal high only)""" - q = NodeconQuery(self.p, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.54.1/32")], nodecons) - - def test_055_range_proper_superset1(self): - """Nodecon query with context range proper superset match""" - q = NodeconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.55.1/32")], nodecons) - - def test_055_range_proper_superset2(self): - """Nodecon query with context range proper superset match (equal)""" - q = NodeconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([], nodecons) - - def test_055_range_proper_superset3(self): - """Nodecon query with context range proper superset match (equal low)""" - q = NodeconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.55.1/32")], nodecons) - - def test_055_range_proper_superset4(self): - """Nodecon query with context range proper superset match (equal high)""" - q = NodeconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("10.1.55.1/32")], nodecons) - - def test_100_v4network_equal(self): - """Nodecon query with IPv4 equal network""" - q = NodeconQuery(self.p, network="192.168.1.0/24", network_overlap=False) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("192.168.1.0/24")], nodecons) - - def test_101_v4network_overlap(self): - """Nodecon query with IPv4 network overlap""" - q = NodeconQuery(self.p, network="192.168.201.0/24", network_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv4Network("192.168.200.0/22")], nodecons) - - def test_110_v6network_equal(self): - """Nodecon query with IPv6 equal network""" - q = NodeconQuery(self.p, network="1100::/16", network_overlap=False) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv6Network("1100::/16")], nodecons) - - def test_111_v6network_overlap(self): - """Nodecon query with IPv6 network overlap""" - q = NodeconQuery(self.p, network="1110:8000::/17", network_overlap=True) - - nodecons = sorted(n.network for n in q.results()) - self.assertListEqual([IPv6Network("1110::/16")], nodecons) diff --git a/tests/test_objclassquery.py b/tests/test_objclassquery.py deleted file mode 100644 index a0f7284b..00000000 --- a/tests/test_objclassquery.py +++ /dev/null @@ -1,111 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import ObjClassQuery - -from .policyrep.util import compile_policy - - -class ObjClassQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/objclassquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Class query with no criteria.""" - # query with no parameters gets all types. - classes = sorted(self.p.classes()) - - q = ObjClassQuery(self.p) - q_classes = sorted(q.results()) - - self.assertListEqual(classes, q_classes) - - def test_001_name_exact(self): - """Class query with exact name match.""" - q = ObjClassQuery(self.p, name="infoflow") - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow"], classes) - - def test_002_name_regex(self): - """Class query with regex name match.""" - q = ObjClassQuery(self.p, name="infoflow(2|3)", name_regex=True) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow2", "infoflow3"], classes) - - def test_010_common_exact(self): - """Class query with exact common name match.""" - q = ObjClassQuery(self.p, common="infoflow") - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow", "infoflow2", - "infoflow4", "infoflow7"], classes) - - def test_011_common_regex(self): - """Class query with regex common name match.""" - q = ObjClassQuery(self.p, common="com_[ab]", common_regex=True) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow5", "infoflow6"], classes) - - def test_020_perm_indirect_intersect(self): - """Class query with indirect, intersect permission name patch.""" - q = ObjClassQuery( - self.p, perms=set(["send"]), perms_indirect=True, perms_equal=False) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow6"], classes) - - def test_021_perm_direct_intersect(self): - """Class query with direct, intersect permission name patch.""" - q = ObjClassQuery( - self.p, perms=set(["super_r"]), perms_indirect=False, perms_equal=False) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow2", "infoflow4", "infoflow8"], classes) - - def test_022_perm_indirect_equal(self): - """Class query with indirect, equal permission name patch.""" - q = ObjClassQuery(self.p, perms=set( - ["low_w", "med_w", "hi_w", "low_r", "med_r", "hi_r", "unmapped"]), - perms_indirect=True, perms_equal=True) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow7"], classes) - - def test_023_perm_direct_equal(self): - """Class query with direct, equal permission name patch.""" - q = ObjClassQuery(self.p, perms=set( - ["super_r", "super_w"]), perms_indirect=False, perms_equal=True) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow2", "infoflow8"], classes) - - def test_024_perm_indirect_regex(self): - """Class query with indirect, regex permission name patch.""" - q = ObjClassQuery( - self.p, perms="(send|setattr)", perms_indirect=True, perms_regex=True) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow6", "infoflow9"], classes) - - def test_025_perm_direct_regex(self): - """Class query with direct, regex permission name patch.""" - q = ObjClassQuery( - self.p, perms="(read|super_r)", perms_indirect=False, perms_regex=True) - - classes = sorted(str(c) for c in q.results()) - self.assertListEqual(["infoflow10", "infoflow2", - "infoflow4", "infoflow8"], - classes) diff --git a/tests/test_pcideviceconquery.py b/tests/test_pcideviceconquery.py deleted file mode 100644 index a8d4d7e0..00000000 --- a/tests/test_pcideviceconquery.py +++ /dev/null @@ -1,206 +0,0 @@ -# Derived from tests/portconquery.py -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import PcideviceconQuery - -from .policyrep.util import compile_policy - - -class PcideviceconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/pcideviceconquery.conf", xen=True) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Pcidevicecon query with no criteria""" - # query with no parameters gets all PCI devices. - rules = sorted(self.p.pcidevicecons()) - - q = PcideviceconQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_010_user_exact(self): - """Pcidevicecon query with context user exact match""" - q = PcideviceconQuery(self.p, user="user10", user_regex=False) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(10)], device) - - def test_011_user_regex(self): - """Pcidevicecon query with context user regex match""" - q = PcideviceconQuery(self.p, user="user11(a|b)", user_regex=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(11), (11000)], device) - - def test_020_role_exact(self): - """Pcidevicecon query with context role exact match""" - q = PcideviceconQuery(self.p, role="role20_r", role_regex=False) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(20)], device) - - def test_021_role_regex(self): - """Pcidevicecon query with context role regex match""" - q = PcideviceconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(21), (21001)], device) - - def test_030_type_exact(self): - """Pcidevicecon query with context type exact match""" - q = PcideviceconQuery(self.p, type_="type30", type_regex=False) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(30)], device) - - def test_031_type_regex(self): - """Pcidevicecon query with context type regex match""" - q = PcideviceconQuery(self.p, type_="type31(b|c)", type_regex=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(31000), (31001)], device) - - def test_040_range_exact(self): - """Pcidevicecon query with context range exact match""" - q = PcideviceconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(40)], device) - - def test_041_range_overlap1(self): - """Pcidevicecon query with context range overlap match (equal)""" - q = PcideviceconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(41)], device) - - def test_041_range_overlap2(self): - """Pcidevicecon query with context range overlap match (subset)""" - q = PcideviceconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(41)], device) - - def test_041_range_overlap3(self): - """Pcidevicecon query with context range overlap match (superset)""" - q = PcideviceconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(41)], device) - - def test_041_range_overlap4(self): - """Pcidevicecon query with context range overlap match (overlap low level)""" - q = PcideviceconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(41)], device) - - def test_041_range_overlap5(self): - """Pcidevicecon query with context range overlap match (overlap high level)""" - q = PcideviceconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(41)], device) - - def test_042_range_subset1(self): - """Pcidevicecon query with context range subset match""" - q = PcideviceconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(42)], device) - - def test_042_range_subset2(self): - """Pcidevicecon query with context range subset match (equal)""" - q = PcideviceconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(42)], device) - - def test_043_range_superset1(self): - """Pcidevicecon query with context range superset match""" - q = PcideviceconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(43)], device) - - def test_043_range_superset2(self): - """Pcidevicecon query with context range superset match (equal)""" - q = PcideviceconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(43)], device) - - def test_044_range_proper_subset1(self): - """Pcidevicecon query with context range proper subset match""" - q = PcideviceconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(44)], device) - - def test_044_range_proper_subset2(self): - """Pcidevicecon query with context range proper subset match (equal)""" - q = PcideviceconQuery(self.p, - range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([], device) - - def test_044_range_proper_subset3(self): - """Pcidevicecon query with context range proper subset match (equal low only)""" - q = PcideviceconQuery(self.p, - range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(44)], device) - - def test_044_range_proper_subset4(self): - """Pcidevicecon query with context range proper subset match (equal high only)""" - q = PcideviceconQuery(self.p, - range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(44)], device) - - def test_045_range_proper_superset1(self): - """Pcidevicecon query with context range proper superset match""" - q = PcideviceconQuery(self.p, - range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(45)], device) - - def test_045_range_proper_superset2(self): - """Pcidevicecon query with context range proper superset match (equal)""" - q = PcideviceconQuery(self.p, - range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([], device) - - def test_045_range_proper_superset3(self): - """Pcidevicecon query with context range proper superset match (equal low)""" - q = PcideviceconQuery(self.p, - range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(45)], device) - - def test_045_range_proper_superset4(self): - """Pcidevicecon query with context range proper superset match (equal high)""" - q = PcideviceconQuery(self.p, - range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - device = sorted(p.device for p in q.results()) - self.assertListEqual([(45)], device) diff --git a/tests/test_pirqconquery.py b/tests/test_pirqconquery.py deleted file mode 100644 index 21dce3db..00000000 --- a/tests/test_pirqconquery.py +++ /dev/null @@ -1,199 +0,0 @@ -# Derived from tests/portconquery.py -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import PirqconQuery - -from .policyrep.util import compile_policy - - -class PirqconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/pirqconquery.conf", xen=True) - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Pirqcon query with no criteria""" - # query with no parameters gets all PCI irqs. - rules = sorted(self.p.pirqcons()) - - q = PirqconQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_010_user_exact(self): - """Pirqcon query with context user exact match""" - q = PirqconQuery(self.p, user="user10", user_regex=False) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(10)], irq) - - def test_011_user_regex(self): - """Pirqcon query with context user regex match""" - q = PirqconQuery(self.p, user="user11(a|b)", user_regex=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(11), (11000)], irq) - - def test_020_role_exact(self): - """Pirqcon query with context role exact match""" - q = PirqconQuery(self.p, role="role20_r", role_regex=False) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(20)], irq) - - def test_021_role_regex(self): - """Pirqcon query with context role regex match""" - q = PirqconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(21), (21001)], irq) - - def test_030_type_exact(self): - """Pirqcon query with context type exact match""" - q = PirqconQuery(self.p, type_="type30", type_regex=False) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(30)], irq) - - def test_031_type_regex(self): - """Pirqcon query with context type regex match""" - q = PirqconQuery(self.p, type_="type31(b|c)", type_regex=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(31000), (31001)], irq) - - def test_040_range_exact(self): - """Pirqcon query with context range exact match""" - q = PirqconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(40)], irq) - - def test_041_range_overlap1(self): - """Pirqcon query with context range overlap match (equal)""" - q = PirqconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(41)], irq) - - def test_041_range_overlap2(self): - """Pirqcon query with context range overlap match (subset)""" - q = PirqconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(41)], irq) - - def test_041_range_overlap3(self): - """Pirqcon query with context range overlap match (superset)""" - q = PirqconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(41)], irq) - - def test_041_range_overlap4(self): - """Pirqcon query with context range overlap match (overlap low level)""" - q = PirqconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(41)], irq) - - def test_041_range_overlap5(self): - """Pirqcon query with context range overlap match (overlap high level)""" - q = PirqconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(41)], irq) - - def test_042_range_subset1(self): - """Pirqcon query with context range subset match""" - q = PirqconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(42)], irq) - - def test_042_range_subset2(self): - """Pirqcon query with context range subset match (equal)""" - q = PirqconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(42)], irq) - - def test_043_range_superset1(self): - """Pirqcon query with context range superset match""" - q = PirqconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(43)], irq) - - def test_043_range_superset2(self): - """Pirqcon query with context range superset match (equal)""" - q = PirqconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(43)], irq) - - def test_044_range_proper_subset1(self): - """Pirqcon query with context range proper subset match""" - q = PirqconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(44)], irq) - - def test_044_range_proper_subset2(self): - """Pirqcon query with context range proper subset match (equal)""" - q = PirqconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([], irq) - - def test_044_range_proper_subset3(self): - """Pirqcon query with context range proper subset match (equal low only)""" - q = PirqconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(44)], irq) - - def test_044_range_proper_subset4(self): - """Pirqcon query with context range proper subset match (equal high only)""" - q = PirqconQuery(self.p, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(44)], irq) - - def test_045_range_proper_superset1(self): - """Pirqcon query with context range proper superset match""" - q = PirqconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(45)], irq) - - def test_045_range_proper_superset2(self): - """Pirqcon query with context range proper superset match (equal)""" - q = PirqconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([], irq) - - def test_045_range_proper_superset3(self): - """Pirqcon query with context range proper superset match (equal low)""" - q = PirqconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(45)], irq) - - def test_045_range_proper_superset4(self): - """Pirqcon query with context range proper superset match (equal high)""" - q = PirqconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - irq = sorted(p.irq for p in q.results()) - self.assertListEqual([(45)], irq) diff --git a/tests/test_polcapquery.py b/tests/test_polcapquery.py deleted file mode 100644 index 577a8a68..00000000 --- a/tests/test_polcapquery.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import PolCapQuery - -from .policyrep.util import compile_policy - - -class PolCapQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/polcapquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Policy capability query with no criteria""" - # query with no parameters gets all capabilities. - allcaps = sorted(self.p.polcaps()) - - q = PolCapQuery(self.p) - qcaps = sorted(q.results()) - - self.assertListEqual(allcaps, qcaps) - - def test_001_name_exact(self): - """Policy capability query with exact match""" - q = PolCapQuery(self.p, name="open_perms", name_regex=False) - - caps = sorted(str(c) for c in q.results()) - self.assertListEqual(["open_perms"], caps) - - def test_002_name_regex(self): - """Policy capability query with regex match""" - q = PolCapQuery(self.p, name="pe?er", name_regex=True) - - caps = sorted(str(c) for c in q.results()) - self.assertListEqual(["network_peer_controls", "open_perms"], caps) diff --git a/tests/test_portconquery.py b/tests/test_portconquery.py deleted file mode 100644 index 4dd50d9c..00000000 --- a/tests/test_portconquery.py +++ /dev/null @@ -1,437 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest -from socket import IPPROTO_UDP - -from setools import PortconQuery, PortconRange - -from .policyrep.util import compile_policy - - -class PortconQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/portconquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Portcon query with no criteria""" - # query with no parameters gets all ports. - rules = sorted(self.p.portcons()) - - q = PortconQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_001_protocol(self): - """Portcon query with protocol match""" - q = PortconQuery(self.p, protocol=IPPROTO_UDP) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(1, 1)], ports) - - def test_010_user_exact(self): - """Portcon query with context user exact match""" - q = PortconQuery(self.p, user="user10", user_regex=False) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(10, 10)], ports) - - def test_011_user_regex(self): - """Portcon query with context user regex match""" - q = PortconQuery(self.p, user="user11(a|b)", user_regex=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(11, 11), PortconRange(11000, 11000)], ports) - - def test_020_role_exact(self): - """Portcon query with context role exact match""" - q = PortconQuery(self.p, role="role20_r", role_regex=False) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(20, 20)], ports) - - def test_021_role_regex(self): - """Portcon query with context role regex match""" - q = PortconQuery(self.p, role="role21(a|c)_r", role_regex=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(21, 21), PortconRange(21001, 21001)], ports) - - def test_030_type_exact(self): - """Portcon query with context type exact match""" - q = PortconQuery(self.p, type_="type30", type_regex=False) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(30, 30)], ports) - - def test_031_type_regex(self): - """Portcon query with context type regex match""" - q = PortconQuery(self.p, type_="type31(b|c)", type_regex=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(31000, 31000), PortconRange(31001, 31001)], ports) - - def test_040_range_exact(self): - """Portcon query with context range exact match""" - q = PortconQuery(self.p, range_="s0:c1 - s0:c0.c4") - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(40, 40)], ports) - - def test_041_range_overlap1(self): - """Portcon query with context range overlap match (equal)""" - q = PortconQuery(self.p, range_="s1:c1 - s1:c0.c4", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(41, 41)], ports) - - def test_041_range_overlap2(self): - """Portcon query with context range overlap match (subset)""" - q = PortconQuery(self.p, range_="s1:c1,c2 - s1:c0.c3", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(41, 41)], ports) - - def test_041_range_overlap3(self): - """Portcon query with context range overlap match (superset)""" - q = PortconQuery(self.p, range_="s1 - s1:c0.c4", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(41, 41)], ports) - - def test_041_range_overlap4(self): - """Portcon query with context range overlap match (overlap low level)""" - q = PortconQuery(self.p, range_="s1 - s1:c1,c2", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(41, 41)], ports) - - def test_041_range_overlap5(self): - """Portcon query with context range overlap match (overlap high level)""" - q = PortconQuery(self.p, range_="s1:c1,c2 - s1:c0.c4", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(41, 41)], ports) - - def test_042_range_subset1(self): - """Portcon query with context range subset match""" - q = PortconQuery(self.p, range_="s2:c1,c2 - s2:c0.c3", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(42, 42)], ports) - - def test_042_range_subset2(self): - """Portcon query with context range subset match (equal)""" - q = PortconQuery(self.p, range_="s2:c1 - s2:c1.c3", range_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(42, 42)], ports) - - def test_043_range_superset1(self): - """Portcon query with context range superset match""" - q = PortconQuery(self.p, range_="s3 - s3:c0.c4", range_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(43, 43)], ports) - - def test_043_range_superset2(self): - """Portcon query with context range superset match (equal)""" - q = PortconQuery(self.p, range_="s3:c1 - s3:c1.c3", range_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(43, 43)], ports) - - def test_044_range_proper_subset1(self): - """Portcon query with context range proper subset match""" - q = PortconQuery(self.p, range_="s4:c1,c2", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(44, 44)], ports) - - def test_044_range_proper_subset2(self): - """Portcon query with context range proper subset match (equal)""" - q = PortconQuery(self.p, range_="s4:c1 - s4:c1.c3", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_044_range_proper_subset3(self): - """Portcon query with context range proper subset match (equal low only)""" - q = PortconQuery(self.p, range_="s4:c1 - s4:c1.c2", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(44, 44)], ports) - - def test_044_range_proper_subset4(self): - """Portcon query with context range proper subset match (equal high only)""" - q = PortconQuery(self.p, range_="s4:c1,c2 - s4:c1.c3", range_subset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(44, 44)], ports) - - def test_045_range_proper_superset1(self): - """Portcon query with context range proper superset match""" - q = PortconQuery(self.p, range_="s5 - s5:c0.c4", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(45, 45)], ports) - - def test_045_range_proper_superset2(self): - """Portcon query with context range proper superset match (equal)""" - q = PortconQuery(self.p, range_="s5:c1 - s5:c1.c3", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_045_range_proper_superset3(self): - """Portcon query with context range proper superset match (equal low)""" - q = PortconQuery(self.p, range_="s5:c1 - s5:c1.c4", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(45, 45)], ports) - - def test_045_range_proper_superset4(self): - """Portcon query with context range proper superset match (equal high)""" - q = PortconQuery(self.p, range_="s5 - s5:c1.c3", range_superset=True, range_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(45, 45)], ports) - - def test_050_single_equal(self): - """Portcon query with single port exact match""" - q = PortconQuery(self.p, ports=(50, 50)) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50, 50)], ports) - - def test_051_range_equal(self): - """Portcon query with port range exact match""" - q = PortconQuery(self.p, ports=(50100, 50110)) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50100, 50110)], ports) - - def test_052_single_subset(self): - """Portcon query with single port subset""" - q = PortconQuery(self.p, ports=(50200, 50200), ports_subset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50200, 50200)], ports) - - def test_053_range_subset(self): - """Portcon query with range subset""" - q = PortconQuery(self.p, ports=(50301, 50309), ports_subset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50300, 50310)], ports) - - def test_053_range_subset_edge1(self): - """Portcon query with range subset, equal edge case""" - q = PortconQuery(self.p, ports=(50300, 50310), ports_subset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50300, 50310)], ports) - - def test_054_single_proper_subset(self): - """Portcon query with single port proper subset""" - q = PortconQuery( - self.p, ports=(50400, 50400), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_055_range_proper_subset(self): - """Portcon query with range proper subset""" - q = PortconQuery( - self.p, ports=(50501, 50509), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50500, 50510)], ports) - - def test_055_range_proper_subset_edge1(self): - """Portcon query with range proper subset, equal edge case""" - q = PortconQuery( - self.p, ports=(50500, 50510), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_055_range_proper_subset_edge2(self): - """Portcon query with range proper subset, low equal edge case""" - q = PortconQuery( - self.p, ports=(50500, 50509), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50500, 50510)], ports) - - def test_055_range_proper_subset_edge3(self): - """Portcon query with range proper subset, high equal edge case""" - q = PortconQuery( - self.p, ports=(50501, 50510), ports_subset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50500, 50510)], ports) - - def test_056_single_superset(self): - """Portcon query with single port superset""" - q = PortconQuery(self.p, ports=(50600, 50602), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50601, 50601)], ports) - - def test_056_single_superset_edge1(self): - """Portcon query with single port superset, equal edge case""" - q = PortconQuery(self.p, ports=(50601, 50601), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50601, 50601)], ports) - - def test_057_range_superset(self): - """Portcon query with range superset""" - q = PortconQuery(self.p, ports=(50700, 50711), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50700, 50710)], ports) - - def test_057_range_superset_edge1(self): - """Portcon query with range superset, equal edge case""" - q = PortconQuery(self.p, ports=(50700, 50710), ports_superset=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50700, 50710)], ports) - - def test_058_single_proper_superset(self): - """Portcon query with single port proper superset""" - q = PortconQuery( - self.p, ports=(50800, 50802), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50801, 50801)], ports) - - def test_058_single_proper_superset_edge1(self): - """Portcon query with single port proper superset, equal edge case""" - q = PortconQuery( - self.p, ports=(50801, 50801), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_058_single_proper_superset_edge2(self): - """Portcon query with single port proper superset, low equal edge case""" - q = PortconQuery( - self.p, ports=(50801, 50802), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50801, 50801)], ports) - - def test_058_single_proper_superset_edge3(self): - """Portcon query with single port proper superset, high equal edge case""" - q = PortconQuery( - self.p, ports=(50800, 50801), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50801, 50801)], ports) - - def test_059_range_proper_superset(self): - """Portcon query with range proper superset""" - q = PortconQuery( - self.p, ports=(50900, 50911), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50901, 50910)], ports) - - def test_059_range_proper_superset_edge1(self): - """Portcon query with range proper superset, equal edge case""" - q = PortconQuery( - self.p, ports=(50901, 50910), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([], ports) - - def test_059_range_proper_superset_edge2(self): - """Portcon query with range proper superset, equal high port edge case""" - q = PortconQuery( - self.p, ports=(50900, 50910), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50901, 50910)], ports) - - def test_059_range_proper_superset_edge3(self): - """Portcon query with range proper superset, equal low port edge case""" - q = PortconQuery( - self.p, ports=(50901, 50911), ports_superset=True, ports_proper=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(50901, 50910)], ports) - - def test_060_single_overlap(self): - """Portcon query with single overlap""" - q = PortconQuery(self.p, ports=(60001, 60001), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60001, 60001)], ports) - - def test_060_single_overlap_edge1(self): - """Portcon query with single overlap, range match low""" - q = PortconQuery(self.p, ports=(60001, 60002), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60001, 60001)], ports) - - def test_060_single_overlap_edge2(self): - """Portcon query with single overlap, range match high""" - q = PortconQuery(self.p, ports=(60000, 60001), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60001, 60001)], ports) - - def test_060_single_overlap_edge3(self): - """Portcon query with single overlap, range match proper superset""" - q = PortconQuery(self.p, ports=(60000, 60002), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60001, 60001)], ports) - - def test_061_range_overlap_low_half(self): - """Portcon query with range overlap, low half match""" - q = PortconQuery(self.p, ports=(60100, 60105), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60101, 60110)], ports) - - def test_062_range_overlap_high_half(self): - """Portcon query with range overlap, high half match""" - q = PortconQuery(self.p, ports=(60205, 60211), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60200, 60210)], ports) - - def test_063_range_overlap_middle(self): - """Portcon query with range overlap, middle match""" - q = PortconQuery(self.p, ports=(60305, 60308), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60300, 60310)], ports) - - def test_064_range_overlap_equal(self): - """Portcon query with range overlap, equal match""" - q = PortconQuery(self.p, ports=(60400, 60410), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60400, 60410)], ports) - - def test_065_range_overlap_superset(self): - """Portcon query with range overlap, superset match""" - q = PortconQuery(self.p, ports=(60500, 60510), ports_overlap=True) - - ports = sorted(p.ports for p in q.results()) - self.assertListEqual([PortconRange(60501, 60509)], ports) diff --git a/tests/test_rbacrulequery.py b/tests/test_rbacrulequery.py deleted file mode 100644 index a0d0fcd4..00000000 --- a/tests/test_rbacrulequery.py +++ /dev/null @@ -1,152 +0,0 @@ -"""RBAC rule query unit tests.""" -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -# pylint: disable=invalid-name,too-many-public-methods -import os -import unittest - -from setools import RBACRuleQuery -from setools import RBACRuletype as RRT -from setools.exception import RuleUseError, RuleNotConditional - -from . import mixins -from .policyrep.util import compile_policy - - -class RBACRuleQueryTest(mixins.ValidateRule, unittest.TestCase): - - """RBAC rule query unit tests.""" - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/rbacrulequery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def validate_allow(self, rule, source, target): - """Validate a role allow rule.""" - self.assertEqual(RRT.allow, rule.ruletype) - self.assertEqual(source, rule.source) - self.assertEqual(target, rule.target) - self.assertRaises(RuleUseError, getattr, rule, "tclass") - self.assertRaises(RuleUseError, getattr, rule, "default") - self.assertRaises(RuleNotConditional, getattr, rule, "conditional") - - def test_000_unset(self): - """RBAC rule query with no criteria.""" - # query with no parameters gets all RBAC rules. - rules = sorted(self.p.rbacrules()) - - q = RBACRuleQuery(self.p) - q_rules = sorted(q.results()) - - self.assertListEqual(rules, q_rules) - - def test_001_source_direct(self): - """RBAC rule query with exact, direct, source match.""" - q = RBACRuleQuery( - self.p, source="test1s", source_indirect=False, source_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - - self.validate_allow(r[0], "test1s", "test1t") - self.validate_rule(r[1], RRT.role_transition, "test1s", "system", "infoflow", "test1t") - - def test_002_source_direct_regex(self): - """RBAC rule query with regex, direct, source match.""" - q = RBACRuleQuery( - self.p, source="test2s(1|2)", source_indirect=False, source_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_allow(r[0], "test2s1", "test2t") - - def test_010_target_direct(self): - """RBAC rule query with exact, direct, target match.""" - q = RBACRuleQuery( - self.p, target="test10t", target_indirect=False, target_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_allow(r[0], "test10s", "test10t") - - def test_011_target_direct_regex(self): - """RBAC rule query with regex, direct, target match.""" - q = RBACRuleQuery( - self.p, target="test11t(1|3)", target_indirect=False, target_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_allow(r[0], "test11s", "test11t1") - - def test_012_target_type(self): - """RBAC rule query with a type as target.""" - q = RBACRuleQuery(self.p, target="test12t") - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RRT.role_transition, "test12s", "test12t", "infoflow", "test12d") - - @unittest.skip("Setting tclass to a string is no longer supported.") - def test_020_class(self): - """RBAC rule query with exact object class match.""" - q = RBACRuleQuery(self.p, tclass="infoflow2", tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RRT.role_transition, "test20", "system", "infoflow2", "test20d2") - - def test_021_class_list(self): - """RBAC rule query with object class list match.""" - q = RBACRuleQuery( - self.p, tclass=["infoflow3", "infoflow4"], tclass_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RRT.role_transition, "test21", "system", "infoflow3", "test21d3") - self.validate_rule(r[1], RRT.role_transition, "test21", "system", "infoflow4", "test21d2") - - def test_022_class_regex(self): - """RBAC rule query with object class regex match.""" - q = RBACRuleQuery(self.p, tclass="infoflow(5|6)", tclass_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RRT.role_transition, "test22", "system", "infoflow5", "test22d2") - self.validate_rule(r[1], RRT.role_transition, "test22", "system", "infoflow6", "test22d3") - - def test_030_default(self): - """RBAC rule query with exact default match.""" - q = RBACRuleQuery( - self.p, default="test30d", default_regex=False) - - r = sorted(q.results()) - self.assertEqual(len(r), 1) - self.validate_rule(r[0], RRT.role_transition, "test30s", "system", "infoflow", "test30d") - - def test_031_default_regex(self): - """RBAC rule query with regex default match.""" - q = RBACRuleQuery( - self.p, default="test31d(2|3)", default_regex=True) - - r = sorted(q.results()) - self.assertEqual(len(r), 2) - self.validate_rule(r[0], RRT.role_transition, "test31s", "system", "infoflow7", "test31d3") - self.validate_rule(r[1], RRT.role_transition, "test31s", "system", "process", "test31d2") - - def test_040_ruletype(self): - """RBAC rule query with rule type.""" - q = RBACRuleQuery(self.p, ruletype=[RRT.allow]) - - num = 0 - for num, r in enumerate(sorted(q.results()), start=1): - self.assertEqual(r.ruletype, RRT.allow) - - # this will have to be updated as number of - # role allows change in the test policy - self.assertEqual(num, 9) diff --git a/tests/test_rolequery.py b/tests/test_rolequery.py deleted file mode 100644 index ba315112..00000000 --- a/tests/test_rolequery.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import RoleQuery - -from .policyrep.util import compile_policy - - -class RoleQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/rolequery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Role query with no criteria.""" - # query with no parameters gets all types. - roles = sorted(self.p.roles()) - - q = RoleQuery(self.p) - q_roles = sorted(q.results()) - - self.assertListEqual(roles, q_roles) - - def test_001_name_exact(self): - """Role query with exact name match.""" - q = RoleQuery(self.p, name="test1") - - roles = sorted(str(r) for r in q.results()) - self.assertListEqual(["test1"], roles) - - def test_002_name_regex(self): - """Role query with regex name match.""" - q = RoleQuery(self.p, name="test2(a|b)", name_regex=True) - - roles = sorted(str(r) for r in q.results()) - self.assertListEqual(["test2a", "test2b"], roles) - - def test_010_type_intersect(self): - """Role query with type set intersection.""" - q = RoleQuery(self.p, types=["test10a", "test10b"]) - - roles = sorted(str(r) for r in q.results()) - self.assertListEqual(["test10r1", "test10r2", "test10r3", - "test10r4", "test10r5", "test10r6"], roles) - - def test_011_type_equality(self): - """Role query with type set equality.""" - q = RoleQuery(self.p, types=["test11a", "test11b"], types_equal=True) - - roles = sorted(str(r) for r in q.results()) - self.assertListEqual(["test11r2"], roles) - - def test_012_type_regex(self): - """Role query with type set match.""" - q = RoleQuery(self.p, types="test12(a|b)", types_regex=True) - - roles = sorted(str(r) for r in q.results()) - self.assertListEqual(["test12r1", "test12r2", "test12r3", - "test12r4", "test12r5", "test12r6"], roles) diff --git a/tests/test_sensitivityquery.py b/tests/test_sensitivityquery.py deleted file mode 100644 index 4796539d..00000000 --- a/tests/test_sensitivityquery.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import SensitivityQuery - -from .policyrep.util import compile_policy - - -class SensitivityQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/sensitivityquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Sensitivity query with no criteria.""" - # query with no parameters gets all sensitivities. - allsens = sorted(str(c) for c in self.p.sensitivities()) - - q = SensitivityQuery(self.p) - qsens = sorted(str(c) for c in q.results()) - - self.assertListEqual(allsens, qsens) - - def test_001_name_exact(self): - """Sensitivity query with exact name match.""" - q = SensitivityQuery(self.p, name="test1") - - sens = sorted(str(c) for c in q.results()) - self.assertListEqual(["test1"], sens) - - def test_002_name_regex(self): - """Sensitivity query with regex name match.""" - q = SensitivityQuery(self.p, name="test2(a|b)", name_regex=True) - - sens = sorted(str(c) for c in q.results()) - self.assertListEqual(["test2a", "test2b"], sens) - - def test_010_alias_exact(self): - """Sensitivity query with exact alias match.""" - q = SensitivityQuery(self.p, alias="test10a") - - sens = sorted(str(t) for t in q.results()) - self.assertListEqual(["test10s1"], sens) - - def test_011_alias_regex(self): - """Sensitivity query with regex alias match.""" - q = SensitivityQuery(self.p, alias="test11(a|b)", alias_regex=True) - - sens = sorted(str(t) for t in q.results()) - self.assertListEqual(["test11s1", "test11s2"], sens) - - def test_020_sens_equal(self): - """Sensitivity query with sens equality.""" - q = SensitivityQuery(self.p, sens="test20") - - sens = sorted(str(u) for u in q.results()) - self.assertListEqual(["test20"], sens) - - def test_021_sens_dom1(self): - """Sensitivity query with sens dominance.""" - q = SensitivityQuery(self.p, sens="test21crit", sens_dom=True) - - sens = sorted(str(u) for u in q.results()) - self.assertListEqual(["test21", "test21crit"], sens) - - def test_021_sens_dom2(self): - """Sensitivity query with sens dominance (equal).""" - q = SensitivityQuery(self.p, sens="test21", sens_dom=True) - - sens = sorted(str(u) for u in q.results()) - self.assertListEqual(["test21"], sens) - - def test_022_sens_domby1(self): - """Sensitivity query with sens dominated-by.""" - q = SensitivityQuery(self.p, sens="test22crit", sens_domby=True) - - sens = sorted(str(u) for u in q.results()) - self.assertListEqual(["test22", "test22crit"], sens) - - def test_022_sens_domby2(self): - """Sensitivity query with sens dominated-by (equal).""" - q = SensitivityQuery(self.p, sens="test22", sens_domby=True) - - sens = sorted(str(u) for u in q.results()) - self.assertListEqual(["test22"], sens) diff --git a/tests/test_typeattrquery.py b/tests/test_typeattrquery.py deleted file mode 100644 index 68f51f16..00000000 --- a/tests/test_typeattrquery.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2014-2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import TypeAttributeQuery - -from .policyrep.util import compile_policy - - -class TypeAttributeQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/typeattrquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Type attribute query with no criteria.""" - # query with no parameters gets all attrs. - allattrs = sorted(self.p.typeattributes()) - - q = TypeAttributeQuery(self.p) - qattrs = sorted(q.results()) - - self.assertListEqual(allattrs, qattrs) - - def test_001_name_exact(self): - """Type attribute query with exact name match.""" - q = TypeAttributeQuery(self.p, name="test1") - - attrs = sorted(str(t) for t in q.results()) - self.assertListEqual(["test1"], attrs) - - def test_002_name_regex(self): - """Type attribute query with regex name match.""" - q = TypeAttributeQuery(self.p, name="test2(a|b)", name_regex=True) - - attrs = sorted(str(t) for t in q.results()) - self.assertListEqual(["test2a", "test2b"], attrs) - - def test_010_type_set_intersect(self): - """Type attribute query with type set intersection.""" - q = TypeAttributeQuery(self.p, types=["test10t1", "test10t7"]) - - attrs = sorted(str(t) for t in q.results()) - self.assertListEqual(["test10a", "test10c"], attrs) - - def test_011_type_set_equality(self): - """Type attribute query with type set equality.""" - q = TypeAttributeQuery(self.p, types=["test11t1", "test11t2", - "test11t3", "test11t5"], types_equal=True) - - attrs = sorted(str(t) for t in q.results()) - self.assertListEqual(["test11a"], attrs) - - def test_012_type_set_regex(self): - """Type attribute query with type set regex match.""" - q = TypeAttributeQuery(self.p, types="test12t(1|2)", types_regex=True) - - attrs = sorted(str(t) for t in q.results()) - self.assertListEqual(["test12a", "test12b"], attrs) diff --git a/tests/test_typequery.py b/tests/test_typequery.py deleted file mode 100644 index d78dd61f..00000000 --- a/tests/test_typequery.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright 2014-2015, Tresys Technology, LLC -# Copyright 2019, Chris PeBenito -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import TypeQuery - -from .policyrep.util import compile_policy - - -class TypeQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/typequery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """Type query with no criteria.""" - # query with no parameters gets all types. - alltypes = sorted(self.p.types()) - - q = TypeQuery(self.p) - qtypes = sorted(q.results()) - - self.assertListEqual(alltypes, qtypes) - - def test_001_name_exact(self): - """Type query with exact name match.""" - q = TypeQuery(self.p, name="test1") - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test1"], types) - - def test_002_name_regex(self): - """Type query with regex name match.""" - q = TypeQuery(self.p, name="test2(a|b)", name_regex=True) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test2a", "test2b"], types) - - def test_010_attr_intersect(self): - """Type query with attribute set intersection.""" - q = TypeQuery(self.p, attrs=["test10a", "test10b"]) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test10t1", "test10t2", "test10t3", - "test10t4", "test10t5", "test10t6"], types) - - def test_011_attr_equality(self): - """Type query with attribute set equality.""" - q = TypeQuery(self.p, attrs=["test11a", "test11b"], attrs_equal=True) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test11t2"], types) - - def test_012_attr_regex(self): - """Type query with attribute regex match.""" - q = TypeQuery(self.p, attrs="test12(a|b)", attrs_regex=True) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test12t1", "test12t2", "test12t3", - "test12t4", "test12t5", "test12t6"], types) - - def test_020_alias_exact(self): - """Type query with exact alias match.""" - q = TypeQuery(self.p, alias="test20a") - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test20t1"], types) - - def test_021_alias_regex(self): - """Type query with regex alias match.""" - q = TypeQuery(self.p, alias="test21(a|b)", alias_regex=True) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test21t1", "test21t2"], types) - - def test_022_alias_dereference(self): - """Type query with alias dereference.""" - q = TypeQuery(self.p, name="test22alias", alias_deref=True) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test22"], types) - - def test_030_permissive(self): - """Type query with permissive match""" - q = TypeQuery(self.p, permissive=True) - - types = sorted(str(t) for t in q.results()) - self.assertListEqual(["test30"], types) diff --git a/tests/test_userquery.py b/tests/test_userquery.py deleted file mode 100644 index ed51e94c..00000000 --- a/tests/test_userquery.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright 2014-2015, Tresys Technology, LLC -# -# SPDX-License-Identifier: GPL-2.0-only -# -import os -import unittest - -from setools import UserQuery - -from .policyrep.util import compile_policy - - -class UserQueryTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.p = compile_policy("tests/userquery.conf") - - @classmethod - def tearDownClass(cls): - os.unlink(cls.p.path) - - def test_000_unset(self): - """User query with no criteria.""" - # query with no parameters gets all types. - allusers = sorted(self.p.users()) - - q = UserQuery(self.p) - qusers = sorted(q.results()) - - self.assertListEqual(allusers, qusers) - - def test_001_name_exact(self): - """User query with exact name match.""" - q = UserQuery(self.p, name="test1_u") - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test1_u"], users) - - def test_002_name_regex(self): - """User query with regex name match.""" - q = UserQuery(self.p, name="test2_u(1|2)", name_regex=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test2_u1", "test2_u2"], users) - - def test_010_role_intersect(self): - """User query with role set intersection.""" - q = UserQuery(self.p, roles=["test10a_r", "test10b_r"]) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test10_u1", "test10_u2", "test10_u3", - "test10_u4", "test10_u5", "test10_u6"], users) - - def test_011_role_equality(self): - """User query with role set equality.""" - q = UserQuery( - self.p, roles=["test11a_r", "test11b_r"], roles_equal=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test11_u2"], users) - - def test_012_role_regex(self): - """User query with role regex match.""" - q = UserQuery(self.p, roles="test12(a|b)_r", roles_regex=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test12_u1", "test12_u2", "test12_u3", - "test12_u4", "test12_u5", "test12_u6"], users) - - def test_020_level_equal(self): - """User query with default level equality.""" - q = UserQuery(self.p, level="s3:c0,c4") - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test20"], users) - - def test_021_level_dom1(self): - """User query with default level dominance.""" - q = UserQuery(self.p, level="s2:c1,c2,c4", level_dom=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test21"], users) - - def test_021_level_dom2(self): - """User query with default level dominance (equal).""" - q = UserQuery(self.p, level="s2:c1,c4", level_dom=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test21"], users) - - def test_022_level_domby1(self): - """User query with default level dominated-by.""" - q = UserQuery(self.p, level="s3:c2", level_domby=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test22"], users) - - def test_022_level_domby2(self): - """User query with default level dominated-by (equal).""" - q = UserQuery(self.p, level="s3:c2,c4", level_domby=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test22"], users) - - def test_023_level_incomp(self): - """User query with default level icomparable.""" - q = UserQuery(self.p, level="s5:c0.c5,c7", level_incomp=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test23"], users) - - def test_040_range_exact(self): - """User query with range exact match""" - q = UserQuery(self.p, range_="s0:c5 - s0:c0.c5") - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test40"], users) - - def test_041_range_overlap1(self): - """User query with range overlap match (equal)""" - q = UserQuery(self.p, range_="s1:c5 - s1:c1.c3,c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test41"], users) - - def test_041_range_overlap2(self): - """User query with range overlap match (subset)""" - q = UserQuery(self.p, range_="s1:c2,c5 - s1:c2.c3,c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test41"], users) - - def test_041_range_overlap3(self): - """User query with range overlap match (superset)""" - q = UserQuery(self.p, range_="s1 - s1:c0.c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test41"], users) - - def test_041_range_overlap4(self): - """User query with range overlap match (overlap low level)""" - q = UserQuery(self.p, range_="s1:c5 - s1:c2,c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test41"], users) - - def test_041_range_overlap5(self): - """User query with range overlap match (overlap high level)""" - q = UserQuery(self.p, range_="s1:c5,c2 - s1:c1.c3,c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test41"], users) - - def test_042_range_subset1(self): - """User query with range subset match""" - q = UserQuery(self.p, range_="s2:c2,c5 - s2:c2.c3,c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test42"], users) - - def test_042_range_subset2(self): - """User query with range subset match (equal)""" - q = UserQuery(self.p, range_="s2:c5 - s2:c1.c3,c5", range_overlap=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test42"], users) - - def test_043_range_superset1(self): - """User query with range superset match""" - q = UserQuery(self.p, range_="s3 - s3:c0.c6", range_superset=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test43"], users) - - def test_043_range_superset2(self): - """User query with range superset match (equal)""" - q = UserQuery(self.p, range_="s3:c5 - s3:c1.c3,c5.c6", range_superset=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test43"], users) - - def test_044_range_proper_subset1(self): - """User query with range proper subset match""" - q = UserQuery(self.p, range_="s4:c2,c5", range_subset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test44"], users) - - def test_044_range_proper_subset2(self): - """User query with range proper subset match (equal)""" - q = UserQuery(self.p, range_="s4:c5 - s4:c1.c3,c5", range_subset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual([], users) - - def test_044_range_proper_subset3(self): - """User query with range proper subset match (equal low)""" - q = UserQuery(self.p, range_="s4:c5 - s4:c1.c2,c5", range_subset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test44"], users) - - def test_044_range_proper_subset4(self): - """User query with range proper subset match (equal high)""" - q = UserQuery(self.p, range_="s4:c1,c5 - s4:c1.c3,c5", range_subset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test44"], users) - - def test_045_range_proper_superset1(self): - """User query with range proper superset match""" - q = UserQuery(self.p, range_="s5 - s5:c0.c5", range_superset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test45"], users) - - def test_045_range_proper_superset2(self): - """User query with range proper superset match (equal)""" - q = UserQuery(self.p, range_="s5:c5 - s5:c1.c3,c5", range_superset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual([], users) - - def test_045_range_proper_superset3(self): - """User query with range proper superset match (equal low)""" - q = UserQuery(self.p, range_="s5:c5 - s5:c1.c5", range_superset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test45"], users) - - def test_045_range_proper_superset4(self): - """User query with range proper superset match (equal high)""" - q = UserQuery(self.p, range_="s5 - s5:c1.c3,c5", range_superset=True, range_proper=True) - - users = sorted(str(u) for u in q.results()) - self.assertListEqual(["test45"], users) diff --git a/tox.ini b/tox.ini index 551ce15c..ff94e95c 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,7 @@ max-line-length = 100 deps = {[testenv]deps} pycodestyle commands_pre = pycodestyle --version -commands = pycodestyle setools/ setoolsgui/ tests/ tests-gui/ seinfo seinfoflow sedta sesearch sediff sechecker apol --statistics +commands = pycodestyle setools/ setoolsgui/ tests/ seinfo seinfoflow sedta sesearch sediff sechecker apol --statistics [testenv:coverage] #setenv = SETOOLS_COVERAGE = 1 @@ -20,7 +20,7 @@ extras = toml commands_pre = coverage --version coverage erase {[testenv]commands_pre} -commands = coverage run --source=setools,setoolsgui -m pytest tests tests-gui +commands = coverage run --source=setools,setoolsgui -m pytest tests coverage report [testenv:lint] @@ -29,14 +29,14 @@ deps = {[testenv]deps} pylint>=2.8.0 commands_pre = pylint --version {[testenv]commands_pre} -commands = pylint -E setools setoolsgui tests tests-gui seinfo seinfoflow sedta sesearch sediff sechecker apol +commands = pylint -E setools setoolsgui tests seinfo seinfoflow sedta sesearch sediff sechecker apol [testenv:mypy] deps = {[testenv]deps} types-setuptools mypy>=1.6.0 commands_pre = mypy --version -commands = mypy -p setools -p setoolsgui -p tests -p tests-gui +commands = mypy -p setools -p setoolsgui -p tests mypy --scripts-are-modules seinfo seinfoflow sedta sesearch sediff sechecker apol [testenv:install] @@ -55,4 +55,4 @@ deps = networkx>=2.6 pytest-qt pytest-xvfb commands_pre = {envpython} setup.py build_ext -i -commands = {envpython} -m pytest tests tests-gui +commands = {envpython} -m pytest tests