Class SEManagePort

java.lang.Object
com.aoindustries.selinux.SEManagePort

public final class SEManagePort extends Object
A policy is a non-overlapping mapping from (port-range, protocol) to SELinux type. Wraps functions of the semanage port commands.

This API hides the complexity of the interactions between default policy and local modifications. Instead, it presents the union of both as a single mapping of ports to SELinux types. This means supporting things like punching holes in default policy ranges when only part of the range is overridden by local policy, and also choosing to "modify" or "add" a port based on whether is an exact match or partial overlap with default policy.

Port mappings are across all IP addresses on a server. Thus it is impossible, for example, to have Apache listening on port 12345/tcp on one IP address while SSH listens on the same port 12345/tcp on a different IP address, even though both of these are custom ports and would not seem to be in conflict since on different IP addresses. By detecting local policy conflicts, the port configuration catches these conflicts instead of letting two services stomp on one another.

TODO: Make a main method to this as command line interface, with a set of commands? Overkill? commands -> Java API -> semanage -> python API

Author:
AO Industries, Inc.
  • Method Details

    • getPolicy

      public static SortedMap<IPortRange,String> getPolicy() throws IOException
      Gets the effective, non-overlapping policy. Local policy takes precedence over default policy.

      The default policy is extended, as needed, to include coverage for all ports from 1 to 65535 for tcp, udp, and sctp.

      Within the default policy, more specific ports will split more general ports, such as port 538/tcp=gdomap_port_t splitting 512-1023/tcp=hi_reserved_port_t into two ranges 512-537/tcp=hi_reserved_port_t and 539-1023/tcp=hi_reserved_port_t

      To give more consistency: adjacent ports of the same SELinux type are automatically coalesced. For example, 80/tcp and 81/tcp are listed separately in default policy, but are combined into 80-81/tcp for this view.

      Returns:
      the unmodifiable mapping of non-overlapping port ranges to SELinux type, covering all ports 1 through 65535 in tcp, udp, and sctp, coalesced into minimum entries.
      Throws:
      IOException
    • configure

      public static boolean configure(Set<? extends IPortRange> portRanges, String type) throws IllegalArgumentException, IllegalStateException, IOException
      Configures one SELinux type to have the given set of ports. This includes the ability to override default policy. This is the core purpose of this API: Just tell it what you want and it will handle the details.

      Before any changes are made, checks for conflicts with any other local policy.

      The provided ports are automatically coalesced into the minimum number of port ranges. For example, if both ports 1234/tcp and 1235/tcp are requested, a single local policy of 1234-1235/tcp is generated.

      In the first modification pass, adds any entries that are missing and not part of the default policy. However, any conflicting local policy is removed as-needed to allow the addition of the new entry.

      While adding the local policy, there are two interactions with default policy considered. First, if the local policy precisely matches a default policy entry of the expected type, the local policy entry is not added. Second, if the local policy has the same exact port range as a default policy entry (of a different type), modify(com.aoapps.net.IPortRange, java.lang.String) will be performed instead of add(com.aoapps.net.IPortRange, java.lang.String).

      In the second modification pass, any remaining extra local policy entries for the type are removed, thus freeing these ports for use in the local policy of other SELinux types.

      When default policy is not used by this type, it is left intact and not overridden to an unreserved type. The security benefits of overriding unused default policy is limited. Leaving the default policy serves two purposes: leaving a more predictable configuration and allowing a different SELinux type to override the port(s) with their own local policy.

      Implementation Note:
      We could punch holes in local policy to avoid overlapping default policy, but we see no conflict with local policy overlapping default policy. As an example, if SSH were listening on both ports 22/tcp and 23/tcp, the current implementation will create a single local policy entry of 22-23/tcp, which overlaps and is partially redundant with the default policy of 22/tcp. One possible benefit of this more complete local policy is more thorough detection of local policy conflicts.

      Parameters:
      portRanges - The set of all ports that should be set to the given type. There must not be any overlap in the provided port ranges.
      type - The SELinux type for the given set of ports.
      Returns:
      if any modification was made to the local policy
      Throws:
      IllegalArgumentException - if any overlapping port numbers found
      IllegalStateException - if detected overlap with local policy of a different type
      IOException