pysnmp
pysnmp copied to clipboard
[Bug]: USM read/write access not working as intended.
Expected behavior
I expect when setting the v2 and v3 users with no subtrees that they would not have read and write access.
# SNMPv2c setup
# SecurityName <-> CommunityName mapping.
config.addV1System(snmpEngine, "my-area", "public")
# Allow read MIB access for this user / securityModels at VACM
config.addVacmUser(snmpEngine, 2, "my-area", "noAuthNoPriv")
Actual behavior
But the users have full access to my OIDs unless I give them a specific subTree to block write/read requests.
enterprise = (1, 3, 6, 1, 4, 1, 66666)
blockWriteSubtree = (1, 3, 6, 1, 4, 1, 66666, 4294967295)
config.addVacmUser(snmpEngine, 2, "my-area", "noAuthNoPriv", enterprise, blockWriteSubtree)
Detailed steps
Here is a simplifed example I am working with. Omitting the blockWriteSubtree will allow the v2 user to write. Same goes for the v3 user. Not passing in the readSubTree and writeSubTree allows the users read/write as well.
import os
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncio.dgram import udp
from pysnmp.proto.api import v2c
from pysnmp.smi import builder
import pysnmp.debug as debug
from pysnmp.proto.rfc1902 import OctetString
from pysnmp.proto.secmod.rfc3414.priv import des
from pysnmp.proto.secmod.rfc3414.auth import hmacmd5
from pyasn1.type.univ import OctetString
import random
# debug.setLogger(debug.Debug('all'))
enterprise = (1, 3, 6, 1, 4, 1, 66666)
blockWriteSubtree = (1, 3, 6, 1, 4, 1, 66666, 4294967295)
oid = (1, 3, 6, 1, 4, 1, 66666, 1)
# Get the path of the mibs folder
script_path = os.path.abspath(__file__)
mibs_path = os.path.join(os.path.dirname(script_path), 'mibs')
# Create SNMP engine
snmpEngine = engine.SnmpEngine()
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(("127.0.0.1", 161))
)
# SNMPv2c setup
# SecurityName <-> CommunityName mapping.
config.addV1System(snmpEngine, "my-area", "public")
# Allow read MIB access for this user / securityModels at VACM
config.addVacmUser(snmpEngine, 2, "my-area", "noAuthNoPriv", enterprise, blockWriteSubtree)
# SNMPv3/USM setup
# use pre-hahsed keys later this will use the keys from the database
authKey = des.Des().hashPassphrase(config.usmHMACMD5AuthProtocol, OctetString("authkey1"))
privKey = des.Des().hashPassphrase(config.usmHMACMD5AuthProtocol, OctetString("privkey1"))
config.addV3User(
snmpEngine,
"usr-md5-des",
config.usmHMACMD5AuthProtocol,
authKey,
config.usmDESPrivProtocol,
privKey,
authKeyType = config.usmKeyTypeMaster,
privKeyType = config.usmKeyTypeMaster
)
# Allow full MIB access for each user at VACM
config.addVacmUser(
snmpEngine, 3, "usr-md5-des", "authPriv", enterprise, enterprise
)
# Create an SNMP context
snmpContext = context.SnmpContext(snmpEngine)
# --- create custom Managed Object Instance ---
mibBuilder = snmpContext.getMibInstrum().getMibBuilder()
MibScalar, MibScalarInstance = mibBuilder.importSymbols(
"SNMPv2-SMI", "MibScalar", "MibScalarInstance"
)
class MyStaticMibScalarInstance(MibScalarInstance):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.value = random.randint(1, 100)
def getValue(self, name, idx):
print(f"{name}: Returning value: {self.value}")
return self.getSyntax().clone(self.value)
def setValue(self, val, name, idx):
self.value = val
print(f"{name}: Setting value: {val}")
return self.getSyntax().clone(self.value)
MyScaler = MibScalar(oid, v2c.Unsigned32())
MyScaler.maxAccess = 'readwrite'
mibBuilder.exportSymbols(
"__MY_MIB",
MyScaler,
MyStaticMibScalarInstance(oid, (0,), v2c.Unsigned32()),
)
# --- end of Managed Object Instance initialization ----
# Register SNMP Applications at the SNMP engine for particular SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)
# Run I/O dispatcher which would receive queries and send responses
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
Python package information
pysnmp-lextudio 5.0.36
Operating system information
Windows 11
Python information
3.12.0
(Optional) Contents of your test script
No response
Relevant log output
No response