pschild
pschild

Reputation: 3138

SNMP4J Client gives "Unsupported security level"

I'm about to implement a Client/Agent setup in order to learn using SNMP. I want to establish a secure and encrypted communication using SNMPv3 and authPriv as security level.
Here's my setup:

Agent
The Agent is running on Ubuntu (within a Docker image). To set it up, I followed this tutorial.
My /etc/snmp/snmpd.conf looks like this:

agentAddress udp:161
...
createUser authOnlyUser MD5 "test1234"
createUser authPrivUser SHA "test1234" DES
createUser internalUser MD5 "test1234"
...
rouser authOnlyUser
rwuser authPrivUser authPriv

SNMP is running on port 161, which is forwarded to port 1025 by Docker.

Client
I could ensure that my Agent is working properly using

  1. snmpget on the same machine (Ubuntu, within Docker):
    snmpget -v3 -a SHA -A test1234 -X test1234 -l authPriv -u authPrivUser localhost 1.3.6.1.2.1.1.1.0
  2. snmpget from a remote machine (Debian):
    snmpget -v3 -u authPrivUser -X test1234 -A test1234 -l authPriv -x DES -a SHA <HOST-IP>:1025 1.3.6.1.2.1.1.1.0
  3. Using SNMP-Tester.

In all three cases I get the expected value for the given OID:
Linux 9b98a8808b1a 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64.

Now I wanted to implement a Client with Java, using the latest version 3.2.2 of snmp4j. This is what I have implemented:

public class SNMPTestClient {

    public static void main(String[] args) throws Exception {
        // enable logging
        ConsoleLogFactory consoleLogFactory = new ConsoleLogFactory();
        consoleLogFactory.getRootLogger().setLogLevel(LogLevel.DEBUG);
        LogFactory.setLogFactory(consoleLogFactory);

        TransportMapping<? extends Address> transport = new DefaultUdpTransportMapping();
        Snmp snmp = new Snmp(transport);

        // create and add user security model
        OctetString localEngineId = new OctetString(MPv3.createLocalEngineID());
        USM usm = new USM(SecurityProtocols.getInstance(), localEngineId, 0);
        SecurityModels.getInstance().addSecurityModel(usm);

        // user credentials
        OctetString securityName = new OctetString("authPrivUser");
        OctetString authPassphrase = new OctetString("test1234");
        OctetString privPassphrase = new OctetString("test1234");
        OID authProtocol = AuthSHA.ID;
        OID privProtocol = PrivDES.ID;

        UsmUser usmUser = new UsmUser(securityName, authProtocol, authPassphrase, privProtocol, privPassphrase);
        snmp.getUSM().addUser(securityName, usmUser);

        // create target
        UserTarget target = new UserTarget();
        target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
        target.setSecurityName(securityName);
        target.setAddress(GenericAddress.parse("udp:127.0.0.1/1025"));
        target.setVersion(SnmpConstants.version3);
        target.setRetries(3);
        target.setTimeout(10000);

        transport.listen();

        ScopedPDU pdu = new ScopedPDU();
        pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1.0")));
        pdu.setType(PDU.GET);
        ResponseEvent event = snmp.send(pdu, target);
        if (event != null) {
            System.out.println(event.getUserObject());
            System.out.println(event.getError());
            System.out.println(event.getPeerAddress());
            PDU responsePDU = event.getResponse();
            System.out.println(responsePDU.getErrorStatus());
            System.out.println(responsePDU.getErrorIndex());
            if (responsePDU.getErrorStatus() == PDU.noError) {
                for (int k = 0; k < responsePDU.size(); k++) {
                    VariableBinding vb = responsePDU.get(k);
                    if (vb != null) {
                        System.out.println(vb.getOid() + "-" + vb.getVariable().toString());
                    }
                }
            } else {
                System.out.println("SNMP Error:" + responsePDU.getErrorStatusText());
            }
        } else {
            System.out.println("SNMP send unsuccessful.");
        }
    }
}

As you can see I'm using the same credentials and protocols like mentioned above. But when I run it I receive the following Exception:
org.snmp4j.MessageException: Message processing model 3 returned error: Unsupported security level

What am I doing wrong here? As the user authPrivUser is configured to use the authPriv security level on the Agent's side and I'm also setting the level to AUTH_PRIV within the client and pass the correct credentials, I don't know why this exception is thrown.

Thanks in advance for any support and hints!

EDIT
I figured out that the code I posted above does work using SNMP4J v2.7.0. Any version >=3.0.0 throws error Unsupported security level. Unfortunately, using an old version from Nov. 2018 cannot be the solution...

Upvotes: 1

Views: 3639

Answers (1)

ooSNMP
ooSNMP

Reputation: 377

In SNMP4J 3.x the security protocol AuthSHA (and AuthMD5) are no longer added by default to the static SecurityProtocols instance because they are now considered as unsafe.

You can add it again by calling:

SecurityProtocols.addAuthenticationProtocol(new AuthSHA());

Upvotes: 6

Related Questions