net-snmp 3.6.4 → 3.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,6 +40,24 @@
40
40
  "1.3.6.1.2.1.1.1.0"
41
41
  ]
42
42
  },
43
+ {
44
+ "type": "node",
45
+ "request": "launch",
46
+ "name": "SNMP community get bulk",
47
+ "skipFiles": [
48
+ "<node_internals>/**"
49
+ ],
50
+ "program": "${workspaceFolder}/example/snmp-get-bulk.js",
51
+ "args": [
52
+ "-v", "2c",
53
+ "-c", "public",
54
+ "-o", "1",
55
+ "-r", "20",
56
+ "127.0.0.1",
57
+ "1.3.6.1.2.1.1.9",
58
+ "1.3.6.1.2.1.2"
59
+ ]
60
+ },
43
61
  {
44
62
  "type": "node",
45
63
  "request": "launch",
package/README.md CHANGED
@@ -231,11 +231,16 @@ RFC 3414:
231
231
 
232
232
  This object contains constants to select a supported digest algorithm for SNMPv3
233
233
  messages that require authentication:
234
- * `md5` - for MD5 message authentication (HMAC-MD5-96)
235
- * `sha` - for SHA message authentication (HMAC-SHA-96)
234
+ * `md5` - for HMAC-MD5 message authentication
235
+ * `sha` - for HMAC-SHA-1 message authentication
236
+ * `sha224` - for HMAC-SHA-224 message authentication
237
+ * `sha256` - for HMAC-SHA-256 message authentication
238
+ * `sha384` - for HMAC-SHA-384 message authentication
239
+ * `sha512` - for HMAC-SHA-512 message authentication
236
240
 
237
- These are the two hash algorithms specified in RFC 3414. Other digest algorithms
238
- are not supported.
241
+ MD5 and SHA (actually SHA-1) are the hash algorithms specified in the original
242
+ SNMPv3 User-Based Security Model RFC (RFC 3414); the other four were added later
243
+ in RFC 7860.
239
244
 
240
245
  ## snmp.PrivProtocols
241
246
 
@@ -310,7 +315,7 @@ Actions
310
315
  - `4 - ECouldNotDecrypt`
311
316
  - `5 - EAuthFailure`
312
317
  - `6 - EReqResOidNoMatch`
313
- - `7 - ENonRepeaterCountMismatch`
318
+ - `7 - (no longer used)
314
319
  - `8 - EOutOfOrder`
315
320
  - `9 - EVersionNoMatch`
316
321
  - `10 - ECommunityNoMatch`
@@ -3194,6 +3199,18 @@ Example programs are included under the module's `example` directory.
3194
3199
 
3195
3200
  * Ignore mismatched returned OIDs by default
3196
3201
 
3202
+ ## Version 3.7.0 - 04/06/2022
3203
+
3204
+ * Add SHA-2 authentication support (SHA-224, SHA-256, SHA-384, SHA-512)
3205
+
3206
+ ## Version 3.7.1 - 05/06/2022
3207
+
3208
+ * Fix DES decrypt corruption issue
3209
+
3210
+ ## Version 3.7.2 - 05/06/2022
3211
+
3212
+ * Improve getBulk response handling
3213
+
3197
3214
  # License
3198
3215
 
3199
3216
  Copyright (c) 2020 Mark Abrahams <mark@abrahams.co.nz>
package/index.js CHANGED
@@ -138,7 +138,11 @@ _expandConstantObject (SecurityLevel);
138
138
  var AuthProtocols = {
139
139
  "1": "none",
140
140
  "2": "md5",
141
- "3": "sha"
141
+ "3": "sha",
142
+ "4": "sha224",
143
+ "5": "sha256",
144
+ "6": "sha384",
145
+ "7": "sha512"
142
146
  };
143
147
 
144
148
  _expandConstantObject (AuthProtocols);
@@ -261,7 +265,7 @@ var ResponseInvalidCode = {
261
265
  4: "ECouldNotDecrypt",
262
266
  5: "EAuthFailure",
263
267
  6: "EReqResOidNoMatch",
264
- 7: "ENonRepeaterCountMismatch",
268
+ // 7: "ENonRepeaterCountMismatch", // no longer used
265
269
  8: "EOutOfOrder",
266
270
  9: "EVersionNoMatch",
267
271
  10: "ECommunityNoMatch",
@@ -875,7 +879,7 @@ var readPdu = function (reader, scoped) {
875
879
  var contextEngineID;
876
880
  var contextName;
877
881
  if ( scoped ) {
878
- reader.readSequence ();
882
+ reader = new ber.Reader (reader.readString (ber.Sequence | ber.Constructor, true));
879
883
  contextEngineID = reader.readString (ber.OctetString, true);
880
884
  contextName = reader.readString ();
881
885
  }
@@ -918,22 +922,45 @@ var createDiscoveryPdu = function (context) {
918
922
  var Authentication = {};
919
923
 
920
924
  Authentication.HMAC_BUFFER_SIZE = 1024*1024;
921
- Authentication.HMAC_BLOCK_SIZE = 64;
922
- Authentication.AUTHENTICATION_CODE_LENGTH = 12;
923
- Authentication.AUTH_PARAMETERS_PLACEHOLDER = Buffer.from('8182838485868788898a8b8c', 'hex');
924
925
 
925
926
  Authentication.algorithms = {};
926
927
 
927
928
  Authentication.algorithms[AuthProtocols.md5] = {
928
929
  KEY_LENGTH: 16,
930
+ AUTHENTICATION_CODE_LENGTH: 12,
929
931
  CRYPTO_ALGORITHM: 'md5'
930
932
  };
931
933
 
932
934
  Authentication.algorithms[AuthProtocols.sha] = {
933
935
  KEY_LENGTH: 20,
936
+ AUTHENTICATION_CODE_LENGTH: 12,
934
937
  CRYPTO_ALGORITHM: 'sha1'
935
938
  };
936
939
 
940
+ Authentication.algorithms[AuthProtocols.sha224] = {
941
+ KEY_LENGTH: 28,
942
+ AUTHENTICATION_CODE_LENGTH: 16,
943
+ CRYPTO_ALGORITHM: 'sha224'
944
+ };
945
+
946
+ Authentication.algorithms[AuthProtocols.sha256] = {
947
+ KEY_LENGTH: 32,
948
+ AUTHENTICATION_CODE_LENGTH: 24,
949
+ CRYPTO_ALGORITHM: 'sha256'
950
+ };
951
+
952
+ Authentication.algorithms[AuthProtocols.sha384] = {
953
+ KEY_LENGTH: 48,
954
+ AUTHENTICATION_CODE_LENGTH: 32,
955
+ CRYPTO_ALGORITHM: 'sha384'
956
+ };
957
+
958
+ Authentication.algorithms[AuthProtocols.sha512] = {
959
+ KEY_LENGTH: 64,
960
+ AUTHENTICATION_CODE_LENGTH: 48,
961
+ CRYPTO_ALGORITHM: 'sha512'
962
+ };
963
+
937
964
  Authentication.authToKeyCache = {};
938
965
 
939
966
  Authentication.computeCacheKey = function (authProtocol, authPasswordString, engineID) {
@@ -947,10 +974,6 @@ Authentication.passwordToKey = function (authProtocol, authPasswordString, engin
947
974
  var firstDigest;
948
975
  var finalDigest;
949
976
  var buf;
950
- var bufOffset = 0;
951
- var passwordIndex = 0;
952
- var count = 0;
953
- var password;
954
977
  var cryptoAlgorithm = Authentication.algorithms[authProtocol].CRYPTO_ALGORITHM;
955
978
 
956
979
  var cacheKey = Authentication.computeCacheKey(authProtocol, authPasswordString, engineID);
@@ -958,15 +981,8 @@ Authentication.passwordToKey = function (authProtocol, authPasswordString, engin
958
981
  return Authentication.authToKeyCache[cacheKey];
959
982
  }
960
983
 
961
- buf = Buffer.alloc (Authentication.HMAC_BUFFER_SIZE);
962
- password = Buffer.from (authPasswordString);
963
-
964
- while (count < Authentication.HMAC_BUFFER_SIZE) {
965
- for (var i = 0; i < Authentication.HMAC_BLOCK_SIZE; i++) {
966
- buf.writeUInt8(password[passwordIndex++ % password.length], bufOffset++);
967
- }
968
- count += Authentication.HMAC_BLOCK_SIZE;
969
- }
984
+ buf = Buffer.alloc (Authentication.HMAC_BUFFER_SIZE, authPasswordString);
985
+
970
986
  hashAlgorithm = crypto.createHash(cryptoAlgorithm);
971
987
  hashAlgorithm.update(buf);
972
988
  firstDigest = hashAlgorithm.digest();
@@ -983,94 +999,61 @@ Authentication.passwordToKey = function (authProtocol, authPasswordString, engin
983
999
  return finalDigest;
984
1000
  };
985
1001
 
986
- Authentication.addParametersToMessageBuffer = function (messageBuffer, authProtocol, authPassword, engineID) {
987
- var authenticationParametersOffset;
988
- var digestToAdd;
1002
+ Authentication.getParametersLength = function (authProtocol) {
1003
+ return Authentication.algorithms[authProtocol].AUTHENTICATION_CODE_LENGTH;
1004
+ };
989
1005
 
990
- // clear the authenticationParameters field in message
991
- authenticationParametersOffset = messageBuffer.indexOf (Authentication.AUTH_PARAMETERS_PLACEHOLDER);
992
- messageBuffer.fill (0, authenticationParametersOffset, authenticationParametersOffset + Authentication.AUTHENTICATION_CODE_LENGTH);
1006
+ Authentication.writeParameters = function (messageBuffer, authProtocol, authPassword, engineID, digestInMessage) {
1007
+ var digestToAdd;
993
1008
 
994
1009
  digestToAdd = Authentication.calculateDigest (messageBuffer, authProtocol, authPassword, engineID);
995
- digestToAdd.copy (messageBuffer, authenticationParametersOffset, 0, Authentication.AUTHENTICATION_CODE_LENGTH);
1010
+ digestToAdd.copy (digestInMessage);
996
1011
  // debug ("Added Auth Parameters: " + digestToAdd.toString('hex'));
997
1012
  };
998
1013
 
999
1014
  Authentication.isAuthentic = function (messageBuffer, authProtocol, authPassword, engineID, digestInMessage) {
1000
- var authenticationParametersOffset;
1015
+ var savedDigest;
1001
1016
  var calculatedDigest;
1002
1017
 
1018
+ if (digestInMessage.length !== Authentication.algorithms[authProtocol].AUTHENTICATION_CODE_LENGTH)
1019
+ return false;
1020
+
1021
+ // save original authenticationParameters field in message
1022
+ savedDigest = Buffer.from (digestInMessage);
1023
+
1003
1024
  // clear the authenticationParameters field in message
1004
- authenticationParametersOffset = messageBuffer.indexOf (digestInMessage);
1005
- messageBuffer.fill (0, authenticationParametersOffset, authenticationParametersOffset + Authentication.AUTHENTICATION_CODE_LENGTH);
1025
+ digestInMessage.fill (0);
1006
1026
 
1007
1027
  calculatedDigest = Authentication.calculateDigest (messageBuffer, authProtocol, authPassword, engineID);
1008
1028
 
1009
1029
  // replace previously cleared authenticationParameters field in message
1010
- digestInMessage.copy (messageBuffer, authenticationParametersOffset, 0, Authentication.AUTHENTICATION_CODE_LENGTH);
1030
+ savedDigest.copy (digestInMessage);
1011
1031
 
1012
1032
  // debug ("Digest in message: " + digestInMessage.toString('hex'));
1013
1033
  // debug ("Calculated digest: " + calculatedDigest.toString('hex'));
1014
- return calculatedDigest.equals (digestInMessage, Authentication.AUTHENTICATION_CODE_LENGTH);
1034
+ return calculatedDigest.equals (digestInMessage);
1015
1035
  };
1016
1036
 
1017
1037
  Authentication.calculateDigest = function (messageBuffer, authProtocol, authPassword, engineID) {
1018
1038
  var authKey = Authentication.passwordToKey (authProtocol, authPassword, engineID);
1019
1039
 
1020
- // Adapted from RFC3147 Section 6.3.1. Processing an Outgoing Message
1021
- var hashAlgorithm;
1022
- var kIpad;
1023
- var kOpad;
1024
- var firstDigest;
1025
- var finalDigest;
1026
- var truncatedDigest;
1027
- var i;
1028
1040
  var cryptoAlgorithm = Authentication.algorithms[authProtocol].CRYPTO_ALGORITHM;
1029
-
1030
- if (authKey.length > Authentication.HMAC_BLOCK_SIZE) {
1031
- hashAlgorithm = crypto.createHash (cryptoAlgorithm);
1032
- hashAlgorithm.update (authKey);
1033
- authKey = hashAlgorithm.digest ();
1034
- }
1035
-
1036
- // MD(K XOR opad, MD(K XOR ipad, msg))
1037
- kIpad = Buffer.alloc (Authentication.HMAC_BLOCK_SIZE);
1038
- kOpad = Buffer.alloc (Authentication.HMAC_BLOCK_SIZE);
1039
- for (i = 0; i < authKey.length; i++) {
1040
- kIpad[i] = authKey[i] ^ 0x36;
1041
- kOpad[i] = authKey[i] ^ 0x5c;
1042
- }
1043
- kIpad.fill (0x36, authKey.length);
1044
- kOpad.fill (0x5c, authKey.length);
1045
-
1046
- // inner MD
1047
- hashAlgorithm = crypto.createHash (cryptoAlgorithm);
1048
- hashAlgorithm.update (kIpad);
1049
- hashAlgorithm.update (messageBuffer);
1050
- firstDigest = hashAlgorithm.digest ();
1051
- // outer MD
1052
- hashAlgorithm = crypto.createHash (cryptoAlgorithm);
1053
- hashAlgorithm.update (kOpad);
1054
- hashAlgorithm.update (firstDigest);
1055
- finalDigest = hashAlgorithm.digest ();
1056
-
1057
- truncatedDigest = Buffer.alloc (Authentication.AUTHENTICATION_CODE_LENGTH);
1058
- finalDigest.copy (truncatedDigest, 0, 0, Authentication.AUTHENTICATION_CODE_LENGTH);
1059
- return truncatedDigest;
1041
+ var hmacAlgorithm = crypto.createHmac (cryptoAlgorithm, authKey);
1042
+ hmacAlgorithm.update (messageBuffer);
1043
+ var digest = hmacAlgorithm.digest ();
1044
+ return digest.subarray (0, Authentication.algorithms[authProtocol].AUTHENTICATION_CODE_LENGTH);
1060
1045
  };
1061
1046
 
1062
1047
  var Encryption = {};
1063
1048
 
1064
- Encryption.PRIV_PARAMETERS_PLACEHOLDER = Buffer.from ('9192939495969798', 'hex');
1065
-
1066
1049
  Encryption.encryptPdu = function (privProtocol, scopedPdu, privPassword, authProtocol, engine) {
1067
1050
  var encryptFunction = Encryption.algorithms[privProtocol].encryptPdu;
1068
1051
  return encryptFunction (scopedPdu, privProtocol, privPassword, authProtocol, engine);
1069
1052
  };
1070
1053
 
1071
- Encryption.decryptPdu = function (privProtocol, encryptedPdu, privParameters, privPassword, authProtocol, engine, forceAutoPaddingDisable) {
1054
+ Encryption.decryptPdu = function (privProtocol, encryptedPdu, privParameters, privPassword, authProtocol, engine) {
1072
1055
  var decryptFunction = Encryption.algorithms[privProtocol].decryptPdu;
1073
- return decryptFunction (encryptedPdu, privProtocol, privParameters, privPassword, authProtocol, engine, forceAutoPaddingDisable);
1056
+ return decryptFunction (encryptedPdu, privProtocol, privParameters, privPassword, authProtocol, engine);
1074
1057
  };
1075
1058
 
1076
1059
  Encryption.debugEncrypt = function (encryptionKey, iv, plainPdu, encryptedPdu) {
@@ -1196,7 +1179,7 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
1196
1179
  };
1197
1180
  };
1198
1181
 
1199
- Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters, privPassword, authProtocol, engine, forceAutoPaddingDisable) {
1182
+ Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters, privPassword, authProtocol, engine) {
1200
1183
  var des = Encryption.algorithms[PrivProtocols.des];
1201
1184
  var privLocalizedKey;
1202
1185
  var decryptionKey;
@@ -1220,23 +1203,9 @@ Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters,
1220
1203
  }
1221
1204
 
1222
1205
  decipher = crypto.createDecipheriv (des.CRYPTO_ALGORITHM, decryptionKey, iv);
1223
- if ( forceAutoPaddingDisable ) {
1224
- decipher.setAutoPadding(false);
1225
- }
1206
+ decipher.setAutoPadding(false);
1226
1207
  decryptedPdu = decipher.update (encryptedPdu);
1227
- // This try-catch is a workaround for a seemingly incorrect error condition
1228
- // - where sometimes a decrypt error is thrown with decipher.final()
1229
- // It replaces this line which should have been sufficient:
1230
- // decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
1231
- try {
1232
- decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
1233
- } catch (error) {
1234
- // debug("Decrypt error: " + error);
1235
- decipher = crypto.createDecipheriv (des.CRYPTO_ALGORITHM, decryptionKey, iv);
1236
- decipher.setAutoPadding(false);
1237
- decryptedPdu = decipher.update (encryptedPdu);
1238
- decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
1239
- }
1208
+ decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
1240
1209
  // Encryption.debugDecrypt (decryptionKey, iv, encryptedPdu, decryptedPdu);
1241
1210
 
1242
1211
  return decryptedPdu;
@@ -1301,13 +1270,6 @@ Encryption.decryptPduAes = function (encryptedPdu, privProtocol, privParameters,
1301
1270
  return decryptedPdu;
1302
1271
  };
1303
1272
 
1304
- Encryption.addParametersToMessageBuffer = function (messageBuffer, msgPrivacyParameters) {
1305
- var privacyParametersOffset;
1306
-
1307
- privacyParametersOffset = messageBuffer.indexOf (Encryption.PRIV_PARAMETERS_PLACEHOLDER);
1308
- msgPrivacyParameters.copy (messageBuffer, privacyParametersOffset, 0, Encryption.DES_IV_LENGTH);
1309
- };
1310
-
1311
1273
  Encryption.algorithms = {};
1312
1274
 
1313
1275
  Encryption.algorithms[PrivProtocols.des] = {
@@ -1391,6 +1353,29 @@ Message.prototype.toBufferV3 = function () {
1391
1353
  if (this.buffer)
1392
1354
  return this.buffer;
1393
1355
 
1356
+ // ScopedPDU
1357
+ var scopedPduWriter = new ber.Writer ();
1358
+ scopedPduWriter.startSequence ();
1359
+ var contextEngineID = this.pdu.contextEngineID ? this.pdu.contextEngineID : this.msgSecurityParameters.msgAuthoritativeEngineID;
1360
+ if ( contextEngineID.length == 0 ) {
1361
+ scopedPduWriter.writeString ("");
1362
+ } else {
1363
+ scopedPduWriter.writeBuffer (contextEngineID, ber.OctetString);
1364
+ }
1365
+ scopedPduWriter.writeString (this.pdu.contextName);
1366
+ this.pdu.toBuffer (scopedPduWriter);
1367
+ scopedPduWriter.endSequence ();
1368
+
1369
+ if ( this.hasPrivacy() ) {
1370
+ var authoritativeEngine = {
1371
+ engineID: this.msgSecurityParameters.msgAuthoritativeEngineID,
1372
+ engineBoots: this.msgSecurityParameters.msgAuthoritativeEngineBoots,
1373
+ engineTime: this.msgSecurityParameters.msgAuthoritativeEngineTime,
1374
+ };
1375
+ encryptionResult = Encryption.encryptPdu (this.user.privProtocol, scopedPduWriter.buffer,
1376
+ this.user.privKey, this.user.authProtocol, authoritativeEngine);
1377
+ }
1378
+
1394
1379
  var writer = new ber.Writer ();
1395
1380
 
1396
1381
  writer.startSequence ();
@@ -1408,77 +1393,56 @@ Message.prototype.toBufferV3 = function () {
1408
1393
  writer.endSequence ();
1409
1394
 
1410
1395
  // msgSecurityParameters
1411
- var msgSecurityParametersWriter = new ber.Writer ();
1412
- msgSecurityParametersWriter.startSequence ();
1413
- //msgSecurityParametersWriter.writeString (this.msgSecurityParameters.msgAuthoritativeEngineID);
1396
+ writer.startSequence (ber.OctetString);
1397
+ writer.startSequence ();
1398
+ //writer.writeString (this.msgSecurityParameters.msgAuthoritativeEngineID);
1414
1399
  // writing a zero-length buffer fails - should fix asn1-ber for this condition
1415
1400
  if ( this.msgSecurityParameters.msgAuthoritativeEngineID.length == 0 ) {
1416
- msgSecurityParametersWriter.writeString ("");
1401
+ writer.writeString ("");
1417
1402
  } else {
1418
- msgSecurityParametersWriter.writeBuffer (this.msgSecurityParameters.msgAuthoritativeEngineID, ber.OctetString);
1403
+ writer.writeBuffer (this.msgSecurityParameters.msgAuthoritativeEngineID, ber.OctetString);
1419
1404
  }
1420
- msgSecurityParametersWriter.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineBoots);
1421
- msgSecurityParametersWriter.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineTime);
1422
- msgSecurityParametersWriter.writeString (this.msgSecurityParameters.msgUserName);
1405
+ writer.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineBoots);
1406
+ writer.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineTime);
1407
+ writer.writeString (this.msgSecurityParameters.msgUserName);
1423
1408
 
1409
+ var msgAuthenticationParameters = '';
1424
1410
  if ( this.hasAuthentication() ) {
1425
- msgSecurityParametersWriter.writeBuffer (Authentication.AUTH_PARAMETERS_PLACEHOLDER, ber.OctetString);
1426
- // should never happen where msgFlags has no authentication but authentication parameters still present
1427
- } else if ( this.msgSecurityParameters.msgAuthenticationParameters.length > 0 ) {
1428
- msgSecurityParametersWriter.writeBuffer (this.msgSecurityParameters.msgAuthenticationParameters, ber.OctetString);
1411
+ var authParametersLength = Authentication.getParametersLength (this.user.authProtocol);
1412
+ msgAuthenticationParameters = Buffer.alloc (authParametersLength);
1413
+ writer.writeBuffer (msgAuthenticationParameters, ber.OctetString);
1429
1414
  } else {
1430
- msgSecurityParametersWriter.writeString ("");
1415
+ writer.writeString ("");
1431
1416
  }
1417
+ var msgAuthenticationParametersOffset = writer._offset - msgAuthenticationParameters.length;
1432
1418
 
1433
1419
  if ( this.hasPrivacy() ) {
1434
- msgSecurityParametersWriter.writeBuffer (Encryption.PRIV_PARAMETERS_PLACEHOLDER, ber.OctetString);
1435
- // should never happen where msgFlags has no privacy but privacy parameters still present
1436
- } else if ( this.msgSecurityParameters.msgPrivacyParameters.length > 0 ) {
1437
- msgSecurityParametersWriter.writeBuffer (this.msgSecurityParameters.msgPrivacyParameters, ber.OctetString);
1438
- } else {
1439
- msgSecurityParametersWriter.writeString ("");
1440
- }
1441
- msgSecurityParametersWriter.endSequence ();
1442
-
1443
- writer.writeBuffer (msgSecurityParametersWriter.buffer, ber.OctetString);
1444
-
1445
- // ScopedPDU
1446
- var scopedPduWriter = new ber.Writer ();
1447
- scopedPduWriter.startSequence ();
1448
- var contextEngineID = this.pdu.contextEngineID ? this.pdu.contextEngineID : this.msgSecurityParameters.msgAuthoritativeEngineID;
1449
- if ( contextEngineID.length == 0 ) {
1450
- scopedPduWriter.writeString ("");
1420
+ writer.writeBuffer (encryptionResult.msgPrivacyParameters, ber.OctetString);
1451
1421
  } else {
1452
- scopedPduWriter.writeBuffer (contextEngineID, ber.OctetString);
1422
+ writer.writeString ("");
1453
1423
  }
1454
- scopedPduWriter.writeString (this.pdu.contextName);
1455
- this.pdu.toBuffer (scopedPduWriter);
1456
- scopedPduWriter.endSequence ();
1424
+ msgAuthenticationParametersOffset -= writer._offset;
1425
+ writer.endSequence ();
1426
+ writer.endSequence ();
1427
+ msgAuthenticationParametersOffset += writer._offset;
1457
1428
 
1458
1429
  if ( this.hasPrivacy() ) {
1459
- var authoritativeEngine = {
1460
- engineID: this.msgSecurityParameters.msgAuthoritativeEngineID,
1461
- engineBoots: this.msgSecurityParameters.msgAuthoritativeEngineBoots,
1462
- engineTime: this.msgSecurityParameters.msgAuthoritativeEngineTime,
1463
- };
1464
- encryptionResult = Encryption.encryptPdu (this.user.privProtocol, scopedPduWriter.buffer,
1465
- this.user.privKey, this.user.authProtocol, authoritativeEngine);
1466
1430
  writer.writeBuffer (encryptionResult.encryptedPdu, ber.OctetString);
1467
1431
  } else {
1468
1432
  writer.writeBuffer (scopedPduWriter.buffer);
1469
1433
  }
1470
1434
 
1435
+ msgAuthenticationParametersOffset -= writer._offset;
1471
1436
  writer.endSequence ();
1437
+ msgAuthenticationParametersOffset += writer._offset;
1472
1438
 
1473
1439
  this.buffer = writer.buffer;
1474
1440
 
1475
- if ( this.hasPrivacy() ) {
1476
- Encryption.addParametersToMessageBuffer(this.buffer, encryptionResult.msgPrivacyParameters);
1477
- }
1478
-
1479
1441
  if ( this.hasAuthentication() ) {
1480
- Authentication.addParametersToMessageBuffer(this.buffer, this.user.authProtocol, this.user.authKey,
1481
- this.msgSecurityParameters.msgAuthoritativeEngineID);
1442
+ msgAuthenticationParameters = this.buffer.subarray (msgAuthenticationParametersOffset,
1443
+ msgAuthenticationParametersOffset + msgAuthenticationParameters.length);
1444
+ Authentication.writeParameters (this.buffer, this.user.authProtocol, this.user.authKey,
1445
+ this.msgSecurityParameters.msgAuthoritativeEngineID, msgAuthenticationParameters);
1482
1446
  }
1483
1447
 
1484
1448
  return this.buffer;
@@ -1513,23 +1477,10 @@ Message.prototype.decryptPdu = function (user, responseCb) {
1513
1477
  decryptedPduReader = new ber.Reader (decryptedPdu);
1514
1478
  this.pdu = readPdu(decryptedPduReader, true);
1515
1479
  return true;
1516
- // really really occasionally the decrypt truncates a single byte
1517
- // causing an ASN read failure in readPdu()
1518
- // in this case, disabling auto padding decrypts the PDU correctly
1519
- // this try-catch provides the workaround for this condition
1520
- } catch (possibleTruncationError) {
1521
- try {
1522
- decryptedPdu = Encryption.decryptPdu(user.privProtocol, this.encryptedPdu,
1523
- this.msgSecurityParameters.msgPrivacyParameters, user.privKey, user.authProtocol,
1524
- this.msgSecurityParameters.msgAuthoritativeEngineID, true);
1525
- decryptedPduReader = new ber.Reader (decryptedPdu);
1526
- this.pdu = readPdu(decryptedPduReader, true);
1527
- return true;
1528
- } catch (error) {
1529
- responseCb (new ResponseInvalidError ("Failed to decrypt PDU: " + error,
1530
- ResponseInvalidCode.ECouldNotDecrypt));
1531
- return false;
1532
- }
1480
+ } catch (error) {
1481
+ responseCb (new ResponseInvalidError ("Failed to decrypt PDU: " + error,
1482
+ ResponseInvalidCode.ECouldNotDecrypt));
1483
+ return false;
1533
1484
  }
1534
1485
 
1535
1486
  };
@@ -1734,7 +1685,7 @@ Message.createFromBuffer = function (buffer, user) {
1734
1685
  message.msgSecurityParameters.msgAuthoritativeEngineBoots = msgSecurityParametersReader.readInt ();
1735
1686
  message.msgSecurityParameters.msgAuthoritativeEngineTime = msgSecurityParametersReader.readInt ();
1736
1687
  message.msgSecurityParameters.msgUserName = msgSecurityParametersReader.readString ();
1737
- message.msgSecurityParameters.msgAuthenticationParameters = Buffer.from(msgSecurityParametersReader.readString (ber.OctetString, true));
1688
+ message.msgSecurityParameters.msgAuthenticationParameters = msgSecurityParametersReader.readString (ber.OctetString, true);
1738
1689
  message.msgSecurityParameters.msgPrivacyParameters = Buffer.from(msgSecurityParametersReader.readString (ber.OctetString, true));
1739
1690
 
1740
1691
  if ( message.hasPrivacy() ) {
@@ -1917,6 +1868,7 @@ Session.prototype.get = function (oids, responseCb) {
1917
1868
 
1918
1869
  Session.prototype.getBulk = function () {
1919
1870
  var oids, nonRepeaters, maxRepetitions, responseCb;
1871
+ var reportOidMismatchErrors = this.reportOidMismatchErrors;
1920
1872
  var backwardsGetNexts = this.backwardsGetNexts;
1921
1873
 
1922
1874
  if (arguments.length >= 4) {
@@ -1938,71 +1890,59 @@ Session.prototype.getBulk = function () {
1938
1890
 
1939
1891
  function feedCb (req, message) {
1940
1892
  var pdu = message.pdu;
1893
+ var reqVarbinds = req.message.pdu.varbinds;
1941
1894
  var varbinds = [];
1942
1895
  var i = 0;
1943
1896
 
1944
- // first walk through and grab non-repeaters
1945
- if (pdu.varbinds.length < nonRepeaters) {
1946
- req.responseCb (new ResponseInvalidError ("Varbind count in "
1947
- + "response '" + pdu.varbinds.length + "' is less than "
1948
- + "non-repeaters '" + nonRepeaters + "' in request",
1949
- ResponseInvalidCode.ENonRepeaterCountMismatch));
1950
- return;
1951
- } else {
1952
- for ( ; i < nonRepeaters; i++) {
1953
- if (isVarbindError (pdu.varbinds[i])) {
1954
- varbinds.push (pdu.varbinds[i]);
1955
- } else if (! oidFollowsOid (req.message.pdu.varbinds[i].oid,
1956
- pdu.varbinds[i].oid)) {
1957
- req.responseCb (new ResponseInvalidError ("OID '"
1958
- + req.message.pdu.varbinds[i].oid + "' in request at "
1959
- + "positiion '" + i + "' does not precede "
1960
- + "OID '" + pdu.varbinds[i].oid + "' in response "
1897
+ for ( ; i < reqVarbinds.length && i < pdu.varbinds.length; i++) {
1898
+ if (isVarbindError (pdu.varbinds[i])) {
1899
+ if ( reportOidMismatchErrors && reqVarbinds[i].oid != pdu.varbinds[i].oid ) {
1900
+ req.responseCb (new ResponseInvalidError ("OID '" + reqVarbinds[i].oid
1901
+ + "' in request at position '" + i + "' does not "
1902
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1903
+ + "at position '" + i + "'", ResponseInvalidCode.EReqResOidNoMatch));
1904
+ return;
1905
+ }
1906
+ } else {
1907
+ if ( ! backwardsGetNexts && ! oidFollowsOid (reqVarbinds[i].oid, pdu.varbinds[i].oid)) {
1908
+ req.responseCb (new ResponseInvalidError ("OID '" + reqVarbinds[i].oid
1909
+ + "' in request at positiion '" + i + "' does not "
1910
+ + "precede OID '" + pdu.varbinds[i].oid + "' in response "
1961
1911
  + "at position '" + i + "'", ResponseInvalidCode.EOutOfOrder));
1962
1912
  return;
1963
- } else {
1964
- varbinds.push (pdu.varbinds[i]);
1965
1913
  }
1966
1914
  }
1915
+ if (i < nonRepeaters)
1916
+ varbinds.push (pdu.varbinds[i]);
1917
+ else
1918
+ varbinds.push ([pdu.varbinds[i]]);
1967
1919
  }
1968
1920
 
1969
- var repeaters = req.message.pdu.varbinds.length - nonRepeaters;
1921
+ var repeaters = reqVarbinds.length - nonRepeaters;
1970
1922
 
1971
- // secondly walk through and grab repeaters
1972
- if (pdu.varbinds.length % (repeaters)) {
1973
- req.responseCb (new ResponseInvalidError ("Varbind count in "
1974
- + "response '" + pdu.varbinds.length + "' is not a "
1975
- + "multiple of repeaters '" + repeaters
1976
- + "' plus non-repeaters '" + nonRepeaters + "' in request",
1977
- ResponseInvalidCode.ENonRepeaterCountMismatch));
1978
- } else {
1979
- while (i < pdu.varbinds.length) {
1980
- for (var j = 0; j < repeaters; j++, i++) {
1981
- var reqIndex = nonRepeaters + j;
1982
- var respIndex = i;
1983
-
1984
- if (isVarbindError (pdu.varbinds[respIndex])) {
1985
- if (! varbinds[reqIndex])
1986
- varbinds[reqIndex] = [];
1987
- varbinds[reqIndex].push (pdu.varbinds[respIndex]);
1988
- } else if ( ! backwardsGetNexts && ! oidFollowsOid (
1989
- req.message.pdu.varbinds[reqIndex].oid,
1990
- pdu.varbinds[respIndex].oid)) {
1991
- req.responseCb (new ResponseInvalidError ("OID '"
1992
- + req.message.pdu.varbinds[reqIndex].oid
1993
- + "' in request at position '" + (reqIndex)
1994
- + "' does not precede OID '"
1995
- + pdu.varbinds[respIndex].oid
1996
- + "' in response at position '" + (respIndex) + "'",
1997
- ResponseInvalidCode.EOutOfOrder));
1998
- return;
1999
- } else {
2000
- if (! varbinds[reqIndex])
2001
- varbinds[reqIndex] = [];
2002
- varbinds[reqIndex].push (pdu.varbinds[respIndex]);
2003
- }
1923
+ for ( ; i < pdu.varbinds.length; i++) {
1924
+ var reqIndex = (i - nonRepeaters) % repeaters + nonRepeaters;
1925
+ var prevIndex = i - repeaters;
1926
+ var prevOid = pdu.varbinds[prevIndex].oid;
1927
+
1928
+ if (isVarbindError (pdu.varbinds[i])) {
1929
+ if ( reportOidMismatchErrors && prevOid != pdu.varbinds[i].oid ) {
1930
+ req.responseCb (new ResponseInvalidError ("OID '" + prevOid
1931
+ + "' in response at position '" + prevIndex + "' does not "
1932
+ + "match OID '" + pdu.varbinds[i].oid + "' in response "
1933
+ + "at position '" + i + "'", ResponseInvalidCode.EReqResOidNoMatch));
1934
+ return;
1935
+ }
1936
+ } else {
1937
+ if ( ! backwardsGetNexts && ! oidFollowsOid (prevOid, pdu.varbinds[i].oid)) {
1938
+ req.responseCb (new ResponseInvalidError ("OID '" + prevOid
1939
+ + "' in response at positiion '" + prevIndex + "' does not "
1940
+ + "precede OID '" + pdu.varbinds[i].oid + "' in response "
1941
+ + "at position '" + i + "'", ResponseInvalidCode.EOutOfOrder));
1942
+ return;
2004
1943
  }
2005
1944
  }
1945
+ varbinds[reqIndex].push (pdu.varbinds[i]);
2006
1946
  }
2007
1947
 
2008
1948
  req.responseCb (null, varbinds);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "net-snmp",
3
- "version": "3.6.4",
3
+ "version": "3.7.2",
4
4
  "description": "JavaScript implementation of the Simple Network Management Protocol (SNMP)",
5
5
  "main": "index.js",
6
6
  "directories": {