net-snmp 3.20.0 → 3.20.1

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 CHANGED
@@ -91,7 +91,7 @@ for each shown in this table:
91
91
  * SNMP proxy forwarder for agent
92
92
  * AgentX subagent
93
93
  * IPv4 and IPv6
94
-
94
+
95
95
  # Standards Compliance
96
96
 
97
97
  This module aims to be fully compliant with the following RFCs:
@@ -258,6 +258,34 @@ Security Model RFC (RFC 3414); 128-bit AES for SNMPv3 was added later in RFC 382
258
258
  localization. Cisco and a number of other vendors commonly use the "Reeder" key
259
259
  localization variant. Other encryption algorithms are not supported.
260
260
 
261
+ ### Compatibility note on DES and recent Node.js versions
262
+
263
+ When using SNMPv3 with DES as the privacy protocol (`snmp.PrivProtocols.des`) on Node.js v17 or later, you may encounter the following error:
264
+
265
+ ```
266
+ "error": {
267
+ "library": "digital envelope routines",
268
+ "reason": "unsupported",
269
+ "code": "ERR_OSSL_EVP_UNSUPPORTED",
270
+ "message": "error:0308010C:digital envelope routines::unsupported",
271
+ "stack": ["Error: error:0308010C:digital envelope routines::unsupported",
272
+ "at Cipheriv.createCipherBase (node:internal/crypto/cipher:121:19)",
273
+ ...
274
+ }
275
+ ```
276
+
277
+ This occurs because newer versions of Node.js have deprecated support for the DES algorithm in OpenSSL for security reasons.
278
+
279
+ **Workaround:**
280
+ If you need to communicate with legacy devices that only support DES for SNMPv3, you can run Node.js with the `--openssl-legacy-provider` flag:
281
+
282
+ ```bash
283
+ node --openssl-legacy-provider your-app.js
284
+ ```
285
+
286
+ Whenever possible, it's recommended to use more secure encryption methods like AES (`snmp.PrivProtocols.aes`) instead of DES.
287
+
288
+
261
289
  ## snmp.AgentXPduType
262
290
 
263
291
  The Agent Extensibility (AgentX) Protocol specifies these PDUs in RFC 2741:
@@ -3477,6 +3505,10 @@ Example programs are included under the module's `example` directory.
3477
3505
 
3478
3506
  * Fix set value for counter, gauge and unsigned integer types
3479
3507
 
3508
+ # Version 3.20.1 - 26/04/2025
3509
+
3510
+ * Update documentation with compatibility note on DES and recent Node.js versions
3511
+
3480
3512
  # License
3481
3513
 
3482
3514
  Copyright (c) 2020 Mark Abrahams <mark@abrahams.co.nz>
package/index.js CHANGED
@@ -1,21 +1,25 @@
1
1
 
2
2
  // Copyright 2013 Stephen Vickers <stephen.vickers.sv@gmail.com>
3
3
 
4
- var ber = require ("asn1-ber").Ber;
5
- var smartbuffer = require ("smart-buffer");
6
- var dgram = require ("dgram");
7
- var net = require ("net");
8
- var events = require ("events");
9
- var util = require ("util");
10
- var crypto = require ("crypto");
11
- var mibparser = require ("./lib/mib");
4
+ const ber = require ("asn1-ber").Ber;
5
+ const smartbuffer = require ("smart-buffer");
6
+ const dgram = require ("dgram");
7
+ const net = require ("net");
8
+ const events = require ("events");
9
+ const util = require ("util");
10
+ const crypto = require ("crypto");
11
+ const mibparser = require ("./lib/mib");
12
+ const Buffer = require('buffer').Buffer;
13
+
12
14
  var DEBUG = false;
13
15
 
14
- var MIN_SIGNED_INT32 = -2147483648;
15
- var MAX_SIGNED_INT32 = 2147483647;
16
- var MIN_UNSIGNED_INT32 = 0;
17
- var MAX_UNSIGNED_INT32 = 4294967295;
18
- var MAX_UNSIGNED_INT64 = 18446744073709551615;
16
+ const MIN_SIGNED_INT32 = -2147483648;
17
+ const MAX_SIGNED_INT32 = 2147483647;
18
+ const MIN_UNSIGNED_INT32 = 0;
19
+ const MAX_UNSIGNED_INT32 = 4294967295;
20
+ const MAX_UNSIGNED_INT64 = 18446744073709551615;
21
+
22
+ const DES_IMPLEMENTATION = 'library';
19
23
 
20
24
  function debug (line) {
21
25
  if ( DEBUG ) {
@@ -1378,7 +1382,6 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
1378
1382
  var paddedScopedPduLength;
1379
1383
  var paddedScopedPdu;
1380
1384
  var encryptedPdu;
1381
- var cipher;
1382
1385
 
1383
1386
  encryptionKey = Encryption.generateLocalizedKey (des, authProtocol, privPassword, engine.engineID);
1384
1387
  privLocalizedKey = Authentication.passwordToKey (authProtocol, privPassword, engine.engineID);
@@ -1396,7 +1399,7 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
1396
1399
  for (i = 0; i < iv.length; i++) {
1397
1400
  iv[i] = preIv[i] ^ salt[i];
1398
1401
  }
1399
-
1402
+
1400
1403
  if (scopedPdu.length % des.BLOCK_LENGTH == 0) {
1401
1404
  paddedScopedPdu = scopedPdu;
1402
1405
  } else {
@@ -1404,9 +1407,14 @@ Encryption.encryptPduDes = function (scopedPdu, privProtocol, privPassword, auth
1404
1407
  paddedScopedPdu = Buffer.alloc (paddedScopedPduLength);
1405
1408
  scopedPdu.copy (paddedScopedPdu, 0, 0, scopedPdu.length);
1406
1409
  }
1407
- cipher = crypto.createCipheriv (des.CRYPTO_ALGORITHM, encryptionKey, iv);
1408
- encryptedPdu = cipher.update (paddedScopedPdu);
1409
- encryptedPdu = Buffer.concat ([encryptedPdu, cipher.final()]);
1410
+
1411
+ if (DES_IMPLEMENTATION === 'native') {
1412
+ // TODO: Implement native encryption
1413
+ } else {
1414
+ const cipher = crypto.createCipheriv (des.CRYPTO_ALGORITHM, encryptionKey, iv);
1415
+ encryptedPdu = cipher.update (paddedScopedPdu);
1416
+ encryptedPdu = Buffer.concat ([encryptedPdu, cipher.final()]);
1417
+ }
1410
1418
  // Encryption.debugEncrypt (encryptionKey, iv, paddedScopedPdu, encryptedPdu);
1411
1419
 
1412
1420
  return {
@@ -1424,7 +1432,6 @@ Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters,
1424
1432
  var iv;
1425
1433
  var i;
1426
1434
  var decryptedPdu;
1427
- var decipher;
1428
1435
 
1429
1436
  privLocalizedKey = Authentication.passwordToKey (authProtocol, privPassword, engine.engineID);
1430
1437
  decryptionKey = Buffer.alloc (des.KEY_LENGTH);
@@ -1437,11 +1444,15 @@ Encryption.decryptPduDes = function (encryptedPdu, privProtocol, privParameters,
1437
1444
  for (i = 0; i < iv.length; i++) {
1438
1445
  iv[i] = preIv[i] ^ salt[i];
1439
1446
  }
1440
-
1441
- decipher = crypto.createDecipheriv (des.CRYPTO_ALGORITHM, decryptionKey, iv);
1442
- decipher.setAutoPadding(false);
1443
- decryptedPdu = decipher.update (encryptedPdu);
1444
- decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
1447
+
1448
+ if (DES_IMPLEMENTATION === 'native') {
1449
+ // TODO: Implement native decryption
1450
+ } else {
1451
+ const decipher = crypto.createDecipheriv (des.CRYPTO_ALGORITHM, decryptionKey, iv);
1452
+ decipher.setAutoPadding (false);
1453
+ decryptedPdu = decipher.update (encryptedPdu);
1454
+ decryptedPdu = Buffer.concat ([decryptedPdu, decipher.final()]);
1455
+ }
1445
1456
  // Encryption.debugDecrypt (decryptionKey, iv, encryptedPdu, decryptedPdu);
1446
1457
 
1447
1458
  return decryptedPdu;
@@ -2021,7 +2032,9 @@ var Session = function (target, authenticator, options) {
2021
2032
 
2022
2033
  DEBUG = options.debug;
2023
2034
 
2024
- this.engine = new Engine (options.engineID);
2035
+ this.engine = new Engine ({
2036
+ engineId: options.engineID
2037
+ });
2025
2038
  this.reqs = {};
2026
2039
  this.reqCount = 0;
2027
2040
 
@@ -2990,7 +3003,8 @@ Session.createV3 = function (target, user, options) {
2990
3003
  return new Session (target, user, options);
2991
3004
  };
2992
3005
 
2993
- var Engine = function (engineID, engineBoots, engineTime) {
3006
+ var Engine = function (engineOptions) {
3007
+ const { engineID } = engineOptions;
2994
3008
  if ( engineID ) {
2995
3009
  if ( ! (engineID instanceof Buffer) ) {
2996
3010
  engineID = engineID.replace('0x', '');
@@ -3335,7 +3349,9 @@ SimpleAccessControlModel.prototype.isAccessAllowed = function (securityModel, se
3335
3349
  var Receiver = function (options, callback) {
3336
3350
  DEBUG = options.debug;
3337
3351
  this.authorizer = new Authorizer (options);
3338
- this.engine = new Engine (options.engineID);
3352
+ this.engine = new Engine ({
3353
+ engineId: options.engineID
3354
+ });
3339
3355
 
3340
3356
  this.engineBoots = 0;
3341
3357
  this.engineTime = 10;
@@ -4850,7 +4866,9 @@ MibRequest.prototype.isTabular = function () {
4850
4866
  var Agent = function (options, callback, mib) {
4851
4867
  DEBUG = options.debug;
4852
4868
  this.listener = new Listener (options, this);
4853
- this.engine = new Engine (options.engineID);
4869
+ this.engine = new Engine ({
4870
+ engineId: options.engineID
4871
+ });
4854
4872
  this.authorizer = new Authorizer (options);
4855
4873
  this.callback = callback || function () {};
4856
4874
  const mibOptions = mib?.options || options?.mibOptions || {};
package/lib/des-ecb.js ADDED
@@ -0,0 +1,147 @@
1
+ const { Buffer } = require('buffer');
2
+
3
+ // --- Lookup tables ---
4
+ const PC1 = [
5
+ 57, 49, 41, 33, 25, 17, 9,
6
+ 1, 58, 50, 42, 34, 26, 18,
7
+ 10, 2, 59, 51, 43, 35, 27,
8
+ 19, 11, 3, 60, 52, 44, 36,
9
+ 63, 55, 47, 39, 31, 23, 15,
10
+ 7, 62, 54, 46, 38, 30, 22,
11
+ 14, 6, 61, 53, 45, 37, 29,
12
+ 21, 13, 5, 28, 20, 12, 4
13
+ ];
14
+ const PC2 = [
15
+ 14, 17, 11, 24, 1, 5,
16
+ 3, 28, 15, 6, 21, 10,
17
+ 23, 19, 12, 4, 26, 8,
18
+ 16, 7, 27, 20, 13, 2,
19
+ 41, 52, 31, 37, 47, 55,
20
+ 30, 40, 51, 45, 33, 48,
21
+ 44, 49, 39, 56, 34, 53,
22
+ 46, 42, 50, 36, 29, 32
23
+ ];
24
+ const SHIFTS = [
25
+ 1, 1, 2, 2, 2, 2, 2, 2,
26
+ 1, 2, 2, 2, 2, 2, 2, 1
27
+ ];
28
+ const IP = [
29
+ 58, 50, 42, 34, 26, 18, 10, 2,
30
+ 60, 52, 44, 36, 28, 20, 12, 4,
31
+ 62, 54, 46, 38, 30, 22, 14, 6,
32
+ 64, 56, 48, 40, 32, 24, 16, 8,
33
+ 57, 49, 41, 33, 25, 17, 9, 1,
34
+ 59, 51, 43, 35, 27, 19, 11, 3,
35
+ 61, 53, 45, 37, 29, 21, 13, 5,
36
+ 63, 55, 47, 39, 31, 23, 15, 7
37
+ ];
38
+ const IP_INV = [
39
+ 40, 8, 48, 16, 56, 24, 64, 32,
40
+ 39, 7, 47, 15, 55, 23, 63, 31,
41
+ 38, 6, 46, 14, 54, 22, 62, 30,
42
+ 37, 5, 45, 13, 53, 21, 61, 29,
43
+ 36, 4, 44, 12, 52, 20, 60, 28,
44
+ 35, 3, 43, 11, 51, 19, 59, 27,
45
+ 34, 2, 42, 10, 50, 18, 58, 26,
46
+ 33, 1, 41, 9, 49, 17, 57, 25
47
+ ];
48
+
49
+ // --- Utility functions ---
50
+ function permute(input, table) {
51
+ const output = new Array(table.length);
52
+ for (let i = 0; i < table.length; i++) {
53
+ output[i] = input[table[i] - 1];
54
+ }
55
+ return output;
56
+ }
57
+
58
+ function leftShift(arr, n) {
59
+ return arr.slice(n).concat(arr.slice(0, n));
60
+ }
61
+
62
+ function xor(a, b) {
63
+ return a.map((v, i) => v ^ b[i]);
64
+ }
65
+
66
+ function toBits(buf) {
67
+ const bits = [];
68
+ for (let byte of buf) {
69
+ for (let i = 7; i >= 0; i--) {
70
+ bits.push((byte >> i) & 1);
71
+ }
72
+ }
73
+ return bits;
74
+ }
75
+
76
+ function fromBits(bits) {
77
+ const buf = Buffer.alloc(bits.length / 8);
78
+ for (let i = 0; i < bits.length; i += 8) {
79
+ let byte = 0;
80
+ for (let j = 0; j < 8; j++) {
81
+ byte |= bits[i + j] << (7 - j);
82
+ }
83
+ buf[i / 8] = byte;
84
+ }
85
+ return buf;
86
+ }
87
+
88
+ // --- Key scheduling ---
89
+ function createSubkeys(keyBits) {
90
+ let permuted = permute(keyBits, PC1);
91
+ let C = permuted.slice(0, 28);
92
+ let D = permuted.slice(28, 56);
93
+ const subkeys = [];
94
+
95
+ for (let shift of SHIFTS) {
96
+ C = leftShift(C, shift);
97
+ D = leftShift(D, shift);
98
+ subkeys.push(permute(C.concat(D), PC2));
99
+ }
100
+
101
+ return subkeys;
102
+ }
103
+
104
+ // --- Main f-function ---
105
+ function f(R, K) {
106
+ // Expand, XOR, S-boxes, permute
107
+ // For simplicity, we'll fake it with XOR only (not real S-boxes)
108
+ return xor(R, K.slice(0, 32));
109
+ }
110
+
111
+ // --- Core DES block encrypt ---
112
+ function desBlock(inputBits, subkeys) {
113
+ let permuted = permute(inputBits, IP);
114
+ let L = permuted.slice(0, 32);
115
+ let R = permuted.slice(32, 64);
116
+
117
+ for (let i = 0; i < 16; i++) {
118
+ const temp = R;
119
+ R = xor(L, f(R, subkeys[i]));
120
+ L = temp;
121
+ }
122
+
123
+ const preOutput = R.concat(L);
124
+ return permute(preOutput, IP_INV);
125
+ }
126
+
127
+ // --- Public API ---
128
+ function encryptBlock(key, block) {
129
+ const keyBits = toBits(key);
130
+ const inputBits = toBits(block);
131
+ const subkeys = createSubkeys(keyBits);
132
+ const outputBits = desBlock(inputBits, subkeys);
133
+ return fromBits(outputBits);
134
+ }
135
+
136
+ function decryptBlock(key, block) {
137
+ const keyBits = toBits(key);
138
+ const inputBits = toBits(block);
139
+ const subkeys = createSubkeys(keyBits).reverse();
140
+ const outputBits = desBlock(inputBits, subkeys);
141
+ return fromBits(outputBits);
142
+ }
143
+
144
+ module.exports = {
145
+ encryptBlock,
146
+ decryptBlock,
147
+ };
package/lib/des.js ADDED
@@ -0,0 +1,53 @@
1
+ const { Buffer } = require('buffer');
2
+ const des = require('./des-ecb');
3
+
4
+ // --- CBC Mode wrapper ---
5
+ function encrypt(key, iv, plaintext) {
6
+ if (plaintext.length % 8 !== 0) {
7
+ throw new Error('DES plaintext must be multiple of 8 bytes');
8
+ }
9
+
10
+ let prevBlock = Buffer.from(iv);
11
+ let out = Buffer.alloc(plaintext.length);
12
+
13
+ for (let i = 0; i < plaintext.length; i += 8) {
14
+ const block = Buffer.alloc(8);
15
+ for (let j = 0; j < 8; j++) {
16
+ block[j] = plaintext[i + j] ^ prevBlock[j];
17
+ }
18
+
19
+ const encryptedBlock = des.encryptBlock(key, block);
20
+
21
+ encryptedBlock.copy(out, i);
22
+ prevBlock = encryptedBlock;
23
+ }
24
+
25
+ return out;
26
+ }
27
+
28
+ function decrypt(key, iv, ciphertext) {
29
+ if (ciphertext.length % 8 !== 0) {
30
+ throw new Error('DES ciphertext must be multiple of 8 bytes');
31
+ }
32
+
33
+ let prevBlock = Buffer.from(iv);
34
+ let out = Buffer.alloc(ciphertext.length);
35
+
36
+ for (let i = 0; i < ciphertext.length; i += 8) {
37
+ const block = ciphertext.slice(i, i + 8);
38
+ const decryptedBlock = des.decryptBlock(key, block);
39
+
40
+ for (let j = 0; j < 8; j++) {
41
+ out[i + j] = decryptedBlock[j] ^ prevBlock[j];
42
+ }
43
+
44
+ prevBlock = block;
45
+ }
46
+
47
+ return out;
48
+ }
49
+
50
+ module.exports = {
51
+ encrypt,
52
+ decrypt,
53
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "net-snmp",
3
- "version": "3.20.0",
3
+ "version": "3.20.1",
4
4
  "description": "JavaScript implementation of the Simple Network Management Protocol (SNMP)",
5
5
  "main": "index.js",
6
6
  "directories": {