{{% if product not in ['ubuntu2404'] %}}

{{% macro arpc_condition(audit_tool, bootc=True) %}}
          <criteria operator="AND" comment="Audit rules are configured for {{{ 'Image Mode' if bootc else 'Package Mode' }}}">
            <extend_definition comment="The system is RHEL Image Mode" definition_ref="bootc" negate="{{{ 'false' if bootc else 'true' }}}" />
{{% if product in ["fedora", "rhel10"] %}}
            <criterion test_ref="test_{{{ audit_tool }}}_all_priv_cmds_covered{{{ '_bootc' if bootc else '' }}}_32bit"
              comment="{{{ audit_tool }}} 32bit cover all privileged commands on the system"/>
            <criterion test_ref="test_{{{ audit_tool }}}_count_matches_system_priv_cmds{{{ '_bootc' if bootc else '' }}}_32bit"
              comment="count of {{{ audit_tool }}} 32bit for priv cmds matches count of priv cmds in the system"/>
            <criteria operator="OR" comment="System either isn't 64-bit or 64-bit version of audit rule is present">
              <!-- System either isn't 64-bit => we just check presence of 32-bit version of audit rule -->
              <extend_definition comment="64-bit system" definition_ref="system_info_architecture_64bit" negate="true" />
              <!-- Or system is 64-bit => in that case we also need to verify the presence of 64-bit version of audit rule -->
              <criteria operator="AND">
                <criterion test_ref="test_{{{ audit_tool }}}_all_priv_cmds_covered{{{ '_bootc' if bootc else '' }}}_64bit"
                  comment="{{{ audit_tool }}} 64bit cover all privileged commands on the system"/>
                <criterion test_ref="test_{{{ audit_tool }}}_count_matches_system_priv_cmds{{{ '_bootc' if bootc else '' }}}_64bit"
                  comment="count of {{{ audit_tool }}} 64bit for priv cmds matches count of priv cmds in the system"/>
              </criteria>
            </criteria>
{{% else %}}
            <criterion test_ref="test_{{{ audit_tool }}}_all_priv_cmds_covered{{{ '_bootc' if bootc else '' }}}"
              comment="{{{ audit_tool }}} cover all privileged commands on the system"/>
            <criterion test_ref="test_{{{ audit_tool }}}_count_matches_system_priv_cmds{{{ '_bootc' if bootc else '' }}}"
              comment="count of {{{ audit_tool }}} for priv cmds matches count of priv cmds in the system"/>
{{% endif %}}
          </criteria>
{{% endmacro %}}

<def-group>
  <definition class="compliance" id="{{{ rule_id }}}" version="1">
    {{{ oval_metadata("Audit rules about the information on the use of privileged commands are enabled.", rule_title=rule_title) }}}
    <criteria operator="OR">
      <criteria operator="AND">
        <extend_definition definition_ref="audit_rules_augenrules" comment="audit augenrules format is used"/>
        <criteria operator="OR">
            {{{ arpc_condition("augenrules", bootc=True) }}}
            {{{ arpc_condition("augenrules", bootc=False) }}}
        </criteria>
      </criteria>

      <criteria operator="AND">
        <extend_definition definition_ref="audit_rules_auditctl" comment="audit auditctl format is used"/>
        <criteria operator="OR">
            {{{ arpc_condition("auditctl", bootc=True) }}}
            {{{ arpc_condition("auditctl", bootc=False) }}}
        </criteria>
      </criteria>
    </criteria>
  </definition>

  <!-- First define OVAL entities that can be reused across tests below -->
  <linux:partition_state id="state_audit_rules_privileged_commands_dev_partitons" version="1">
    <linux:device operation="pattern match">^(/dev/.*|composefs)$</linux:device>
  </linux:partition_state>

  <linux:partition_state id="state_audit_rules_privileged_commands_nosuid_partitons" version="1">
    <linux:mount_options datatype="string" entity_check="at least one"
      operation="equals">nosuid</linux:mount_options>
  </linux:partition_state>

<linux:partition_state id="state_audit_rules_privileged_commands_noexec_partitons" version="1">
    <linux:mount_options datatype="string" entity_check="at least one"
      operation="equals">noexec</linux:mount_options>
  </linux:partition_state>

  <!-- This object is created mainly to improve performance when collecting file objects.
       Here all mount points are collected and filtered to include only devices under /dev in
       order to ignore special file systems. Then, the mount options are checked to exclude
       file systems mounted with nosuid or noexec. The privileged commands can't execute on these
       file systems, so there is no reason to probe these file systems. -->
  <linux:partition_object id="object_audit_rules_privileged_commands_exec_partitions" version="1">
    <linux:mount_point operation="pattern match">^(?!/proc(/.*|$)).*$</linux:mount_point>
    <filter action="include">state_audit_rules_privileged_commands_dev_partitons</filter>
    <filter action="exclude">state_audit_rules_privileged_commands_nosuid_partitons</filter>
    <filter action="exclude">state_audit_rules_privileged_commands_noexec_partitons</filter>
  </linux:partition_object>

  <local_variable id="var_audit_rules_privileged_commands_exec_mountpoints" version="1"
    datatype="string" comment="Mount points where suid or sgid files can be executed">
    <object_component item_field="mount_point"
      object_ref="object_audit_rules_privileged_commands_exec_partitions"/>
  </local_variable>

  <unix:file_state id="state_setuid_or_setgid_set" operator="OR" version="1">
    <unix:suid datatype="boolean">true</unix:suid>
    <unix:sgid datatype="boolean">true</unix:sgid>
  </unix:file_state>

  <unix:file_state id="state_dracut_tmp_files" version="1">
    <unix:filepath operation="pattern match">^/var/tmp/dracut.*</unix:filepath>
  </unix:file_state>

  <unix:file_state id="state_audit_rules_privileged_commands_sysroot" version="1"
        comment="Used to filter out all files in the /sysroot directory">
    <unix:filepath operation="pattern match">^/sysroot/.*$</unix:filepath>
  </unix:file_state>

  <!-- This file_object will only find privileged commands located only in file systems that allow
       their execution. The recurse_file_system parameter is set to defined in order to make sure
       the probe doesn't leave the scope of that mount point. For example, when probing "/", the
       probe will ignore any child directory which is a mount point for any other partition.
       This will ensure considerable performance improvement. -->
  <unix:file_object id="object_audit_rules_privileged_commands" version="1"
    comment="Files with setuid or setgid permission in file systems that allow their execution">
    <unix:behaviors recurse="directories" recurse_direction="down"
      recurse_file_system="defined" max_depth="-1"/>
    <unix:path operation="equals" var_check="at least one"
      var_ref="var_audit_rules_privileged_commands_exec_mountpoints"/>
    <unix:filename operation="pattern match">^\w+</unix:filename>
    <filter action="include">state_setuid_or_setgid_set</filter>
    <filter action="exclude">state_dracut_tmp_files</filter>
  </unix:file_object>
  <unix:file_object id="object_audit_rules_privileged_commands_bootc" version="1"
    comment="Files with setuid or setgid permission in file systems that allow their execution">
    <unix:behaviors recurse="directories" recurse_direction="down"
      recurse_file_system="defined" max_depth="-1"/>
    <unix:path operation="equals">/</unix:path>
    <unix:filename operation="pattern match">^\w+</unix:filename>
    <filter action="include">state_setuid_or_setgid_set</filter>
    <filter action="exclude">state_dracut_tmp_files</filter>
    <filter action="exclude">state_audit_rules_privileged_commands_sysroot</filter>
  </unix:file_object>

  <!-- The intention of the first test is to ensure that exists at least one rule for each
       privileged command found in the system. Therefore, a list of objects will be extracted
       from auditd rules and compared to privileged commands found in relevant partitions. -->
{{% if product in ["fedora", "rhel10"] %}}
  <local_variable id="var_audit_rules_privileged_commands_rule_regex_32bit" version="1"
    datatype="string" comment="Regex for auditd rule">
    <literal_component>^[\s]*-a always,exit -F arch=b32 (?:-F path=([\S]+))+(?: -F perm=x)? -F auid>={{{ auid }}} -F auid!=(?:4294967295|unset)[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$</literal_component>
  </local_variable>
  <local_variable id="var_audit_rules_privileged_commands_rule_regex_64bit" version="1"
    datatype="string" comment="Regex for auditd rule">
    <literal_component>^[\s]*-a always,exit -F arch=b64 (?:-F path=([\S]+))+(?: -F perm=x)? -F auid>={{{ auid }}} -F auid!=(?:4294967295|unset)[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$</literal_component>
  </local_variable>
{{% else %}}
  <local_variable id="var_audit_rules_privileged_commands_rule_regex" version="1"
    datatype="string" comment="Regex for auditd rule">
    <literal_component>^[\s]*-a always,exit (?:-F path=([\S]+))+(?: -F perm=x)? -F auid>={{{ auid }}} -F auid!=(?:4294967295|unset)[\s]+(?:-k[\s]+|-F[\s]+key=)[\S]+[\s]*$</literal_component>
  </local_variable>
{{% endif %}}

{{% macro arpc_variables_and_states(bootc) %}}
  <local_variable id="var_audit_rules_privileged_commands_priv_cmds{{{ '_bootc' if bootc else '' }}}" version="1"
    datatype="string" comment="Filepath of all privileged commands found in the system">
    <object_component item_field="filepath" object_ref="object_audit_rules_privileged_commands{{{ '_bootc' if bootc else '' }}}"/>
  </local_variable>

  <local_variable id="var_audit_rules_privileged_commands_priv_cmds_count{{{ '_bootc' if bootc else '' }}}" version="1"
    datatype="int" comment="Count all privileged commands present in the system">
    <count>
      <object_component item_field="filepath"
        object_ref="object_audit_rules_privileged_commands{{{ '_bootc' if bootc else '' }}}"/>
    </count>
  </local_variable>

  <ind:variable_object id="object_audit_rules_privileged_commands_priv_cmds_count{{{ '_bootc' if bootc else '' }}}" version="1"
    comment="Number of all privileged commands in the system, regardless of audit rules.">
    <ind:var_ref>var_audit_rules_privileged_commands_priv_cmds_count{{{ '_bootc' if bootc else '' }}}</ind:var_ref>
  </ind:variable_object>

  <!-- This state is used to filter out all the auditd rules related to non privileged commands.
       When collectiong the paths in the textfilecontent54_object objects below, this state will
       ensure that the list is composed only by privileged commands present in the system. Other
       paths values will be ignored. -->
  <ind:textfilecontent54_state id="state_unprivileged_commands{{{ '_bootc' if bootc else '' }}}" version="1">
    <ind:subexpression datatype="string" operation="not equal" var_check="all"
      var_ref="var_audit_rules_privileged_commands_priv_cmds{{{ '_bootc' if bootc else '' }}}"/>
  </ind:textfilecontent54_state>

  <ind:textfilecontent54_state id="state_priv_cmds_from_system{{{ '_bootc' if bootc else '' }}}" version="1">
    <ind:subexpression datatype="string" operation="pattern match" var_check="at least one"
      var_ref="var_audit_rules_privileged_commands_priv_cmds{{{ '_bootc' if bootc else '' }}}"/>
  </ind:textfilecontent54_state>
{{% endmacro %}}

{{% macro arpc_object_priv_cmds(audit_tool, bits=None, bootc=False) %}}
  <ind:textfilecontent54_object id="object_priv_cmds_from_{{{ audit_tool }}}{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" version="1">
    {{% if audit_tool == "augenrules" %}}
    <ind:filepath operation="pattern match">^/etc/audit/rules\.d/.*\.rules$</ind:filepath>
    {{% elif audit_tool == "auditctl" %}}
    <ind:filepath>/etc/audit/audit.rules</ind:filepath>
    {{% else %}}
    {{{ raise("Unknown audit tool: " + audit_tool) }}}
    {{% endif %}}
    <ind:pattern operation="pattern match"
      var_ref="var_audit_rules_privileged_commands_rule_regex{{{ ('_' + bits + 'bit') if bits else '' }}}"/>
    <ind:instance operation="greater than or equal" datatype="int">1</ind:instance>
    <filter action="exclude">state_unprivileged_commands{{{ '_bootc' if bootc else '' }}}</filter>
  </ind:textfilecontent54_object>
{{% endmacro %}}

{{% macro arpc_test_all_priv_cmds_covered(audit_tool, bits=None, bootc=False) %}}
  <ind:textfilecontent54_test id="test_{{{ audit_tool }}}_all_priv_cmds_covered{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" version="1"
    check="all" check_existence="all_exist"
    comment="There is one {{{ audit_tool }}} rule for each privileged command on the system.">
    <ind:object object_ref="object_priv_cmds_from_{{{ audit_tool }}}{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" />
    <ind:state state_ref="state_priv_cmds_from_system{{{ '_bootc' if bootc else '' }}}" />
  </ind:textfilecontent54_test>
{{% endmacro %}}

{{% macro arpc_var_priv_cmds_count(audit_tool, bits=None, bootc=False) %}}
  <local_variable id="var_priv_cmds_from_{{{ audit_tool }}}_count{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" version="1"
    datatype="int" comment="Count privileged commands found in audit rules in {{{ audit_tool }}} format">
    <count>
      <object_component item_field="subexpression" object_ref="object_priv_cmds_from_{{{ audit_tool }}}{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" />
    </count>
  </local_variable>
{{% endmacro %}}

{{% macro arpc_state_priv_cmds_count(audit_tool, bits=None, bootc=False) %}}
  <ind:variable_state id="state_priv_cmds_from_{{{ audit_tool }}}_count{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" version="1">
    <ind:value datatype="int" operation="equals" var_check="at least one"
      var_ref="var_priv_cmds_from_{{{ audit_tool }}}_count{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}"/>
  </ind:variable_state>
{{% endmacro %}}

{{% macro arpc_test_count_matches_system_priv_cmds(audit_tool, bits=None, bootc=False) %}}
  <ind:variable_test id="test_{{{ audit_tool }}}_count_matches_system_priv_cmds{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}" version="1"
    check="all" check_existence="all_exist"
    comment="Count of {{{ audit_tool }}} for priv cmds matches the count of priv cmds in the system">
    <ind:object object_ref="object_audit_rules_privileged_commands_priv_cmds_count{{{ '_bootc' if bootc else '' }}}"/>
    <ind:state state_ref="state_priv_cmds_from_{{{ audit_tool }}}_count{{{ '_bootc' if bootc else '' }}}{{{ ('_' + bits + 'bit') if bits else '' }}}"/>
  </ind:variable_test>
{{% endmacro %}}

{{% for bootc in [False, True] %}}
    {{{ arpc_variables_and_states(bootc) }}}
    {{% if product in ["fedora", "rhel10"] %}}
        {{% set bits_options = ["32", "64"] %}}
    {{% else %}}
        {{% set bits_options = [None] %}}
    {{% endif %}}
    {{% for bits in bits_options %}}
        {{% for audit_tool in ["augenrules", "auditctl"] %}}
            {{{ arpc_object_priv_cmds(audit_tool, bits=bits, bootc=bootc) }}}
            {{{ arpc_test_all_priv_cmds_covered(audit_tool, bits=bits, bootc=bootc) }}}
            {{{ arpc_var_priv_cmds_count(audit_tool, bits=bits, bootc=bootc) }}}
            {{{ arpc_state_priv_cmds_count(audit_tool, bits=bits, bootc=bootc) }}}
            {{{ arpc_test_count_matches_system_priv_cmds(audit_tool, bits=bits, bootc=bootc) }}}
        {{% endfor %}}
    {{% endfor %}}
{{% endfor %}}

</def-group>
{{% endif %}}
