<def-group>
  <definition class="compliance" id="mount_option_nodev_removable_partitions" version="2">
    <metadata>
      <title>Add nodev Option to Removable Media Partitions</title>
      <affected family="unix">
        <platform>Red Hat Enterprise Linux 6</platform>
      </affected>
      <description>The nodev mount option prevents files from being interpreted
      as character or block devices. Legitimate character and block devices
      should exist in the /dev directory on the root partition or within chroot
      jails built for system services. All other locations should not allow
      character and block devices.</description>
      <reference source="JL" ref_id="RHEL6_20150305" ref_url="test_attestation"/>
    </metadata>
    <criteria operator="OR">
      <!-- First check if specified removable partition truly exists on the system. If not, don't check /etc/fstab & runtime configuration
           since there's no device to check against -->
      <criterion test_ref="test_removable_partition_doesnt_exist" comment="Check if removable partition really exists on the system" />
      <!-- Removable device exists. Check if it's CD/DVD drive. If so, verify that at least one from all of the possible its alternative
           names in /etc/fstab & runtime configuration are configured with 'nodev' option -->
      <criteria operator="AND">
        <criterion test_ref="test_var_removable_partition_is_cd_dvd_drive" comment="Check if removable partition value represents CD/DVD drive" />
        <criterion test_ref="test_nodev_etc_fstab_cd_dvd_drive" comment="Check if at least one from CD/DVD drive alternative names is using 'nodev' mount option in /etc/fstab" />
        <criterion test_ref="test_nodev_runtime_cd_dvd_drive" comment="Check if at least one from CD/DVD drive alternative names is using 'nodev' mount option in runtime configuration" />
      </criteria>
      <!-- Removable device exists & isn't CD/DVD drive. Check the particular devices is configured with 'nodev' mount option in both
           /etc/fstab & runtime configuration -->
      <criteria operator="AND">
        <criterion test_ref="test_nodev_etc_fstab_not_cd_dvd_drive" comment="Check if removable partition is using 'nodev' mount option in /etc/fstab" />
        <criterion test_ref="test_nodev_runtime_not_cd_dvd_drive" comment="Check if removable partition is using 'nodev' mount option in runtime configuration" />
      </criteria>
    </criteria>
  </definition>

  <!-- First check if specified removable partition really exists on the system.
       If not return PASS since there's nothing to check /etc/fstab & runtime settings against. -->
  <unix:file_test id="test_removable_partition_doesnt_exist" check="all" check_existence="none_exist" comment="Check if expected removable partitions truly exist on the system" version="1">
    <unix:object object_ref="object_removable_partition_doesnt_exist" />
  </unix:file_test>

  <unix:file_object id="object_removable_partition_doesnt_exist" version="1">
    <unix:filepath var_ref="var_removable_partition" var_check="at least one" />
  </unix:file_object>

  <!-- Specified removable partition exists on the system. Check if it represents a CD / DVD drive -->
  <ind:variable_test id="test_var_removable_partition_is_cd_dvd_drive" check="all" comment="Check if removable partition variable value represents CD/DVD drive" version="1">
    <ind:object object_ref="object_var_removable_partition_is_cd_dvd_drive" />
    <ind:state state_ref="state_var_removable_partition_is_cd_dvd_drive" />
  </ind:variable_test>

  <ind:variable_object id="object_var_removable_partition_is_cd_dvd_drive" version="1">
    <ind:var_ref>var_removable_partition</ind:var_ref>
  </ind:variable_object>

  <ind:variable_state id="state_var_removable_partition_is_cd_dvd_drive" version="1">
    <ind:value operation="equals">/dev/cdrom</ind:value>
  </ind:variable_state>

  <!-- If specified removable partition represents CD / DVD drive, create a variable
       holding also alternative names for CD / DVD block special device as used by udev -->
  <constant_variable id="variable_cd_dvd_drive_alternative_names" datatype="string" comment="CD/DVD drive alternative names whitelist" version="1">
    <value>/dev/cdrom</value>
    <value>/dev/dvd</value>
    <value>/dev/scd0</value>
    <value>/dev/sr0</value>
  </constant_variable>

  <!-- For each of the CD / DVD drive alternative names create regular expression pattern
       to be used in textfilecontent54_object below -->
  <local_variable id="variable_cd_dvd_drive_regex_pattern" datatype="string" comment="Regular expression pattern for CD / DVD drive alternative names" version="1">
    <concat>
      <literal_component>^[\s]*</literal_component>
      <variable_component var_ref="variable_cd_dvd_drive_alternative_names" />
      <!-- Capture the mount options field (4-th column of /etc/fstab) -->
      <literal_component>[\s]+[/\w]+[\s]+[\w]+[\s]+([^\s]+)(?:[\s]+[\d]+){2}$</literal_component>
    </concat>
  </local_variable>

  <!-- If specified removable partition represents CD / DVD drive, use all alternative
       names to check /etc/fstab & runtime settings -->
  <ind:textfilecontent54_test id="test_nodev_etc_fstab_cd_dvd_drive" check="all" comment="'nodev' mount option used for at least one CD / DVD drive alternative names in /etc/fstab" version="1">
    <ind:object object_ref="object_nodev_etc_fstab_cd_dvd_drive" />
    <ind:state state_ref="state_nodev_etc_fstab_cd_dvd_drive" />
  </ind:textfilecontent54_test>

  <ind:textfilecontent54_object id="object_nodev_etc_fstab_cd_dvd_drive" version="1">
    <ind:filepath>/etc/fstab</ind:filepath>
    <ind:pattern operation="pattern match" datatype="string" var_ref="variable_cd_dvd_drive_regex_pattern" var_check="at least one" />
    <ind:instance datatype="int" operation="greater than or equal">1</ind:instance>
  </ind:textfilecontent54_object>

  <ind:textfilecontent54_state id="state_nodev_etc_fstab_cd_dvd_drive" version="1">
    <ind:subexpression operation="pattern match" datatype="string">^.*,?nodev,?.*$</ind:subexpression>
  </ind:textfilecontent54_state>

  <linux:partition_test id="test_nodev_runtime_cd_dvd_drive" check="all" comment="'nodev' mount option used for at least one CD / DVD drive alternative names in runtime configuration" version="1">
    <linux:object object_ref="object_nodev_runtime_cd_dvd_drive" />
  </linux:partition_test>

  <linux:partition_object id="object_nodev_runtime_cd_dvd_drive" version="1">
    <!-- CD / DVD drive can be mounted under any mount_point. We don't know ahead its exact name.
         => Capture all & filter out only the relevant ones via the corresponding state -->
    <linux:mount_point operation="pattern match">^.*$</linux:mount_point>
    <!-- Therefore from all the captured mount points select only those having
         device set to some CD / DVD drive alternative name and simultaneously
         having 'nodev' mount option used -->
    <filter action="include">state_nodev_runtime_cd_dvd_drive</filter>
  </linux:partition_object>

  <linux:partition_state id="state_nodev_runtime_cd_dvd_drive" version="1">
    <linux:device datatype="string" operation="equals" var_ref="variable_cd_dvd_drive_alternative_names" var_check="at least one" />
    <linux:mount_options datatype="string" entity_check="at least one" operation="equals">nodev</linux:mount_options>
  </linux:partition_state>

  <!-- Specified removable partition exists & doesn't represent a CD/DVD drive.
       Check if configured with 'nodev' mount option in both /etc/fstab & runtime configuration -->
  <ind:textfilecontent54_test id="test_nodev_etc_fstab_not_cd_dvd_drive" check="at least one" check_existence="all_exist" comment="Check if removable partition is configured with 'nodev' mount option in /etc/fstab" version="1">
    <ind:object object_ref="object_nodev_etc_fstab_not_cd_dvd_drive" />
    <ind:state state_ref="state_nodev_etc_fstab_not_cd_dvd_drive" />
  </ind:textfilecontent54_test>

  <!-- Create regular expression pattern for the device to be used in the
       textfilecontent54_object below -->
  <local_variable id="variable_not_cd_dvd_drive_regex_pattern" datatype="string" comment="Regular expression pattern for removable block special device other than CD / DVD drive" version="1">
    <concat>
      <literal_component>^[\s]*</literal_component>
      <variable_component var_ref="var_removable_partition" />
      <!-- Capture the mount options field (4-th column of /etc/fstab) -->
      <literal_component>[\s]+[/\w]+[\s]+[\w]+[\s]+([^\s]+)(?:[\s]+[\d]+){2}$</literal_component>
    </concat>
  </local_variable>

  <ind:textfilecontent54_object id="object_nodev_etc_fstab_not_cd_dvd_drive" version="1">
    <ind:filepath>/etc/fstab</ind:filepath>
    <ind:pattern operation="pattern match" datatype="string" var_ref="variable_not_cd_dvd_drive_regex_pattern" var_check="at least one" />
    <ind:instance datatype="int" operation="greater than or equal">1</ind:instance>
  </ind:textfilecontent54_object>

  <ind:textfilecontent54_state id="state_nodev_etc_fstab_not_cd_dvd_drive" version="1">
    <ind:subexpression operation="pattern match" datatype="string">^.*,?nodev,?.*</ind:subexpression>
  </ind:textfilecontent54_state>

  <linux:partition_test id="test_nodev_runtime_not_cd_dvd_drive" check="all" check_existence="all_exist" comment="'nodev' mount option used for removable partition in runtime configuration" version="1">
    <linux:object object_ref="object_nodev_runtime_not_cd_dvd_drive" />
  </linux:partition_test>

  <linux:partition_object id="object_nodev_runtime_not_cd_dvd_drive" version="1">
    <!-- Removable partition can be mounted under any mount point. We don't know it's
         exact name ahead => capture all & filter out only those relevant later via state -->
    <linux:mount_point operation="pattern match">^.*$</linux:mount_point>
    <!-- From all the captured mount points select only those having device equal
         to 'var_removable_partition' variable value and simultaneously having
         'nodev' mount option set -->
    <filter action="include">state_nodev_runtime_not_cd_dvd_drive</filter>
  </linux:partition_object>

  <linux:partition_state id="state_nodev_runtime_not_cd_dvd_drive" version="1">
    <linux:device datatype="string" operation="equals" var_ref="var_removable_partition" var_check="at least one" />
    <linux:mount_options datatype="string" entity_check="at least one" operation="equals">nodev</linux:mount_options>
  </linux:partition_state>

  <external_variable comment="removable partition" datatype="string" id="var_removable_partition" version="1" />

</def-group>
