SNMPv3 agent returns authorization error

Hi,

I am unable to access managed objects using SNMPv3 from the following agent codes.
There is some authorization issues.

I am using the iReasoning MIB browser, and have configured it to use SNMPv3 with the following USM configuration:

user: cm2get
auth algorithm: sha
auth password: password
privacy algo: des
privacy password: password

My Agent Code:
package snmp;
import java.io.File;
import java.io.IOException;

import org.snmp4j.TransportMapping;
import org.snmp4j.agent.BaseAgent;
import org.snmp4j.agent.CommandProcessor;
import org.snmp4j.agent.DuplicateRegistrationException;
import org.snmp4j.agent.MOGroup;
import org.snmp4j.agent.ManagedObject;
import org.snmp4j.agent.mo.DefaultMOFactory;
import org.snmp4j.agent.mo.MOTableRow;
import org.snmp4j.agent.mo.snmp.RowStatus;
import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB;
import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB.SnmpCommunityEntryRow;
import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB;
import org.snmp4j.agent.mo.snmp.SnmpTargetMIB;
import org.snmp4j.agent.mo.snmp.StorageType;
import org.snmp4j.agent.mo.snmp.VacmMIB;
import org.snmp4j.agent.security.MutableVACM;
import org.snmp4j.log.ConsoleLogAdapter;
import org.snmp4j.log.ConsoleLogFactory;
import org.snmp4j.log.LogFactory;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModel;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.transport.TransportMappings;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.PrivDES;
import org.snmp4j.security.UsmUser;

public class SnmpApp extends BaseAgent 
{
    
    private static final String address = "0.0.0.0/2001";

    private static SnmpApp m_instance = null;
    private MYMib mymib ;

    private static final OID AUTHENTICATION_PROTOCOL = AuthSHA.ID;
    private static final String AUTHENTICATION_PASSWORD = "password";
    private static final OID PRIVACY_PROTOCOL = PrivDES.ID;
    private static final String PRIVACY_PASSWORD = "password";
    
    private String securityName = "cm2get";
   
    public static SnmpApp getInstance()
    {
        if (m_instance == null)
            try {
                m_instance = new SnmpApp(address) ;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
        return m_instance;
    }

    public SnmpApp(String address) throws IOException {
        
        // These files does not exist and are not used but has to be specified
        // Read snmp4j docs for more info
        super(new File("conf.agent"), new File("bootCounter.agent"),
                new CommandProcessor(
                        new OctetString(MPv3.createLocalEngineID())));
        
        
        try {
            LogFactory.setLogFactory(new ConsoleLogFactory());
            ConsoleLogAdapter.setDebugEnabled(true);
            
            mymib = new MYMib(DefaultMOFactory.getInstance());
            mymib.registerMOs(server, new OctetString("public")); // Register MY mib
        } catch (DuplicateRegistrationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    /**
     * We let clients of this agent register the MO they
     * need so this method does nothing
     */
    @Override
    protected void registerManagedObjects() {
    }

    /**
     * Clients can register the MO they need
     */
    public void registerManagedObject(ManagedObject mo) {
        try {
            server.register(mo, null);
        } catch (DuplicateRegistrationException ex) {
            throw new RuntimeException(ex);
        }
    }
    
    public void unregisterManagedObject(MOGroup moGroup) {
        moGroup.unregisterMOs(server, getContext(moGroup));
    }

    /*
     * Empty implementation
     */
    @Override
    protected void addNotificationTargets(SnmpTargetMIB targetMIB,
            SnmpNotificationMIB notificationMIB) {
    }

    /**
     * Minimal View based Access Control
     * 
     * http://www.faqs.org/rfcs/rfc2575.html
     */
    @Override
    protected void addViews(VacmMIB vacm) {

        
        
        // SNMPv3
        if (securityName != null && !securityName.equals("")) {
            
            System.out.println("Test");
              **vacm.addGroup(
                SecurityModel.SECURITY_MODEL_USM,
                new OctetString(securityName),
                new OctetString("v3group"),
                StorageType.volatile_
              );

              vacm.addAccess(
               new OctetString("v3group"),
                new OctetString("public"),
                SecurityModel.SECURITY_MODEL_USM,
                SecurityLevel.AUTH_PRIV,
                MutableVACM.VACM_MATCH_EXACT,
                new OctetString("fullReadView"),
               new OctetString("fullWriteView"),
                new OctetString("fullNotifyView"),
                StorageType.volatile_
              );
             
            }
        
        vacm.addViewTreeFamily(new OctetString("fullReadView"), new OID("1.3"),
                new OctetString(), VacmMIB.vacmViewIncluded,
                StorageType.nonVolatile);
        
        vacm.addViewTreeFamily(new OctetString("fullWriteView"), new OID("1.3"),
                new OctetString(), VacmMIB.vacmViewIncluded,
               StorageType.nonVolatile);
       
        vacm.addViewTreeFamily(new OctetString("fullNotifyView"), new OID("1.3"),
                new OctetString(), VacmMIB.vacmViewIncluded,
                StorageType.nonVolatile);
          
    }
    
    

    /**
     * User based Security Model, only applicable to
     * SNMP v.3
     * 
     */
    protected void addUsmUser(USM usm) {
        if (securityName == null || securityName.equals("")) {
              System.out.println("No security name.");
              return;
            }

            UsmUser user = new UsmUser(
              new OctetString(securityName),
              AUTHENTICATION_PROTOCOL,
              new OctetString(AUTHENTICATION_PASSWORD),
              PRIVACY_PROTOCOL,
              new OctetString(PRIVACY_PASSWORD)
            );
            usm.addUser(user.getSecurityName(), null, user);
    }

    protected void initTransportMappings() throws IOException {
        transportMappings = new TransportMapping[1];
        Address addr = GenericAddress.parse(address);
        TransportMapping tm = TransportMappings.getInstance()
                .createTransportMapping(addr);
        transportMappings[0] = tm;
    }

    
    
    
    /**
     * Start method invokes some initialization methods needed to
     * start the agent
     * @throws IOException
     */
    public void start() throws IOException {

        init();
        
        System.out.println("Started SnmpApp") ;
        
        
        // This method reads some old config from a file and causes
        // unexpected behavior.
        // loadConfig(ImportModes.REPLACE_CREATE); 
        addShutdownHook();
        getServer().addContext(new OctetString("public"));
        finishInit();
        SecurityProtocols.getInstance().addDefaultProtocols();
        run();
        sendColdStartNotification();
    }
    

    
    protected void unregisterManagedObjects() {
        // here we should unregister those objects previously registered...
    }

    /**
     * The table of community strings configured in the SNMP
     * engine's Local Configuration Datastore (LCD).
     * 
     * We only configure one, "public".
     */
    protected void addCommunities(SnmpCommunityMIB communityMIB) {
        Variable[] com2sec = new Variable[] { 
                new OctetString("public"), // community name
                new OctetString("cpublic"), // security name
                getAgent().getContextEngineID(), // local engine ID
                new OctetString("public"), // default context name
                new OctetString(), // transport tag
                new Integer32(StorageType.nonVolatile), // storage type
                new Integer32(RowStatus.active) // row status
        };
        MOTableRow row = communityMIB.getSnmpCommunityEntry().createRow(
                new OctetString("public2public").toSubIndex(true), com2sec);
        communityMIB.getSnmpCommunityEntry().addRow((SnmpCommunityEntryRow) row);
        
        
    }


}

This is the debug log:

Api Tested
Initialized Salt to b737e2e718b626c2.
Adding user cm2get = UsmUser[secName=cm2get,authProtocol=1.3.6.1.6.3.10.1.1.3,authPassphrase=password,privProtocol=1.3.6.1.6.3.10.1.2.2,privPassphrase=password,localizationEngineID=null]
Test
Started SnmpApp
UDP receive buffer size for socket 0.0.0.0/2001 is set to: 65536
Notification 1.3.6.1.6.3.1.1.5.1 reported with [] for context 
Received message from /127.0.0.1/54217 with length 44: 30:2a:02:01:01:04:06:70:75:62:6c:69:63:a0:1d:02:04:50:c0:64:31:02:01:00:02:01:00:30:0f:30:0d:06:09:2b:06:01:04:01:01:01:02:00:05:00
Fire process PDU event: CommandResponderEvent[securityModel=2, securityLevel=1, maxSizeResponsePDU=65535, pduHandle=PduHandle[1354785841], stateReference=StateReference[msgID=0,pduHandle=PduHandle[1354785841],securityEngineID=null,securityModel=null,securityName=public,securityLevel=1,contextEngineID=null,contextName=null,retryMsgIDs=null], pdu=GET[requestID=1354785841, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.4.1.1.1.2.0 = Null]], messageProcessingModel=1, securityName=public, processed=false, peerAddress=127.0.0.1/54217, transportMapping=org.snmp4j.transport.DefaultUdpTransportMapping@63f78fb6, tmStateReference=null]
Looking up coexistence info for 'public'
Found coexistence info for 'public'=CoexistenceInfo[securityName=cpublic,contextEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,contextName=public,transportTag=]
Address 127.0.0.1/54217 passes filter, because source address filtering is disabled
Created subrequest 0 with scope org.snmp4j.agent.DefaultMOContextScope[context=public,lowerBound=1.3.6.1.4.1.1.1.2.0,lowerIncluded=true,upperBound=1.3.6.1.4.1.1.1.2.0,upperIncluded=true] from 1.3.6.1.4.1.1.1.2.0 = Null
SnmpSubRequests initialized: [org.snmp4j.agent.request.SnmpRequest$SnmpSubRequest[scope=org.snmp4j.agent.DefaultMOContextScope[context=public,lowerBound=1.3.6.1.4.1.1.1.2.0,lowerIncluded=true,upperBound=1.3.6.1.4.1.1.1.2.0,upperIncluded=true],vb=1.3.6.1.4.1.1.1.2.0 = Null,status=RequestStatus{processed=false, phaseComplete=false, errorStatus=0},query=null,index=0,targetMO=null]]
java.lang.Exception: Error 'Authorization error' generated at: 1.3.6.1.4.1.1.1.2.0 = Null
Sending message to 127.0.0.1/54217 with length 44: 30:2a:02:01:01:04:06:70:75:62:6c:69:63:a2:1d:02:04:50:c0:64:31:02:01:10:02:01:01:30:0f:30:0d:06:09:2b:06:01:04:01:01:01:02:00:05:00
    at org.snmp4j.agent.request.SnmpRequest$SnmpSubRequest.requestStatusChanged(SnmpRequest.java:627)
    at org.snmp4j.agent.request.RequestStatus.fireRequestStatusChanged(RequestStatus.java:89)
    at org.snmp4j.agent.request.RequestStatus.setErrorStatus(RequestStatus.java:52)
    at org.snmp4j.agent.CommandProcessor.setAuthorizationError(CommandProcessor.java:506)
    at org.snmp4j.agent.CommandProcessor.processRequest(CommandProcessor.java:379)
    at org.snmp4j.agent.CommandProcessor.dispatchCommand(CommandProcessor.java:340)
    at org.snmp4j.agent.CommandProcessor$Command.run(CommandProcessor.java:566)
    at org.snmp4j.agent.CommandProcessor.processPdu(CommandProcessor.java:163)
    at org.snmp4j.MessageDispatcherImpl.fireProcessPdu(MessageDispatcherImpl.java:694)
    at org.snmp4j.MessageDispatcherImpl.dispatchMessage(MessageDispatcherImpl.java:310)
    at org.snmp4j.MessageDispatcherImpl.processMessage(MessageDispatcherImpl.java:390)
    at org.snmp4j.MessageDispatcherImpl.processMessage(MessageDispatcherImpl.java:350)
    at org.snmp4j.transport.AbstractTransportMapping.fireProcessMessage(AbstractTransportMapping.java:76)
    at org.snmp4j.transport.DefaultUdpTransportMapping$ListenThread.run(DefaultUdpTransportMapping.java:430)
    at java.base/java.lang.Thread.run(Unknown Source)

The browser configuration is not correct. It is using SNMPv2c! Please do not ask me for support on the iReasoning browser (I do not know it). You could use my MIB Explorer instead :wink:

Ok. I switched to MIB Explorer currently.
Please guide me if I do it correctly.

  1. Import MIB (File > Import MIB File…)
  2. Edit > Targets… > USM User
    -> Create a USM
    User Profile Name: cm2get
    Security Name: cm2get
    Authentication Protocol: SHA-1
    Password: password
    Privacy Protocol: DES
    Password: password
    * Leave Principal and Localization Engine ID unchecked
    -> Create a new target
    Name: New Target
    MIB Set: -
    Transport: UDP
    Address: 127.0.0.1/2001
    Version: SNMPv3
    Timeout: 1000
    User: cm2get

I get the follow error in MIB Explorer when I perform a GET.

DEBUG org.snmp4j.mp.MPv3 Context engine ID of scoped PDU is empty! Setting it to authoritative engine ID: 80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8
DEBUG org.snmp4j.security.USM getUser(engineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8, securityName=cm2get)
DEBUG org.snmp4j.security.USM RFC3414 §3.1.4.a Outgoing message needs to be encrypted
DEBUG org.snmp4j.security.PrivDES Preparing decrypt_params.
DEBUG org.snmp4j.security.PrivDES Preparing iv for encryption.
DEBUG org.snmp4j.security.PrivacyGeneric Using padding.
DEBUG org.snmp4j.security.PrivDES Encryption finished.
DEBUG org.snmp4j.mp.MPv3 Adding cache entry: StateReference[msgID=TimedMessageID{msgID=939218776,creationNanoTime=42038839236000},pduHandle=MxpPduHandle[transactionID=554327777,totalMessagesSent=0,indexOfMessageResponded=0,responseRuntimeNanos=0],securityEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,securityModel=org.snmp4j.security.USM@470362bf,securityName=cm2get,securityLevel=3,contextEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,contextName=,retryMsgIDs=null]
DEBUG org.snmp4j.Snmp Running pending async request with handle MxpPduHandle[transactionID=554327777,totalMessagesSent=0,indexOfMessageResponded=0,responseRuntimeNanos=0] and retry count left 1
DEBUG org.snmp4j.transport.DefaultUdpTransportMapping Sending message to 127.0.0.1/2001 with length 142: 30:81:8b:02:01:03:30:11:02:04:37:fb:57:58:02:03:00:ff:ff:04:01:07:02:01:03:04:39:30:37:04:0d:80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8:02:01:3a:02:03:00:9b:4c:04:06:63:6d:32:67:65:74:04:0c:df:20:0d:2a:b5:c8:34:dd:61:c1:24:e2:04:08:00:00:00:3a:2f:cd:bd:35:04:38:2f:86:d6:8e:15:bb:7b:27:55:c7:2e:27:2a:ff:40:82:33:b8:58:8d:f5:c2:a3:f6:36:42:16:fd:5e:9b:55:87:fe:cb:3b:ba:73:77:03:59:da:b8:1f:04:81:f5:4f:a1:db:3f:80:80:c2:3d:4c:ab
INFO SNMP.GETBULK.Request 554327777 - New Target - UDP:127.0.0.1/2001: SNMPv3, retries=1, timeout=1000 engineID=, context=, contextID= cm2get: secName=cm2get, secModel=3, SHA-1=password, DES=password, localized=false, principal=false type=a5, err=0, errind=2 VB[0] 1.3.6.1.4.1.1.1.2(5)=Null
DEBUG org.snmp4j.security.USM getUser(engineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8, securityName=cm2get)
DEBUG org.snmp4j.security.USM RFC3414 §3.1.4.a Outgoing message needs to be encrypted
DEBUG org.snmp4j.security.PrivDES Preparing decrypt_params.
DEBUG org.snmp4j.security.PrivDES Preparing iv for encryption.
DEBUG org.snmp4j.security.PrivacyGeneric Using padding.
DEBUG org.snmp4j.security.PrivDES Encryption finished.
DEBUG org.snmp4j.mp.MPv3 Adding cache entry: StateReference[msgID=TimedMessageID{msgID=939218777,creationNanoTime=42039841610600},pduHandle=PduHandle[554327777],securityEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,securityModel=org.snmp4j.security.USM@470362bf,securityName=cm2get,securityLevel=3,contextEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,contextName=,retryMsgIDs=null]
DEBUG org.snmp4j.mp.MPv3 Adding previous message IDs [TimedMessageID{msgID=939218776,creationNanoTime=42038839236000}] to new entry StateReference[msgID=TimedMessageID{msgID=939218777,creationNanoTime=42039841610600},pduHandle=PduHandle[554327777],securityEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,securityModel=org.snmp4j.security.USM@470362bf,securityName=cm2get,securityLevel=3,contextEngineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8,contextName=,retryMsgIDs=null]
DEBUG org.snmp4j.Snmp Running pending async request with handle PduHandle[554327777] and retry count left 0
DEBUG org.snmp4j.transport.DefaultUdpTransportMapping Sending message to 127.0.0.1/2001 with length 142: 30:81:8b:02:01:03:30:11:02:04:37:fb:57:59:02:03:00:ff:ff:04:01:07:02:01:03:04:39:30:37:04:0d:80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8:02:01:3a:02:03:00:9b:4d:04:06:63:6d:32:67:65:74:04:0c:a4:6b:a6:4d:c8:fe:dc:4c:4a:7c:cb:de:04:08:00:00:00:3a:2f:cd:bd:36:04:38:46:01:58:60:ff:d8:21:83:5b:84:03:75:80:45:26:74:00:42:22:5c:8a:d9:29:d5:f5:35:86:80:15:8e:52:a9:a4:a1:51:d6:a4:69:08:4e:c0:bc:d3:a2:fb:b1:3b:85:07:d4:3e:1a:df:2d:b3:46
DEBUG org.snmp4j.Snmp Request timed out: 554327777
DEBUG org.snmp4j.Snmp Cancelling pending request with handle MxpPduHandle[transactionID=554327777,totalMessagesSent=0,indexOfMessageResponded=0,responseRuntimeNanos=0]
WARN SNMP.GETBULK.Response 554327777 - Request timed out
DEBUG org.snmp4j.Snmp Cancelling pending request with handle null

The SNMP4J agent shows the following:

Received message from /127.0.0.1/58781 with length 142: 30:81:8b:02:01:03:30:11:02:04:37:fb:57:59:02:03:00:ff:ff:04:01:07:02:01:03:04:39:30:37:04:0d:80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8:02:01:3a:02:03:00:9b:4d:04:06:63:6d:32:67:65:74:04:0c:a4:6b:a6:4d:c8:fe:dc:4c:4a:7c:cb:de:04:08:00:00:00:3a:2f:cd:bd:36:04:38:46:01:58:60:ff:d8:21:83:5b:84:03:75:80:45:26:74:00:42:22:5c:8a:d9:29:d5:f5:35:86:80:15:8e:52:a9:a4:a1:51:d6:a4:69:08:4e:c0:bc:d3:a2:fb:b1:3b:85:07:d4:3e:1a:df:2d:b3:46
getUser(engineID=80:00:13:70:01:c0:a8:b8:01:6a:40:2c:a8, securityName=cm2get)
CheckTime: time ok (non authoritative)
Message from 127.0.0.1/58781 not dispatched, reason: statusInfo=noError, status=-1406

That status code means “invalid engine ID”. You need to specify the correct one in MIB Explorer or discover the engine ID. Be aware the

MPv3.createLocalEngineID()

will always create a randomly new engine ID. To store the engine ID persistently use the EngineBootsCounterFile class.

Thanks for your reply.

It was indeed the error.
However, how can I use an EngineBootsCounterFile? My only understanding for this engine id needs to be 5 to 32 octet long.

I edited the Agent code as such

super(new File("conf.agent"), new File("bootCounter.agent"),
			new CommandProcessor(
					new OctetString(allcontextandEngineId)));

Where allcontextandEngineId=“public”.
After configuring the MIB Explorer target to use “public” for the context and “public” for the context engine ID. I am able to retrieve the value.

However, if I changed allcontextandEngineId to “public2” in the Agent code for all the relevant context and engine id. The “invalid engine ID” status code will reappear at the agent.

It seems to be the configuration for MIB explorer.
It seems to be that the field used for engine id is not the field which indicates engine id.
I need to click the engine id button to show what engine id was used and configured it at the empty field instead

There are two fields:

  1. Authoritative engine ID (or short “engine ID”)
  2. Context engine ID

The first one is the one that is used by the USM. The second one, selects a PDU processing subsystem within the target agent (identified by the first engine ID). In most cases, the second engine ID is the same as the first. Most tools will set the context engine ID to the provided/discovered engine ID (1.) of the agent’s authoritative engine if the context engine ID is empty. But if you set it, it needs to be there in the agent, otherwise you will get a REPORT PDU as response.

Hope this helps.

1 Like