When sending SNMPv3 traps, you are in control. Sender of V2TRAP notifications using protocol version 3 is the authoritative SNMP engine, meaning it supplies the engine id, engine boots and engine time values.
Since you are both the originator of the notification and authoritative SNMP engine, there is nothing you need to "discover" making SNMP version 3 Trap notifications the only SNMP operation that doesn't use the discovery procedure.
Since it is that straight forward, we can dive into the code straight away.
Here is a simplest possible example of how to build a noAuthNoPriv SNMP notification:
SnmpV3Packet packet = new SnmpV3Packet(); // Set the security name packet.NoAuthNoPriv(ASCIIEncoding.UTF8.GetBytes("mysecurityname")); // Set your engine id packet.USM.EngineId.Set(new byte[] { 0x00, 0x08, 0x02, 0x01, 0x10, 0x12, 0x14, 0xa0, 0xb1, 0xc2 }); // Engine id is also stored in the ScopedPdu so just duplicate it packet.ScopedPdu.ContextEngineId.Set(packet.USM.EngineId); // Set your engine boots (can be 0) packet.USM.EngineBoots = 20; // Set your engine time packet.USM.EngineTime = 200; // Set message reportable flag to false. You don't really want to receive errors packet.MsgFlags.Reportable = false; // Pdu type is V2TRAP packet.Pdu.Type = PduType.V2Trap; // Set the TRAP object ID value packet.Pdu.TrapObjectID.Set(new int[] { 1, 3, 6, 1, 2, 1, 2, 2, 1, 0 }); // Set your system up time value (this has nothing to do with engineTime) packet.Pdu.TrapSysUpTime.Value = 23456; // Add variable bindings to the Pdu to further describe the TRAP packet.Pdu.VbList.Add(new Oid(new int[] { 1, 3, 6, 1, 2, 1, 1, 1, 0 }), new OctetString("Test noAuthNoPriv")); // Finally, encode into a byte buffer ready for sending byte[] outBuffer = packet.encode(); // Send it to the manager sock.SendTo(outBuffer,new IPEndPoint(IPAddress.Loopback, 162));
In this example I just made up the authoritative SNMP engine values (id, boots and time). While this will work, it is pointless to use SNMPv3 and then have a massive security hole like this in your implementation. What you should do is generate an engine id that is unique, keep track how many times your snmp engine has been started to use as engineBoots value and keep track of how long the engine has been running for the engineTime value.
Sending the above example to a net-snmp snmptrapd application you will get the following debug dump:
dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: SNMPv3 Message dumph_recv: SNMP Version Number dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: msgGlobalData dumph_recv: msgID dumpx_recv: 02 04 7B EA 66 C6 dumpv_recv: Integer: 2078959302 (0x7BEA66C6) dumph_recv: msgMaxSize dumpx_recv: 02 03 01 00 00 dumpv_recv: Integer: 65536 (0x10000) dumph_recv: msgFlags dumpx_recv: 04 01 00 dumpv_recv: String: . dumph_recv: msgSecurityModel dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: SM msgSecurityParameters dumph_recv: msgAuthoritativeEngineID dumpx_recv: 04 0A 00 08 02 01 10 12 14 A0 B1 C2 dumpv_recv: String: ....... ±A dumph_recv: msgAuthoritativeEngineBoots dumpx_recv: 02 01 14 dumpv_recv: Integer: 20 (0x14) dumph_recv: msgAuthoritativeEngineTime dumpx_recv: 02 02 00 C8 dumpv_recv: Integer: 200 (0xC8) dumph_recv: msgUserName dumpx_recv: 04 09 6D 69 6C 61 6E 73 68 61 37 dumpv_recv: String: milansha7 dumph_recv: msgAuthenticationParameters dumpx_recv: 04 00 dumpv_recv: String: dumph_recv: msgPrivacyParameters dumpx_recv: 04 00 dumpv_recv: String: dumph_recv: ScopedPDU dumph_recv: contextEngineID dumpx_recv: 04 0A 00 08 02 01 10 12 14 A0 B1 C2 dumpv_recv: String: ....... ±A dumph_recv: contextName dumpx_recv: 04 00 dumpv_recv: String: dumph_recv: TRAP2 dumpv_recv: Command TRAP2 dumph_recv: request_id dumpx_recv: 02 04 62 EE 96 81 dumpv_recv: Integer: 1659803265 (0x62EE9681) dumph_recv: error status dumpx_recv: 02 01 00 dumpv_recv: Integer: 0 (0x00) dumph_recv: error index dumpx_recv: 02 01 00 dumpv_recv: Integer: 0 (0x00) dumph_recv: VarBindList dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 08 2B 06 01 02 01 01 03 00 dumpv_recv: ObjID: DISMAN-EVENT-MIB::sysUpTimeInstance dumph_recv: Value dumpx_recv: 43 02 5B A0 dumpv_recv: UInteger: 23456 (0x5BA0) dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 0A 2B 06 01 06 03 01 01 04 01 00 dumpv_recv: ObjID: SNMPv2-MIB::snmpTrapOID.0 dumph_recv: Value dumpx_recv: 06 09 2B 06 01 02 01 02 02 01 00 dumpv_recv: ObjID: IF-MIB::ifEntry.0 dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 08 2B 06 01 02 01 01 01 00 dumpv_recv: ObjID: SNMPv2-MIB::sysDescr.0 dumph_recv: Value dumpx_recv: 04 11 54 65 73 74 20 6E 6F 41 75 74 68 4E 6F 50 72 69 76 dumpv_recv: String: Test noAuthNoPriv
To configure a noAuthNoPriv user, add createUser -e 0x00080201101214a0b1c2 mysecurityname to the snmptrapd.conf configuration file.
As you can see from the above debug dump, packet is received and decoded correctly.
Using SNMPv3 without authentication is not very useful, here is now to introduce authentication into your TRAP sending app:
SnmpV3Packet packet = new SnmpV3Packet(); // Set security name and authentication parameters needed for a authNoPriv TRAP packet.authNoPriv(ASCIIEncoding.UTF8.GetBytes("myauthenticationname"), ASCIIEncoding.UTF8.GetBytes("authpasswd"), AuthenticationDigests.MD5); // Set your engine id packet.USM.EngineId.Set(new byte[] { 0x00, 0x08, 0x02, 0x01, 0x10, 0x12, 0x14, 0xa0, 0xb1, 0xc2 }); // Engine id is also stored in the ScopedPdu so just duplicate it packet.ScopedPdu.ContextEngineId.Set(packet.USM.EngineId); // Set your engine boots (can be 0) packet.USM.EngineBoots = 20; // Set your engine time packet.USM.EngineTime = 200; // Set message reportable flag to false. You don't really want to receive errors packet.MsgFlags.Reportable = false; // Pdu type is V2TRAP packet.Pdu.Type = PduType.V2Trap; // Set the TRAP object ID value packet.Pdu.TrapObjectID.Set(new int[] { 1, 3, 6, 1, 2, 1, 2, 2, 1, 0 }); // Set your system up time value (this has nothing to do with engineTime) packet.Pdu.TrapSysUpTime.Value = 23456; // Add variable bindings to the Pdu to further describe the TRAP packet.Pdu.VbList.Add(new Oid(new int[] { 1, 3, 6, 1, 2, 1, 1, 1, 0 }), new OctetString("Test noAuthNoPriv")); // Finally, encode into a byte buffer ready for sending byte[] outBuffer = packet.encode(); // Send it to the manager sock.SendTo(outBuffer,new IPEndPoint(IPAddress.Loopback, 162));
Packet dump on the receiving side shows that authentication is correctly encoded and verified:
dumpx_recv:02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: SNMPv3 Message dumph_recv: SNMP Version Number dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: msgGlobalData dumph_recv: msgID dumpx_recv: 02 04 7C 5C 95 AF dumpv_recv: Integer: 2086442415 (0x7C5C95AF) dumph_recv: msgMaxSize dumpx_recv: 02 03 01 00 00 dumpv_recv: Integer: 65536 (0x10000) dumph_recv: msgFlags dumpx_recv: 04 01 01 dumpv_recv: String: . dumph_recv: msgSecurityModel dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: SM msgSecurityParameters dumph_recv: msgAuthoritativeEngineID dumpx_recv: 04 0A 00 08 02 01 10 12 14 A0 B1 C2 dumpv_recv: String: ....... ±A dumph_recv: msgAuthoritativeEngineBoots dumpx_recv: 02 01 14 dumpv_recv: Integer: 20 (0x14) dumph_recv: msgAuthoritativeEngineTime dumpx_recv: 02 02 00 C8 dumpv_recv: Integer: 200 (0xC8) dumph_recv: msgUserName dumpx_recv: 04 14 6D 79 61 75 74 68 65 6E 74 69 63 61 74 69 6F 6E 6E 61 6D 65 dumpv_recv: String: myauthenticationname dumph_recv: msgAuthenticationParameters dumpx_recv: 04 0C 8F DD 59 BF F8 A1 2A C2 5E 68 FC 71 dumpv_recv: String: .YY¿o¡*A^hüq dumph_recv: msgPrivacyParameters dumpx_recv: 04 00 dumpv_recv: String: dumph_recv: ScopedPDU dumph_recv: contextEngineID dumpx_recv: 04 0A 00 08 02 01 10 12 14 A0 B1 C2 dumpv_recv: String: ....... ±A dumph_recv: contextName dumpx_recv: 04 00 dumpv_recv: String: dumph_recv: TRAP2 dumpv_recv: Command TRAP2 dumph_recv: request_id dumpx_recv: 02 04 11 4E 18 23 dumpv_recv: Integer: 290330659 (0x114E1823) dumph_recv: error status dumpx_recv: 02 01 00 dumpv_recv: Integer: 0 (0x00) dumph_recv: error index dumpx_recv: 02 01 00 dumpv_recv: Integer: 0 (0x00) dumph_recv: VarBindList dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 08 2B 06 01 02 01 01 03 00 dumpv_recv: ObjID: DISMAN-EVENT-MIB::sysUpTimeInstance dumph_recv: Value dumpx_recv: 43 02 5B A0 dumpv_recv: UInteger: 23456 (0x5BA0) dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 0A 2B 06 01 06 03 01 01 04 01 00 dumpv_recv: ObjID: SNMPv2-MIB::snmpTrapOID.0 dumph_recv: Value dumpx_recv: 06 09 2B 06 01 02 01 02 02 01 00 dumpv_recv: ObjID: IF-MIB::ifEntry.0 dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 08 2B 06 01 02 01 01 01 00 dumpv_recv: ObjID: SNMPv2-MIB::sysDescr.0 dumph_recv: Value dumpx_recv: 04 0F 54 65 73 74 20 61 75 74 68 4E 6F 50 72 69 76 dumpv_recv: String: Test authNoPriv
For the full benefit of SNMPv3, you will use authPriv security model that includes both authentication and privacy encryption of the Pdu. To enable encryption, you need to initialize the SNMP packet with the authPriv() method:
SnmpV3Packet packet = new SnmpV3Packet(); // Set security name and authentication and privacy parameters needed for authPriv TRAP packet.authPriv(ASCIIEncoding.UTF8.GetBytes("myauthprivname"), ASCIIEncoding.UTF8.GetBytes("authpasswd"), AuthenticationDigests.MD5, ASCIIEncoding.UTF8.GetBytes("privpasswd"), PrivacyProtocols.DES); // Set your engine id packet.USM.EngineId.Set(new byte[] { 0x00, 0x08, 0x02, 0x01, 0x10, 0x12, 0x14, 0xa0, 0xb1, 0xc2 }); // Engine id is also stored in the ScopedPdu so just duplicate it packet.ScopedPdu.ContextEngineId.Set(packet.USM.EngineId); // Set your engine boots (can be 0) packet.USM.EngineBoots = 20; // Set your engine time packet.USM.EngineTime = 200; // Set message reportable flag to false. You don't really want to receive errors packet.MsgFlags.Reportable = false; // Pdu type is V2TRAP packet.Pdu.Type = PduType.V2Trap; // Set the TRAP object ID value packet.Pdu.TrapObjectID.Set(new int[] { 1, 3, 6, 1, 2, 1, 2, 2, 1, 0 }); // Set your system up time value (this has nothing to do with engineTime) packet.Pdu.TrapSysUpTime.Value = 23456; // Add variable bindings to the Pdu to further describe the TRAP packet.Pdu.VbList.Add(new Oid(new int[] { 1, 3, 6, 1, 2, 1, 1, 1, 0 }), new OctetString("Test authNoPriv")); // Finally, encode into a byte buffer ready for sending byte[] outBuffer = packet.encode(); // Send it to the manager sock.SendTo(outBuffer,new IPEndPoint(IPAddress.Loopback, 162));
Receiver debug output will look like this:
dumpx_recv:02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: SNMPv3 Message dumph_recv: SNMP Version Number dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: msgGlobalData dumph_recv: msgID dumpx_recv: 02 04 5A E6 5D 23 dumpv_recv: Integer: 1525046563 (0x5AE65D23) dumph_recv: msgMaxSize dumpx_recv: 02 03 01 00 00 dumpv_recv: Integer: 65536 (0x10000) dumph_recv: msgFlags dumpx_recv: 04 01 03 dumpv_recv: String: . dumph_recv: msgSecurityModel dumpx_recv: 02 01 03 dumpv_recv: Integer: 3 (0x03) dumph_recv: SM msgSecurityParameters dumph_recv: msgAuthoritativeEngineID dumpx_recv: 04 0A 00 08 02 01 10 12 14 A0 B1 C2 dumpv_recv: String: ....... ±A dumph_recv: msgAuthoritativeEngineBoots dumpx_recv: 02 01 14 dumpv_recv: Integer: 20 (0x14) dumph_recv: msgAuthoritativeEngineTime dumpx_recv: 02 02 00 C8 dumpv_recv: Integer: 200 (0xC8) dumph_recv: msgUserName dumpx_recv: 04 0E 6D 79 61 75 74 68 70 72 69 76 6E 61 6D 65 dumpv_recv: String: myauthprivname dumph_recv: msgAuthenticationParameters dumpx_recv: 04 0C 13 7F 7F 26 00 C2 51 F3 16 AB 25 04 dumpv_recv: String: ...&.AQó.«%. dumph_recv: msgPrivacyParameters dumpx_recv: 04 08 00 00 00 14 45 F4 DA B1 dumpv_recv: String: ....EôU± dumph_recv: ScopedPDU dumph_recv: contextEngineID dumpx_recv: 04 0A 00 08 02 01 10 12 14 A0 B1 C2 dumpv_recv: String: ....... ±A dumph_recv: contextName dumpx_recv: 04 00 dumpv_recv: String: dumph_recv: TRAP2 dumpv_recv: Command TRAP2 dumph_recv: request_id dumpx_recv: 02 04 7F 0B B7 B2 dumpv_recv: Integer: 2131474354 (0x7F0BB7B2) dumph_recv: error status dumpx_recv: 02 01 00 dumpv_recv: Integer: 0 (0x00) dumph_recv: error index dumpx_recv: 02 01 00 dumpv_recv: Integer: 0 (0x00) dumph_recv: VarBindList dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 08 2B 06 01 02 01 01 03 00 dumpv_recv: ObjID: DISMAN-EVENT-MIB::sysUpTimeInstance dumph_recv: Value dumpx_recv: 43 02 5B A0 dumpv_recv: UInteger: 23456 (0x5BA0) dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 0A 2B 06 01 06 03 01 01 04 01 00 dumpv_recv: ObjID: SNMPv2-MIB::snmpTrapOID.0 dumph_recv: Value dumpx_recv: 06 09 2B 06 01 02 01 02 02 01 00 dumpv_recv: ObjID: IF-MIB::ifEntry.0 dumph_recv: VarBind dumph_recv: Name dumpx_recv: 06 08 2B 06 01 02 01 01 01 00 dumpv_recv: ObjID: SNMPv2-MIB::sysDescr.0 dumph_recv: Value dumpx_recv: 04 0D 54 65 73 74 20 61 75 74 68 50 72 69 76 dumpv_recv: String: Test authPriv
As you can see from the dump, both authentication and privacy parameters are present in the packet and data is correctly received, authenticated and unencrypted by the receiving manager.
To generate SNMP receiver dump data I have used net-snmp snmptrapd.exe utility version 5.4.2.1 on Windows with the following snmptrapd.conf configuration:
createUser -e 0x00080201101214a0b1c2 mysecurityname createUser -e 0x00080201101214a0b1c2 myauthenticationname MD5 authpasswd createUser -e 0x00080201101214a0b1c2 myauthprivname MD5 authpasswd DES privpasswd
Test output was collected by executing snmptrapd -Le -Ddump.