the SnmpV3MessageProcessingModel.getPeerEngineInfo() method is implemented
to communicate discovered peer SNMP engine information to SNMP apps what can be used for fine usmUserTable configuration.pull/45/head
parent
bdaef1032a
commit
a0894c9008
|
@ -42,6 +42,9 @@ Revision 4.2.5rc2
|
|||
renamed into securityEngineId as it's semantically correct
|
||||
- Oneliner transport target classes now support the getTransportInfo()
|
||||
method that returns network addresses used on protocol level.
|
||||
- The SnmpV3MessageProcessingModel.getPeerEngineInfo() method is implemented
|
||||
to communicate discovered peer SNMP engine information to SNMP apps what
|
||||
can be used for fine usmUserTable configuration.
|
||||
- AsynNotificationOriginator.cfgCmdGen() does not take into account
|
||||
securityModel & securityLevel when reducing LCD access via addTrapUser().
|
||||
This improves LCD consistency on sparse add/del operatons but also
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# Command Generator
|
||||
#
|
||||
# Send SNMP GET request using the following scenario and options:
|
||||
#
|
||||
# * try to communicate with a SNMPv3 Engine using:
|
||||
# ** a non-existing user
|
||||
# ** over IPv4/UDP
|
||||
# ** to an Agent at demo.snmplabs.com:161
|
||||
# * if remote SNMP Engine ID is discovered, send SNMP GET request:
|
||||
# ** with SNMPv3, user 'usr-md5-none', MD5 authentication, no privacy
|
||||
# at discovered securityEngineId
|
||||
# ** to the same SNMP Engine ID
|
||||
# ** for an OID in text form
|
||||
#
|
||||
from pysnmp.entity import engine
|
||||
from pysnmp.entity.rfc3413.oneliner import cmdgen
|
||||
|
||||
snmpEngine = engine.SnmpEngine()
|
||||
|
||||
cmdGen = cmdgen.CommandGenerator(snmpEngine)
|
||||
|
||||
transportTarget = cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161))
|
||||
|
||||
#
|
||||
# Discover remote SNMP EngineID
|
||||
#
|
||||
|
||||
authData = cmdgen.UsmUserData('non-existing-user')
|
||||
|
||||
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
|
||||
authData, transportTarget
|
||||
)
|
||||
|
||||
# Check for errors and print out results
|
||||
if errorIndication == 'unknownUserName':
|
||||
snmpV3MessageProcessor = snmpEngine.messageProcessingSubsystems[3]
|
||||
securityEngineId, contextEngineId, contextName = snmpV3MessageProcessor.getPeerEngineInfo(*transportTarget.getTransportInfo())
|
||||
if securityEngineId:
|
||||
print('securityEngineId = %s' % securityEngineId.prettyPrint())
|
||||
else:
|
||||
print('Peer EngineID not available')
|
||||
raise Exception()
|
||||
else:
|
||||
print('Can\'t discover peer EngineID', errorIndication)
|
||||
raise Exception()
|
||||
|
||||
#
|
||||
# Query remote SNMP Engine using usmUserTable entry configured for it
|
||||
#
|
||||
|
||||
authData = cmdgen.UsmUserData('usr-md5-none', 'authkey1',
|
||||
securityEngineId=securityEngineId)
|
||||
|
||||
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
|
||||
authData, transportTarget, '1.3.6.1.2.1.1.1.0'
|
||||
)
|
||||
|
||||
# Check for errors and print out results
|
||||
if errorIndication:
|
||||
print(errorIndication)
|
||||
else:
|
||||
if errorStatus:
|
||||
print('%s at %s' % (
|
||||
errorStatus.prettyPrint(),
|
||||
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
|
||||
)
|
||||
)
|
||||
else:
|
||||
for name, val in varBinds:
|
||||
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
|
|
@ -67,10 +67,19 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
def __init__(self):
|
||||
AbstractMessageProcessingModel.__init__(self)
|
||||
self.__scopedPDU = ScopedPDU()
|
||||
self.__engineIDs = {}
|
||||
self.__engineIDsExpQueue = {}
|
||||
self.__engineIdCache = {}
|
||||
self.__engineIdCacheExpQueue = {}
|
||||
self.__expirationTimer = 0
|
||||
|
||||
|
||||
def getPeerEngineInfo(self, transportDomain, transportAddress):
|
||||
k = transportDomain, transportAddress
|
||||
if k in self.__engineIdCache:
|
||||
return self.__engineIdCache[k]['securityEngineId'], \
|
||||
self.__engineIdCache[k]['contextEngineId'], \
|
||||
self.__engineIdCache[k]['contextName']
|
||||
else:
|
||||
return None, None, None
|
||||
|
||||
# 7.1.1a
|
||||
def prepareOutgoingMessage(
|
||||
self,
|
||||
|
@ -97,8 +106,8 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
debug.logger & debug.flagMP and debug.logger('prepareOutgoingMessage: new msgID %s' % msgID)
|
||||
|
||||
k = (transportDomain, transportAddress)
|
||||
if k in self.__engineIDs:
|
||||
peerSnmpEngineData = self.__engineIDs[k]
|
||||
if k in self.__engineIdCache:
|
||||
peerSnmpEngineData = self.__engineIdCache[k]
|
||||
else:
|
||||
peerSnmpEngineData = None
|
||||
|
||||
|
@ -110,11 +119,11 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
contextEngineId = snmpEngineID
|
||||
else:
|
||||
contextEngineId = peerSnmpEngineData['contextEngineId']
|
||||
# Defaulting contextEngineID to securityEngineID should
|
||||
# Defaulting contextEngineID to securityEngineId should
|
||||
# probably be done on Agent side (see 7.1.3.d.2,) so this
|
||||
# is a sort of workaround.
|
||||
if not contextEngineId:
|
||||
contextEngineId = peerSnmpEngineData['securityEngineID']
|
||||
contextEngineId = peerSnmpEngineData['securityEngineId']
|
||||
# 7.1.5
|
||||
if not contextName:
|
||||
contextName = self._emptyStr
|
||||
|
@ -185,11 +194,11 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
|
||||
# 7.1.9.a
|
||||
if pdu.tagSet in rfc3411.unconfirmedClassPDUs:
|
||||
securityEngineID = snmpEngineID
|
||||
securityEngineId = snmpEngineID
|
||||
else:
|
||||
if peerSnmpEngineData is None:
|
||||
# Force engineID discovery (rfc3414, 4)
|
||||
securityEngineID = securityName = self._emptyStr
|
||||
securityEngineId = securityName = self._emptyStr
|
||||
securityLevel = 1
|
||||
# Clear possible auth&priv flags
|
||||
headerData.setComponentByPosition(
|
||||
|
@ -212,9 +221,9 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
)
|
||||
debug.logger & debug.flagMP and debug.logger('prepareOutgoingMessage: force engineID discovery')
|
||||
else:
|
||||
securityEngineID = peerSnmpEngineData['securityEngineID']
|
||||
securityEngineId = peerSnmpEngineData['securityEngineId']
|
||||
|
||||
debug.logger & debug.flagMP and debug.logger('prepareOutgoingMessage: securityModel %r, securityEngineID %r, securityName %r, securityLevel %r' % (securityModel, securityEngineID, securityName, securityLevel))
|
||||
debug.logger & debug.flagMP and debug.logger('prepareOutgoingMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r' % (securityModel, securityEngineId, securityName, securityLevel))
|
||||
|
||||
# 7.1.9.b
|
||||
( securityParameters,
|
||||
|
@ -224,7 +233,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
msg,
|
||||
snmpEngineMaxMessageSize.syntax,
|
||||
securityModel,
|
||||
securityEngineID,
|
||||
securityEngineId,
|
||||
securityName,
|
||||
securityLevel,
|
||||
scopedPDU
|
||||
|
@ -417,7 +426,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
errorIndication = errind.unsupportedSecurityModel
|
||||
)
|
||||
|
||||
debug.logger & debug.flagMP and debug.logger('prepareResponseMessage: securityModel %r, securityEngineID %r, securityName %r, securityLevel %r' % (securityModel, snmpEngineID, securityName, securityLevel))
|
||||
debug.logger & debug.flagMP and debug.logger('prepareResponseMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r' % (securityModel, snmpEngineID, securityName, securityLevel))
|
||||
|
||||
# 7.1.8a
|
||||
try:
|
||||
|
@ -511,7 +520,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
# 7.2.6
|
||||
smHandler = snmpEngine.securityModels[securityModel]
|
||||
try:
|
||||
( securityEngineID,
|
||||
( securityEngineId,
|
||||
securityName,
|
||||
scopedPDU,
|
||||
maxSizeResponseScopedPDU,
|
||||
|
@ -598,26 +607,26 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
# (seems to be irrelevant on Py3 but just in case)
|
||||
del origTraceback
|
||||
else:
|
||||
# Sniff for engineIDs
|
||||
# Sniff for engineIdCache
|
||||
k = (transportDomain, transportAddress)
|
||||
if k not in self.__engineIDs:
|
||||
if k not in self.__engineIdCache:
|
||||
contextEngineId, contextName, pdus = scopedPDU
|
||||
pdu = pdus.getComponent()
|
||||
# Here we assume that authentic/default EngineIDs
|
||||
# come only in the course of engine-to-engine communication.
|
||||
if pdu.tagSet in rfc3411.internalClassPDUs:
|
||||
self.__engineIDs[k] = {
|
||||
'securityEngineID': securityEngineID,
|
||||
self.__engineIdCache[k] = {
|
||||
'securityEngineId': securityEngineId,
|
||||
'contextEngineId': contextEngineId,
|
||||
'contextName': contextName
|
||||
}
|
||||
}
|
||||
|
||||
expireAt = int(self.__expirationTimer + 300 / snmpEngine.transportDispatcher.getTimerResolution())
|
||||
if expireAt not in self.__engineIDsExpQueue:
|
||||
self.__engineIDsExpQueue[expireAt] = []
|
||||
self.__engineIDsExpQueue[expireAt].append(k)
|
||||
if expireAt not in self.__engineIdCacheExpQueue:
|
||||
self.__engineIdCacheExpQueue[expireAt] = []
|
||||
self.__engineIdCacheExpQueue[expireAt].append(k)
|
||||
|
||||
debug.logger & debug.flagMP and debug.logger('prepareDataElements: cache securityEngineID %r for %r %r' % (securityEngineID, transportDomain, transportAddress))
|
||||
debug.logger & debug.flagMP and debug.logger('prepareDataElements: cache securityEngineId %r for %r %r' % (securityEngineId, transportDomain, transportAddress))
|
||||
|
||||
snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
|
||||
snmpEngineID = snmpEngineID.syntax
|
||||
|
@ -714,7 +723,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
# 7.2.13
|
||||
if pduType in rfc3411.confirmedClassPDUs:
|
||||
# 7.2.13a
|
||||
if securityEngineID != snmpEngineID:
|
||||
if securityEngineId != snmpEngineID:
|
||||
smHandler.releaseStateInformation(securityStateReference)
|
||||
raise error.StatusInformation(
|
||||
errorIndication = errind.engineIDMismatch
|
||||
|
@ -784,11 +793,11 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel):
|
|||
)
|
||||
|
||||
def __expireEnginesInfo(self):
|
||||
if self.__expirationTimer in self.__engineIDsExpQueue:
|
||||
for engineKey in self.__engineIDsExpQueue[self.__expirationTimer]:
|
||||
del self.__engineIDs[engineKey]
|
||||
if self.__expirationTimer in self.__engineIdCacheExpQueue:
|
||||
for engineKey in self.__engineIdCacheExpQueue[self.__expirationTimer]:
|
||||
del self.__engineIdCache[engineKey]
|
||||
debug.logger & debug.flagMP and debug.logger('__expireEnginesInfo: expiring %r' % (engineKey,))
|
||||
del self.__engineIDsExpQueue[self.__expirationTimer]
|
||||
del self.__engineIdCacheExpQueue[self.__expirationTimer]
|
||||
self.__expirationTimer = self.__expirationTimer + 1
|
||||
|
||||
def receiveTimerTick(self, snmpEngine, timeNow):
|
||||
|
|
Loading…
Reference in New Issue