Hello community,
here is the log from the commit of package python-pysnmp for openSUSE:Factory checked in at 2019-08-05 10:36:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pysnmp (Old)
and /work/SRC/openSUSE:Factory/.python-pysnmp.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pysnmp"
Mon Aug 5 10:36:20 2019 rev:13 rq:720140 version:4.4.10
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pysnmp/python-pysnmp.changes 2019-02-11 21:27:30.231012021 +0100
+++ /work/SRC/openSUSE:Factory/.python-pysnmp.new.4126/python-pysnmp.changes 2019-08-05 10:36:27.439334026 +0200
@@ -1,0 +2,30 @@
+Wed Jul 31 20:44:55 UTC 2019 - Martin Hauke
+
+- Update to version 4.4.10
+ * Reworked VACM access control function. Most important changes include:
+
+ + Added subtree match negation support (vacmViewTreeFamilyType)
+ + Added subtree family mask support (vacmViewTreeFamilyMask)
+ + Added prefix content name matching support (vacmAccessContextMatch)
+ + Added key VACM tables caching for better `isAccessAllowed` lookup
+ performance
+
+ One potential incompatibility may be caused by the `addContext()` call
+ which now needs to be made explicitly during low-level VACM configuration
+ rather than be a side effect of `addVacmAccess()` call.
+
+ * Rebased MIB importing code onto `importlib` because `imp` is long
+ deprecated
+ * Received MIB objects resolution made more forgiving to errors, added
+ optional `ignoreErrors` parameter to `ObjectType.resolveWithMib()` to
+ control that behaviour.
+ * Fixed asyncore main loop to respect non-default timer resolution
+ * Fixed `.setTimerResolution()` behaviour of abstract main loop dispatcher
+ to update call intervals of the existing periodic dispatcher jobs
+ * Fixed `var-bindings` initialization to prevent pyasn1 encoder failures
+ with newer pyasn1 versions where `SequenceOf` type looses its default
+ initializer.
+ * Fixed crash on uninitialized component serialization left out in
+ SNMP v1 TRAP PDU to SNMPv2/3 TRAP PDU proxy translation routine.
+
+-------------------------------------------------------------------
Old:
----
pysnmp-4.4.9.tar.gz
New:
----
pysnmp-4.4.10.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pysnmp.spec ++++++
--- /var/tmp/diff_new_pack.i0ZeRD/_old 2019-08-05 10:36:28.163333943 +0200
+++ /var/tmp/diff_new_pack.i0ZeRD/_new 2019-08-05 10:36:28.167333943 +0200
@@ -12,13 +12,13 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pysnmp
-Version: 4.4.9
+Version: 4.4.10
Release: 0
Summary: A pure-Python SNMPv1/v2c/v3 library
License: BSD-2-Clause
++++++ pysnmp-4.4.9.tar.gz -> pysnmp-4.4.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/CHANGES.txt new/pysnmp-4.4.10/CHANGES.txt
--- old/pysnmp-4.4.9/CHANGES.txt 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/CHANGES.txt 2019-07-30 20:29:22.000000000 +0200
@@ -1,4 +1,33 @@
+Revision 4.4.10, released 2019-07-29
+------------------------------------
+
+- Reworked VACM access control function. Most important changes include:
+
+ * Added subtree match negation support (vacmViewTreeFamilyType)
+ * Added subtree family mask support (vacmViewTreeFamilyMask)
+ * Added prefix content name matching support (vacmAccessContextMatch)
+ * Added key VACM tables caching for better `isAccessAllowed` lookup
+ performance
+
+ One potential incompatibility may be caused by the `addContext()` call
+ which now needs to be made explicitly during low-level VACM configuration
+ rather than be a side effect of `addVacmAccess()` call.
+
+- Rebased MIB importing code onto `importlib` because `imp` is long
+ deprecated
+- Received MIB objects resolution made more forgiving to errors, added
+ optional `ignoreErrors` parameter to `ObjectType.resolveWithMib()` to
+ control that behaviour.
+- Fixed asyncore main loop to respect non-default timer resolution
+- Fixed `.setTimerResolution()` behaviour of abstract main loop dispatcher
+ to update call intervals of the existing periodic dispatcher jobs
+- Fixed `var-bindings` initialization to prevent pyasn1 encoder failures
+ with newer pyasn1 versions where `SequenceOf` type looses its default
+ initializer.
+- Fixed crash on uninitialized component serialization left out in
+ SNMP v1 TRAP PDU to SNMPv2/3 TRAP PDU proxy translation routine.
+
Revision 4.4.9, released 2019-02-09
-----------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/docs/source/examples/v3arch/asyncore/agent/cmdrsp/advanced-topics.rst new/pysnmp-4.4.10/docs/source/examples/v3arch/asyncore/agent/cmdrsp/advanced-topics.rst
--- old/pysnmp-4.4.9/docs/source/examples/v3arch/asyncore/agent/cmdrsp/advanced-topics.rst 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/docs/source/examples/v3arch/asyncore/agent/cmdrsp/advanced-topics.rst 2019-07-30 20:29:22.000000000 +0200
@@ -37,4 +37,14 @@
:download:`Download` script.
+.. include:: /../../examples/v3arch/asyncore/agent/cmdrsp/detailed-vacm-configuration.py
+ :start-after: """
+ :end-before: """#
+
+.. literalinclude:: /../../examples/v3arch/asyncore/agent/cmdrsp/detailed-vacm-configuration.py
+ :start-after: """#
+ :language: python
+
+:download:`Download` script.
+
See also: :doc:`library reference `.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/examples/v3arch/asyncore/agent/cmdrsp/detailed-vacm-configuration.py new/pysnmp-4.4.10/examples/v3arch/asyncore/agent/cmdrsp/detailed-vacm-configuration.py
--- old/pysnmp-4.4.9/examples/v3arch/asyncore/agent/cmdrsp/detailed-vacm-configuration.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pysnmp-4.4.10/examples/v3arch/asyncore/agent/cmdrsp/detailed-vacm-configuration.py 2019-07-30 20:29:22.000000000 +0200
@@ -0,0 +1,117 @@
+"""
+Detailed VACM configuration
++++++++++++++++++++++++++++
+
+Serves MIB subtrees under different conditions:
+
+* Respond to SNMPv2c commands
+* with SNMP community "public"
+* over IPv4/UDP, listening at 127.0.0.1:161
+* Serve MIB under non-default contextName `abcd`
+* Allow access to `SNMPv2-MIB::system` subtree
+* Although deny access to `SNMPv2-MIB::sysUpTime` by a bit mask
+* Use partial context name matching (`a`)
+
+This example demonstrates detailed VACM configuration performed via
+low-level VACM calls: `addContext`, `addVacmGroup`, `addVacmAccess`
+and `addVacmView`. Each function populates one of the tables
+defined in `SNMP-VIEW-BASED-ACM-MIB` and used strictly as described
+in the above mentioned MIB.
+
+The following Net-SNMP's commands will GET a value at this Agent:
+
+| $ snmpget -v2c -c public 127.0.0.1 SNMPv2-MIB::sysLocation.0
+
+However this command will fail:
+
+| $ snmpget -v2c -c public 127.0.0.1 SNMPv2-MIB::sysUpTime.0
+
+This command will not reveal `SNMPv2-MIB::sysUpTime.0` among other objects:
+
+| $ snmpwalk -v2c -c public 127.0.0.1 SNMPv2-MIB::system
+"""#
+from pysnmp.entity import engine, config
+from pysnmp.entity.rfc3413 import cmdrsp, context
+from pysnmp.carrier.asyncore.dgram import udp
+
+# Create SNMP engine with autogenernated engineID and pre-bound
+# to socket transport dispatcher
+snmpEngine = engine.SnmpEngine()
+
+# Transport setup
+
+# UDP over IPv4
+config.addTransport(
+ snmpEngine,
+ udp.domainName,
+ udp.UdpTransport().openServerMode(('127.0.0.1', 161))
+)
+
+# Register default MIB instrumentation controller with a new SNMP context
+
+contextName = 'abcd'
+
+snmpContext = context.SnmpContext(snmpEngine)
+
+snmpContext.registerContextName(
+ contextName, snmpEngine.msgAndPduDsp.mibInstrumController)
+
+# Add new SNMP community name, map it to a new security name and
+# SNMP context
+
+securityName = 'my-area'
+communityName = 'public'
+
+config.addV1System(
+ snmpEngine, securityName, communityName,
+ contextEngineId=snmpContext.contextEngineId,
+ contextName=contextName)
+
+# VACM configuration settings
+
+securityModel = 2 # SNMPv2c
+securityLevel = 1 # noAuthNoPriv
+
+vacmGroup = 'my-group'
+readViewName = 'my-read-view'
+
+# We will match by context name prefix
+contextPrefix = contextName[:1]
+
+# Populate SNMP-VIEW-BASED-ACM-MIB::vacmContextTable
+config.addContext(snmpEngine, contextName)
+
+# Populate SNMP-VIEW-BASED-ACM-MIB::vacmSecurityToGroupTable
+config.addVacmGroup(
+ snmpEngine, vacmGroup, securityModel, securityName)
+
+# Populate SNMP-VIEW-BASED-ACM-MIB::vacmAccessTable
+config.addVacmAccess(
+ snmpEngine, vacmGroup, contextPrefix, securityModel, securityLevel,
+ 'prefix', readViewName, '', '')
+
+# Populate SNMP-VIEW-BASED-ACM-MIB::vacmViewTreeFamilyTable
+
+# Allow the whole system subtree
+config.addVacmView(
+ snmpEngine, readViewName, 'included', '1.3.6.1.2.1.1.1', '1.1.1.1.1.1.1.0')
+
+# ...but exclude one sub-branch (just one scalar OID)
+config.addVacmView(
+ snmpEngine, readViewName, 'excluded', '1.3.6.1.2.1.1.3', '1.1.1.1.1.1.1.1')
+
+# Register SNMP Applications at the SNMP engine for particular SNMP context
+cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
+cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
+cmdrsp.NextCommandResponder(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 Exception:
+ snmpEngine.transportDispatcher.closeDispatcher()
+ raise
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/__init__.py new/pysnmp-4.4.10/pysnmp/__init__.py
--- old/pysnmp-4.4.9/pysnmp/__init__.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/__init__.py 2019-07-30 20:29:22.000000000 +0200
@@ -1,5 +1,5 @@
# http://www.python.org/dev/peps/pep-0396/
-__version__ = '4.4.9'
+__version__ = '4.4.10'
# backward compatibility
version = tuple([int(x) for x in __version__.split('.')])
majorVersionId = version[0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/carrier/asyncore/dispatch.py new/pysnmp-4.4.10/pysnmp/carrier/asyncore/dispatch.py
--- old/pysnmp-4.4.9/pysnmp/carrier/asyncore/dispatch.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/carrier/asyncore/dispatch.py 2019-07-30 20:29:22.000000000 +0200
@@ -42,7 +42,7 @@
def runDispatcher(self, timeout=0.0):
while self.jobsArePending() or self.transportsAreWorking():
try:
- loop(timeout and timeout or self.timeout,
+ loop(timeout or self.getTimerResolution(),
use_poll=True, map=self.__sockMap, count=1)
except KeyboardInterrupt:
raise
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/carrier/base.py new/pysnmp-4.4.10/pysnmp/carrier/base.py
--- old/pysnmp-4.4.9/pysnmp/carrier/base.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/carrier/base.py 2019-07-30 20:29:22.000000000 +0200
@@ -4,19 +4,25 @@
# Copyright (c) 2005-2019, Ilya Etingof
# License: http://snmplabs.com/pysnmp/license.html
#
+import sys
+
from pysnmp.carrier import error
class TimerCallable(object):
def __init__(self, cbFun, callInterval):
self.__cbFun = cbFun
- self.__callInterval = callInterval
self.__nextCall = 0
+ if sys.version_info > (2, 6):
+ self.__callInterval = callInterval
+ else:
+ self.interval = callInterval
+
def __call__(self, timeNow):
if self.__nextCall <= timeNow:
self.__cbFun(timeNow)
- self.__nextCall = timeNow + self.__callInterval
+ self.__nextCall = timeNow + self.interval
def __eq__(self, cbFun):
return self.__cbFun == cbFun
@@ -36,6 +42,15 @@
def __ge__(self, cbFun):
return self.__cbFun >= cbFun
+ if sys.version_info > (2, 6):
+ @property
+ def interval(self):
+ return self.__callInterval
+
+ @interval.setter
+ def interval(self, callInterval):
+ self.__callInterval = callInterval
+
class AbstractTransportDispatcher(object):
def __init__(self):
@@ -151,6 +166,12 @@
def setTimerResolution(self, timerResolution):
if timerResolution < 0.01 or timerResolution > 10:
raise error.CarrierError('Impossible timer resolution')
+
+ for timerCallable in self.__timerCallables:
+ if timerCallable.interval == self.__timerResolution:
+ # Update periodics for default resolutions
+ timerCallable.interval = timerResolution
+
self.__timerResolution = timerResolution
self.__timerDelta = timerResolution * 0.05
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/entity/config.py new/pysnmp-4.4.10/pysnmp/entity/config.py
--- old/pysnmp-4.4.9/pysnmp/entity/config.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/entity/config.py 2019-07-30 20:29:22.000000000 +0200
@@ -11,6 +11,7 @@
from pysnmp.proto.secmod.rfc3826.priv import aes
from pysnmp.proto.secmod.rfc7860.auth import hmacsha2
from pysnmp.proto.secmod.eso.priv import des3, aes192, aes256
+from pysnmp.proto import rfc1902
from pysnmp.proto import rfc1905
from pysnmp import error
@@ -461,22 +462,20 @@
return vacmAccessEntry, tblIdx
-def addVacmAccess(snmpEngine, groupName, contextName, securityModel,
- securityLevel, prefix, readView, writeView, notifyView):
- vacmAccessEntry, tblIdx = __cookVacmAccessInfo(snmpEngine, groupName,
- contextName, securityModel,
- securityLevel)
-
- addContext(snmpEngine, contextName)
+def addVacmAccess(snmpEngine, groupName, contextPrefix, securityModel,
+ securityLevel, contextMatch, readView, writeView, notifyView):
+ vacmAccessEntry, tblIdx = __cookVacmAccessInfo(
+ snmpEngine, groupName, contextPrefix, securityModel,
+ securityLevel)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),)
)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
- ((vacmAccessEntry.name + (1,) + tblIdx, contextName),
+ ((vacmAccessEntry.name + (1,) + tblIdx, contextPrefix),
(vacmAccessEntry.name + (2,) + tblIdx, securityModel),
(vacmAccessEntry.name + (3,) + tblIdx, securityLevel),
- (vacmAccessEntry.name + (4,) + tblIdx, prefix),
+ (vacmAccessEntry.name + (4,) + tblIdx, contextMatch),
(vacmAccessEntry.name + (5,) + tblIdx, readView),
(vacmAccessEntry.name + (6,) + tblIdx, writeView),
(vacmAccessEntry.name + (7,) + tblIdx, notifyView),
@@ -484,13 +483,10 @@
)
-def delVacmAccess(snmpEngine, groupName, contextName, securityModel,
+def delVacmAccess(snmpEngine, groupName, contextPrefix, securityModel,
securityLevel):
- vacmAccessEntry, tblIdx = __cookVacmAccessInfo(snmpEngine, groupName,
- contextName, securityModel,
- securityLevel)
-
- delContext(snmpEngine, contextName)
+ vacmAccessEntry, tblIdx = __cookVacmAccessInfo(
+ snmpEngine, groupName, contextPrefix, securityModel, securityLevel)
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmAccessEntry.name + (9,) + tblIdx, 'destroy'),)
@@ -507,16 +503,30 @@
return vacmViewTreeFamilyEntry, tblIdx
-def addVacmView(snmpEngine, viewName, viewType, subTree, mask):
- vacmViewTreeFamilyEntry, tblIdx = __cookVacmViewInfo(snmpEngine, viewName,
- subTree)
+def addVacmView(snmpEngine, viewName, viewType, subTree, subTreeMask):
+ vacmViewTreeFamilyEntry, tblIdx = __cookVacmViewInfo(
+ snmpEngine, viewName, subTree)
+
+ # Allow bitmask specification in form of an OID
+ if rfc1902.OctetString('.').asOctets() in rfc1902.OctetString(subTreeMask):
+ subTreeMask = rfc1902.ObjectIdentifier(subTreeMask)
+
+ if isinstance(subTreeMask, rfc1902.ObjectIdentifier):
+ subTreeMask = tuple(subTreeMask)
+ if len(subTreeMask) < len(subTree):
+ subTreeMask += (1,) * (len(subTree) - len(subTreeMask))
+
+ subTreeMask = rfc1902.OctetString.fromBinaryString(
+ ''.join(str(x) for x in subTreeMask))
+
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'destroy'),)
)
+
snmpEngine.msgAndPduDsp.mibInstrumController.writeVars(
((vacmViewTreeFamilyEntry.name + (1,) + tblIdx, viewName),
(vacmViewTreeFamilyEntry.name + (2,) + tblIdx, subTree),
- (vacmViewTreeFamilyEntry.name + (3,) + tblIdx, mask),
+ (vacmViewTreeFamilyEntry.name + (3,) + tblIdx, subTreeMask),
(vacmViewTreeFamilyEntry.name + (4,) + tblIdx, viewType),
(vacmViewTreeFamilyEntry.name + (6,) + tblIdx, 'createAndGo'))
)
@@ -548,15 +558,16 @@
(groupName, securityLevel, readView, writeView,
notifyView) = __cookVacmUserInfo(snmpEngine, securityModel, securityName,
securityLevel)
+ addContext(snmpEngine, contextName)
addVacmGroup(snmpEngine, groupName, securityModel, securityName)
addVacmAccess(snmpEngine, groupName, contextName, securityModel,
- securityLevel, 1, readView, writeView, notifyView)
+ securityLevel, 'exact', readView, writeView, notifyView)
if readSubTree:
- addVacmView(snmpEngine, readView, "included", readSubTree, null)
+ addVacmView(snmpEngine, readView, 'included', readSubTree, null)
if writeSubTree:
- addVacmView(snmpEngine, writeView, "included", writeSubTree, null)
+ addVacmView(snmpEngine, writeView, 'included', writeSubTree, null)
if notifySubTree:
- addVacmView(snmpEngine, notifyView, "included", notifySubTree, null)
+ addVacmView(snmpEngine, notifyView, 'included', notifySubTree, null)
def delVacmUser(snmpEngine, securityModel, securityName, securityLevel,
@@ -565,6 +576,7 @@
(groupName, securityLevel, readView, writeView,
notifyView) = __cookVacmUserInfo(snmpEngine, securityModel,
securityName, securityLevel)
+ delContext(snmpEngine, contextName)
delVacmGroup(snmpEngine, securityModel, securityName)
delVacmAccess(snmpEngine, groupName, contextName, securityModel, securityLevel)
if readSubTree:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/hlapi/varbinds.py new/pysnmp-4.4.10/pysnmp/hlapi/varbinds.py
--- old/pysnmp-4.4.9/pysnmp/hlapi/varbinds.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/hlapi/varbinds.py 2019-07-30 20:29:22.000000000 +0200
@@ -36,14 +36,15 @@
else:
varBind = ObjectType(ObjectIdentity(varBind[0]), varBind[1])
- __varBinds.append(varBind.resolveWithMib(mibViewController))
+ __varBinds.append(varBind.resolveWithMib(mibViewController, ignoreErrors=False))
return __varBinds
def unmakeVarBinds(self, snmpEngine, varBinds, lookupMib=True):
if lookupMib:
mibViewController = self.getMibViewController(snmpEngine)
- varBinds = [ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds]
+ varBinds = [ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(
+ mibViewController) for x in varBinds]
return varBinds
@@ -52,7 +53,8 @@
def makeVarBinds(self, snmpEngine, varBinds):
mibViewController = self.getMibViewController(snmpEngine)
if isinstance(varBinds, NotificationType):
- varBinds.resolveWithMib(mibViewController)
+ varBinds.resolveWithMib(
+ mibViewController, ignoreErrors=False)
__varBinds = []
for varBind in varBinds:
if isinstance(varBind, ObjectType):
@@ -61,11 +63,13 @@
varBind = ObjectType(*varBind)
else:
varBind = ObjectType(ObjectIdentity(varBind[0]), varBind[1])
- __varBinds.append(varBind.resolveWithMib(mibViewController))
+ __varBinds.append(varBind.resolveWithMib(
+ mibViewController, ignoreErrors=False))
return __varBinds
def unmakeVarBinds(self, snmpEngine, varBinds, lookupMib=False):
if lookupMib:
mibViewController = self.getMibViewController(snmpEngine)
- varBinds = [ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds]
+ varBinds = [ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(
+ mibViewController) for x in varBinds]
return varBinds
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/proto/acmod/rfc3415.py new/pysnmp-4.4.10/pysnmp/proto/acmod/rfc3415.py
--- old/pysnmp-4.4.9/pysnmp/proto/acmod/rfc3415.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/proto/acmod/rfc3415.py 2019-07-30 20:29:22.000000000 +0200
@@ -16,6 +16,117 @@
_powOfTwoSeq = (128, 64, 32, 16, 8, 4, 2, 1)
+ def __init__(self):
+ self._contextBranchId = -1
+ self._groupNameBranchId = -1
+ self._accessBranchId = -1
+ self._viewTreeBranchId = -1
+
+ self._contextMap = {}
+ self._groupNameMap = {}
+ self._accessMap = {}
+ self._viewTreeMap = {}
+
+ def _addAccessEntry(self, groupName, contextPrefix, securityModel,
+ securityLevel, prefixMatch, readView, writeView,
+ notifyView):
+ if not groupName:
+ return
+
+ groups = self._accessMap
+
+ try:
+ views = groups[groupName]
+
+ except KeyError:
+ views = groups[groupName] = {}
+
+ for viewType, viewName in (
+ ('read', readView), ('write', writeView),
+ ('notify', notifyView)):
+
+ try:
+ matches = views[viewType]
+
+ except KeyError:
+ matches = views[viewType] = {}
+
+ try:
+ contexts = matches[prefixMatch]
+
+ except KeyError:
+ contexts = matches[prefixMatch] = {}
+
+ try:
+ models = contexts[contextPrefix]
+
+ except KeyError:
+ models = contexts[contextPrefix] = {}
+
+ try:
+ levels = models[securityModel]
+
+ except KeyError:
+ levels = models[securityModel] = {}
+
+ levels[securityLevel] = viewName
+
+ def _getFamilyViewName(self, groupName, contextName, securityModel, securityLevel, viewType):
+ groups = self._accessMap
+
+ try:
+ views = groups[groupName]
+
+ except KeyError:
+ raise error.StatusInformation(errorIndication=errind.noGroupName)
+
+ try:
+ matches = views[viewType]
+
+ except KeyError:
+ raise error.StatusInformation(errorIndication=errind.noAccessEntry)
+
+ try:
+ # vacmAccessTable #2: exact match shortcut
+ return matches[1][contextName][securityModel][securityLevel]
+
+ except KeyError:
+ pass
+
+ # vacmAccessTable #2: fuzzy look-up
+
+ candidates = []
+
+ for match, names in matches.items():
+
+ for context, models in names.items():
+
+ if match == 1 and contextName != context:
+ continue
+
+ if match == 2 and contextName[:len(context)] != context:
+ continue
+
+ for model, levels in models.items():
+ for level, viewName in levels.items():
+
+ # priorities:
+ # - matching securityModel
+ # - exact context name match
+ # - longer partial match
+ # - highest securityLevel
+ rating = securityModel == model, match == 1, len(context), level
+
+ candidates.append((rating, viewName))
+
+ if not candidates:
+ raise error.StatusInformation(errorIndication=errind.notInView)
+
+ candidates.sort()
+
+ rating, viewName = candidates[0]
+ return viewName
+
def isAccessAllowed(self,
snmpEngine,
securityModel,
@@ -24,118 +135,245 @@
viewType,
contextName,
variableName):
+
mibInstrumController = snmpEngine.msgAndPduDsp.mibInstrumController
debug.logger & debug.flagACL and debug.logger(
- 'isAccessAllowed: securityModel %s, securityName %s, securityLevel %s, viewType %s, contextName %s for variableName %s' % (
- securityModel, securityName, securityLevel, viewType, contextName, variableName))
+ 'isAccessAllowed: securityModel %s, securityName %s, '
+ 'securityLevel %s, viewType %s, contextName %s for '
+ 'variableName %s' % (securityModel, securityName,
+ securityLevel, viewType, contextName,
+ variableName))
- # 3.2.1
- vacmContextEntry, = mibInstrumController.mibBuilder.importSymbols(
- 'SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry')
+ # Rebuild contextName map if changed
- tblIdx = vacmContextEntry.getInstIdFromIndices(contextName)
- try:
- vacmContextEntry.getNode(
- vacmContextEntry.name + (1,) + tblIdx
- ).syntax
+ vacmContextName, = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB', 'vacmContextName')
+
+ if self._contextBranchId != vacmContextName.branchVersionId:
+
+ self._contextMap.clear()
+
+ nextMibNode = vacmContextName
+
+ while True:
+ try:
+ nextMibNode = vacmContextName.getNextNode(nextMibNode.name)
+
+ except NoSuchInstanceError:
+ break
+
+ self._contextMap[nextMibNode.syntax] = True
- except NoSuchInstanceError:
+ self._contextBranchId = vacmContextName.branchVersionId
+
+ # 3.2.1
+ if contextName not in self._contextMap:
raise error.StatusInformation(errorIndication=errind.noSuchContext)
+ # Rebuild groupName map if changed
+
+ vacmGroupName, = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB', 'vacmGroupName')
+
+ if self._groupNameBranchId != vacmGroupName.branchVersionId:
+
+ vacmSecurityToGroupEntry, = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB', 'vacmSecurityToGroupEntry')
+
+ self._groupNameMap.clear()
+
+ nextMibNode = vacmGroupName
+
+ while True:
+ try:
+ nextMibNode = vacmGroupName.getNextNode(nextMibNode.name)
+
+ except NoSuchInstanceError:
+ break
+
+ instId = nextMibNode.name[len(vacmGroupName.name):]
+
+ indices = vacmSecurityToGroupEntry.getIndicesFromInstId(instId)
+
+ self._groupNameMap[indices] = nextMibNode.syntax
+
+ self._groupNameBranchId = vacmGroupName.branchVersionId
+
# 3.2.2
- vacmSecurityToGroupEntry, = mibInstrumController.mibBuilder.importSymbols(
- 'SNMP-VIEW-BASED-ACM-MIB', 'vacmSecurityToGroupEntry')
- tblIdx = vacmSecurityToGroupEntry.getInstIdFromIndices(
- securityModel, securityName
- )
+ indices = securityModel, securityName
try:
- vacmGroupName = vacmSecurityToGroupEntry.getNode(
- vacmSecurityToGroupEntry.name + (3,) + tblIdx
- ).syntax
+ groupName = self._groupNameMap[indices]
- except NoSuchInstanceError:
+ except KeyError:
raise error.StatusInformation(errorIndication=errind.noGroupName)
- # 3.2.3
- vacmAccessEntry, = mibInstrumController.mibBuilder.importSymbols(
- 'SNMP-VIEW-BASED-ACM-MIB', 'vacmAccessEntry'
- )
-
- # XXX partial context name match
- tblIdx = vacmAccessEntry.getInstIdFromIndices(
- vacmGroupName, contextName, securityModel, securityLevel
- )
-
- # 3.2.4
- if viewType == 'read':
- entryIdx = vacmAccessEntry.name + (5,) + tblIdx
- elif viewType == 'write':
- entryIdx = vacmAccessEntry.name + (6,) + tblIdx
- elif viewType == 'notify':
- entryIdx = vacmAccessEntry.name + (7,) + tblIdx
- else:
- raise error.ProtocolError('Unknown view type %s' % viewType)
+ # Rebuild access map if changed
- try:
- viewName = vacmAccessEntry.getNode(entryIdx).syntax
+ vacmAccessStatus, = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB', 'vacmAccessStatus')
- except NoSuchInstanceError:
- raise error.StatusInformation(errorIndication=errind.noAccessEntry)
+ if self._accessBranchId != vacmAccessStatus.branchVersionId:
+
+ (vacmAccessEntry,
+ vacmAccessContextPrefix,
+ vacmAccessSecurityModel,
+ vacmAccessSecurityLevel,
+ vacmAccessContextMatch,
+ vacmAccessReadViewName,
+ vacmAccessWriteViewName,
+ vacmAccessNotifyViewName) = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB',
+ 'vacmAccessEntry',
+ 'vacmAccessContextPrefix',
+ 'vacmAccessSecurityModel',
+ 'vacmAccessSecurityLevel',
+ 'vacmAccessContextMatch',
+ 'vacmAccessReadViewName',
+ 'vacmAccessWriteViewName',
+ 'vacmAccessNotifyViewName')
+
+ self._accessMap.clear()
+
+ nextMibNode = vacmAccessStatus
+
+ while True:
+ try:
+ nextMibNode = vacmAccessStatus.getNextNode(nextMibNode.name)
+
+ except NoSuchInstanceError:
+ break
+
+ if nextMibNode.syntax != 1: # active row
+ continue
+
+ instId = nextMibNode.name[len(vacmAccessStatus.name):]
+
+ indices = vacmAccessEntry.getIndicesFromInstId(instId)
+
+ vacmGroupName = indices[0]
+
+ self._addAccessEntry(
+ vacmGroupName,
+ vacmAccessContextPrefix.getNode(
+ vacmAccessContextPrefix.name + instId).syntax,
+ vacmAccessSecurityModel.getNode(
+ vacmAccessSecurityModel.name + instId).syntax,
+ vacmAccessSecurityLevel.getNode(
+ vacmAccessSecurityLevel.name + instId).syntax,
+ vacmAccessContextMatch.getNode(
+ vacmAccessContextMatch.name + instId).syntax,
+ vacmAccessReadViewName.getNode(
+ vacmAccessReadViewName.name + instId).syntax,
+ vacmAccessWriteViewName.getNode(
+ vacmAccessWriteViewName.name + instId).syntax,
+ vacmAccessNotifyViewName.getNode(
+ vacmAccessNotifyViewName.name + instId).syntax
+ )
+
+ self._accessBranchId = vacmAccessStatus.branchVersionId
+
+ viewName = self._getFamilyViewName(
+ groupName, contextName, securityModel, securityLevel, viewType)
+
+ # Rebuild family subtree map if changed
+
+ vacmViewTreeFamilyViewName, = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB', 'vacmViewTreeFamilyViewName')
+
+ if self._viewTreeBranchId != vacmViewTreeFamilyViewName.branchVersionId:
+
+ (vacmViewTreeFamilySubtree,
+ vacmViewTreeFamilyMask,
+ vacmViewTreeFamilyType) = mibInstrumController.mibBuilder.importSymbols(
+ 'SNMP-VIEW-BASED-ACM-MIB',
+ 'vacmViewTreeFamilySubtree',
+ 'vacmViewTreeFamilyMask',
+ 'vacmViewTreeFamilyType')
+
+ self._viewTreeMap.clear()
- if not viewName:
- raise error.StatusInformation(errorIndication=errind.noSuchView)
+ powerOfTwo = [2 ** exp for exp in range(7, -1, -1)]
- # XXX split onto object & instance ?
+ nextMibNode = vacmViewTreeFamilyViewName
+
+ while True:
+ try:
+ nextMibNode = vacmViewTreeFamilyViewName.getNextNode(
+ nextMibNode.name)
+
+ except NoSuchInstanceError:
+ break
+
+ if nextMibNode.syntax not in self._viewTreeMap:
+ self._viewTreeMap[nextMibNode.syntax] = []
+
+ instId = nextMibNode.name[len(vacmViewTreeFamilyViewName.name):]
+
+ subtree = vacmViewTreeFamilySubtree.getNode(
+ vacmViewTreeFamilySubtree.name + instId).syntax
+
+ mask = vacmViewTreeFamilyMask.getNode(
+ vacmViewTreeFamilyMask.name + instId).syntax
+
+ mode = vacmViewTreeFamilyType.getNode(
+ vacmViewTreeFamilyType.name + instId).syntax
+
+ mask = mask.asNumbers()
+ maskLength = min(len(mask) * 8, len(subtree))
+
+ ignoredSubOids = [
+ i * 8 + j for i, octet in enumerate(mask)
+ for j, bit in enumerate(powerOfTwo)
+ if not (bit & octet) and i * 8 + j < maskLength
+ ]
+
+ if ignoredSubOids:
+ pattern = list(subtree)
+
+ for ignoredSubOid in ignoredSubOids:
+ pattern[ignoredSubOid] = 0
+
+ subtree = subtree.clone(pattern)
+
+ entry = subtree, ignoredSubOids, mode == 1
+
+ self._viewTreeMap[nextMibNode.syntax].append(entry)
+
+ for entries in self._viewTreeMap.values():
+ entries.sort(key=lambda x: (len(x[0]), x[0]))
+
+ self._viewTreeBranchId = vacmViewTreeFamilyViewName.branchVersionId
# 3.2.5a
- vacmViewTreeFamilyEntry, = mibInstrumController.mibBuilder.importSymbols(
- 'SNMP-VIEW-BASED-ACM-MIB', 'vacmViewTreeFamilyEntry')
- tblIdx = vacmViewTreeFamilyEntry.getInstIdFromIndices(viewName)
-
- # Walk over entries
- initialTreeName = treeName = vacmViewTreeFamilyEntry.name + (2,) + tblIdx
- maskName = vacmViewTreeFamilyEntry.name + (3,) + tblIdx
-
- while True:
- vacmViewTreeFamilySubtree = vacmViewTreeFamilyEntry.getNextNode(
- treeName
- )
- vacmViewTreeFamilyMask = vacmViewTreeFamilyEntry.getNextNode(
- maskName
- )
-
- treeName = vacmViewTreeFamilySubtree.name
- maskName = vacmViewTreeFamilyMask.name
-
- if initialTreeName != treeName[:len(initialTreeName)]:
- # 3.2.5b
- raise error.StatusInformation(errorIndication=errind.notInView)
-
- l = len(vacmViewTreeFamilySubtree.syntax)
- if l > len(variableName):
- continue
-
- if vacmViewTreeFamilyMask.syntax:
- mask = []
- for c in vacmViewTreeFamilyMask.syntax.asNumbers():
- mask.extend([b & c for b in self._powOfTwoSeq])
-
- m = len(mask) - 1
- idx = l - 1
- while idx:
- if (idx > m or mask[idx] and
- vacmViewTreeFamilySubtree.syntax[idx] != variableName[idx]):
- break
- idx -= 1
-
- if idx:
- continue # no match
-
- else: # no mask
- if vacmViewTreeFamilySubtree.syntax != variableName[:l]:
- continue # no match
+ indices = viewName
+
+ try:
+ entries = self._viewTreeMap[indices]
+
+ except KeyError:
+ return error.StatusInformation(errorIndication=errind.notInView)
+
+ accessAllowed = False
+
+ for entry in entries:
+ subtree, ignoredSubOids, included = entry
+
+ if ignoredSubOids:
+ subOids = list(variableName)
+
+ for ignoredSubOid in ignoredSubOids:
+ subOids[ignoredSubOid] = 0
+
+ normalizedVariableName = subtree.clone(subOids)
+
+ else:
+ normalizedVariableName = variableName
+
+ if subtree.isPrefixOf(normalizedVariableName):
+ accessAllowed = included
- # 3.2.5c
- return error.StatusInformation(errorIndication=errind.accessAllowed)
+ # 3.2.5c
+ if not accessAllowed:
+ raise error.StatusInformation(errorIndication=errind.notInView)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/proto/api/v1.py new/pysnmp-4.4.10/pysnmp/proto/api/v1.py
--- old/pysnmp-4.4.9/pysnmp/proto/api/v1.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/proto/api/v1.py 2019-07-30 20:29:22.000000000 +0200
@@ -66,7 +66,8 @@
pdu.setComponentByPosition(
2, self._errorIndex, verifyConstraints=False, matchTags=False, matchConstraints=False
)
- pdu.setComponentByPosition(3)
+ varBindList = pdu.setComponentByPosition(3).getComponentByPosition(3)
+ varBindList.clear()
@staticmethod
def getRequestID(pdu):
@@ -170,7 +171,8 @@
pdu.setComponentByPosition(2, self._genericTrap, verifyConstraints=False, matchTags=False, matchConstraints=False)
pdu.setComponentByPosition(3, self._zeroInt, verifyConstraints=False, matchTags=False, matchConstraints=False)
pdu.setComponentByPosition(4, self._zeroTime, verifyConstraints=False, matchTags=False, matchConstraints=False)
- pdu.setComponentByPosition(5)
+ varBindList = pdu.setComponentByPosition(5).getComponentByPosition(5)
+ varBindList.clear()
@staticmethod
def getEnterprise(pdu):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/proto/api/v2c.py new/pysnmp-4.4.10/pysnmp/proto/api/v2c.py
--- old/pysnmp-4.4.9/pysnmp/proto/api/v2c.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/proto/api/v2c.py 2019-07-30 20:29:22.000000000 +0200
@@ -91,7 +91,8 @@
pdu.setComponentByPosition(
2, self._maxRepetitions, verifyConstraints=False, matchTags=False, matchConstraints=False
)
- pdu.setComponentByPosition(3)
+ varBindList = pdu.setComponentByPosition(3).getComponentByPosition(3)
+ varBindList.clear()
@staticmethod
def getNonRepeaters(pdu):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/proto/proxy/rfc2576.py new/pysnmp-4.4.10/pysnmp/proto/proxy/rfc2576.py
--- old/pysnmp-4.4.9/pysnmp/proto/proxy/rfc2576.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/proto/proxy/rfc2576.py 2019-07-30 20:29:22.000000000 +0200
@@ -142,15 +142,17 @@
(oid, __v1ToV2ValueMap[v1Val.tagSet].clone(v1Val))
)
- if pduType in rfc3411.responseClassPDUs:
- # 4.1.2.2.1&2
+ if pduType not in rfc3411.notificationClassPDUs:
errorStatus = int(v1.apiPDU.getErrorStatus(v1Pdu))
errorIndex = int(v1.apiPDU.getErrorIndex(v1Pdu, muteErrors=True))
- if errorStatus == 2: # noSuchName
- if origV2Pdu.tagSet == v2c.GetNextRequestPDU.tagSet:
- v2VarBinds = [(o, rfc1905.endOfMibView) for o, v in v2VarBinds]
- else:
- v2VarBinds = [(o, rfc1905.noSuchObject) for o, v in v2VarBinds]
+
+ if pduType in rfc3411.responseClassPDUs:
+ # 4.1.2.2.1&2
+ if errorStatus == 2: # noSuchName
+ if origV2Pdu.tagSet == v2c.GetNextRequestPDU.tagSet:
+ v2VarBinds = [(o, rfc1905.endOfMibView) for o, v in v2VarBinds]
+ else:
+ v2VarBinds = [(o, rfc1905.noSuchObject) for o, v in v2VarBinds]
# partial one-to-one mapping - 4.2.1
v2c.apiPDU.setErrorStatus(v2Pdu, errorStatus)
@@ -158,13 +160,11 @@
# 4.1.2.1 --> no-op
- elif pduType in rfc3411.confirmedClassPDUs:
- v2c.apiPDU.setErrorStatus(v2Pdu, 0)
- v2c.apiPDU.setErrorIndex(v2Pdu, 0)
-
- if pduType not in rfc3411.notificationClassPDUs:
v2c.apiPDU.setRequestID(v2Pdu, int(v1.apiPDU.getRequestID(v1Pdu)))
+ else:
+ v2c.apiPDU.setDefaults(v2Pdu)
+
v2c.apiPDU.setVarBinds(v2Pdu, v2VarBinds)
debug.logger & debug.flagPrx and debug.logger('v1ToV2: v2Pdu %s' % v2Pdu.prettyPrint())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pysnmp-4.4.9/pysnmp/smi/builder.py new/pysnmp-4.4.10/pysnmp/smi/builder.py
--- old/pysnmp-4.4.9/pysnmp/smi/builder.py 2019-02-09 16:02:16.000000000 +0100
+++ new/pysnmp-4.4.10/pysnmp/smi/builder.py 2019-07-30 20:29:22.000000000 +0200
@@ -6,16 +6,38 @@
#
import os
import sys
-import imp
import struct
import marshal
import time
import traceback
try:
+ import importlib
+
+ try:
+ PY_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER
+ SOURCE_SUFFIXES = importlib.machinery.SOURCE_SUFFIXES
+ BYTECODE_SUFFIXES = importlib.machinery.BYTECODE_SUFFIXES
+
+ except Exception:
+ raise ImportError()
+
+except ImportError:
+ import imp
+
+ PY_MAGIC_NUMBER = imp.get_magic()
+ SOURCE_SUFFIXES = [s[0] for s in imp.get_suffixes()
+ if s[2] == imp.PY_SOURCE]
+ BYTECODE_SUFFIXES = [s[0] for s in imp.get_suffixes()
+ if s[2] == imp.PY_COMPILED]
+
+PY_SUFFIXES = SOURCE_SUFFIXES + BYTECODE_SUFFIXES
+
+try:
from errno import ENOENT
except ImportError:
ENOENT = -1
+
from pysnmp import version as pysnmp_version
from pysnmp.smi import error
from pysnmp import debug
@@ -31,13 +53,7 @@
class __AbstractMibSource(object):
def __init__(self, srcName):
self._srcName = srcName
- self.__magic = imp.get_magic()
- self.__sfx = {}
self.__inited = None
- for sfx, mode, typ in imp.get_suffixes():
- if typ not in self.__sfx:
- self.__sfx[typ] = []
- self.__sfx[typ].append((sfx, len(sfx), mode))
debug.logger & debug.flagBld and debug.logger('trying %s' % self)
def __repr__(self):
@@ -45,13 +61,13 @@
def _uniqNames(self, files):
u = set()
+
for f in files:
if f.startswith('__init__.'):
continue
- for typ in (imp.PY_SOURCE, imp.PY_COMPILED):
- for sfx, sfxLen, mode in self.__sfx[typ]:
- if f[-sfxLen:] == sfx:
- u.add(f[:-sfxLen])
+
+ u.update(f[:-len(sfx)] for sfx in PY_SUFFIXES if f.endswith(sfx))
+
return tuple(u)
# MibSource API follows
@@ -76,9 +92,10 @@
def read(self, f):
pycTime = pyTime = -1
- for pycSfx, pycSfxLen, pycMode in self.__sfx[imp.PY_COMPILED]:
+ for pycSfx in BYTECODE_SUFFIXES:
+
try:
- pycData, pycPath = self._getData(f + pycSfx, pycMode)
+ pycData, pycPath = self._getData(f + pycSfx, 'rb')
except IOError:
why = sys.exc_info()[1]
@@ -91,7 +108,7 @@
raise error.MibLoadError('MIB file %s access error: %s' % (f + pycSfx, why))
else:
- if self.__magic == pycData[:4]:
+ if PY_MAGIC_NUMBER == pycData[:4]:
pycData = pycData[4:]
pycTime = struct.unpack('