I am writing a SNMP v3 trap/informs sender using snmp4j with authentication, but I'm surprised that informs are correctly acknowledged even if there's an authentication failure. I also developed the trap receiver using snmp4j to help me debugging.
I've noticed several unexpected scenarios:
1st scenario: sending an INFORM with Auth / NoPriv, with unknown username or wrong password => the INFORM is not acknowledged, there's just no response, the sender has to wait for timeout. On the receiver side however, an AuthenticationFailureEvent is fired, but I would have expected that snmp4j responds something to the sender with an error. Overridden method processPdu is not called. I guess it may depends on the receiver implementations, or there is a standard behaviour for this?
2nd scenario: sending an INFORM with existing username but no password (with NoAuth / NoPriv), whereas it's configured with a password on the receiver => the INFORM is acknowledged with RESPONSE, without any error, and my trap receiver even doesn't fire an AuthenticationFailureEvent as it should. I would expect that the receiver rejects the request if it's unauthenticated. Did I forget to initialize something? I can't imagine there's such a security hole in snmp4j.
The code I use for initializing receiver: (I don't show here overridden methods processPdu and authenticationFailure)
EmbeddedSNMPReceiver(final int port, final Optional<UsmUser> user) throws IOException {
final MessageDispatcherImpl dispatcher = new MessageDispatcherImpl();
dispatcher.addAuthenticationFailureListener(this);
final UdpAddress listenAddress = new UdpAddress("localhost/" + port);
final TransportMapping transport = new DefaultUdpTransportMapping(listenAddress);
SecurityProtocols.getInstance().addDefaultProtocols();
final USM usm = new USM(SecurityProtocols.getInstance(), new OctetString("RECEIVER"), 0);
snmp = new Snmp(dispatcher, transport);
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3(usm));
SecurityModels.getInstance().addSecurityModel(usm);
if (user.isPresent()) {
snmp.getUSM().addUser(user.get().getSecurityName(), user.get());
}
snmp.addCommandResponder(this);
snmp.listen();
}
public static void main(String[] args) {
// FOR DEBUG
try {
final OctetString octUsername = new OctetString("zaza");
final OID userAuthOID = AuthSHA.ID;
final OctetString octUserPassphrase = new OctetString("12345678");
final UsmUser user = new UsmUser(octUsername, userAuthOID, octUserPassphrase, null, null);
final EmbeddedSNMPReceiver server = new EmbeddedSNMPReceiver(1099, Optional.of(user));
Thread.sleep(500000);
server.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
PS: to clarify, I start the receiver in a separate process than sender to avoid issues with snmp4j stateful nature / singletons...