Message processing model 3 returned error: Unknown security name

Hello,
I developed an agent that supports SNMPv3 and a client sending Get request. Very simple but I got errors :

  • With engineId on client : Message processing model 3 returned error: Unknown security name
  • Without engineId on client : an error on serverr side : Unknown engine ID
    I looked for a solution to fix this issue but no success.
    Can you help on that.
    Thanks

With engine_id : client exception
org.snmp4j.MessageException: Message processing model 3 returned error: Unknown security name
at org.snmp4j.MessageDispatcherImpl.sendPdu(MessageDispatcherImpl.java:527)
at org.snmp4j.Snmp.sendMessage(Snmp.java:1088)
at org.snmp4j.Snmp.send(Snmp.java:981)
at org.snmp4j.Snmp.send(Snmp.java:961)
at org.snmp4j.Snmp.send(Snmp.java:926)
at MySnmpV3Test.sendSnmp(MySnmpV3Test.java:66)
at MySnmpV3Test.snmpGet(MySnmpV3Test.java:46)
at MySnmpV3Test.main(MySnmpV3Test.java:115)

Without engine_id : (server side) :

Without engine id
Received message from /127.0.0.1/40155 with length 60: 30:3a:02:01:03:30:10:02:03:00:e7:53:02:03:00:ff:ff:04:01:04:02:01:03:04:10:30:0e:04:00:02:01:00:02:01:00:04:00:04:00:04:00:30:11:04:00:04:00:a0:0b:02:01:00:02:01:00:02:01:00:30:00
RFC3414 ยง3.2.3 Unknown engine ID:
RFC3414 ยง3.1.4.b Outgoing message is not encrypted
Sending message to 127.0.0.1/40155 with length 103: 30:65:02:01:03:30:10:02:03:00:e7:53:02:03:00:ff:ff:04:01:00:02:01:03:04:1d:30:1b:04:0d:80:00:13:70:01:7f:00:00:01:65:6b:12:34:02:01:00:02:01:00:04:00:04:00:04:00:30:2f:04:0d:80:00:13:70:01:7f:00:00:01:65:6b:12:34:04:00:a8:1c:02:01:00:02:01:00:02:01:00:30:11:30:0f:06:0a:2b:06:01:06:03:0f:01:01:04:00:41:01:05
Message from 127.0.0.1/40155 not dispatched, reason: statusInfo=1.3.6.1.6.3.15.1.1.4.0 = 5, status=1410

Hereafter my code :

Agent SERVER :

*public class MyAgent extends BaseAgent {

public MyAgent() {

	super(new File(CsdClusterHelper.getVarFolder(), "snmp-conf2.agent"),
			new File(CsdClusterHelper.getVarFolder(), "snmp-bootCounter2.agent"),
			new CommandProcessor(new OctetString(MPv3.createLocalEngineID())));
	agent.setWorkerPool(ThreadPool.create("SnmpAgentRequestPool", 4));
	...
}

protected void addUsmUser(USM usm) {

	// the security name of the user (typically the user name).
	OctetString securityName = new OctetString("snmpuser");

	// Passphrase
	OctetString securityPassphrase = new OctetString("snmpPassword");

	UsmUser user = new UsmUser(securityName, AuthMD5.ID, securityPassphrase, PrivDES.ID, securityPassphrase);
	usm.addUser(user.getSecurityName(), usm.getLocalEngineID(), user);

	System.out.println("engine id : " + usm.getLocalEngineID().toHexString());
}

@Override
protected void addViews(VacmMIB vacm) {

	String securityName = "snmpuser";

	vacm.addGroup(SecurityModel.SECURITY_MODEL_USM, new OctetString(securityName), new OctetString(GROUP_V3),
			StorageType.nonVolatile);

	vacm.addAccess(new OctetString(GROUP_V3), new OctetString(), SecurityModel.SECURITY_MODEL_USM,
			SecurityLevel.AUTH_PRIV, MutableVACM.VACM_MATCH_EXACT, new OctetString("fullReadViewPublic"),
			new OctetString("fullWriteViewPublic"), new OctetString("fullNotifyViewPublic"),
			StorageType.nonVolatile);

	vacm.addViewTreeFamily(new OctetString("fullReadViewPublic"), new OID("1.3.6.1.4.1.35003"), new OctetString(),
			VacmMIB.vacmViewIncluded, StorageType.nonVolatile);
	vacm.addViewTreeFamily(new OctetString("fullNotifyViewPublic"), new OID("1.3.6.1.4.1.35003"), new OctetString(),
			VacmMIB.vacmViewIncluded, StorageType.nonVolatile);
}

}
*

Snmp Client for test (Get request)

  • public class MySnmpV3Test {

    protected Snmp snmp;
    protected String address = “127.0.0.1/16002”;
    protected String PROTOCOL = “udp:”;
    private static OctetString securityName = new OctetString(“snmpuser”);
    private static OID authProtocol = AuthMD5.ID;
    private static OctetString passPhrase = new OctetString(“snmpPassword”);
    private static OID privProtocol = PrivDES.ID;
    private static int securityLevel = SecurityLevel.AUTH_PRIV;
    OctetString engineId = OctetString.fromHexString(“80:00:13:70:01:7f:00:00:01:9f:68:66:06”, ‘:’);

    protected USM usm = null;

    public void snmpGet() {
    usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
    SecurityModels.getInstance().addSecurityModel(usm);
    createSNMPsession();
    addSnmpUser();
    sendSnmp();
    }

    private void sendSnmp() {
    // send the PDU
    ResponseEvent response;
    try {
    // Target
    UserTarget target = new UserTarget();
    Address targetAddress = GenericAddress.parse(PROTOCOL + address);
    target.setAddress(targetAddress);
    target.setRetries(0);
    target.setTimeout(5000);
    target.setVersion(SnmpConstants.version3);
    target.setSecurityLevel(securityLevel);
    target.setSecurityName(securityName);

      	// PDU
      	ScopedPDU pdu = new ScopedPDU();
      	pdu.add(new VariableBinding(new OID("1.3.6.1.4.1.35003.2.1.0")));
      	response = snmp.send(pdu, target);
    
      	// extract the response PDU (could be null if timed out)
      	PDU responsePDU = response.getResponse();
      	if (responsePDU == null) {
      		System.out.println("No response, timeOut...");
      	} else if (responsePDU.getErrorStatus() == PDU.noError) {
      		Vector<? extends VariableBinding> vbs = responsePDU.getVariableBindings();
      		for (VariableBinding vb : vbs) {
      			System.out.println("RESPONSE: " + vb + " ," + vb.getVariable().getSyntaxString());
      			System.out.println("pdu: " + responsePDU.toString());
      		}
      	} else {
      		System.out.println("ERROR:" + responsePDU.getErrorStatusText() + ":" + responsePDU.getErrorStatus());
      		System.out.println("ERROR:" + responsePDU);
      	}
      } catch (IOException e) {
      	e.printStackTrace();
      } finally {
      	try {
      		snmp.close();
      	} catch (IOException e) {
      		e.printStackTrace();
      	}
      }
    

    }

    protected void createSNMPsession() {
    TransportMapping<? extends Address> transport;
    try {
    transport = new DefaultUdpTransportMapping();
    snmp = new Snmp(transport);
    snmp.setLocalEngine(engineId.getValue(), 0, 0);// OctetString(usm.getLocalEngineID()).getValue(), 0, 0);
    transport.listen();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    protected void addSnmpUser() {
    UsmUser usmUser = new UsmUser(securityName, authProtocol, passPhrase, privProtocol, passPhrase);
    System.out.println("engine id : " + usm.getLocalEngineID());
    // snmp.getUSM().addUser(securityName, usm.getLocalEngineID(), usmUser);
    snmp.getUSM().addUser(securityName, usmUser);
    }

    public static void main(String[] args) {
    new MySnmpV3Test().snmpGet();
    }
    }*

Having lived through that same error message myself, I will tell you what I used to diagnose that. Please bear in mind that I am off the mainstream versions so this might be a little different for you.

In short the “Unknown security name” means exactly that: the system is using USM to fetch the applicable parameters to form the packet for sending and the security name is empty. There are a couple different ways this could (and did!) happen for me:

  1. Make sure you set usm.setEngineDiscoveryEnabled(true) unless you know the engineID you would use for each agent. If you do know it in advance, then your USM user cache should add each user with a specific engineID. That engineID is that of the agent, not the manager.

  2. The USM cache lookup is progressive going from the more specific resolution involving the engineId and the security name all the way down to just having the securityName only. If you have duplicates of the engineId or places where the same user may have different security parameters, it can make the resolution nearly impossible and you get left with what seems to be the default record which (for me) had the user name and pretty much nothing else. To debug that, try running USM::getUser() with various parameters to make sure you have data.

Hello,
Thanks bkuhhirte for your contribution.
EngineId is very hard to understand. almost problems are due to engineId.
I set usm.setEngineDiscoveryEnabled(true) on my trap receiver and it succeded to receive traps from agent.
However when I set it when requesting the agent to get value of an OID, it doesn’t help.

Should I put the statement : usm.setEngineDiscoveryEnabled(true) also on SnmpAgent code ?
Or only on client side (when trying the GET or SET…)

Michel,
Let’s first talk about the theory and then how you can break down the problem further. The engineId should represent a globally unique identifier for the system under management (your agent) and the system doing the managing (the manager). In order to ensure that I don’t have a man-in-the-middle (MITM) attack, I need to know my counterpart more than just that the userid and password are accepted. So in SNMPv3 the first thing we exchange is the engineID from the agent to the manager. In practice, it is entirely possible to find duplicates of that engineID for many different reasons (sloppy admins, non-unique generation techniques, etc.), but that is a different topic entirely.

I suspect part of your problem is that you are using an untested manager against an untested agent and you don’t know which side of the conversation is having problems. To lessen that ambiguity, I took your manager code and tested it against the agent I use for integration tests and with some minor changes it works properly. Non-functional changes were altering the userid and password (my agent is different) and the OID requested, but the only other line I changed was:

byte[] engineId = MPv3.createLocalEngineID();
snmp.setLocalEngine(engineId, 0, 0);    

Once I made that change, I get the following response:

engine id : 80:00:13:70:01:7f:00:00:01:3a:03:35:63
Message from 127.0.0.1/59634 not dispatched, reason: statusInfo=1.3.6.1.6.3.15.1.1.4.0 = 1, status=1410
RESPONSE: 1.3.6.1.2.1.1.3.0 = 0:00:01.06 ,TimeTicks
pdu: RESPONSE[{contextEngineID=80:00:13:70:01:7f:00:00:01:fb:79:03:73, contextName=}, 
requestID=1970378591, errorStatus=0, errorIndex=0, VBS[1.3.6.1.2.1.1.3.0 = 0:00:01.06]]
1 Like

Hello,
Thanks for your contribution.
Yes I know, most of SNMPv3 errors are globally due to engine identifiers that are not the same between Manager and Agent.

The SNMP agent sets its identifier using : MPv3.createLocalEngineID();
This value AGENT_ENGINE_ID is random and is different after each agent restart.

On your Manager (The system doing the management), you use the same java statement :
byte[] engineId = MPv3.createLocalEngineID();
snmp.setLocalEngine(engineId, 0, 0);
The engineId value (MANAGER_ENGINE_ID) is different from the Agent engine ID (AGENT_ENGINE_ID).
The communication between Manager and Agent succeeds only if the Manager uses the same engineId value (the Agent engineId) !

I don’t understand how it works for you even if used Engine identifers are not identical between Manager and Agent ?
Maybe the solution is to fix the engineId value, then use this value from all managers managing the system on which runs the Agent.

Thanks
Regards
Michel

The above statement is not true! Manger and agent must have different engine IDs.

Nevertheless, the manager (non-authoritative) must use the authoritative engine ID of the agent for its USM user configuration in order to be able to successfully send SNMPv3 requests to the agent and receive valid responses.

Hello Frank,
Sure it was not clear for me when the authoritative engine ID should or not be used.
I thought that the communication between manager and agent should have the same identifier, which is not exact.

I’m little confused when and where we must use or not the authoritative engine ID.
The following is an snippet of snmp4j java code. Which statement is correct ?
If you can please an help on that.

    // 1. Create the USM
	USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
    //OR
	USM usm = new USM(SecurityProtocols.getInstance(), authoritativeEngineID, 0);
	
	SecurityModels.getInstance().addSecurityModel(usm);

	//2. Localize the USER
	UsmUser usmUser = new UsmUser(securityName, authProtocol, authPass, privProtocol, privPass);

	snmp.getUSM().addUser(securityName, authoritativeEngineID, usmUser);
	//OR
	snmp.getUSM().addUser(securityName, usmUser);
	
	//3. Send Request or Notification
	userTarget.setSecurityName(securityName);
	userTarget.setAuthoritativeEngineID(authoritativeEngineID);
	//OR nothing
	
	snmp.setLocalEngine(authoritativeEngineID, 0,  0);
	//OR
	snmp.setLocalEngine(MPv3.createLocalEngineID(), 0,  0);
	//OR nothing
	
	//Now send it to SNMP-agent to get response or to a trap receiver 
	snmp.send(pdu, target);

Thanks
Regards
Michel

// 1. Create the USM
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
//OR
// This is not correct: here the local engine ID is provided which can be authoritative and non-authoritative, depending on which message type is send or received: USM usm = new USM(SecurityProtocols.getInstance(), authoritativeEngineID, 0);

SecurityModels.getInstance().addSecurityModel(usm);

//2. Localize the USER
// Not correct: if you add a user with engine ID, it must be localised (to localise, use the constructor with engine ID, which is the local engine ID of the target, i.e. its authoritative engine ID for commands like GET, SET, GETNEXT, GETBULK): UsmUser usmUser = new UsmUser(securityName, authProtocol, authPass, privProtocol, privPass);
snmp.getUSM().addUser(securityName, authoritativeEngineID, usmUser);
//OR
// This would work, with non-localised users only: snmp.getUSM().addUser(securityName, usmUser);

//3. Send Request or Notification
userTarget.setSecurityName(securityName);
// Wrong, the authoritative engine ID of a notification is the sender's local engine ID: userTarget.setAuthoritativeEngineID(authoritativeEngineID);
//OR nothing

// Wrong, because Snmp instance should use the same localEngineID as then USM, of course - see above: snmp.setLocalEngine(authoritativeEngineID, 0,  0);
//OR
// Again wrong, because you create now a different local engine ID that does not match the local engine ID of USM: snmp.setLocalEngine(MPv3.createLocalEngineID(), 0,  0);
//OR nothing
// nothing is correct for the Snmp instance, because it will use the USM local engine ID by default.

Hope my above comments are somehow readable. To summarise it:

  • Each SNMP entity has its own local engine ID that need to differ from its communication partner(s).
  • The autoritative engine ID is a label for one of those two engine IDs which denotes which of the two parties will authorise the SNMPv3 message.
    ** For SNMP commands GET*, SET, INFORM it is the command receiver.
    ** For SNMP notifications TRAP, TRAPv2 it is the sender of the notification.

HI Frank,
Great!
Very clear. The use of authoritative engineID depends on the entity (sender, receiver, command-type).
A last question on this topic:
On SNMP agent, I declared two users. The question is : should I use the authoritative engineID or NOT on Agent side, like below:
USM usm = new USM(SecurityProtocols.getInstance(), authoritativeEngineID, 0);
//OR USM usm = new USM(SecurityProtocols.getInstance(), 0);

protected void addUsmUsers(USM usm) {
//USER1
UsmUser usmUser1 = new UsmUser(securityName, authProtocol, authPass, privProtocol, privPass);
usm.addUser(securityName1, authoritativeEngineID, usmUser);
//OR usm.addUser(securityName1, usmUser);

//USER2
UsmUser usmUser2 = new UsmUser(securityName2, authProtocol, authPass, privProtocol, privPass);
usm.addUser(securityName2, authoritativeEngineID, usmUser2);
//OR : usm.addUser(securityName2, usmUser);
}
}

Thanks for you for you support.

Hi Michel,

The answer depends on what you want to do with the users! If the users should respond to GET*, SET, INFORM requests, then use the local engine ID of the agent as the authoritative engine ID of the user.

Best regards,
Frank

Yes, users are used to answer to SET/GET requests.
But they are also used to send traps to external third application !

Then the following is sufficient:

localEngineID = createOrLoadAgentEngineID();
Snmp, USM, MPv3 <— localEngineID
UsmUser <— localEngineID (means: all users are localized to the local engine ID of the agent)

Thanks Franck for you support.