net-snmp 3.6.4 → 3.7.0

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.
Files changed (3) hide show
  1. package/README.md +13 -4
  2. package/index.js +103 -125
  3. package/package.json +1 -1
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
 
@@ -3194,6 +3199,10 @@ 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
+
3197
3206
  # License
3198
3207
 
3199
3208
  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);
@@ -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,86 +999,53 @@ 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);
@@ -1301,13 +1284,6 @@ Encryption.decryptPduAes = function (encryptedPdu, privProtocol, privParameters,
1301
1284
  return decryptedPdu;
1302
1285
  };
1303
1286
 
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
1287
  Encryption.algorithms = {};
1312
1288
 
1313
1289
  Encryption.algorithms[PrivProtocols.des] = {
@@ -1391,6 +1367,29 @@ Message.prototype.toBufferV3 = function () {
1391
1367
  if (this.buffer)
1392
1368
  return this.buffer;
1393
1369
 
1370
+ // ScopedPDU
1371
+ var scopedPduWriter = new ber.Writer ();
1372
+ scopedPduWriter.startSequence ();
1373
+ var contextEngineID = this.pdu.contextEngineID ? this.pdu.contextEngineID : this.msgSecurityParameters.msgAuthoritativeEngineID;
1374
+ if ( contextEngineID.length == 0 ) {
1375
+ scopedPduWriter.writeString ("");
1376
+ } else {
1377
+ scopedPduWriter.writeBuffer (contextEngineID, ber.OctetString);
1378
+ }
1379
+ scopedPduWriter.writeString (this.pdu.contextName);
1380
+ this.pdu.toBuffer (scopedPduWriter);
1381
+ scopedPduWriter.endSequence ();
1382
+
1383
+ if ( this.hasPrivacy() ) {
1384
+ var authoritativeEngine = {
1385
+ engineID: this.msgSecurityParameters.msgAuthoritativeEngineID,
1386
+ engineBoots: this.msgSecurityParameters.msgAuthoritativeEngineBoots,
1387
+ engineTime: this.msgSecurityParameters.msgAuthoritativeEngineTime,
1388
+ };
1389
+ encryptionResult = Encryption.encryptPdu (this.user.privProtocol, scopedPduWriter.buffer,
1390
+ this.user.privKey, this.user.authProtocol, authoritativeEngine);
1391
+ }
1392
+
1394
1393
  var writer = new ber.Writer ();
1395
1394
 
1396
1395
  writer.startSequence ();
@@ -1408,77 +1407,56 @@ Message.prototype.toBufferV3 = function () {
1408
1407
  writer.endSequence ();
1409
1408
 
1410
1409
  // msgSecurityParameters
1411
- var msgSecurityParametersWriter = new ber.Writer ();
1412
- msgSecurityParametersWriter.startSequence ();
1413
- //msgSecurityParametersWriter.writeString (this.msgSecurityParameters.msgAuthoritativeEngineID);
1410
+ writer.startSequence (ber.OctetString);
1411
+ writer.startSequence ();
1412
+ //writer.writeString (this.msgSecurityParameters.msgAuthoritativeEngineID);
1414
1413
  // writing a zero-length buffer fails - should fix asn1-ber for this condition
1415
1414
  if ( this.msgSecurityParameters.msgAuthoritativeEngineID.length == 0 ) {
1416
- msgSecurityParametersWriter.writeString ("");
1415
+ writer.writeString ("");
1417
1416
  } else {
1418
- msgSecurityParametersWriter.writeBuffer (this.msgSecurityParameters.msgAuthoritativeEngineID, ber.OctetString);
1417
+ writer.writeBuffer (this.msgSecurityParameters.msgAuthoritativeEngineID, ber.OctetString);
1419
1418
  }
1420
- msgSecurityParametersWriter.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineBoots);
1421
- msgSecurityParametersWriter.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineTime);
1422
- msgSecurityParametersWriter.writeString (this.msgSecurityParameters.msgUserName);
1419
+ writer.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineBoots);
1420
+ writer.writeInt (this.msgSecurityParameters.msgAuthoritativeEngineTime);
1421
+ writer.writeString (this.msgSecurityParameters.msgUserName);
1423
1422
 
1423
+ var msgAuthenticationParameters = '';
1424
1424
  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);
1425
+ var authParametersLength = Authentication.getParametersLength (this.user.authProtocol);
1426
+ msgAuthenticationParameters = Buffer.alloc (authParametersLength);
1427
+ writer.writeBuffer (msgAuthenticationParameters, ber.OctetString);
1429
1428
  } else {
1430
- msgSecurityParametersWriter.writeString ("");
1429
+ writer.writeString ("");
1431
1430
  }
1431
+ var msgAuthenticationParametersOffset = writer._offset - msgAuthenticationParameters.length;
1432
1432
 
1433
1433
  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 ("");
1434
+ writer.writeBuffer (encryptionResult.msgPrivacyParameters, ber.OctetString);
1451
1435
  } else {
1452
- scopedPduWriter.writeBuffer (contextEngineID, ber.OctetString);
1436
+ writer.writeString ("");
1453
1437
  }
1454
- scopedPduWriter.writeString (this.pdu.contextName);
1455
- this.pdu.toBuffer (scopedPduWriter);
1456
- scopedPduWriter.endSequence ();
1438
+ msgAuthenticationParametersOffset -= writer._offset;
1439
+ writer.endSequence ();
1440
+ writer.endSequence ();
1441
+ msgAuthenticationParametersOffset += writer._offset;
1457
1442
 
1458
1443
  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
1444
  writer.writeBuffer (encryptionResult.encryptedPdu, ber.OctetString);
1467
1445
  } else {
1468
1446
  writer.writeBuffer (scopedPduWriter.buffer);
1469
1447
  }
1470
1448
 
1449
+ msgAuthenticationParametersOffset -= writer._offset;
1471
1450
  writer.endSequence ();
1451
+ msgAuthenticationParametersOffset += writer._offset;
1472
1452
 
1473
1453
  this.buffer = writer.buffer;
1474
1454
 
1475
- if ( this.hasPrivacy() ) {
1476
- Encryption.addParametersToMessageBuffer(this.buffer, encryptionResult.msgPrivacyParameters);
1477
- }
1478
-
1479
1455
  if ( this.hasAuthentication() ) {
1480
- Authentication.addParametersToMessageBuffer(this.buffer, this.user.authProtocol, this.user.authKey,
1481
- this.msgSecurityParameters.msgAuthoritativeEngineID);
1456
+ msgAuthenticationParameters = this.buffer.subarray (msgAuthenticationParametersOffset,
1457
+ msgAuthenticationParametersOffset + msgAuthenticationParameters.length);
1458
+ Authentication.writeParameters (this.buffer, this.user.authProtocol, this.user.authKey,
1459
+ this.msgSecurityParameters.msgAuthoritativeEngineID, msgAuthenticationParameters);
1482
1460
  }
1483
1461
 
1484
1462
  return this.buffer;
@@ -1734,7 +1712,7 @@ Message.createFromBuffer = function (buffer, user) {
1734
1712
  message.msgSecurityParameters.msgAuthoritativeEngineBoots = msgSecurityParametersReader.readInt ();
1735
1713
  message.msgSecurityParameters.msgAuthoritativeEngineTime = msgSecurityParametersReader.readInt ();
1736
1714
  message.msgSecurityParameters.msgUserName = msgSecurityParametersReader.readString ();
1737
- message.msgSecurityParameters.msgAuthenticationParameters = Buffer.from(msgSecurityParametersReader.readString (ber.OctetString, true));
1715
+ message.msgSecurityParameters.msgAuthenticationParameters = msgSecurityParametersReader.readString (ber.OctetString, true);
1738
1716
  message.msgSecurityParameters.msgPrivacyParameters = Buffer.from(msgSecurityParametersReader.readString (ber.OctetString, true));
1739
1717
 
1740
1718
  if ( message.hasPrivacy() ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "net-snmp",
3
- "version": "3.6.4",
3
+ "version": "3.7.0",
4
4
  "description": "JavaScript implementation of the Simple Network Management Protocol (SNMP)",
5
5
  "main": "index.js",
6
6
  "directories": {