net-snmp 3.5.8 → 3.6.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.
- package/README.md +21 -6
- package/example/snmp-receiver.js +2 -1
- package/index.js +91 -64
- package/package.json +1 -1
- package/test/receiver-test.sh +2 -3
package/README.md
CHANGED
@@ -243,8 +243,8 @@ This object contains constants to select a supported encryption algorithm for
|
|
243
243
|
SNMPv3 messages that require privacy:
|
244
244
|
* `des` - for DES encryption (CBC-DES)
|
245
245
|
* `aes` - for 128-bit AES encryption (CFB-AES-128)
|
246
|
-
* `aes256b` - for 256-bit AES encryption (CFB-AES-256) with "Blumenthal" key
|
247
|
-
* `aes256r` - for 256-bit AES encryption (CFB-AES-256) with "Reeder" key
|
246
|
+
* `aes256b` - for 256-bit AES encryption (CFB-AES-256) with "Blumenthal" key localization
|
247
|
+
* `aes256r` - for 256-bit AES encryption (CFB-AES-256) with "Reeder" key localization
|
248
248
|
|
249
249
|
DES is the sole encryption algorithm specified in the original SNMPv3 User-Based
|
250
250
|
Security Model RFC (RFC 3414); 128-bit AES for SNMPv3 was added later in RFC 3826.
|
@@ -1062,7 +1062,7 @@ The `table()` method fetches the value for all OIDs lexicographically
|
|
1062
1062
|
following a specified OID in the MIB tree which have the specified OID as
|
1063
1063
|
their base, much like the `subtree()` method.
|
1064
1064
|
|
1065
|
-
This method is designed to fetch
|
1065
|
+
This method is designed to fetch conceptual tables, for example the ifTable
|
1066
1066
|
(`1.3.6.1.2.1.2.2`) table. The values for returned varbinds will be structured
|
1067
1067
|
into objects to represent conceptual rows. Each row is then placed into an
|
1068
1068
|
object with the rows index being the key, e.g.:
|
@@ -1171,7 +1171,7 @@ be in the resulting table.
|
|
1171
1171
|
|
1172
1172
|
This method should be used when only selected columns are required, and
|
1173
1173
|
will be many times faster than the `table()` method since a much smaller
|
1174
|
-
amount of data will be
|
1174
|
+
amount of data will be fetched.
|
1175
1175
|
|
1176
1176
|
The following example fetches the ifTable (`1.3.6.1.2.1.2.2`) table, and
|
1177
1177
|
specifies that only the ifDescr (`1.3.6.1.2.1.2.2.1.2`) and ifPhysAddress
|
@@ -1259,7 +1259,7 @@ returned by the `process.uptime ()` function multiplied by `100`.
|
|
1259
1259
|
SNMP version 2c messages are quite different in comparison with version 1.
|
1260
1260
|
The version 2c trap has a much simpler format, simply a sequence of varbinds.
|
1261
1261
|
The first varbind to be placed in the trap message will be for the
|
1262
|
-
`sysUptime.0` OID (`1.3.6.1.
|
1262
|
+
`sysUptime.0` OID (`1.3.6.1.2.1.1.3.0`). The value for this varbind will
|
1263
1263
|
be the value returned by the `process.uptime ()` function multiplied by 100
|
1264
1264
|
(this can be overridden by providing `upTime` in the optional `options`
|
1265
1265
|
parameter, as documented below).
|
@@ -1280,7 +1280,7 @@ following items:
|
|
1280
1280
|
|
1281
1281
|
* `agentAddr` - IP address used to populate the agent-addr field for SNMP
|
1282
1282
|
version 1 type traps, and defaults to `127.0.0.1`
|
1283
|
-
* `upTime` - Value of the `sysUptime.0` OID (`1.3.6.1.
|
1283
|
+
* `upTime` - Value of the `sysUptime.0` OID (`1.3.6.1.2.1.1.3.0`) in the
|
1284
1284
|
trap, defaults to the value returned by the `process.uptime ()` function
|
1285
1285
|
multiplied by 100
|
1286
1286
|
|
@@ -1452,6 +1452,7 @@ class:
|
|
1452
1452
|
var options = {
|
1453
1453
|
port: 162,
|
1454
1454
|
disableAuthorization: false,
|
1455
|
+
includeAuthentication: false,
|
1455
1456
|
accessControlModelType: snmp.AccessControlModelType.None,
|
1456
1457
|
engineID: "8000B98380XXXXXXXXXXXXXXXXXXXXXXXX", // where the X's are random hex digits
|
1457
1458
|
address: null,
|
@@ -1483,6 +1484,8 @@ an object, possibly empty, and can contain the following fields:
|
|
1483
1484
|
* `transport` - the transport family to use - defaults to `udp4`
|
1484
1485
|
* `address` - the IP address to bind to - default to `null`, which means bind to all IP
|
1485
1486
|
addresses
|
1487
|
+
* `includeAuthentication` - adds the community (v1/2c) or user name (v3) information
|
1488
|
+
to the notification callback - defaults to `false`
|
1486
1489
|
|
1487
1490
|
The `callback` parameter is a callback function of the form
|
1488
1491
|
`function (error, notification)`. On an error condition, the `notification`
|
@@ -3166,6 +3169,18 @@ Example programs are included under the module's `example` directory.
|
|
3166
3169
|
|
3167
3170
|
* Fix processing of negative integers larger than 32 bits
|
3168
3171
|
|
3172
|
+
## Version 3.6.0 - 18/02/2022
|
3173
|
+
|
3174
|
+
* Add calculated key cache to remove authNoPriv and authPriv performance bottleneck
|
3175
|
+
|
3176
|
+
## Version 3.6.1 - 21/03/2022
|
3177
|
+
|
3178
|
+
* Add v3 context to non-initial PDUs
|
3179
|
+
|
3180
|
+
## Version 3.6.2 - 07/04/2022
|
3181
|
+
|
3182
|
+
* Add option for receiver to receive client authentication identity
|
3183
|
+
|
3169
3184
|
# License
|
3170
3185
|
|
3171
3186
|
Copyright (c) 2020 Mark Abrahams <mark@abrahams.co.nz>
|
package/example/snmp-receiver.js
CHANGED
package/index.js
CHANGED
@@ -427,16 +427,16 @@ function readUint (buffer, isSigned) {
|
|
427
427
|
value *= 256;
|
428
428
|
value += buffer.readByte ();
|
429
429
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
430
|
+
if (isSigned && i <= 0) {
|
431
|
+
if ((value & 0x80) == 0x80) {
|
432
|
+
signedBitSet = true;
|
433
|
+
}
|
434
|
+
}
|
435
435
|
}
|
436
436
|
|
437
|
-
|
438
|
-
|
439
|
-
|
437
|
+
if (signedBitSet) {
|
438
|
+
value -= 2 ** (i * 8);
|
439
|
+
}
|
440
440
|
|
441
441
|
return value;
|
442
442
|
}
|
@@ -934,17 +934,32 @@ Authentication.algorithms[AuthProtocols.sha] = {
|
|
934
934
|
CRYPTO_ALGORITHM: 'sha1'
|
935
935
|
};
|
936
936
|
|
937
|
+
Authentication.authToKeyCache = {};
|
938
|
+
|
939
|
+
Authentication.computeCacheKey = function (authProtocol, authPasswordString, engineID) {
|
940
|
+
var engineIDString = engineID.toString('base64');
|
941
|
+
return authProtocol + authPasswordString + engineIDString;
|
942
|
+
};
|
943
|
+
|
937
944
|
// Adapted from RFC3414 Appendix A.2.1. Password to Key Sample Code for MD5
|
938
945
|
Authentication.passwordToKey = function (authProtocol, authPasswordString, engineID) {
|
939
946
|
var hashAlgorithm;
|
940
947
|
var firstDigest;
|
941
948
|
var finalDigest;
|
942
|
-
var buf
|
949
|
+
var buf;
|
943
950
|
var bufOffset = 0;
|
944
951
|
var passwordIndex = 0;
|
945
952
|
var count = 0;
|
946
|
-
var password
|
953
|
+
var password;
|
947
954
|
var cryptoAlgorithm = Authentication.algorithms[authProtocol].CRYPTO_ALGORITHM;
|
955
|
+
|
956
|
+
var cacheKey = Authentication.computeCacheKey(authProtocol, authPasswordString, engineID);
|
957
|
+
if (Authentication.authToKeyCache[cacheKey] !== undefined) {
|
958
|
+
return Authentication.authToKeyCache[cacheKey];
|
959
|
+
}
|
960
|
+
|
961
|
+
buf = Buffer.alloc (Authentication.HMAC_BUFFER_SIZE);
|
962
|
+
password = Buffer.from (authPasswordString);
|
948
963
|
|
949
964
|
while (count < Authentication.HMAC_BUFFER_SIZE) {
|
950
965
|
for (var i = 0; i < Authentication.HMAC_BLOCK_SIZE; i++) {
|
@@ -964,6 +979,7 @@ Authentication.passwordToKey = function (authProtocol, authPasswordString, engin
|
|
964
979
|
finalDigest = hashAlgorithm.digest();
|
965
980
|
// debug ("Localized key: " + finalDigest.toString('hex'));
|
966
981
|
|
982
|
+
Authentication.authToKeyCache[cacheKey] = finalDigest;
|
967
983
|
return finalDigest;
|
968
984
|
};
|
969
985
|
|
@@ -2322,6 +2338,7 @@ Session.prototype.set = function (varbinds, responseCb) {
|
|
2322
2338
|
Session.prototype.simpleGet = function (pduClass, feedCb, varbinds,
|
2323
2339
|
responseCb, options) {
|
2324
2340
|
var id = _generateId (this.idBitsSize);
|
2341
|
+
options = Object.assign({}, options, { context: this.context });
|
2325
2342
|
var pdu = SimplePdu.createFromVariables (pduClass, id, varbinds, options);
|
2326
2343
|
var message;
|
2327
2344
|
var req;
|
@@ -3109,6 +3126,7 @@ var Receiver = function (options, callback) {
|
|
3109
3126
|
this.port = options.port || 162;
|
3110
3127
|
options.port = this.port;
|
3111
3128
|
this.disableAuthorization = options.disableAuthorization || false;
|
3129
|
+
this.includeAuthentication = options.includeAuthentication || false;
|
3112
3130
|
this.context = (options && options.context) ? options.context : "";
|
3113
3131
|
this.listener = new Listener (options, this);
|
3114
3132
|
};
|
@@ -3145,29 +3163,38 @@ Receiver.prototype.onMsg = function (buffer, rinfo) {
|
|
3145
3163
|
// Inform/trap processing
|
3146
3164
|
// debug (JSON.stringify (message.pdu, null, 2));
|
3147
3165
|
if ( message.pdu.type == PduType.Trap || message.pdu.type == PduType.TrapV2 ) {
|
3148
|
-
this.callback (null, this.formatCallbackData (message
|
3166
|
+
this.callback (null, this.formatCallbackData (message, rinfo) );
|
3149
3167
|
} else if ( message.pdu.type == PduType.InformRequest ) {
|
3150
3168
|
message.pdu.type = PduType.GetResponse;
|
3151
3169
|
message.buffer = null;
|
3152
3170
|
message.setReportable (false);
|
3153
3171
|
this.listener.send (message, rinfo);
|
3154
3172
|
message.pdu.type = PduType.InformRequest;
|
3155
|
-
this.callback (null, this.formatCallbackData (message
|
3173
|
+
this.callback (null, this.formatCallbackData (message, rinfo) );
|
3156
3174
|
} else {
|
3157
3175
|
this.callback (new RequestInvalidError ("Unexpected PDU type " + message.pdu.type + " (" + PduType[message.pdu.type] + ")"));
|
3158
3176
|
}
|
3159
3177
|
};
|
3160
3178
|
|
3161
|
-
Receiver.prototype.formatCallbackData = function (
|
3162
|
-
if ( pdu.contextEngineID ) {
|
3163
|
-
pdu.contextEngineID = pdu.contextEngineID.toString('hex');
|
3179
|
+
Receiver.prototype.formatCallbackData = function (message, rinfo) {
|
3180
|
+
if ( message.pdu.contextEngineID ) {
|
3181
|
+
message.pdu.contextEngineID = message.pdu.contextEngineID.toString('hex');
|
3164
3182
|
}
|
3165
|
-
delete pdu.nonRepeaters;
|
3166
|
-
delete pdu.maxRepetitions;
|
3167
|
-
|
3168
|
-
pdu: pdu,
|
3169
|
-
rinfo: rinfo
|
3183
|
+
delete message.pdu.nonRepeaters;
|
3184
|
+
delete message.pdu.maxRepetitions;
|
3185
|
+
const formattedData = {
|
3186
|
+
pdu: message.pdu,
|
3187
|
+
rinfo: rinfo
|
3170
3188
|
};
|
3189
|
+
if (this.includeAuthentication) {
|
3190
|
+
if (message.community) {
|
3191
|
+
formattedData.pdu.community = message.community;
|
3192
|
+
} else if (message.user) {
|
3193
|
+
formattedData.pdu.user = message.user.name;
|
3194
|
+
}
|
3195
|
+
}
|
3196
|
+
|
3197
|
+
return formattedData;
|
3171
3198
|
};
|
3172
3199
|
|
3173
3200
|
Receiver.prototype.close = function() {
|
@@ -3546,11 +3573,11 @@ MibNode.prototype.getConstraintsFromProvider = function () {
|
|
3546
3573
|
};
|
3547
3574
|
|
3548
3575
|
MibNode.prototype.setValue = function (newValue) {
|
3549
|
-
|
3550
|
-
|
3551
|
-
|
3552
|
-
|
3553
|
-
|
3576
|
+
var len;
|
3577
|
+
var min;
|
3578
|
+
var max;
|
3579
|
+
var range;
|
3580
|
+
var found = false;
|
3554
3581
|
var constraints = this.getConstraintsFromProvider ();
|
3555
3582
|
if ( ! constraints ) {
|
3556
3583
|
this.value = newValue;
|
@@ -3561,35 +3588,35 @@ MibNode.prototype.setValue = function (newValue) {
|
|
3561
3588
|
return false;
|
3562
3589
|
}
|
3563
3590
|
} else if ( constraints.ranges ) {
|
3564
|
-
|
3565
|
-
|
3566
|
-
|
3567
|
-
|
3568
|
-
|
3569
|
-
|
3570
|
-
|
3571
|
-
|
3572
|
-
|
3573
|
-
|
3574
|
-
|
3575
|
-
|
3576
|
-
|
3577
|
-
|
3578
|
-
|
3579
|
-
|
3580
|
-
|
3581
|
-
|
3582
|
-
|
3583
|
-
|
3584
|
-
|
3585
|
-
|
3586
|
-
|
3587
|
-
|
3588
|
-
|
3589
|
-
|
3590
|
-
|
3591
|
-
|
3592
|
-
|
3591
|
+
for ( range of constraints.ranges ) {
|
3592
|
+
min = "min" in range ? range.min : Number.MIN_SAFE_INTEGER;
|
3593
|
+
max = "max" in range ? range.max : Number.MAX_SAFE_INTEGER;
|
3594
|
+
if ( newValue >= min && newValue <= max ) {
|
3595
|
+
found = true;
|
3596
|
+
break;
|
3597
|
+
}
|
3598
|
+
}
|
3599
|
+
if ( ! found ) {
|
3600
|
+
return false;
|
3601
|
+
}
|
3602
|
+
} else if ( constraints.sizes ) {
|
3603
|
+
// if size is constrained, value must have a length property
|
3604
|
+
if ( ! ( "length" in newValue ) ) {
|
3605
|
+
return false;
|
3606
|
+
}
|
3607
|
+
len = newValue.length;
|
3608
|
+
for ( range of constraints.sizes ) {
|
3609
|
+
min = "min" in range ? range.min : Number.MIN_SAFE_INTEGER;
|
3610
|
+
max = "max" in range ? range.max : Number.MAX_SAFE_INTEGER;
|
3611
|
+
if ( len >= min && len <= max ) {
|
3612
|
+
found = true;
|
3613
|
+
break;
|
3614
|
+
}
|
3615
|
+
}
|
3616
|
+
if ( ! found ) {
|
3617
|
+
return false;
|
3618
|
+
}
|
3619
|
+
}
|
3593
3620
|
this.value = newValue;
|
3594
3621
|
return true;
|
3595
3622
|
};
|
@@ -3977,25 +4004,25 @@ Mib.prototype.setTableRowDefaultValues = function (name, values) {
|
|
3977
4004
|
};
|
3978
4005
|
|
3979
4006
|
Mib.prototype.setScalarRanges = function (name, ranges ) {
|
3980
|
-
|
3981
|
-
|
4007
|
+
let provider = this.getProvider(name);
|
4008
|
+
provider.constraints = { ranges };
|
3982
4009
|
};
|
3983
4010
|
|
3984
4011
|
Mib.prototype.setTableColumnRanges = function(name, column, ranges ) {
|
3985
|
-
|
3986
|
-
|
3987
|
-
|
4012
|
+
let provider = this.getProvider(name);
|
4013
|
+
let tc = provider.tableColumns;
|
4014
|
+
tc[column].constraints = { ranges };
|
3988
4015
|
};
|
3989
4016
|
|
3990
4017
|
Mib.prototype.setScalarSizes = function (name, sizes ) {
|
3991
|
-
|
3992
|
-
|
4018
|
+
let provider = this.getProvider(name);
|
4019
|
+
provider.constraints = { sizes };
|
3993
4020
|
};
|
3994
4021
|
|
3995
4022
|
Mib.prototype.setTableColumnSizes = function(name, column, sizes ) {
|
3996
|
-
|
3997
|
-
|
3998
|
-
|
4023
|
+
let provider = this.getProvider(name);
|
4024
|
+
let tc = provider.tableColumns;
|
4025
|
+
tc[column].constraints = { sizes };
|
3999
4026
|
};
|
4000
4027
|
|
4001
4028
|
Mib.prototype.registerProviders = function (providers) {
|
package/package.json
CHANGED
package/test/receiver-test.sh
CHANGED
@@ -61,8 +61,8 @@ node ${HOME_DIR}/example/snmp-trap.js -v 3 -l authNoPriv -u ${USER_AUTH} -a ${AU
|
|
61
61
|
node ${HOME_DIR}/example/snmp-trap.js -v 3 -l authPriv -u ${USER_PRIV} -a ${AUTH_PROTOCOL} -A ${AUTH_KEY} -x ${PRIV_PROTOCOL} -X ${PRIV_KEY} ${PARAMS} ${HOST} ${TRAP_OID}
|
62
62
|
node ${HOME_DIR}/example/snmp-inform.js -v 2c -c ${COMMUNITY} ${PARAMS} ${HOST} ${TRAP_OID}
|
63
63
|
node ${HOME_DIR}/example/snmp-inform.js -v 3 -l noAuthNoPriv -u ${USER_NONE} ${PARAMS} ${HOST} ${TRAP_OID}
|
64
|
-
node ${HOME_DIR}/example/snmp-inform.js -v 3 -u ${USER_AUTH} -a ${AUTH_PROTOCOL} -A ${AUTH_KEY} ${PARAMS} ${HOST} ${TRAP_OID}
|
65
|
-
node ${HOME_DIR}/example/snmp-inform.js -v 3 -u ${USER_PRIV} -a ${AUTH_PROTOCOL} -A ${AUTH_KEY} -x ${PRIV_PROTOCOL} -X ${PRIV_KEY} ${PARAMS} ${HOST} ${TRAP_OID}
|
64
|
+
node ${HOME_DIR}/example/snmp-inform.js -v 3 -l authNoPriv -u ${USER_AUTH} -a ${AUTH_PROTOCOL} -A ${AUTH_KEY} ${PARAMS} ${HOST} ${TRAP_OID}
|
65
|
+
node ${HOME_DIR}/example/snmp-inform.js -v 3 -l authPriv -u ${USER_PRIV} -a ${AUTH_PROTOCOL} -A ${AUTH_KEY} -x ${PRIV_PROTOCOL} -X ${PRIV_KEY} ${PARAMS} ${HOST} ${TRAP_OID}
|
66
66
|
ENDOFCMDS
|
67
67
|
|
68
68
|
COUNT=1
|
@@ -81,4 +81,3 @@ while read CMD ; do
|
|
81
81
|
done <${CMDS}
|
82
82
|
|
83
83
|
rm -f ${CMDS}
|
84
|
-
|