SNMP4J-AgentX 4.2.0 | SNMP4J-Unix-Transport 1.2.2 Releases

The SNMP4J-4.2.0 release provides multi-subagent Unix transport mapping support for master- and subagent connections per master agent. In addition, agent audit policy and restricted security for sample agents have been implemented. Bug fixes for the Unix transport mapping has been applied as well.

CHANGES SNMP4J-AgentX 4.2.0

  • SECURITY: Added support for agent auditing for TestMasterAgent and TestSubagent using an AgentPolicyProfile.
  • Changed: AgentXRequest.getSecurityLevel() to return SecurityLevel.NO_AUTH_NO_PRIV instead of throwing an UnsupportedOperationException to support agent auditing.
  • Changed: TestMasterAgent now reads configuration from a properties file instead of programmatic initialization.
  • Added: Support for multiple subagents through Unix domain transport mapping on a single master agent.
  • Updated: README_SECURITY.txt with information about agent auditing.

CHANGES SNMP4J-Unix-Transport 1.2.2

  • Fixed: UnixSocketStreamTransportMapping ignored isServerEnabled() and bound its socket path even in client mode, unlike DefaultTcpTransportMapping and TLSTM, which bind their listen address only if the server is enabled. A client mode transport mapping that opens outgoing connections only - as created for instance by AgentXSubagent.addMaster(..), which explicitly calls setServerEnabled(false) - therefore competed for the socket path of the transport mapping that serves incoming connections on it. An IP based transport mapping can bind an ephemeral port in that situation, but a Unix domain socket path is the address itself, so listen() failed with “Address already in use” as soon as both transport mappings used the same path. To keep the previous behavior for transport mappings that are used as a server, the constructor that takes a listen address enables the server mode now, as the corresponding constructor of DefaultTcpTransportMapping does. Use the new UnixSocketStreamTransportMapping(UnixDomainAddress,boolean) constructor or setServerEnabled(false) for a client mode transport mapping.
  • Added: A client mode UnixSocketStreamTransportMapping (see setServerEnabled(boolean)) binds its socket path to the outgoing socket of every connection it opens, so that the peer can tell this SNMP entity apart from other entities that connect to it. A Unix domain socket that has not been bound has no address at all, thus all peers that connect with an unbound socket are reported with the same empty address by the accepting entity, which keeps its connections in a map that is keyed by that address: only the connection that arrived last could be addressed. Several AgentX sub-agents can therefore share one Unix domain master agent now, as long as each of them uses its own socket path. If the path cannot be bound, the connection is opened with an unbound socket as before and a warning is logged, and an entity that accepts a connection from an unbound socket logs a warning as well. New API: UnixSocketStreamTransportMapping.ServerThread.bindOutgoingSocket(SocketChannel).
  • Fixed: UnixSocketStreamTransportMapping.close() removed the socket file of its listen address even if it had not created that file, which could remove the socket of another SNMP entity that used the same path.
    Only a socket file that this transport mapping has bound itself is removed now (see the new
    removeBoundSocketFile() method and the boundSocketPath member). close() also skipped closing the transport mapping altogether if it had no listen address.
  • Fixed: UnixSocketStreamTransportMapping.listen() logged that the listen address had been bound successfully even if nothing had been bound at all, which is the case in client mode and for a transport mapping without a listen address (for example one created by GenericAddress.newLocalAddress("unix"), whose address is empty). It reports the actual outcome now.
  • Fixed: UnixDomainAddress.isValid() and parseAddress(String) threw a NullPointerException for a socket path that has no parent path element, that is for a plain socket file name like “snmp4j-agent.sock” - the natural form for a socket in the working directory - as well as for the empty path and for a file system root. Such an address could therefore not be parsed at all, because GenericAddress.parse(String) discards an address whose parsing throws an exception. isValid() also threw a NullPointerException if no socket path had been set at all.
  • Fixed: UnixDomainAddress.isValid() does not check file system permissions anymore. It checks now that the socket path is not empty and that it fits into the sun_path member of the sockaddr_un structure of the operating system (see the new MAX_SOCKET_PATH_LENGTH constant), because those are the properties of the address itself. Before, it required write and search permission on the directory of the socket path, which is what binding a socket needs but not what connecting to one needs: an existing socket in a read-only directory (for example, below /var/run) was reported as invalid, although it can be connected, whereas a socket file without write permission for the SNMP4J process was reported as valid although connecting to it fails with “Permission denied”. As a consequence, parseAddress(String) does not depend on the current working directory, on the effective user of the process, and on the state of the file system anymore. An over-long socket path is rejected now, which was accepted before, although it cannot be bound.
  • Fixed: UnixDomainAddress.parseAddress(String) returns false instead of throwing an InvalidPathException if the supplied address contains a NUL character, and false instead of throwing a NullPointerException if the supplied address is null.
  • Added: New org.snmp4j.transport.unix.audit package with the UnixDomainAgentProfilePolicy, a subclass of the DefaultAgentAuditPolicy of SNMP4J-Agent that supports the “unix” address domain of UnixDomainAddress.
    Because a Unix domain socket operation is always local, the InetAddress based network access restrictions of the AgentPolicyProfile are not applicable to it and the file system access that such an operation needs is checked instead: the socket’s (local) file path is matched against the allowed files and directories of the profile, where LISTEN is checked as a CREATE, CLOSE as a DELETE, SEND as a WRITE, and RECEIVE as a READ file operation. Transport operations of other address domains are audited by the DefaultAgentAuditPolicy unchanged. The new optional (provided) dependency to SNMP4J-Agent is required for this package only.
  • Added: UnixDomainAddress.isBindable() and UnixDomainAddress.isConnectable() check whether the current process may listen on respectively send to a Unix domain socket address, using the permissions that the corresponding operation actually requires: write and search permission on the socket’s directory to bind it and write permission on the socket file to connect to it. Because both are a snapshot of the current file system state, a failing bind or connect still has to be handled. In addition, UnixDomainAddress.getParentDirectory() returns the absolute directory that contains the socket file and UnixDomainAddress.MAX_SOCKET_PATH_LENGTH provides the maximum length of a Unix domain socket path in bytes.
  • Updated: Dependency to SNMP4J to 3.13.1 and SNMP4J-Agent to 3.10.1.