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.
- package/README.md +13 -4
- package/index.js +103 -125
- 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
|
235
|
-
* `sha` - for SHA message authentication
|
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
|
-
|
238
|
-
|
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
|
-
|
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.
|
987
|
-
|
988
|
-
|
1002
|
+
Authentication.getParametersLength = function (authProtocol) {
|
1003
|
+
return Authentication.algorithms[authProtocol].AUTHENTICATION_CODE_LENGTH;
|
1004
|
+
};
|
989
1005
|
|
990
|
-
|
991
|
-
|
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 (
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
1031
|
-
|
1032
|
-
|
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
|
-
|
1412
|
-
|
1413
|
-
//
|
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
|
-
|
1415
|
+
writer.writeString ("");
|
1417
1416
|
} else {
|
1418
|
-
|
1417
|
+
writer.writeBuffer (this.msgSecurityParameters.msgAuthoritativeEngineID, ber.OctetString);
|
1419
1418
|
}
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
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
|
-
|
1426
|
-
|
1427
|
-
|
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
|
-
|
1429
|
+
writer.writeString ("");
|
1431
1430
|
}
|
1431
|
+
var msgAuthenticationParametersOffset = writer._offset - msgAuthenticationParameters.length;
|
1432
1432
|
|
1433
1433
|
if ( this.hasPrivacy() ) {
|
1434
|
-
|
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
|
-
|
1436
|
+
writer.writeString ("");
|
1453
1437
|
}
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
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
|
-
|
1481
|
-
|
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 =
|
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() ) {
|