diff options
author | Ilya Etingof <etingof@gmail.com> | 2019-02-26 08:56:24 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-26 08:56:24 +0100 |
commit | 3f2f132a9fdf7a48ec6131d5498145dded3cfcad (patch) | |
tree | 63e6170b35f6b392bf2e3d3feb6996b886e4d36f /pysnmp/proto | |
parent | 2ad26f8bfef0e39b3789d9e6d4fcbf76820c9867 (diff) | |
download | pysnmp-git-3f2f132a9fdf7a48ec6131d5498145dded3cfcad.tar.gz |
PEP-8 long lines and dunders (#245)
This patch massively reformats the whole codebase mainly wrapping
long lines and eliminating dundered private attributes.
Diffstat (limited to 'pysnmp/proto')
31 files changed, 1786 insertions, 1153 deletions
diff --git a/pysnmp/proto/acmod/rfc3415.py b/pysnmp/proto/acmod/rfc3415.py index fb4c4adf..13d9de12 100644 --- a/pysnmp/proto/acmod/rfc3415.py +++ b/pysnmp/proto/acmod/rfc3415.py @@ -17,65 +17,63 @@ class Vacm(object): _powOfTwoSeq = (128, 64, 32, 16, 8, 4, 2, 1) - def isAccessAllowed(self, - snmpEngine, - securityModel, - securityName, - securityLevel, - viewType, - contextName, - variableName): + def isAccessAllowed(self, snmpEngine, securityModel, securityName, + securityLevel, viewType, contextName, variableName): + mibInstrumController = snmpEngine.msgAndPduDsp.mibInstrumController + mibBuilder = mibInstrumController.mibBuilder debug.logger & debug.FLAG_ACL 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( + vacmContextEntry, = mibBuilder.importSymbols( 'SNMP-VIEW-BASED-ACM-MIB', 'vacmContextEntry') tblIdx = vacmContextEntry.getInstIdFromIndices(contextName) + try: vacmContextEntry.getNode( - vacmContextEntry.name + (1,) + tblIdx - ).syntax + vacmContextEntry.name + (1,) + tblIdx).syntax except NoSuchInstanceError: raise error.StatusInformation(errorIndication=errind.noSuchContext) # 3.2.2 - vacmSecurityToGroupEntry, = mibInstrumController.mibBuilder.importSymbols( + vacmSecurityToGroupEntry, = mibBuilder.importSymbols( 'SNMP-VIEW-BASED-ACM-MIB', 'vacmSecurityToGroupEntry') + tblIdx = vacmSecurityToGroupEntry.getInstIdFromIndices( - securityModel, securityName - ) + securityModel, securityName) try: vacmGroupName = vacmSecurityToGroupEntry.getNode( - vacmSecurityToGroupEntry.name + (3,) + tblIdx - ).syntax + vacmSecurityToGroupEntry.name + (3,) + tblIdx).syntax except NoSuchInstanceError: raise error.StatusInformation(errorIndication=errind.noGroupName) # 3.2.3 - vacmAccessEntry, = mibInstrumController.mibBuilder.importSymbols( - 'SNMP-VIEW-BASED-ACM-MIB', 'vacmAccessEntry' - ) + vacmAccessEntry, = mibBuilder.importSymbols( + 'SNMP-VIEW-BASED-ACM-MIB', 'vacmAccessEntry') # XXX partial context name match tblIdx = vacmAccessEntry.getInstIdFromIndices( - vacmGroupName, contextName, securityModel, securityLevel - ) + 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) @@ -93,19 +91,20 @@ class Vacm(object): # 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 - ) + treeName) + vacmViewTreeFamilyMask = vacmViewTreeFamilyEntry.getNextNode( - maskName - ) + maskName) treeName = vacmViewTreeFamilySubtree.name maskName = vacmViewTreeFamilyMask.name @@ -125,10 +124,12 @@ class Vacm(object): 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: diff --git a/pysnmp/proto/acmod/void.py b/pysnmp/proto/acmod/void.py index 2f8c4e97..e3ee848f 100644 --- a/pysnmp/proto/acmod/void.py +++ b/pysnmp/proto/acmod/void.py @@ -15,17 +15,11 @@ class Vacm(object): """Void Access Control Model""" ACCESS_MODEL_ID = 0 - def isAccessAllowed(self, - snmpEngine, - securityModel, - securityName, - securityLevel, - viewType, - contextName, - variableName): + def isAccessAllowed(self, snmpEngine, securityModel, securityName, + securityLevel, viewType, contextName, variableName): debug.logger & debug.FLAG_ACL and debug.logger( - 'isAccessAllowed: viewType %s for variableName %s - OK' % (viewType, variableName) - ) + 'isAccessAllowed: viewType %s for variableName ' + '%s - OK' % (viewType, variableName)) # rfc3415 3.2.5c return error.StatusInformation(errorIndication=errind.accessAllowed) diff --git a/pysnmp/proto/api/v1.py b/pysnmp/proto/api/v1.py index 827a6a0d..f13920e7 100644 --- a/pysnmp/proto/api/v1.py +++ b/pysnmp/proto/api/v1.py @@ -39,10 +39,18 @@ class VarBindAPI(object): @staticmethod def setOIDVal(varBind, oidVal): oid, val = oidVal[0], oidVal[1] + varBind.setComponentByPosition(0, oid) + if val is None: val = null - varBind.setComponentByPosition(1).getComponentByPosition(1).setComponentByType(val.getTagSet(), val, verifyConstraints=False, matchTags=False, matchConstraints=False, innerFlag=True) + + (varBind.setComponentByPosition(1) + .getComponentByPosition(1) + .setComponentByType(val.getTagSet(), val, + verifyConstraints=False, matchTags=False, + matchConstraints=False, innerFlag=True)) + return varBind @staticmethod @@ -61,14 +69,17 @@ class PDUAPI(object): def setDefaults(self, pdu): pdu.setComponentByPosition( - 0, getNextRequestID(), verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, getNextRequestID(), verifyConstraints=False, matchTags=False, + matchConstraints=False) + pdu.setComponentByPosition( - 1, self._errorStatus, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, self._errorStatus, verifyConstraints=False, matchTags=False, + matchConstraints=False) + pdu.setComponentByPosition( - 2, self._errorIndex, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 2, self._errorIndex, verifyConstraints=False, matchTags=False, + matchConstraints=False) + pdu.setComponentByPosition(3) @staticmethod @@ -90,12 +101,14 @@ class PDUAPI(object): @staticmethod def getErrorIndex(pdu, muteErrors=False): errorIndex = pdu.getComponentByPosition(2) + if errorIndex > len(pdu[3]): if muteErrors: return errorIndex.clone(len(pdu[3])) + raise error.ProtocolError( - 'Error index out of range: %s > %s' % (errorIndex, len(pdu[3])) - ) + 'Error index out of range: %s > %s' % (errorIndex, len(pdu[3]))) + return errorIndex @staticmethod @@ -119,20 +132,23 @@ class PDUAPI(object): @staticmethod def getVarBinds(pdu): - return [apiVarBind.getOIDVal(varBind) for varBind in pdu.getComponentByPosition(3)] + return [apiVarBind.getOIDVal(varBind) + for varBind in pdu.getComponentByPosition(3)] @staticmethod def setVarBinds(pdu, varBinds): varBindList = pdu.setComponentByPosition(3).getComponentByPosition(3) + varBindList.clear() + for idx, varBind in enumerate(varBinds): if isinstance(varBind, VarBind): varBindList.setComponentByPosition(idx, varBind) + else: varBindList.setComponentByPosition(idx) apiVarBind.setOIDVal( - varBindList.getComponentByPosition(idx), varBind - ) + varBindList.getComponentByPosition(idx), varBind) def getResponse(self, reqPDU): rspPDU = GetResponsePDU() @@ -143,8 +159,10 @@ class PDUAPI(object): def getVarBindTable(self, reqPDU, rspPDU): if apiPDU.getErrorStatus(rspPDU) == 2: varBindRow = [(vb[0], null) for vb in apiPDU.getVarBinds(reqPDU)] + else: varBindRow = apiPDU.getVarBinds(rspPDU) + return [varBindRow] def getNextVarBinds(self, varBinds, errorIndex=None): @@ -173,14 +191,32 @@ class TrapPDUAPI(object): try: import socket agentAddress = IpAddress(socket.gethostbyname(socket.gethostname())) + except Exception: agentAddress = IpAddress('0.0.0.0') + self._networkAddress = NetworkAddress().setComponentByPosition(0, agentAddress) - pdu.setComponentByPosition(0, self._entOid, verifyConstraints=False, matchTags=False, matchConstraints=False) - pdu.setComponentByPosition(1, self._networkAddress, verifyConstraints=False, matchTags=False, matchConstraints=False) - 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( + 0, self._entOid, verifyConstraints=False, matchTags=False, + matchConstraints=False) + + pdu.setComponentByPosition( + 1, self._networkAddress, verifyConstraints=False, matchTags=False, + matchConstraints=False) + + 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) @staticmethod @@ -197,7 +233,9 @@ class TrapPDUAPI(object): @staticmethod def setAgentAddr(pdu, value): - pdu.setComponentByPosition(1).getComponentByPosition(1).setComponentByPosition(0, value) + (pdu.setComponentByPosition(1) + .getComponentByPosition(1) + .setComponentByPosition(0, value)) @staticmethod def getGenericTrap(pdu): @@ -233,24 +271,28 @@ class TrapPDUAPI(object): @staticmethod def getVarBinds(pdu): - varBinds = [] - for varBind in pdu.getComponentByPosition(5): - varBinds.append(apiVarBind.getOIDVal(varBind)) - return varBinds + return [apiVarBind.getOIDVal(varBind) + for varBind in pdu.getComponentByPosition(5)] @staticmethod def setVarBinds(pdu, varBinds): varBindList = pdu.setComponentByPosition(5).getComponentByPosition(5) + varBindList.clear() + idx = 0 + for varBind in varBinds: if isinstance(varBind, VarBind): varBindList.setComponentByPosition(idx, varBind) + else: varBindList.setComponentByPosition(idx) + apiVarBind.setOIDVal( varBindList.getComponentByPosition(idx), varBind ) + idx += 1 @@ -262,8 +304,14 @@ class MessageAPI(object): _community = univ.OctetString('public') def setDefaults(self, msg): - msg.setComponentByPosition(0, self._version, verifyConstraints=False, matchTags=False, matchConstraints=False) - msg.setComponentByPosition(1, self._community, verifyConstraints=False, matchTags=False, matchConstraints=False) + msg.setComponentByPosition( + 0, self._version, verifyConstraints=False, matchTags=False, + matchConstraints=False) + + msg.setComponentByPosition( + 1, self._community, verifyConstraints=False, matchTags=False, + matchConstraints=False) + return msg @staticmethod @@ -288,14 +336,20 @@ class MessageAPI(object): @staticmethod def setPDU(msg, value): - msg.setComponentByPosition(2).getComponentByPosition(2).setComponentByType(value.getTagSet(), value, verifyConstraints=False, matchTags=False, matchConstraints=False, innerFlag=True) + (msg.setComponentByPosition(2) + .getComponentByPosition(2) + .setComponentByType(value.getTagSet(), value, verifyConstraints=False, + matchTags=False, matchConstraints=False, + innerFlag=True)) def getResponse(self, reqMsg): rspMsg = Message() + self.setDefaults(rspMsg) self.setVersion(rspMsg, self.getVersion(reqMsg)) self.setCommunity(rspMsg, self.getCommunity(reqMsg)) self.setPDU(rspMsg, apiPDU.getResponse(self.getPDU(reqMsg))) + return rspMsg diff --git a/pysnmp/proto/api/v2c.py b/pysnmp/proto/api/v2c.py index 05de2da1..c415ca9a 100644 --- a/pysnmp/proto/api/v2c.py +++ b/pysnmp/proto/api/v2c.py @@ -53,7 +53,8 @@ apiVarBind = v1.apiVarBind class PDUAPI(v1.PDUAPI): _errorStatus = rfc1905.errorStatus.clone(0) - _errorIndex = univ.Integer(0).subtype(subtypeSpec=constraint.ValueRangeConstraint(0, rfc1905.max_bindings)) + _errorIndex = univ.Integer(0).subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, rfc1905.max_bindings)) def getResponse(self, reqPDU): rspPDU = ResponsePDU() @@ -86,14 +87,14 @@ class PDUAPI(v1.PDUAPI): def setEndOfMibError(self, pdu, errorIndex): varBindList = self.getVarBindList(pdu) varBindList[errorIndex - 1].setComponentByPosition( - 1, rfc1905.endOfMibView, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, rfc1905.endOfMibView, verifyConstraints=False, matchTags=False, + matchConstraints=False) def setNoSuchInstanceError(self, pdu, errorIndex): varBindList = self.getVarBindList(pdu) varBindList[errorIndex - 1].setComponentByPosition( - 1, rfc1905.noSuchInstance, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, rfc1905.noSuchInstance, verifyConstraints=False, matchTags=False, + matchConstraints=False) apiPDU = PDUAPI() @@ -105,15 +106,19 @@ class BulkPDUAPI(PDUAPI): def setDefaults(self, pdu): PDUAPI.setDefaults(self, pdu) + pdu.setComponentByPosition( - 0, getNextRequestID(), verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, getNextRequestID(), verifyConstraints=False, matchTags=False, + matchConstraints=False) + pdu.setComponentByPosition( - 1, self._nonRepeaters, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, self._nonRepeaters, verifyConstraints=False, matchTags=False, + matchConstraints=False) + pdu.setComponentByPosition( - 2, self._maxRepetitions, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 2, self._maxRepetitions, verifyConstraints=False, matchTags=False, + matchConstraints=False) + pdu.setComponentByPosition(3) @staticmethod @@ -152,9 +157,11 @@ class BulkPDUAPI(PDUAPI): if R: for i in range(0, len(rspVarBinds) - N, R): varBindRow = rspVarBinds[:N] + rspVarBinds[N + i:N + R + i] + # ignore stray OIDs / non-rectangular table if len(varBindRow) == N + R: varBindTable.append(varBindRow) + elif N: varBindTable.append(rspVarBinds[:N]) @@ -175,9 +182,11 @@ class TrapPDUAPI(v1.PDUAPI): def setDefaults(self, pdu): v1.PDUAPI.setDefaults(self, pdu) + varBinds = [(self.sysUpTime, self._zeroTime), # generic trap (self.snmpTrapOID, self._genTrap)] + self.setVarBinds(pdu, varBinds) @@ -188,16 +197,24 @@ class MessageAPI(v1.MessageAPI): _version = rfc1901.version.clone(1) def setDefaults(self, msg): - msg.setComponentByPosition(0, self._version, verifyConstraints=False, matchTags=False, matchConstraints=False) - msg.setComponentByPosition(1, self._community, verifyConstraints=False, matchTags=False, matchConstraints=False) + msg.setComponentByPosition( + 0, self._version, verifyConstraints=False, matchTags=False, + matchConstraints=False) + + msg.setComponentByPosition( + 1, self._community, verifyConstraints=False, matchTags=False, + matchConstraints=False) + return msg def getResponse(self, reqMsg): rspMsg = Message() + self.setDefaults(rspMsg) self.setVersion(rspMsg, self.getVersion(reqMsg)) self.setCommunity(rspMsg, self.getCommunity(reqMsg)) self.setPDU(rspMsg, apiPDU.getResponse(self.getPDU(reqMsg))) + return rspMsg diff --git a/pysnmp/proto/api/verdec.py b/pysnmp/proto/api/verdec.py index e6ec7fd9..142a68c2 100644 --- a/pysnmp/proto/api/verdec.py +++ b/pysnmp/proto/api/verdec.py @@ -18,13 +18,17 @@ def decodeMessageVersion(wholeMsg): wholeMsg, asn1Spec=univ.Sequence(), recursiveFlag=False, substrateFun=lambda a, b, c: (a, b[:c]) ) + ver, wholeMsg = decoder.decode( wholeMsg, asn1Spec=univ.Integer(), recursiveFlag=False, substrateFun=lambda a, b, c: (a, b[:c]) ) + if eoo.endOfOctets.isSameTypeWith(ver): raise ProtocolError('EOO at SNMP version component') + return ver except PyAsn1Error as exc: - raise ProtocolError('Invalid BER at SNMP version component: %s' % exc) + raise ProtocolError('Invalid BER at SNMP version ' + 'component: %s' % exc) diff --git a/pysnmp/proto/cache.py b/pysnmp/proto/cache.py index 9eae19c9..eed689ff 100644 --- a/pysnmp/proto/cache.py +++ b/pysnmp/proto/cache.py @@ -9,30 +9,30 @@ from pysnmp.proto import error class Cache(object): def __init__(self): - self.__cacheRepository = {} + self._cacheRepository = {} def add(self, index, **kwargs): - self.__cacheRepository[index] = kwargs + self._cacheRepository[index] = kwargs return index def pop(self, index): - if index in self.__cacheRepository: - cachedParams = self.__cacheRepository[index] + if index in self._cacheRepository: + cachedParams = self._cacheRepository[index] else: return - del self.__cacheRepository[index] + del self._cacheRepository[index] return cachedParams def update(self, index, **kwargs): - if index not in self.__cacheRepository: + if index not in self._cacheRepository: raise error.ProtocolError( 'Cache miss on update for %s' % kwargs ) - self.__cacheRepository[index].update(kwargs) + self._cacheRepository[index].update(kwargs) def expire(self, cbFun, cbCtx): - for index, cachedParams in list(self.__cacheRepository.items()): + for index, cachedParams in list(self._cacheRepository.items()): if cbFun: if cbFun(index, cachedParams, cbCtx): - if index in self.__cacheRepository: - del self.__cacheRepository[index] + if index in self._cacheRepository: + del self._cacheRepository[index] diff --git a/pysnmp/proto/errind.py b/pysnmp/proto/errind.py index 0c0dcb80..758a9ae1 100644 --- a/pysnmp/proto/errind.py +++ b/pysnmp/proto/errind.py @@ -10,30 +10,34 @@ class ErrorIndication(Exception): """SNMPv3 error-indication values""" def __init__(self, descr=None): - self.__value = self.__descr = self.__class__.__name__[0].lower() + self.__class__.__name__[1:] + self._value = ( + self.__class__.__name__[0].lower() + + self.__class__.__name__[1:]) + self._descr = self._value + if descr: - self.__descr = descr + self._descr = descr def __eq__(self, other): - return self.__value == other + return self._value == other def __ne__(self, other): - return self.__value != other + return self._value != other def __lt__(self, other): - return self.__value < other + return self._value < other def __le__(self, other): - return self.__value <= other + return self._value <= other def __gt__(self, other): - return self.__value > other + return self._value > other def __ge__(self, other): - return self.__value >= other + return self._value >= other def __str__(self): - return self.__descr + return self._descr # SNMP message processing errors @@ -42,84 +46,96 @@ class SerializationError(ErrorIndication): pass -serializationError = SerializationError('SNMP message serialization error') +serializationError = SerializationError( + 'SNMP message serialization error') class DeserializationError(ErrorIndication): pass -deserializationError = DeserializationError('SNMP message deserialization error') +deserializationError = DeserializationError( + 'SNMP message deserialization error') class ParseError(DeserializationError): pass -parseError = ParseError('SNMP message deserialization error') +parseError = ParseError( + 'SNMP message deserialization error') class UnsupportedMsgProcessingModel(ErrorIndication): pass -unsupportedMsgProcessingModel = UnsupportedMsgProcessingModel('Unknown SNMP message processing model ID encountered') +unsupportedMsgProcessingModel = UnsupportedMsgProcessingModel( + 'Unknown SNMP message processing model ID encountered') class UnknownPDUHandler(ErrorIndication): pass -unknownPDUHandler = UnknownPDUHandler('Unhandled PDU type encountered') +unknownPDUHandler = UnknownPDUHandler( + 'Unhandled PDU type encountered') class UnsupportedPDUtype(ErrorIndication): pass -unsupportedPDUtype = UnsupportedPDUtype('Unsupported SNMP PDU type encountered') +unsupportedPDUtype = UnsupportedPDUtype( + 'Unsupported SNMP PDU type encountered') class RequestTimedOut(ErrorIndication): pass -requestTimedOut = RequestTimedOut('No SNMP response received before timeout') +requestTimedOut = RequestTimedOut( + 'No SNMP response received before timeout') class EmptyResponse(ErrorIndication): pass -emptyResponse = EmptyResponse('Empty SNMP response message') +emptyResponse = EmptyResponse( + 'Empty SNMP response message') class NonReportable(ErrorIndication): pass -nonReportable = NonReportable('Report PDU generation not attempted') +nonReportable = NonReportable( + 'Report PDU generation not attempted') class DataMismatch(ErrorIndication): pass -dataMismatch = DataMismatch('SNMP request/response parameters mismatched') +dataMismatch = DataMismatch( + 'SNMP request/response parameters mismatched') class EngineIDMismatch(ErrorIndication): pass -engineIDMismatch = EngineIDMismatch('SNMP engine ID mismatch encountered') +engineIDMismatch = EngineIDMismatch( + 'SNMP engine ID mismatch encountered') class UnknownEngineID(ErrorIndication): pass -unknownEngineID = UnknownEngineID('Unknown SNMP engine ID encountered') +unknownEngineID = UnknownEngineID( + 'Unknown SNMP engine ID encountered') class TooBig(ErrorIndication): @@ -133,14 +149,16 @@ class LoopTerminated(ErrorIndication): pass -loopTerminated = LoopTerminated('Infinite SNMP entities talk terminated') +loopTerminated = LoopTerminated( + 'Infinite SNMP entities talk terminated') class InvalidMsg(ErrorIndication): pass -invalidMsg = InvalidMsg('Invalid SNMP message header parameters encountered') +invalidMsg = InvalidMsg( + 'Invalid SNMP message header parameters encountered') # SNMP security modules errors @@ -149,112 +167,128 @@ class UnknownCommunityName(ErrorIndication): pass -unknownCommunityName = UnknownCommunityName('Unknown SNMP community name encountered') +unknownCommunityName = UnknownCommunityName( + 'Unknown SNMP community name encountered') class NoEncryption(ErrorIndication): pass -noEncryption = NoEncryption('No encryption services configured') +noEncryption = NoEncryption( + 'No encryption services configured') class EncryptionError(ErrorIndication): pass -encryptionError = EncryptionError('Ciphering services not available') +encryptionError = EncryptionError( + 'Ciphering services not available') class DecryptionError(ErrorIndication): pass -decryptionError = DecryptionError('Ciphering services not available or ciphertext is broken') +decryptionError = DecryptionError( + 'Ciphering services not available or ciphertext is broken') class NoAuthentication(ErrorIndication): pass -noAuthentication = NoAuthentication('No authentication services configured') +noAuthentication = NoAuthentication( + 'No authentication services configured') class AuthenticationError(ErrorIndication): pass -authenticationError = AuthenticationError('Ciphering services not available or bad parameters') +authenticationError = AuthenticationError( + 'Ciphering services not available or bad parameters') class AuthenticationFailure(ErrorIndication): pass -authenticationFailure = AuthenticationFailure('Authenticator mismatched') +authenticationFailure = AuthenticationFailure( + 'Authenticator mismatched') class UnsupportedAuthProtocol(ErrorIndication): pass -unsupportedAuthProtocol = UnsupportedAuthProtocol('Authentication protocol is not supported') +unsupportedAuthProtocol = UnsupportedAuthProtocol( + 'Authentication protocol is not supported') class UnsupportedPrivProtocol(ErrorIndication): pass -unsupportedPrivProtocol = UnsupportedPrivProtocol('Privacy protocol is not supported') +unsupportedPrivProtocol = UnsupportedPrivProtocol( + 'Privacy protocol is not supported') class UnknownSecurityName(ErrorIndication): pass -unknownSecurityName = UnknownSecurityName('Unknown SNMP security name encountered') +unknownSecurityName = UnknownSecurityName( + 'Unknown SNMP security name encountered') class UnsupportedSecurityModel(ErrorIndication): pass -unsupportedSecurityModel = UnsupportedSecurityModel('Unsupported SNMP security model') +unsupportedSecurityModel = UnsupportedSecurityModel( + 'Unsupported SNMP security model') class UnsupportedSecurityLevel(ErrorIndication): pass -unsupportedSecurityLevel = UnsupportedSecurityLevel('Unsupported SNMP security level') +unsupportedSecurityLevel = UnsupportedSecurityLevel( + 'Unsupported SNMP security level') class NotInTimeWindow(ErrorIndication): pass -notInTimeWindow = NotInTimeWindow('SNMP message timing parameters not in windows of trust') +notInTimeWindow = NotInTimeWindow( + 'SNMP message timing parameters not in windows of trust') class UnknownUserName(ErrorIndication): pass -unknownUserName = UnknownUserName('Unknown USM user') +unknownUserName = UnknownUserName( + 'Unknown USM user') class WrongDigest(ErrorIndication): pass -wrongDigest = WrongDigest('Wrong SNMP PDU digest') +wrongDigest = WrongDigest( + 'Wrong SNMP PDU digest') class ReportPduReceived(ErrorIndication): pass -reportPduReceived = ReportPduReceived('Remote SNMP engine reported error') +reportPduReceived = ReportPduReceived( + 'Remote SNMP engine reported error') # SNMP access-control errors @@ -263,36 +297,40 @@ class NoSuchView(ErrorIndication): pass -noSuchView = NoSuchView('No such MIB view currently exists') +noSuchView = NoSuchView( + 'No such MIB view currently exists') class NoAccessEntry(ErrorIndication): pass - -noAccessEntry = NoAccessEntry('Access to MIB node denined') +noAccessEntry = NoAccessEntry( + 'Access to MIB node denined') class NoGroupName(ErrorIndication): pass -noGroupName = NoGroupName('No such VACM group configured') +noGroupName = NoGroupName( + 'No such VACM group configured') class NoSuchContext(ErrorIndication): pass -noSuchContext = NoSuchContext('SNMP context now found') +noSuchContext = NoSuchContext( + 'SNMP context now found') class NotInView(ErrorIndication): pass -notInView = NotInView('Requested OID is out of MIB view') +notInView = NotInView( + 'Requested OID is out of MIB view') class AccessAllowed(ErrorIndication): @@ -306,7 +344,8 @@ class OtherError(ErrorIndication): pass -otherError = OtherError('Unspecified SNMP engine error occurred') +otherError = OtherError( + 'Unspecified SNMP engine error occurred') # SNMP Apps errors @@ -315,4 +354,5 @@ class OidNotIncreasing(ErrorIndication): pass -oidNotIncreasing = OidNotIncreasing('OID not increasing') +oidNotIncreasing = OidNotIncreasing( + 'OID not increasing') diff --git a/pysnmp/proto/error.py b/pysnmp/proto/error.py index 52e84642..4847bddf 100644 --- a/pysnmp/proto/error.py +++ b/pysnmp/proto/error.py @@ -23,8 +23,11 @@ class SnmpV3Error(ProtocolError): class StatusInformation(SnmpV3Error): def __init__(self, **kwargs): SnmpV3Error.__init__(self) + self.__errorIndication = kwargs - debug.logger & (debug.FLAG_DSP | debug.FLAG_MP | debug.FLAG_SM | debug.FLAG_ACL) and debug.logger( + + debug.logger & (debug.FLAG_DSP | debug.FLAG_MP | + debug.FLAG_SM | debug.FLAG_ACL) and debug.logger( 'StatusInformation: %s' % kwargs) def __str__(self): diff --git a/pysnmp/proto/mpmod/base.py b/pysnmp/proto/mpmod/base.py index 61b26662..835aca53 100644 --- a/pysnmp/proto/mpmod/base.py +++ b/pysnmp/proto/mpmod/base.py @@ -20,6 +20,7 @@ class AbstractMessageProcessingModel(object): securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, pdu, expectResponse, sendPduHandle): + raise error.ProtocolError('method not implemented') def prepareResponseMessage(self, snmpEngine, messageProcessingModel, @@ -27,15 +28,18 @@ class AbstractMessageProcessingModel(object): contextEngineId, contextName, pduVersion, pdu, maxSizeResponseScopedPDU, stateReference, statusInformation): + raise error.ProtocolError('method not implemented') def prepareDataElements(self, snmpEngine, transportDomain, transportAddress, wholeMsg): + raise error.ProtocolError('method not implemented') def releaseStateInformation(self, sendPduHandle): try: self._cache.popBySendPduHandle(sendPduHandle) + except error.ProtocolError: pass # XXX maybe these should all follow some scheme? diff --git a/pysnmp/proto/mpmod/cache.py b/pysnmp/proto/mpmod/cache.py index 0cb343bd..265355a4 100644 --- a/pysnmp/proto/mpmod/cache.py +++ b/pysnmp/proto/mpmod/cache.py @@ -27,25 +27,37 @@ class Cache(object): def pushByStateRef(self, stateReference, **msgInfo): if stateReference in self.__stateReferenceIndex: - raise error.ProtocolError('Cache dup for stateReference=%s at %s' % (stateReference, self)) + raise error.ProtocolError( + 'Cache dup for stateReference=%s at %s' % (stateReference, self)) + expireAt = self.__expirationTimer + 600 + self.__stateReferenceIndex[stateReference] = msgInfo, expireAt # Schedule to expire if expireAt not in self.__expirationQueue: self.__expirationQueue[expireAt] = {} + if 'stateReference' not in self.__expirationQueue[expireAt]: self.__expirationQueue[expireAt]['stateReference'] = {} + self.__expirationQueue[expireAt]['stateReference'][stateReference] = 1 def popByStateRef(self, stateReference): if stateReference in self.__stateReferenceIndex: cacheInfo = self.__stateReferenceIndex[stateReference] + else: - raise error.ProtocolError('Cache miss for stateReference=%s at %s' % (stateReference, self)) + raise error.ProtocolError( + 'Cache miss for stateReference=%s at ' + '%s' % (stateReference, self)) + del self.__stateReferenceIndex[stateReference] + cacheEntry, expireAt = cacheInfo + del self.__expirationQueue[expireAt]['stateReference'][stateReference] + return cacheEntry # Client mode cache handling @@ -56,9 +68,10 @@ class Cache(object): def pushByMsgId(self, msgId, **msgInfo): if msgId in self.__msgIdIndex: raise error.ProtocolError( - 'Cache dup for msgId=%s at %s' % (msgId, self) - ) + 'Cache dup for msgId=%s at %s' % (msgId, self)) + expireAt = self.__expirationTimer + 600 + self.__msgIdIndex[msgId] = msgInfo, expireAt self.__sendPduHandleIdx[msgInfo['sendPduHandle']] = msgId @@ -66,22 +79,29 @@ class Cache(object): # Schedule to expire if expireAt not in self.__expirationQueue: self.__expirationQueue[expireAt] = {} + if 'msgId' not in self.__expirationQueue[expireAt]: self.__expirationQueue[expireAt]['msgId'] = {} + self.__expirationQueue[expireAt]['msgId'][msgId] = 1 def popByMsgId(self, msgId): if msgId in self.__msgIdIndex: cacheInfo = self.__msgIdIndex[msgId] + else: raise error.ProtocolError( - 'Cache miss for msgId=%s at %s' % (msgId, self) - ) + 'Cache miss for msgId=%s at %s' % (msgId, self)) + msgInfo, expireAt = cacheInfo + del self.__sendPduHandleIdx[msgInfo['sendPduHandle']] del self.__msgIdIndex[msgId] + cacheEntry, expireAt = cacheInfo + del self.__expirationQueue[expireAt]['msgId'][msgId] + return cacheEntry def popBySendPduHandle(self, sendPduHandle): @@ -92,11 +112,15 @@ class Cache(object): # Uses internal clock to expire pending messages if self.__expirationTimer in self.__expirationQueue: cacheInfo = self.__expirationQueue[self.__expirationTimer] + if 'stateReference' in cacheInfo: for stateReference in cacheInfo['stateReference']: del self.__stateReferenceIndex[stateReference] + if 'msgId' in cacheInfo: for msgId in cacheInfo['msgId']: del self.__msgIdIndex[msgId] + del self.__expirationQueue[self.__expirationTimer] + self.__expirationTimer += 1 diff --git a/pysnmp/proto/mpmod/rfc2576.py b/pysnmp/proto/mpmod/rfc2576.py index 8bad83c2..36011619 100644 --- a/pysnmp/proto/mpmod/rfc2576.py +++ b/pysnmp/proto/mpmod/rfc2576.py @@ -32,9 +32,11 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, pdu, expectResponse, sendPduHandle): + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder - snmpEngineId, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineId, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineId = snmpEngineId.syntax # rfc3412: 7.1.1b @@ -42,8 +44,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # serve unique PDU request-id msgID = self._cache.newMsgID() reqID = pdu.getComponentByPosition(0) + debug.logger & debug.FLAG_MP and debug.logger( - 'prepareOutgoingMessage: PDU request-id %s replaced with unique ID %s' % (reqID, msgID)) + 'prepareOutgoingMessage: PDU request-id %s replaced with ' + 'unique ID %s' % (reqID, msgID)) # rfc3412: 7.1.4 # Since there's no SNMP engine identification in v1/2c, @@ -56,17 +60,19 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextName = null debug.logger & debug.FLAG_MP and debug.logger( - 'prepareOutgoingMessage: using contextEngineId %r contextName %r' % (contextEngineId, contextName)) + 'prepareOutgoingMessage: using contextEngineId %r contextName ' + '%r' % (contextEngineId, contextName)) # rfc3412: 7.1.6 - scopedPDU = (contextEngineId, contextName, pdu) + scopedPDU = contextEngineId, contextName, pdu msg = self._snmpMsgSpec + msg.setComponentByPosition(0, self.MESSAGE_PROCESSING_MODEL_ID) msg.setComponentByPosition(2) msg.getComponentByPosition(2).setComponentByType( - pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, + matchConstraints=False) # rfc3412: 7.1.7 globalData = (msg,) @@ -74,15 +80,15 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): k = int(securityModel) if k in snmpEngine.securityModels: smHandler = snmpEngine.securityModels[k] + else: raise error.StatusInformation( - errorIndication=errind.unsupportedSecurityModel - ) + errorIndication=errind.unsupportedSecurityModel) # rfc3412: 7.1.9.a & rfc2576: 5.2.1 --> no-op - snmpEngineMaxMessageSize, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', - 'snmpEngineMaxMessageSize') + snmpEngineMaxMessageSize, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') # fix unique request-id right prior PDU serialization if pdu.tagSet in rfc3411.CONFIRMED_CLASS_PDUS: @@ -90,12 +96,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): pdu.setComponentByPosition(0, msgID) # rfc3412: 7.1.9.b - (securityParameters, - wholeMsg) = smHandler.generateRequestMsg( + securityParameters, wholeMsg = smHandler.generateRequestMsg( snmpEngine, self.MESSAGE_PROCESSING_MODEL_ID, globalData, snmpEngineMaxMessageSize.syntax, securityModel, - snmpEngineId, securityName, securityLevel, scopedPDU - ) + snmpEngineId, securityName, securityLevel, scopedPDU) # return original request-id right after PDU serialization if pdu.tagSet in rfc3411.CONFIRMED_CLASS_PDUS: @@ -105,15 +109,16 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # rfc3412: 7.1.9.c if pdu.tagSet in rfc3411.CONFIRMED_CLASS_PDUS: # XXX rfc bug? why stateReference should be created? - self._cache.pushByMsgId(int(msgID), sendPduHandle=sendPduHandle, - reqID=reqID, snmpEngineId=snmpEngineId, - securityModel=securityModel, - securityName=securityName, - securityLevel=securityLevel, - contextEngineId=contextEngineId, - contextName=contextName, - transportDomain=transportDomain, - transportAddress=transportAddress) + self._cache.pushByMsgId( + int(msgID), sendPduHandle=sendPduHandle, + reqID=reqID, snmpEngineId=snmpEngineId, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + transportDomain=transportDomain, + transportAddress=transportAddress) communityName = msg.getComponentByPosition(1) # for observer @@ -128,11 +133,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId=contextEngineId, contextName=contextName, communityName=communityName, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc2576.prepareOutgoingMessage' - ) + snmpEngine, 'rfc2576.prepareOutgoingMessage') return transportDomain, transportAddress, wholeMsg @@ -142,9 +146,11 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId, contextName, pduVersion, pdu, maxSizeResponseScopedPDU, stateReference, statusInformation): + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder - snmpEngineId, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineId, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineId = snmpEngineId.syntax # rfc3412: 7.1.2.b @@ -152,6 +158,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): raise error.StatusInformation(errorIndication=errind.nonReportable) cachedParams = self._cache.popByStateRef(stateReference) + msgID = cachedParams['msgID'] reqID = cachedParams['reqID'] contextEngineId = cachedParams['contextEngineId'] @@ -165,7 +172,8 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): transportAddress = cachedParams['transportAddress'] debug.logger & debug.FLAG_MP and debug.logger( - 'prepareResponseMessage: cache read msgID %s transportDomain %s transportAddress %s by stateReference %s' % ( + 'prepareResponseMessage: cache read msgID %s transportDomain %s ' + 'transportAddress %s by stateReference %s' % ( msgID, transportDomain, transportAddress, stateReference)) # rfc3412: 7.1.3 @@ -189,14 +197,15 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): scopedPDU = (contextEngineId, contextName, pdu) debug.logger & debug.FLAG_MP and debug.logger( - 'prepareResponseMessage: using contextEngineId %r contextName %r' % (contextEngineId, contextName)) + 'prepareResponseMessage: using contextEngineId %r contextName ' + '%r' % (contextEngineId, contextName)) msg = self._snmpMsgSpec msg.setComponentByPosition(0, messageProcessingModel) msg.setComponentByPosition(2) msg.getComponentByPosition(2).setComponentByType( - pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, + matchConstraints=False) # att: msgId not set back to PDU as it's up to responder app @@ -206,20 +215,19 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): k = int(securityModel) if k in snmpEngine.securityModels: smHandler = snmpEngine.securityModels[k] + else: raise error.StatusInformation( - errorIndication=errind.unsupportedSecurityModel - ) + errorIndication=errind.unsupportedSecurityModel) # set original request-id right prior to PDU serialization pdu.setComponentByPosition(0, reqID) # rfc3412: 7.1.8.a - (securityParameters, wholeMsg) = smHandler.generateResponseMsg( + securityParameters, wholeMsg = smHandler.generateResponseMsg( snmpEngine, self.MESSAGE_PROCESSING_MODEL_ID, globalData, maxMessageSize, securityModel, snmpEngineId, securityName, - securityLevel, scopedPDU, securityStateReference - ) + securityLevel, scopedPDU, securityStateReference) # recover unique request-id right after PDU serialization pdu.setComponentByPosition(0, msgID) @@ -235,11 +243,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextName=contextName, securityEngineId=snmpEngineId, communityName=msg.getComponentByPosition(1), - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc2576.prepareResponseMessage' - ) + snmpEngine, 'rfc2576.prepareResponseMessage') return transportDomain, transportAddress, wholeMsg @@ -247,12 +254,14 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): def prepareDataElements(self, snmpEngine, transportDomain, transportAddress, wholeMsg): + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder # rfc3412: 7.2.2 msg, restOfWholeMsg = decoder.decode(wholeMsg, asn1Spec=self._snmpMsgSpec) - debug.logger & debug.FLAG_MP and debug.logger('prepareDataElements: %s' % (msg.prettyPrint(),)) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareDataElements: %s' % (msg.prettyPrint(),)) if eoo.endOfOctets.isSameTypeWith(msg): raise error.StatusInformation(errorIndication=errind.parseError) @@ -261,8 +270,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): msgVersion = msg.getComponentByPosition(0) # rfc2576: 5.2.1 - snmpEngineMaxMessageSize, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') + snmpEngineMaxMessageSize, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') communityName = msg.getComponentByPosition(1) + # transportDomain identifies local endpoint securityParameters = (communityName, (transportDomain, transportAddress)) messageProcessingModel = int(msg.getComponentByPosition(0)) @@ -293,7 +304,8 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): ) debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: SM returned securityEngineId %r securityName %r' % (securityEngineId, securityName)) + 'prepareDataElements: SM returned securityEngineId %r ' + 'securityName %r' % (securityEngineId, securityName)) except error.StatusInformation as exc: statusInformation = exc @@ -305,11 +317,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): securityModel=securityModel, securityLevel=securityLevel, securityParameters=securityParameters, - statusInformation=statusInformation) - ) + statusInformation=statusInformation)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc2576.prepareDataElements:sm-failure' - ) + snmpEngine, 'rfc2576.prepareDataElements:sm-failure') raise @@ -332,6 +343,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # 7.2.10a try: cachedReqParams = self._cache.popByMsgId(int(msgID)) + except error.ProtocolError: smHandler.releaseStateInformation(securityStateReference) raise error.StatusInformation(errorIndication=errind.dataMismatch) @@ -340,11 +352,12 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): pdu.setComponentByPosition(0, cachedReqParams['reqID']) debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: unique PDU request-id %s replaced with original ID %s' % ( - msgID, cachedReqParams['reqID'])) + 'prepareDataElements: unique PDU request-id %s replaced with ' + 'original ID %s' % (msgID, cachedReqParams['reqID'])) # 7.2.10b sendPduHandle = cachedReqParams['sendPduHandle'] + else: sendPduHandle = None @@ -363,7 +376,9 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): securityLevel != cachedReqParams['securityLevel'] or contextEngineId != cachedReqParams['contextEngineId'] or contextName != cachedReqParams['contextName']): + smHandler.releaseStateInformation(securityStateReference) + raise error.StatusInformation(errorIndication=errind.dataMismatch) stateReference = None @@ -379,11 +394,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextName=contextName, securityEngineId=securityEngineId, communityName=communityName, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc2576.prepareDataElements:response' - ) + snmpEngine, 'rfc2576.prepareDataElements:response') # rfc3412: 7.2.12c smHandler.releaseStateInformation(securityStateReference) @@ -401,19 +415,23 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): reqID = pdu.getComponentByPosition(0) msgID = self._cache.newMsgID() pdu.setComponentByPosition(0, msgID) + debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: received PDU request-id %s replaced with unique ID %s' % (reqID, msgID)) + 'prepareDataElements: received PDU request-id %s replaced with ' + 'unique ID %s' % (reqID, msgID)) # rfc3412: 7.2.13a - snmpEngineId, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineId, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + if securityEngineId != snmpEngineId.syntax: smHandler.releaseStateInformation(securityStateReference) raise error.StatusInformation( - errorIndication=errind.engineIDMismatch - ) + errorIndication=errind.engineIDMismatch) # rfc3412: 7.2.13b stateReference = self._cache.newStateReference() + self._cache.pushByStateRef( stateReference, msgVersion=messageProcessingModel, msgID=msgID, reqID=reqID, contextEngineId=contextEngineId, @@ -437,14 +455,14 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextName=contextName, securityEngineId=securityEngineId, communityName=communityName, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc2576.prepareDataElements:confirmed' - ) + snmpEngine, 'rfc2576.prepareDataElements:confirmed') debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: cached by new stateReference %s' % stateReference) + 'prepareDataElements: cached by new stateReference ' + '%s' % stateReference) # rfc3412: 7.2.13c return (messageProcessingModel, securityModel, securityName, @@ -469,11 +487,10 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): contextName=contextName, securityEngineId=securityEngineId, communityName=communityName, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc2576.prepareDataElements:unconfirmed' - ) + snmpEngine, 'rfc2576.prepareDataElements:unconfirmed') # This is not specified explicitly in RFC smHandler.releaseStateInformation(securityStateReference) @@ -485,6 +502,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): stateReference) smHandler.releaseStateInformation(securityStateReference) + raise error.StatusInformation(errorIndication=errind.unsupportedPDUtype) diff --git a/pysnmp/proto/mpmod/rfc3412.py b/pysnmp/proto/mpmod/rfc3412.py index 6ff9fa8d..20852db6 100644 --- a/pysnmp/proto/mpmod/rfc3412.py +++ b/pysnmp/proto/mpmod/rfc3412.py @@ -30,49 +30,53 @@ class ScopedPDU(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('contextEngineId', univ.OctetString()), namedtype.NamedType('contextName', univ.OctetString()), - namedtype.NamedType('data', rfc1905.PDUs()) - ) + namedtype.NamedType('data', rfc1905.PDUs())) class ScopedPduData(univ.Choice): componentType = namedtype.NamedTypes( namedtype.NamedType('plaintext', ScopedPDU()), - namedtype.NamedType('encryptedPDU', univ.OctetString()), - ) + namedtype.NamedType('encryptedPDU', univ.OctetString())) class HeaderData(univ.Sequence): componentType = namedtype.NamedTypes( - namedtype.NamedType('msgID', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), - namedtype.NamedType('msgMaxSize', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(484, 2147483647))), - namedtype.NamedType('msgFlags', univ.OctetString().subtype(subtypeSpec=constraint.ValueSizeConstraint(1, 1))), + namedtype.NamedType( + 'msgID', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), + namedtype.NamedType( + 'msgMaxSize', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(484, 2147483647))), + namedtype.NamedType( + 'msgFlags', univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(1, 1))), # NOTE (etingof): constrain SNMPv3 message to only USM+ security models # because SNMPv1/v2c seems incompatible in pysnmp implementation, not sure # if it's intended by the SNMP standard at all... - namedtype.NamedType('msgSecurityModel', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(3, 2147483647))) - ) + namedtype.NamedType( + 'msgSecurityModel', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(3, 2147483647)))) class SNMPv3Message(univ.Sequence): componentType = namedtype.NamedTypes( - namedtype.NamedType('msgVersion', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), + namedtype.NamedType( + 'msgVersion', univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), namedtype.NamedType('msgGlobalData', HeaderData()), namedtype.NamedType('msgSecurityParameters', univ.OctetString()), - namedtype.NamedType('msgData', ScopedPduData()) - ) + namedtype.NamedType('msgData', ScopedPduData())) # XXX move somewhere? -_snmpErrors = {(1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0): errind.unsupportedSecurityLevel, - (1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0): errind.notInTimeWindow, - (1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0): errind.unknownUserName, - (1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0): errind.unknownEngineID, - (1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0): errind.wrongDigest, - (1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0): errind.decryptionError} +_snmpErrors = { + (1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0): errind.unsupportedSecurityLevel, + (1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0): errind.notInTimeWindow, + (1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0): errind.unknownUserName, + (1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0): errind.unknownEngineID, + (1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0): errind.wrongDigest, + (1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0): errind.decryptionError +} class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): @@ -80,26 +84,28 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): SNMP_MSG_SPEC = SNMPv3Message _emptyStr = univ.OctetString('') - _msgFlags = {0: univ.OctetString('\x00'), - 1: univ.OctetString('\x01'), - 3: univ.OctetString('\x03'), - 4: univ.OctetString('\x04'), - 5: univ.OctetString('\x05'), - 7: univ.OctetString('\x07')} + _msgFlags = { + 0: univ.OctetString('\x00'), + 1: univ.OctetString('\x01'), + 3: univ.OctetString('\x03'), + 4: univ.OctetString('\x04'), + 5: univ.OctetString('\x05'), + 7: univ.OctetString('\x07') + } def __init__(self): AbstractMessageProcessingModel.__init__(self) - self.__scopedPDU = ScopedPDU() - self.__engineIdCache = {} - self.__engineIdCacheExpQueue = {} - self.__expirationTimer = 0 + self._scopedPDU = ScopedPDU() + 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']) + if k in self._engineIdCache: + return (self._engineIdCache[k]['securityEngineId'], + self._engineIdCache[k]['contextEngineId'], + self._engineIdCache[k]['contextName']) else: return None, None, None @@ -109,29 +115,35 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, pdu, expectResponse, sendPduHandle): - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', - 'snmpEngineID') + + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + + snmpEngineID, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineID = snmpEngineID.syntax # 7.1.1b msgID = self._cache.newMsgID() - debug.logger & debug.FLAG_MP and debug.logger('prepareOutgoingMessage: new msgID %s' % msgID) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareOutgoingMessage: new msgID %s' % msgID) + + k = transportDomain, transportAddress + if k in self._engineIdCache: + peerSnmpEngineData = self._engineIdCache[k] - k = (transportDomain, transportAddress) - if k in self.__engineIdCache: - peerSnmpEngineData = self.__engineIdCache[k] else: peerSnmpEngineData = None debug.logger & debug.FLAG_MP and debug.logger( - 'prepareOutgoingMessage: peer SNMP engine data %s for transport %s, address %s' % ( - peerSnmpEngineData, transportDomain, transportAddress)) + 'prepareOutgoingMessage: peer SNMP engine data %s ' + 'for transport %s, address ' + '%s' % (peerSnmpEngineData, transportDomain, transportAddress)) # 7.1.4 if contextEngineId is None: if peerSnmpEngineData is None: contextEngineId = snmpEngineID + else: contextEngineId = peerSnmpEngineData['contextEngineId'] # Defaulting contextEngineID to securityEngineId should @@ -144,88 +156,98 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextName = self._emptyStr debug.logger & debug.FLAG_MP and debug.logger( - 'prepareOutgoingMessage: using contextEngineId %r, contextName %r' % (contextEngineId, contextName)) + 'prepareOutgoingMessage: using contextEngineId %r, contextName ' + '%r' % (contextEngineId, contextName)) # 7.1.6 - scopedPDU = self.__scopedPDU + scopedPDU = self._scopedPDU scopedPDU.setComponentByPosition(0, contextEngineId) scopedPDU.setComponentByPosition(1, contextName) scopedPDU.setComponentByPosition(2) scopedPDU.getComponentByPosition(2).setComponentByType( - pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, + matchConstraints=False) # 7.1.7 msg = self._snmpMsgSpec # 7.1.7a msg.setComponentByPosition( - 0, self.MESSAGE_PROCESSING_MODEL_ID, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, self.MESSAGE_PROCESSING_MODEL_ID, verifyConstraints=False, + matchTags=False, matchConstraints=False) + headerData = msg.setComponentByPosition(1).getComponentByPosition(1) # 7.1.7b - headerData.setComponentByPosition(0, msgID, verifyConstraints=False, matchTags=False, matchConstraints=False) + headerData.setComponentByPosition( + 0, msgID, verifyConstraints=False, matchTags=False, + matchConstraints=False) - snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpEngineMaxMessageSize, = mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') # 7.1.7c # XXX need to coerce MIB value as it has incompatible constraints set headerData.setComponentByPosition( - 1, snmpEngineMaxMessageSize.syntax, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, snmpEngineMaxMessageSize.syntax, verifyConstraints=False, + matchTags=False, matchConstraints=False) # 7.1.7d msgFlags = 0 if securityLevel == 1: pass + elif securityLevel == 2: msgFlags |= 0x01 + elif securityLevel == 3: msgFlags |= 0x03 + else: raise error.ProtocolError( - 'Unknown securityLevel %s' % securityLevel - ) + 'Unknown securityLevel %s' % securityLevel) if pdu.tagSet in rfc3411.CONFIRMED_CLASS_PDUS: msgFlags |= 0x04 headerData.setComponentByPosition( - 2, self._msgFlags[msgFlags], verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 2, self._msgFlags[msgFlags], verifyConstraints=False, + matchTags=False, matchConstraints=False) # 7.1.7e # XXX need to coerce MIB value as it has incompatible constraints set headerData.setComponentByPosition(3, int(securityModel)) - debug.logger & debug.FLAG_MP and debug.logger('prepareOutgoingMessage: %s' % (msg.prettyPrint(),)) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareOutgoingMessage: %s' % (msg.prettyPrint(),)) if securityModel in snmpEngine.securityModels: smHandler = snmpEngine.securityModels[securityModel] + else: raise error.StatusInformation( - errorIndication=errind.unsupportedSecurityModel - ) + errorIndication=errind.unsupportedSecurityModel) # 7.1.9.a if pdu.tagSet in rfc3411.UNCONFIRMED_CLASS_PDUS: securityEngineId = snmpEngineID + else: if peerSnmpEngineData is None: # Force engineID discovery (rfc3414, 4) securityEngineId = securityName = self._emptyStr securityLevel = 1 + # Clear possible auth&priv flags headerData.setComponentByPosition( - 2, self._msgFlags[msgFlags & 0xfc], verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 2, self._msgFlags[msgFlags & 0xfc], verifyConstraints=False, + matchTags=False, matchConstraints=False) + # XXX - scopedPDU = self.__scopedPDU + scopedPDU = self._scopedPDU scopedPDU.setComponentByPosition( - 0, self._emptyStr, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, self._emptyStr, verifyConstraints=False, matchTags=False, + matchConstraints=False) scopedPDU.setComponentByPosition(1, contextName) scopedPDU.setComponentByPosition(2) @@ -234,19 +256,22 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): pMod.apiPDU.setDefaults(emptyPdu) scopedPDU.getComponentByPosition(2).setComponentByType( - emptyPdu.tagSet, emptyPdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) - debug.logger & debug.FLAG_MP and debug.logger('prepareOutgoingMessage: force engineID discovery') + emptyPdu.tagSet, emptyPdu, verifyConstraints=False, + matchTags=False, matchConstraints=False) + + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareOutgoingMessage: force engineID discovery') + else: securityEngineId = peerSnmpEngineData['securityEngineId'] debug.logger & debug.FLAG_MP and debug.logger( - 'prepareOutgoingMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r' % ( - securityModel, securityEngineId, securityName, securityLevel)) + 'prepareOutgoingMessage: securityModel %r, securityEngineId %r, ' + 'securityName %r, securityLevel ' + '%r' % (securityModel, securityEngineId, securityName, securityLevel)) # 7.1.9.b - (securityParameters, - wholeMsg) = smHandler.generateRequestMsg( + securityParameters, wholeMsg = smHandler.generateRequestMsg( snmpEngine, self.MESSAGE_PROCESSING_MODEL_ID, msg, snmpEngineMaxMessageSize.syntax, securityModel, securityEngineId, securityName, securityLevel, scopedPDU @@ -259,15 +284,16 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.1.9.c if pdu.tagSet in rfc3411.CONFIRMED_CLASS_PDUS: # XXX rfc bug? why stateReference should be created? - self._cache.pushByMsgId(msgID, sendPduHandle=sendPduHandle, - msgID=msgID, snmpEngineID=snmpEngineID, - securityModel=securityModel, - securityName=securityName, - securityLevel=securityLevel, - contextEngineId=contextEngineId, - contextName=contextName, - transportDomain=transportDomain, - transportAddress=transportAddress) + self._cache.pushByMsgId( + msgID, sendPduHandle=sendPduHandle, + msgID=msgID, snmpEngineID=snmpEngineID, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + transportDomain=transportDomain, + transportAddress=transportAddress) snmpEngine.observer.storeExecutionContext( snmpEngine, 'rfc3412.prepareOutgoingMessage', @@ -292,7 +318,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId, contextName, pduVersion, pdu, maxSizeResponseScopedPDU, stateReference, statusInformation): - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + + snmpEngineID, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineID = snmpEngineID.syntax # 7.1.2.b @@ -309,13 +338,15 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): transportDomain = cachedParams['transportDomain'] transportAddress = cachedParams['transportAddress'] - debug.logger & debug.FLAG_MP and debug.logger('prepareResponseMessage: stateReference %s' % stateReference) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareResponseMessage: stateReference %s' % stateReference) # 7.1.3 if statusInformation is not None and 'oid' in statusInformation: # 7.1.3a if pdu is None: pduType = None + else: requestID = pdu.getComponentByPosition(0) pduType = pdu.tagSet @@ -325,16 +356,18 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): pduType is not None and pduType not in rfc3411.CONFIRMED_CLASS_PDUS): raise error.StatusInformation( - errorIndication=errind.loopTerminated - ) + errorIndication=errind.loopTerminated) # 7.1.3c reportPDU = rfc1905.ReportPDU() - pMod.apiPDU.setVarBinds(reportPDU, ((statusInformation['oid'], statusInformation['val']),)) + pMod.apiPDU.setVarBinds( + reportPDU, ((statusInformation['oid'], statusInformation['val']),)) pMod.apiPDU.setErrorStatus(reportPDU, 0) pMod.apiPDU.setErrorIndex(reportPDU, 0) + if pdu is None: pMod.apiPDU.setRequestID(reportPDU, 0) + else: # noinspection PyUnboundLocalVariable pMod.apiPDU.setRequestID(reportPDU, requestID) @@ -342,18 +375,21 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.1.3d.1 if 'securityLevel' in statusInformation: securityLevel = statusInformation['securityLevel'] + else: securityLevel = 1 # 7.1.3d.2 if 'contextEngineId' in statusInformation: contextEngineId = statusInformation['contextEngineId'] + else: contextEngineId = snmpEngineID # 7.1.3d.3 if 'contextName' in statusInformation: contextName = statusInformation['contextName'] + else: contextName = "" @@ -361,7 +397,8 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): pdu = reportPDU debug.logger & debug.FLAG_MP and debug.logger( - 'prepareResponseMessage: prepare report PDU for statusInformation %s' % statusInformation) + 'prepareResponseMessage: prepare report PDU for ' + 'statusInformation %s' % statusInformation) # 7.1.4 if not contextEngineId: contextEngineId = snmpEngineID # XXX impl-dep manner @@ -371,47 +408,54 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextName = self._emptyStr debug.logger & debug.FLAG_MP and debug.logger( - 'prepareResponseMessage: using contextEngineId %r, contextName %r' % (contextEngineId, contextName)) + 'prepareResponseMessage: using contextEngineId %r, contextName ' + '%r' % (contextEngineId, contextName)) # 7.1.6 - scopedPDU = self.__scopedPDU + scopedPDU = self._scopedPDU scopedPDU.setComponentByPosition(0, contextEngineId) scopedPDU.setComponentByPosition(1, contextName) scopedPDU.setComponentByPosition(2) scopedPDU.getComponentByPosition(2).setComponentByType( - pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, + matchConstraints=False) # 7.1.7 msg = self._snmpMsgSpec # 7.1.7a msg.setComponentByPosition( - 0, self.MESSAGE_PROCESSING_MODEL_ID, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, self.MESSAGE_PROCESSING_MODEL_ID, verifyConstraints=False, + matchTags=False, matchConstraints=False) headerData = msg.setComponentByPosition(1).getComponentByPosition(1) # 7.1.7b - headerData.setComponentByPosition(0, msgID, verifyConstraints=False, matchTags=False, matchConstraints=False) + headerData.setComponentByPosition( + 0, msgID, verifyConstraints=False, matchTags=False, + matchConstraints=False) - snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpEngineMaxMessageSize, = mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') # 7.1.7c # XXX need to coerce MIB value as it has incompatible constraints set headerData.setComponentByPosition( - 1, snmpEngineMaxMessageSize.syntax, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, snmpEngineMaxMessageSize.syntax, verifyConstraints=False, + matchTags=False, matchConstraints=False) # 7.1.7d msgFlags = 0 + if securityLevel == 1: pass + elif securityLevel == 2: msgFlags |= 0x01 + elif securityLevel == 3: msgFlags |= 0x03 + else: raise error.ProtocolError('Unknown securityLevel %s' % securityLevel) @@ -419,39 +463,43 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): msgFlags |= 0x04 headerData.setComponentByPosition( - 2, self._msgFlags[msgFlags], verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 2, self._msgFlags[msgFlags], verifyConstraints=False, matchTags=False, + matchConstraints=False) # 7.1.7e headerData.setComponentByPosition( - 3, securityModel, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 3, securityModel, verifyConstraints=False, matchTags=False, + matchConstraints=False) - debug.logger & debug.FLAG_MP and debug.logger('prepareResponseMessage: %s' % (msg.prettyPrint(),)) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareResponseMessage: %s' % (msg.prettyPrint(),)) if securityModel in snmpEngine.securityModels: smHandler = snmpEngine.securityModels[securityModel] + else: - raise error.StatusInformation(errorIndication=errind.unsupportedSecurityModel) + raise error.StatusInformation( + errorIndication=errind.unsupportedSecurityModel) debug.logger & debug.FLAG_MP and debug.logger( - 'prepareResponseMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r' % ( + 'prepareResponseMessage: securityModel %r, securityEngineId %r, ' + 'securityName %r, securityLevel %r' % ( securityModel, snmpEngineID, securityName, securityLevel)) # 7.1.8a try: - (securityParameters, - wholeMsg) = smHandler.generateResponseMsg( + securityParameters, wholeMsg = smHandler.generateResponseMsg( snmpEngine, self.MESSAGE_PROCESSING_MODEL_ID, msg, snmpEngineMaxMessageSize.syntax, securityModel, snmpEngineID, securityName, securityLevel, scopedPDU, - securityStateReference - ) + securityStateReference) + except error.StatusInformation: # 7.1.8.b raise - debug.logger & debug.FLAG_MP and debug.logger('prepareResponseMessage: SM finished') + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareResponseMessage: SM finished') # Message size constraint verification if len(wholeMsg) > min(snmpEngineMaxMessageSize.syntax, maxMessageSize): @@ -468,11 +516,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId=contextEngineId, contextName=contextName, securityEngineId=snmpEngineID, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.prepareResponseMessage' - ) + snmpEngine, 'rfc3412.prepareResponseMessage') return transportDomain, transportAddress, wholeMsg @@ -483,11 +530,14 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.2.2 msg, restOfwholeMsg = decoder.decode(wholeMsg, asn1Spec=self._snmpMsgSpec) - debug.logger & debug.FLAG_MP and debug.logger('prepareDataElements: %s' % (msg.prettyPrint(),)) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareDataElements: %s' % (msg.prettyPrint(),)) if eoo.endOfOctets.isSameTypeWith(msg): raise error.StatusInformation(errorIndication=errind.parseError) + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + # 7.2.3 headerData = msg.getComponentByPosition(1) msgVersion = messageProcessingModel = msg.getComponentByPosition(0) @@ -498,12 +548,12 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): securityParameters = msg.getComponentByPosition(2) debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: msg data msgVersion %s msgID %s securityModel %s' % ( - msgVersion, msgID, securityModel)) + 'prepareDataElements: msg data msgVersion %s msgID %s ' + 'securityModel %s' % (msgVersion, msgID, securityModel)) # 7.2.4 if securityModel not in snmpEngine.securityModels: - snmpUnknownSecurityModels, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpUnknownSecurityModels, = mibBuilder.importSymbols( '__SNMP-MPD-MIB', 'snmpUnknownSecurityModels') snmpUnknownSecurityModels.syntax += 1 raise error.StatusInformation(errorIndication=errind.unsupportedSecurityModel) @@ -511,22 +561,28 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.2.5 if msgFlags & 0x03 == 0x00: securityLevel = 1 + elif (msgFlags & 0x03) == 0x01: securityLevel = 2 + elif (msgFlags & 0x03) == 0x03: securityLevel = 3 + else: - snmpInvalidMsgs, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB', 'snmpInvalidMsgs') + snmpInvalidMsgs, = mibBuilder.importSymbols( + '__SNMP-MPD-MIB', 'snmpInvalidMsgs') snmpInvalidMsgs.syntax += 1 raise error.StatusInformation(errorIndication=errind.invalidMsg) if msgFlags & 0x04: reportableFlag = 1 + else: reportableFlag = 0 # 7.2.6 smHandler = snmpEngine.securityModels[securityModel] + try: (securityEngineId, securityName, @@ -535,15 +591,17 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): securityStateReference) = smHandler.processIncomingMsg( snmpEngine, messageProcessingModel, maxMessageSize, securityParameters, securityModel, securityLevel, - wholeMsg, msg - ) - debug.logger & debug.FLAG_MP and debug.logger('prepareDataElements: SM succeeded') + wholeMsg, msg) + + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareDataElements: SM succeeded') except error.StatusInformation as exc: statusInformation = exc debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: SM failed, statusInformation %s' % statusInformation) + 'prepareDataElements: SM failed, statusInformation ' + '%s' % statusInformation) snmpEngine.observer.storeExecutionContext( snmpEngine, 'rfc3412.prepareDataElements:sm-failure', @@ -552,11 +610,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): securityModel=securityModel, securityLevel=securityLevel, securityParameters=securityParameters, - statusInformation=statusInformation) - ) + statusInformation=statusInformation)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.prepareDataElements:sm-failure' - ) + snmpEngine, 'rfc3412.prepareDataElements:sm-failure') if 'errorIndication' in statusInformation: # 7.2.6a @@ -565,16 +622,20 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): securityStateReference = statusInformation['securityStateReference'] contextEngineId = statusInformation['contextEngineId'] contextName = statusInformation['contextName'] + if 'scopedPDU' in statusInformation: scopedPDU = statusInformation['scopedPDU'] pdu = scopedPDU.getComponentByPosition(2).getComponent() + else: pdu = None + maxSizeResponseScopedPDU = statusInformation['maxSizeResponseScopedPDU'] securityName = None # XXX secmod cache used # 7.2.6a2 stateReference = self._cache.newStateReference() + self._cache.pushByStateRef( stateReference, msgVersion=messageProcessingModel, msgID=msgID, contextEngineId=contextEngineId, @@ -585,8 +646,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): msgMaxSize=maxMessageSize, maxSizeResponseScopedPDU=maxSizeResponseScopedPDU, transportDomain=transportDomain, - transportAddress=transportAddress - ) + transportAddress=transportAddress) # 7.2.6a3 try: @@ -594,16 +654,18 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): snmpEngine, 3, securityModel, securityName, securityLevel, contextEngineId, contextName, 1, pdu, maxSizeResponseScopedPDU, stateReference, - statusInformation - ) + statusInformation) + except error.StatusInformation: pass - debug.logger & debug.FLAG_MP and debug.logger('prepareDataElements: error reported') + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareDataElements: error reported') # 7.2.6b if sys.version_info[0] <= 2: raise statusInformation + else: origTraceback = sys.exc_info()[2] @@ -616,31 +678,36 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): del origTraceback else: # Sniff for engineIdCache - k = (transportDomain, transportAddress) - if k not in self.__engineIdCache: + k = transportDomain, transportAddress + if k not in self._engineIdCache: contextEngineId = scopedPDU[0] contextName = scopedPDU[1] + pdus = scopedPDU[2] 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.INTERNAL_CLASS_PDUS: - self.__engineIdCache[k] = { + self._engineIdCache[k] = { 'securityEngineId': securityEngineId, 'contextEngineId': contextEngineId, 'contextName': contextName } - expireAt = int(self.__expirationTimer + 300 / snmpEngine.transportDispatcher.getTimerResolution()) - if expireAt not in self.__engineIdCacheExpQueue: - self.__engineIdCacheExpQueue[expireAt] = [] - self.__engineIdCacheExpQueue[expireAt].append(k) + timerResolution = snmpEngine.transportDispatcher.getTimerResolution() + expireAt = int(self._expirationTimer + 300 / timerResolution) + + if expireAt not in self._engineIdCacheExpQueue: + self._engineIdCacheExpQueue[expireAt] = [] + + self._engineIdCacheExpQueue[expireAt].append(k) debug.logger & debug.FLAG_MP and debug.logger( 'prepareDataElements: cache securityEngineId %r for %r %r' % ( securityEngineId, transportDomain, transportAddress)) - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineID, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineID = snmpEngineID.syntax # 7.2.7 XXX PDU would be parsed here? @@ -662,33 +729,39 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.2.10a try: cachedReqParams = self._cache.popByMsgId(msgID) + except error.ProtocolError: smHandler.releaseStateInformation(securityStateReference) - raise error.StatusInformation( - errorIndication=errind.dataMismatch - ) + raise error.StatusInformation(errorIndication=errind.dataMismatch) + # 7.2.10b sendPduHandle = cachedReqParams['sendPduHandle'] + else: sendPduHandle = None debug.logger & debug.FLAG_MP and debug.logger( - 'prepareDataElements: using sendPduHandle %s for msgID %s' % (sendPduHandle, msgID)) + 'prepareDataElements: using sendPduHandle %s for msgID ' + '%s' % (sendPduHandle, msgID)) # 7.2.11 if pduType in rfc3411.INTERNAL_CLASS_PDUS: # 7.2.11a varBinds = pMod.apiPDU.getVarBinds(pdu) + if varBinds: + errorIndication = _snmpErrors.get( + varBinds[0][0], + errind.ReportPduReceived(varBinds[0][0].prettyPrint())) + statusInformation = error.StatusInformation( - errorIndication=_snmpErrors.get(varBinds[0][0], errind.ReportPduReceived(varBinds[0][0].prettyPrint())), + errorIndication=errorIndication, oid=varBinds[0][0], val=varBinds[0][1], - sendPduHandle=sendPduHandle - ) + sendPduHandle=sendPduHandle) + else: statusInformation = error.StatusInformation( - sendPduHandle=sendPduHandle - ) + sendPduHandle=sendPduHandle) # 7.2.11b (incomplete implementation) @@ -702,11 +775,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId=contextEngineId, contextName=contextName, securityEngineId=securityEngineId, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.prepareDataElements:internal' - ) + snmpEngine, 'rfc3412.prepareDataElements:internal') # 7.2.11c smHandler.releaseStateInformation(securityStateReference) @@ -730,10 +802,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): securityLevel != cachedReqParams['securityLevel'] or contextEngineId != cachedReqParams['contextEngineId'] or contextName != cachedReqParams['contextName']): + smHandler.releaseStateInformation(securityStateReference) - raise error.StatusInformation( - errorIndication=errind.dataMismatch - ) + + raise error.StatusInformation(errorIndication=errind.dataMismatch) snmpEngine.observer.storeExecutionContext( snmpEngine, 'rfc3412.prepareDataElements:response', @@ -745,11 +817,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId=contextEngineId, contextName=contextName, securityEngineId=securityEngineId, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.prepareDataElements:response' - ) + snmpEngine, 'rfc3412.prepareDataElements:response') # 7.2.12c smHandler.releaseStateInformation(securityStateReference) @@ -768,11 +839,11 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): if securityEngineId != snmpEngineID: smHandler.releaseStateInformation(securityStateReference) raise error.StatusInformation( - errorIndication=errind.engineIDMismatch - ) + errorIndication=errind.engineIDMismatch) # 7.2.13b stateReference = self._cache.newStateReference() + self._cache.pushByStateRef( stateReference, msgVersion=messageProcessingModel, msgID=msgID, contextEngineId=contextEngineId, @@ -782,10 +853,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): reportableFlag=reportableFlag, msgMaxSize=maxMessageSize, maxSizeResponseScopedPDU=maxSizeResponseScopedPDU, transportDomain=transportDomain, - transportAddress=transportAddress - ) + transportAddress=transportAddress) - debug.logger & debug.FLAG_MP and debug.logger('prepareDataElements: new stateReference %s' % stateReference) + debug.logger & debug.FLAG_MP and debug.logger( + 'prepareDataElements: new stateReference %s' % stateReference) snmpEngine.observer.storeExecutionContext( snmpEngine, 'rfc3412.prepareDataElements:confirmed', @@ -797,11 +868,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId=contextEngineId, contextName=contextName, securityEngineId=securityEngineId, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.prepareDataElements:confirmed' - ) + snmpEngine, 'rfc3412.prepareDataElements:confirmed') # 7.2.13c return (messageProcessingModel, securityModel, securityName, @@ -812,6 +882,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.2.14 if pduType in rfc3411.UNCONFIRMED_CLASS_PDUS: + # Pass new stateReference to let app browse request details stateReference = self._cache.newStateReference() @@ -825,11 +896,10 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): contextEngineId=contextEngineId, contextName=contextName, securityEngineId=securityEngineId, - pdu=pdu) - ) + pdu=pdu)) + snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.prepareDataElements:unconfirmed' - ) + snmpEngine, 'rfc3412.prepareDataElements:unconfirmed') # This is not specified explicitly in RFC smHandler.releaseStateInformation(securityStateReference) @@ -841,18 +911,22 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): stateReference) smHandler.releaseStateInformation(securityStateReference) - raise error.StatusInformation( - errorIndication=errind.unsupportedPDUtype - ) - def __expireEnginesInfo(self): - if self.__expirationTimer in self.__engineIdCacheExpQueue: - for engineKey in self.__engineIdCacheExpQueue[self.__expirationTimer]: - del self.__engineIdCache[engineKey] - debug.logger & debug.FLAG_MP and debug.logger('__expireEnginesInfo: expiring %r' % (engineKey,)) - del self.__engineIdCacheExpQueue[self.__expirationTimer] - self.__expirationTimer += 1 + raise error.StatusInformation(errorIndication=errind.unsupportedPDUtype) + + def _expireEnginesInfo(self): + if self._expirationTimer in self._engineIdCacheExpQueue: + + for engineKey in self._engineIdCacheExpQueue[self._expirationTimer]: + del self._engineIdCache[engineKey] + + debug.logger & debug.FLAG_MP and debug.logger( + '__expireEnginesInfo: expiring %r' % (engineKey,)) + + del self._engineIdCacheExpQueue[self._expirationTimer] + + self._expirationTimer += 1 def receiveTimerTick(self, snmpEngine, timeNow): - self.__expireEnginesInfo() + self._expireEnginesInfo() AbstractMessageProcessingModel.receiveTimerTick(self, snmpEngine, timeNow) diff --git a/pysnmp/proto/proxy/rfc2576.py b/pysnmp/proto/proxy/rfc2576.py index 359a3b4f..de5a5fdb 100644 --- a/pysnmp/proto/proxy/rfc2576.py +++ b/pysnmp/proto/proxy/rfc2576.py @@ -102,7 +102,8 @@ def v1ToV2(v1Pdu, origV2Pdu=None, snmpTrapCommunity=''): pduType = v1Pdu.tagSet v2Pdu = V1_TO_V2_PDU_MAP[pduType].clone() - debug.logger & debug.FLAG_PRX and debug.logger('v1ToV2: v1Pdu %s' % v1Pdu.prettyPrint()) + debug.logger & debug.FLAG_PRX and debug.logger( + 'v1ToV2: v1Pdu %s' % v1Pdu.prettyPrint()) v2VarBinds = [] @@ -114,21 +115,24 @@ def v1ToV2(v1Pdu, origV2Pdu=None, snmpTrapCommunity=''): # 3.1.2 genericTrap = v1.apiTrapPDU.getGenericTrap(v1Pdu) if genericTrap == 6: - snmpTrapOIDParam = v1.apiTrapPDU.getEnterprise(v1Pdu) + (0, int(v1.apiTrapPDU.getSpecificTrap(v1Pdu))) + snmpTrapOIDParam = (v1.apiTrapPDU.getEnterprise(v1Pdu) + + (0, int(v1.apiTrapPDU.getSpecificTrap(v1Pdu)))) # 3.1.3 else: snmpTrapOIDParam = v2c.ObjectIdentifier(V1_TO_V2_TRAP_MAP[genericTrap]) # 3.1.4 - v2VarBinds.append((v2c.apiTrapPDU.sysUpTime, sysUpTime)) - v2VarBinds.append((v2c.apiTrapPDU.snmpTrapOID, snmpTrapOIDParam)) v2VarBinds.append( - (v2c.apiTrapPDU.snmpTrapAddress, v1.apiTrapPDU.getAgentAddr(v1Pdu)) - ) - v2VarBinds.append((v2c.apiTrapPDU.snmpTrapCommunity, v2c.OctetString(snmpTrapCommunity))) - v2VarBinds.append((v2c.apiTrapPDU.snmpTrapEnterprise, - v1.apiTrapPDU.getEnterprise(v1Pdu))) + (v2c.apiTrapPDU.sysUpTime, sysUpTime)) + v2VarBinds.append( + (v2c.apiTrapPDU.snmpTrapOID, snmpTrapOIDParam)) + v2VarBinds.append( + (v2c.apiTrapPDU.snmpTrapAddress, v1.apiTrapPDU.getAgentAddr(v1Pdu))) + v2VarBinds.append( + (v2c.apiTrapPDU.snmpTrapCommunity, v2c.OctetString(snmpTrapCommunity))) + v2VarBinds.append( + (v2c.apiTrapPDU.snmpTrapEnterprise, v1.apiTrapPDU.getEnterprise(v1Pdu))) varBinds = v1.apiTrapPDU.getVarBinds(v1Pdu) @@ -142,13 +146,13 @@ def v1ToV2(v1Pdu, origV2Pdu=None, snmpTrapCommunity=''): v1Val = v1Val.getComponent() v2VarBinds.append( - (oid, V1_TO_V2_VALUE_MAP[v1Val.tagSet].clone(v1Val)) - ) + (oid, V1_TO_V2_VALUE_MAP[v1Val.tagSet].clone(v1Val))) if pduType in rfc3411.RESPONSE_CLASS_PDUS: # 4.1.2.2.1&2 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] @@ -171,13 +175,15 @@ def v1ToV2(v1Pdu, origV2Pdu=None, snmpTrapCommunity=''): v2c.apiPDU.setVarBinds(v2Pdu, v2VarBinds) - debug.logger & debug.FLAG_PRX and debug.logger('v1ToV2: v2Pdu %s' % v2Pdu.prettyPrint()) + debug.logger & debug.FLAG_PRX and debug.logger( + 'v1ToV2: v2Pdu %s' % v2Pdu.prettyPrint()) return v2Pdu def v2ToV1(v2Pdu, origV1Pdu=None): - debug.logger & debug.FLAG_PRX and debug.logger('v2ToV1: v2Pdu %s' % v2Pdu.prettyPrint()) + debug.logger & debug.FLAG_PRX and debug.logger( + 'v2ToV1: v2Pdu %s' % v2Pdu.prettyPrint()) pduType = v2Pdu.tagSet @@ -224,7 +230,8 @@ def v2ToV1(v2Pdu, origV1Pdu=None): for oid, val in v2VarBinds: # snmpTrapAddress if oid == v2c.apiTrapPDU.snmpTrapAddress: - v1.apiTrapPDU.setAgentAddr(v1Pdu, v1.IpAddress(val)) # v2c.OctetString is more constrained + # v2c.OctetString is more constrained + v1.apiTrapPDU.setAgentAddr(v1Pdu, v1.IpAddress(val)) break else: @@ -232,7 +239,8 @@ def v2ToV1(v2Pdu, origV1Pdu=None): # 3.2.3 if snmpTrapOIDParam in V2_TO_V1_TRAP_MAP: - v1.apiTrapPDU.setGenericTrap(v1Pdu, V2_TO_V1_TRAP_MAP[snmpTrapOIDParam]) + v1.apiTrapPDU.setGenericTrap( + v1Pdu, V2_TO_V1_TRAP_MAP[snmpTrapOIDParam]) else: v1.apiTrapPDU.setGenericTrap(v1Pdu, 6) @@ -273,6 +281,7 @@ def v2ToV1(v2Pdu, origV1Pdu=None): while idx >= 0: # 4.1.2.1 oid, val = v2VarBinds[idx] + if v2c.Counter64.tagSet == val.tagSet: if origV1Pdu.tagSet == v1.GetRequestPDU.tagSet: v1.apiPDU.setErrorStatus(v1Pdu, 2) @@ -298,8 +307,7 @@ def v2ToV1(v2Pdu, origV1Pdu=None): v2ErrorStatus = v2c.apiPDU.getErrorStatus(v2Pdu) if v2ErrorStatus: v1.apiPDU.setErrorStatus( - v1Pdu, V2_TO_V1_ERROR_MAP.get(v2ErrorStatus, 5) - ) + v1Pdu, V2_TO_V1_ERROR_MAP.get(v2ErrorStatus, 5)) v1.apiPDU.setErrorIndex(v1Pdu, v2c.apiPDU.getErrorIndex(v2Pdu, muteErrors=True)) elif pduType in rfc3411.CONFIRMED_CLASS_PDUS: @@ -309,6 +317,7 @@ def v2ToV1(v2Pdu, origV1Pdu=None): # Translate Var-Binds if (pduType in rfc3411.RESPONSE_CLASS_PDUS and v1.apiPDU.getErrorStatus(v1Pdu)): + v1VarBinds = v1.apiPDU.getVarBinds(origV1Pdu) else: @@ -327,6 +336,7 @@ def v2ToV1(v2Pdu, origV1Pdu=None): v1Pdu, v2c.apiPDU.getRequestID(v2Pdu) ) - debug.logger & debug.FLAG_PRX and debug.logger('v2ToV1: v1Pdu %s' % v1Pdu.prettyPrint()) + debug.logger & debug.FLAG_PRX and debug.logger( + 'v2ToV1: v1Pdu %s' % v1Pdu.prettyPrint()) return v1Pdu diff --git a/pysnmp/proto/rfc1155.py b/pysnmp/proto/rfc1155.py index e194f1c0..f78e6dc1 100644 --- a/pysnmp/proto/rfc1155.py +++ b/pysnmp/proto/rfc1155.py @@ -29,15 +29,19 @@ class IpAddress(univ.OctetString): if isinstance(value, str) and len(value) != 4: try: value = [int(x) for x in value.split('.')] - except: + + except Exception: raise error.ProtocolError('Bad IP address syntax %s' % value) + if len(value) != 4: raise error.ProtocolError('Bad IP address syntax') + return univ.OctetString.prettyIn(self, value) def prettyOut(self, value): if value: return '.'.join(['%d' % x for x in self.__class__(value).asNumbers()]) + else: return '' @@ -70,18 +74,24 @@ class NetworkAddress(univ.Choice): if the type of *value* is not allowed for this Choice instance. """ cloned = univ.Choice.clone(self, **kwargs) + if value is not univ.noValue: if isinstance(value, NetworkAddress): value = value.getComponent() + elif not isinstance(value, IpAddress): # IpAddress is the only supported type, perhaps forever because # this is SNMPv1. value = IpAddress(value) + try: tagSet = value.tagSet + except AttributeError: raise PyAsn1Error('component value %r has no tag set' % (value,)) + cloned.setComponentByType(tagSet, value) + return cloned # RFC 1212, section 4.1.6: @@ -94,17 +104,21 @@ class NetworkAddress(univ.Choice): def cloneFromName(self, value, impliedFlag, parentRow, parentIndices): kind = value[0] clone = self.clone() + if kind == 1: clone['internet'] = tuple(value[1:5]) return clone, value[5:] + else: raise SmiError('unknown NetworkAddress type %r' % (kind,)) def cloneAsName(self, impliedFlag, parentRow, parentIndices): kind = self.getName() component = self.getComponent() + if kind == 'internet': return (1,) + tuple(component.asNumbers()) + else: raise SmiError('unknown NetworkAddress type %r' % (kind,)) @@ -145,7 +159,9 @@ class TypeCoercionHackMixIn: # XXX keep this old-style class till pyasn1 types if componentType: if idx >= len(componentType): raise PyAsn1Error('Component type error out of range') + t = componentType[idx].getType() + if not t.getTagSet().isSuperTagSetOf(value.getTagSet()): raise PyAsn1Error('Component type error %r vs %r' % (t, value)) diff --git a/pysnmp/proto/rfc1157.py b/pysnmp/proto/rfc1157.py index b0ddbb08..30a26bc7 100644 --- a/pysnmp/proto/rfc1157.py +++ b/pysnmp/proto/rfc1157.py @@ -27,8 +27,9 @@ class VarBindList(univ.SequenceOf): errorStatus = univ.Integer( - namedValues=namedval.NamedValues(('noError', 0), ('tooBig', 1), ('noSuchName', 2), - ('badValue', 3), ('readOnly', 4), ('genErr', 5))) + namedValues=namedval.NamedValues( + ('noError', 0), ('tooBig', 1), ('noSuchName', 2), + ('badValue', 3), ('readOnly', 4), ('genErr', 5))) class _RequestBase(univ.Sequence): @@ -65,8 +66,10 @@ class SetRequestPDU(_RequestBase): genericTrap = univ.Integer().clone( - namedValues=namedval.NamedValues(('coldStart', 0), ('warmStart', 1), ('linkDown', 2), ('linkUp', 3), - ('authenticationFailure', 4), ('egpNeighborLoss', 5), ('enterpriseSpecific', 6))) + namedValues=namedval.NamedValues( + ('coldStart', 0), ('warmStart', 1), ('linkDown', 2), ('linkUp', 3), + ('authenticationFailure', 4), ('egpNeighborLoss', 5), + ('enterpriseSpecific', 6))) class TrapPDU(univ.Sequence): diff --git a/pysnmp/proto/rfc1902.py b/pysnmp/proto/rfc1902.py index e1c037ee..50252c36 100644 --- a/pysnmp/proto/rfc1902.py +++ b/pysnmp/proto/rfc1902.py @@ -95,7 +95,8 @@ class Integer32(univ.Integer): """ class X(cls): - subtypeSpec = cls.subtypeSpec + constraint.SingleValueConstraint(*values) + subtypeSpec = cls.subtypeSpec + constraint.SingleValueConstraint( + *values) X.__name__ = cls.__name__ return X @@ -106,7 +107,8 @@ class Integer32(univ.Integer): """ class X(cls): - subtypeSpec = cls.subtypeSpec + constraint.ValueRangeConstraint(minimum, maximum) + subtypeSpec = cls.subtypeSpec + constraint.ValueRangeConstraint( + minimum, maximum) X.__name__ = cls.__name__ return X @@ -171,6 +173,7 @@ class Integer(Integer32): *values.values()) X.__name__ = cls.__name__ + return X @@ -234,10 +237,12 @@ class OctetString(univ.OctetString): return self.fixedLength def clone(self, *args, **kwargs): - return univ.OctetString.clone(self, *args, **kwargs).setFixedLength(self.getFixedLength()) + return univ.OctetString.clone( + self, *args, **kwargs).setFixedLength(self.getFixedLength()) def subtype(self, *args, **kwargs): - return univ.OctetString.subtype(self, *args, **kwargs).setFixedLength(self.getFixedLength()) + return univ.OctetString.subtype( + self, *args, **kwargs).setFixedLength(self.getFixedLength()) @classmethod def withSize(cls, minimum, maximum): @@ -245,7 +250,8 @@ class OctetString(univ.OctetString): """ class X(cls): - subtypeSpec = cls.subtypeSpec + constraint.ValueSizeConstraint(minimum, maximum) + subtypeSpec = cls.subtypeSpec + constraint.ValueSizeConstraint( + minimum, maximum) X.__name__ = cls.__name__ return X @@ -328,11 +334,15 @@ class IpAddress(OctetString): if isinstance(value, str) and len(value) != 4: try: value = [int(x) for x in value.split('.')] - except: + + except Exception: raise error.ProtocolError('Bad IP address syntax %s' % value) + value = OctetString.prettyIn(self, value) + if len(value) != 4: raise error.ProtocolError('Bad IP address syntax') + return value def prettyOut(self, value): @@ -340,6 +350,7 @@ class IpAddress(OctetString): return '.'.join( ['%d' % x for x in self.__class__(value).asNumbers()] ) + else: return '' @@ -643,30 +654,44 @@ class Bits(OctetString): def prettyIn(self, bits): if not isinstance(bits, (tuple, list)): return OctetString.prettyIn(self, bits) # raw bitstring + octets = [] + for bit in bits: # tuple of named bits v = self.namedValues.getValue(bit) + if v is None: raise error.ProtocolError('Unknown named bit %s' % bit) + d, m = divmod(v, 8) if d >= len(octets): octets.extend([0] * (d - len(octets) + 1)) + octets[d] |= 0x01 << (7 - m) + return OctetString.prettyIn(self, octets) def prettyOut(self, value): names = [] + ints = self.__class__(value).asNumbers() + for i, v in enumerate(ints): v = ints[i] + j = 7 + while j >= 0: if v & (0x01 << j): name = self.namedValues.getName(i * 8 + 7 - j) + if name is None: name = 'UnknownBit-%s' % (i * 8 + 7 - j,) + names.append(name) + j -= 1 + return ', '.join([str(x) for x in names]) @classmethod diff --git a/pysnmp/proto/rfc1905.py b/pysnmp/proto/rfc1905.py index 6a2637e2..15f56194 100644 --- a/pysnmp/proto/rfc1905.py +++ b/pysnmp/proto/rfc1905.py @@ -90,11 +90,12 @@ class VarBindList(univ.SequenceOf): errorStatus = univ.Integer( namedValues=namedval.NamedValues( - ('noError', 0), ('tooBig', 1), ('noSuchName', 2), ('badValue', 3), ('readOnly', 4), - ('genErr', 5), ('noAccess', 6), ('wrongType', 7), ('wrongLength', 8), - ('wrongEncoding', 9), ('wrongValue', 10), ('noCreation', 11), - ('inconsistentValue', 12), ('resourceUnavailable', 13), ('commitFailed', 14), - ('undoFailed', 15), ('authorizationError', 16), ('notWritable', 17), + ('noError', 0), ('tooBig', 1), ('noSuchName', 2), ('badValue', 3), + ('readOnly', 4), ('genErr', 5), ('noAccess', 6), ('wrongType', 7), + ('wrongLength', 8), ('wrongEncoding', 9), ('wrongValue', 10), + ('noCreation', 11), ('inconsistentValue', 12), + ('resourceUnavailable', 13), ('commitFailed', 14), ('undoFailed', 15), + ('authorizationError', 16), ('notWritable', 17), ('inconsistentName', 18)) ) @@ -105,13 +106,17 @@ class PDU(univ.Sequence): namedtype.NamedType('request-id', rfc1902.Integer32()), namedtype.NamedType('error-status', errorStatus), namedtype.NamedType('error-index', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, max_bindings))), + univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint( + 0, max_bindings))), namedtype.NamedType('variable-bindings', VarBindList()) ) -nonRepeaters = univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, max_bindings)) -maxRepetitions = univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, max_bindings)) +nonRepeaters = univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, max_bindings)) +maxRepetitions = univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, max_bindings)) # Base class for bulk PDU diff --git a/pysnmp/proto/rfc3412.py b/pysnmp/proto/rfc3412.py index 7a3baa86..4e0f401c 100644 --- a/pysnmp/proto/rfc3412.py +++ b/pysnmp/proto/rfc3412.py @@ -28,6 +28,7 @@ class MsgAndPduDispatcher(object): self.mibInstrumController = instrum.MibInstrumController( builder.MibBuilder() ) + else: self.mibInstrumController = mibInstrumController @@ -37,25 +38,25 @@ class MsgAndPduDispatcher(object): ) # Requests cache - self.__cache = cache.Cache() + self._cache = cache.Cache() # Registered context engine IDs - self.__appsRegistration = {} + self._appsRegistration = {} # Source of sendPduHandle and cache of requesting apps - self.__sendPduHandle = nextid.Integer(0xffffff) + self._sendPduHandle = nextid.Integer(0xffffff) # To pass transport info to app (legacy) - self.__transportInfo = {} + self._transportInfo = {} # legacy def getTransportInfo(self, stateReference): - if stateReference in self.__transportInfo: - return self.__transportInfo[stateReference] + if stateReference in self._transportInfo: + return self._transportInfo[stateReference] + else: raise error.ProtocolError( - 'No data for stateReference %s' % stateReference - ) + 'No data for stateReference %s' % stateReference) # Application registration with dispatcher @@ -66,42 +67,45 @@ class MsgAndPduDispatcher(object): # 4.3.3 for pduType in pduTypes: - k = (contextEngineId, pduType) - if k in self.__appsRegistration: + k = contextEngineId, pduType + if k in self._appsRegistration: raise error.ProtocolError( - 'Duplicate registration %r/%s' % (contextEngineId, pduType) - ) + 'Duplicate registration %r/%s' % (contextEngineId, pduType)) # 4.3.4 - self.__appsRegistration[k] = processPdu + self._appsRegistration[k] = processPdu debug.logger & debug.FLAG_DSP and debug.logger( - 'registerContextEngineId: contextEngineId %r pduTypes %s' % (contextEngineId, pduTypes)) + 'registerContextEngineId: contextEngineId %r pduTypes ' + '%s' % (contextEngineId, pduTypes)) # 4.4.1 def unregisterContextEngineId(self, contextEngineId, pduTypes): """Unregister application with dispatcher""" + # 4.3.4 if contextEngineId is None: # Default to local snmpEngineId - contextEngineId, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', - 'snmpEngineID') + contextEngineId, = self.mibInstrumController.mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') for pduType in pduTypes: - k = (contextEngineId, pduType) - if k in self.__appsRegistration: - del self.__appsRegistration[k] + k = contextEngineId, pduType + if k in self._appsRegistration: + del self._appsRegistration[k] debug.logger & debug.FLAG_DSP and debug.logger( - 'unregisterContextEngineId: contextEngineId %r pduTypes %s' % (contextEngineId, pduTypes)) + 'unregisterContextEngineId: contextEngineId %r pduTypes ' + '%s' % (contextEngineId, pduTypes)) def getRegisteredApp(self, contextEngineId, pduType): - k = (contextEngineId, pduType) - if k in self.__appsRegistration: - return self.__appsRegistration[k] - k = (null, pduType) - if k in self.__appsRegistration: - return self.__appsRegistration[k] # wildcard + k = contextEngineId, pduType + if k in self._appsRegistration: + return self._appsRegistration[k] + + k = null, pduType + if k in self._appsRegistration: + return self._appsRegistration[k] # wildcard # Dispatcher <-> application API @@ -115,20 +119,23 @@ class MsgAndPduDispatcher(object): """PDU dispatcher -- prepare and serialize a request or notification""" # 4.1.1.2 k = int(messageProcessingModel) + if k in snmpEngine.messageProcessingSubsystems: mpHandler = snmpEngine.messageProcessingSubsystems[k] + else: raise error.StatusInformation( - errorIndication=errind.unsupportedMsgProcessingModel - ) + errorIndication=errind.unsupportedMsgProcessingModel) debug.logger & debug.FLAG_DSP and debug.logger( - 'sendPdu: securityName %s, PDU\n%s' % (securityName, PDU.prettyPrint())) + 'sendPdu: securityName %s, PDU\n' + '%s' % (securityName, PDU.prettyPrint())) # 4.1.1.3 - sendPduHandle = self.__sendPduHandle() + sendPduHandle = self._sendPduHandle() + if expectResponse: - self.__cache.add( + self._cache.add( sendPduHandle, messageProcessingModel=messageProcessingModel, sendPduHandle=sendPduHandle, @@ -137,11 +144,14 @@ class MsgAndPduDispatcher(object): cbCtx=cbCtx ) - debug.logger & debug.FLAG_DSP and debug.logger('sendPdu: current time %d ticks, one tick is %s seconds' % ( - snmpEngine.transportDispatcher.getTimerTicks(), snmpEngine.transportDispatcher.getTimerResolution())) + debug.logger & debug.FLAG_DSP and debug.logger( + 'sendPdu: current time %d ticks, one tick is %s ' + 'seconds' % (snmpEngine.transportDispatcher.getTimerTicks(), + snmpEngine.transportDispatcher.getTimerResolution())) debug.logger & debug.FLAG_DSP and debug.logger( - 'sendPdu: new sendPduHandle %s, timeout %s ticks, cbFun %s' % (sendPduHandle, timeout, cbFun)) + 'sendPdu: new sendPduHandle %s, timeout %s ticks, cbFun ' + '%s' % (sendPduHandle, timeout, cbFun)) origTransportDomain = transportDomain origTransportAddress = transportAddress @@ -157,17 +167,20 @@ class MsgAndPduDispatcher(object): pduVersion, PDU, expectResponse, sendPduHandle ) - debug.logger & debug.FLAG_DSP and debug.logger('sendPdu: MP succeeded') + debug.logger & debug.FLAG_DSP and debug.logger( + 'sendPdu: MP succeeded') + except PySnmpError: if expectResponse: - self.__cache.pop(sendPduHandle) + self._cache.pop(sendPduHandle) self.releaseStateInformation(snmpEngine, sendPduHandle, messageProcessingModel) + raise # 4.1.1.6 if snmpEngine.transportDispatcher is None: if expectResponse: - self.__cache.pop(sendPduHandle) + self._cache.pop(sendPduHandle) raise error.PySnmpError('Transport dispatcher not set') @@ -187,27 +200,30 @@ class MsgAndPduDispatcher(object): try: snmpEngine.transportDispatcher.sendMessage( - outgoingMessage, transportDomain, transportAddress - ) + outgoingMessage, transportDomain, transportAddress) + except PySnmpError: if expectResponse: - self.__cache.pop(sendPduHandle) + self._cache.pop(sendPduHandle) raise - snmpEngine.observer.clearExecutionContext(snmpEngine, 'rfc3412.sendPdu') + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.sendPdu') # Update cache with orignal req params (used for retrying) if expectResponse: - self.__cache.update(sendPduHandle, - transportDomain=origTransportDomain, - transportAddress=origTransportAddress, - securityModel=securityModel, - securityName=securityName, - securityLevel=securityLevel, - contextEngineId=contextEngineId, - contextName=contextName, - pduVersion=pduVersion, - PDU=PDU) + self._cache.update( + sendPduHandle, + transportDomain=origTransportDomain, + transportAddress=origTransportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + pduVersion=pduVersion, + PDU=PDU + ) return sendPduHandle @@ -217,17 +233,20 @@ class MsgAndPduDispatcher(object): contextEngineId, contextName, pduVersion, PDU, maxSizeResponseScopedPDU, stateReference, statusInformation): + # Extract input values and initialize defaults k = int(messageProcessingModel) + if k in snmpEngine.messageProcessingSubsystems: mpHandler = snmpEngine.messageProcessingSubsystems[k] + else: raise error.StatusInformation( - errorIndication=errind.unsupportedMsgProcessingModel - ) + errorIndication=errind.unsupportedMsgProcessingModel) debug.logger & debug.FLAG_DSP and debug.logger( - 'returnResponsePdu: PDU %s' % (PDU and PDU.prettyPrint() or "<empty>",)) + 'returnResponsePdu: PDU ' + '%s' % (PDU and PDU.prettyPrint() or "<empty>",)) # 4.1.2.2 try: @@ -240,19 +259,26 @@ class MsgAndPduDispatcher(object): statusInformation ) - debug.logger & debug.FLAG_DSP and debug.logger('returnResponsePdu: MP suceeded') + debug.logger & debug.FLAG_DSP and debug.logger( + 'returnResponsePdu: MP suceeded') except error.StatusInformation: # 4.1.2.3 raise + mibBuilder = self.mibInstrumController.mibBuilder + # Handle oversized messages XXX transport constrains? - snmpEngineMaxMessageSize, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', - 'snmpEngineMaxMessageSize') + snmpEngineMaxMessageSize, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') + if (snmpEngineMaxMessageSize.syntax and len(outgoingMessage) > snmpEngineMaxMessageSize.syntax): - snmpSilentDrops, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpSilentDrops') + + snmpSilentDrops, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpSilentDrops') snmpSilentDrops.syntax += 1 + raise error.StatusInformation(errorIndication=errind.tooBig) snmpEngine.observer.storeExecutionContext( @@ -271,45 +297,50 @@ class MsgAndPduDispatcher(object): ) # 4.1.2.4 - snmpEngine.transportDispatcher.sendMessage(outgoingMessage, - transportDomain, - transportAddress) + snmpEngine.transportDispatcher.sendMessage( + outgoingMessage, transportDomain, transportAddress) snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.returnResponsePdu' - ) + snmpEngine, 'rfc3412.returnResponsePdu') # 4.2.1 def receiveMessage(self, snmpEngine, transportDomain, transportAddress, wholeMsg): """Message dispatcher -- de-serialize message into PDU""" + mibBuilder = self.mibInstrumController.mibBuilder + # 4.2.1.1 - snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols( - '__SNMPv2-MIB', 'snmpInPkts' - ) + snmpInPkts, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpInPkts') snmpInPkts.syntax += 1 + restOfWholeMsg = null # XXX fix decoder non-recursive return + # 4.2.1.2 try: - restOfWholeMsg = null # XXX fix decoder non-recursive return msgVersion = verdec.decodeMessageVersion(wholeMsg) except error.ProtocolError: - snmpInASNParseErrs, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', - 'snmpInASNParseErrs') + snmpInASNParseErrs, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpInASNParseErrs') snmpInASNParseErrs.syntax += 1 + return null # n.b the whole buffer gets dropped - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: msgVersion %s, msg decoded' % msgVersion) + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: msgVersion %s, msg decoded' % msgVersion) messageProcessingModel = msgVersion try: - mpHandler = snmpEngine.messageProcessingSubsystems[int(messageProcessingModel)] + mpHandler = snmpEngine.messageProcessingSubsystems[ + int(messageProcessingModel)] except KeyError: - snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInBadVersions') + snmpInBadVersions, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpInBadVersions') snmpInBadVersions.syntax += 1 + return restOfWholeMsg # 4.2.1.3 -- no-op @@ -329,48 +360,56 @@ class MsgAndPduDispatcher(object): maxSizeResponseScopedPDU, statusInformation, stateReference) = mpHandler.prepareDataElements( - snmpEngine, transportDomain, transportAddress, wholeMsg - ) + snmpEngine, transportDomain, transportAddress, wholeMsg) - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: MP succeded') + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: MP succeded') except error.StatusInformation as exc: statusInformation = exc + if 'sendPduHandle' in statusInformation: # Dropped REPORT -- re-run pending reqs queue as some # of them may be waiting for this REPORT debug.logger & debug.FLAG_DSP and debug.logger( - 'receiveMessage: MP failed, statusInformation %s, forcing a retry' % statusInformation) + 'receiveMessage: MP failed, statusInformation %s, ' + 'forcing retry' % statusInformation) + self.__expireRequest( statusInformation['sendPduHandle'], - self.__cache.pop(statusInformation['sendPduHandle']), + self._cache.pop(statusInformation['sendPduHandle']), snmpEngine, - statusInformation - ) + statusInformation) + return restOfWholeMsg except PyAsn1Error as exc: - debug.logger & debug.FLAG_MP and debug.logger('receiveMessage: %s' % exc) - snmpInASNParseErrs, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInASNParseErrs') + debug.logger & debug.FLAG_MP and debug.logger( + 'receiveMessage: %s' % exc) + snmpInASNParseErrs, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpInASNParseErrs') snmpInASNParseErrs.syntax += 1 return restOfWholeMsg - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: PDU %s' % PDU.prettyPrint()) + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: PDU %s' % PDU.prettyPrint()) # 4.2.2 if sendPduHandle is None: # 4.2.2.1 (request or notification) - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: pduType %s' % pduType) + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: pduType %s' % pduType) + # 4.2.2.1.1 processPdu = self.getRegisteredApp(contextEngineId, pduType) # 4.2.2.1.2 if processPdu is None: # 4.2.2.1.2.a - snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB', - 'snmpUnknownPDUHandlers') + snmpUnknownPDUHandlers, = importSymbols( + '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers') snmpUnknownPDUHandlers.syntax += 1 # 4.2.2.1.2.b @@ -380,7 +419,8 @@ class MsgAndPduDispatcher(object): 'val': snmpUnknownPDUHandlers.syntax } - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: unhandled PDU type') + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: unhandled PDU type') # 4.2.2.1.2.c try: @@ -391,20 +431,19 @@ class MsgAndPduDispatcher(object): securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, PDU, maxSizeResponseScopedPDU, stateReference, - statusInformation - ) + statusInformation) snmpEngine.transportDispatcher.sendMessage( outgoingMessage, destTransportDomain, - destTransportAddress - ) + destTransportAddress) except PySnmpError as exc: debug.logger & debug.FLAG_DSP and debug.logger( 'receiveMessage: report failed, statusInformation %s' % exc) else: - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: reporting succeeded') + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: reporting succeeded') # 4.2.2.1.2.d return restOfWholeMsg @@ -421,42 +460,44 @@ class MsgAndPduDispatcher(object): securityLevel=securityLevel, contextEngineId=contextEngineId, contextName=contextName, - pdu=PDU) - ) + pdu=PDU)) # pass transport info to app (legacy) if stateReference is not None: - self.__transportInfo[stateReference] = ( - transportDomain, transportAddress - ) + self._transportInfo[stateReference] = ( + transportDomain, transportAddress) # 4.2.2.1.3 (asynchronous function) - processPdu(snmpEngine, messageProcessingModel, - securityModel, securityName, securityLevel, - contextEngineId, contextName, pduVersion, - PDU, maxSizeResponseScopedPDU, stateReference) + processPdu( + snmpEngine, messageProcessingModel, securityModel, + securityName, securityLevel, contextEngineId, + contextName, pduVersion, PDU, maxSizeResponseScopedPDU, + stateReference) snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.receiveMessage:request' - ) + snmpEngine, 'rfc3412.receiveMessage:request') # legacy if stateReference is not None: - del self.__transportInfo[stateReference] + del self._transportInfo[stateReference] + + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: processPdu initiated') - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: processPdu initiated') return restOfWholeMsg + else: # 4.2.2.2 (response) # 4.2.2.2.1 - cachedParams = self.__cache.pop(sendPduHandle) + cachedParams = self._cache.pop(sendPduHandle) # 4.2.2.2.2 if cachedParams is None: - snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB', - 'snmpUnknownPDUHandlers') + snmpUnknownPDUHandlers, = mibBuilder.importSymbols( + '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers') snmpUnknownPDUHandlers.syntax += 1 + return restOfWholeMsg debug.logger & debug.FLAG_DSP and debug.logger( @@ -476,42 +517,44 @@ class MsgAndPduDispatcher(object): securityLevel=securityLevel, contextEngineId=contextEngineId, contextName=contextName, - pdu=PDU) - ) + pdu=PDU)) # 4.2.2.2.4 processResponsePdu = cachedParams['cbFun'] - processResponsePdu(snmpEngine, messageProcessingModel, - securityModel, securityName, securityLevel, - contextEngineId, contextName, pduVersion, - PDU, statusInformation, - cachedParams['sendPduHandle'], - cachedParams['cbCtx']) + processResponsePdu( + snmpEngine, messageProcessingModel, securityModel, + securityName, securityLevel, contextEngineId, contextName, + pduVersion, PDU, statusInformation, + cachedParams['sendPduHandle'], + cachedParams['cbCtx']) snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3412.receiveMessage:response' - ) + snmpEngine, 'rfc3412.receiveMessage:response') - debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: processResponsePdu succeeded') + debug.logger & debug.FLAG_DSP and debug.logger( + 'receiveMessage: processResponsePdu succeeded') return restOfWholeMsg def releaseStateInformation(self, snmpEngine, sendPduHandle, messageProcessingModel): k = int(messageProcessingModel) + if k in snmpEngine.messageProcessingSubsystems: mpHandler = snmpEngine.messageProcessingSubsystems[k] mpHandler.releaseStateInformation(sendPduHandle) - self.__cache.pop(sendPduHandle) + self._cache.pop(sendPduHandle) # Cache expiration stuff # noinspection PyUnusedLocal def __expireRequest(self, cacheKey, cachedParams, snmpEngine, statusInformation=None): + timeNow = snmpEngine.transportDispatcher.getTimerTicks() + timeoutAt = cachedParams['timeout'] if statusInformation is None and timeNow < timeoutAt: @@ -519,24 +562,25 @@ class MsgAndPduDispatcher(object): processResponsePdu = cachedParams['cbFun'] - debug.logger & debug.FLAG_DSP and debug.logger('__expireRequest: req cachedParams %s' % cachedParams) + debug.logger & debug.FLAG_DSP and debug.logger( + '__expireRequest: req cachedParams %s' % cachedParams) # Fail timed-out requests if not statusInformation: statusInformation = error.StatusInformation( - errorIndication=errind.requestTimedOut - ) + errorIndication=errind.requestTimedOut) + + self.releaseStateInformation( + snmpEngine, cachedParams['sendPduHandle'], + cachedParams['messageProcessingModel']) - self.releaseStateInformation(snmpEngine, - cachedParams['sendPduHandle'], - cachedParams['messageProcessingModel']) + processResponsePdu( + snmpEngine, None, None, None, None, None, None, None, None, + statusInformation, + cachedParams['sendPduHandle'], cachedParams['cbCtx']) - processResponsePdu(snmpEngine, None, None, None, None, None, - None, None, None, statusInformation, - cachedParams['sendPduHandle'], - cachedParams['cbCtx']) return True # noinspection PyUnusedLocal def receiveTimerTick(self, snmpEngine, timeNow): - self.__cache.expire(self.__expireRequest, snmpEngine) + self._cache.expire(self.__expireRequest, snmpEngine) diff --git a/pysnmp/proto/secmod/cache.py b/pysnmp/proto/secmod/cache.py index f5843c50..1859bbad 100644 --- a/pysnmp/proto/secmod/cache.py +++ b/pysnmp/proto/secmod/cache.py @@ -21,10 +21,8 @@ class Cache(object): def pop(self, stateReference): if stateReference in self.__cacheEntries: - securityData = self.__cacheEntries[stateReference] - else: - raise error.ProtocolError( - 'Cache miss for stateReference=%s at %s' % (stateReference, self) - ) - del self.__cacheEntries[stateReference] - return securityData + return self.__cacheEntries.pop(stateReference) + + raise error.ProtocolError( + 'Cache miss for stateReference=%s at ' + '%s' % (stateReference, self)) diff --git a/pysnmp/proto/secmod/eso/priv/aes192.py b/pysnmp/proto/secmod/eso/priv/aes192.py index 7df0a0f5..cbbc748e 100644 --- a/pysnmp/proto/secmod/eso/priv/aes192.py +++ b/pysnmp/proto/secmod/eso/priv/aes192.py @@ -14,7 +14,8 @@ class AesBlumenthal192(aesbase.AbstractAesBlumenthal): http://tools.ietf.org/html/draft-blumenthal-aes-usm-04 """ - SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 1) # cusmAESCfb192PrivProtocol + # cusmAESCfb192PrivProtocol + SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 1) KEY_SIZE = 24 @@ -29,5 +30,6 @@ class Aes192(aesbase.AbstractAesReeder): Known to be used by many vendors including Cisco and others. """ - SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 101) # cusmAESCfb192PrivProtocol (non-standard OID) + # cusmAESCfb192PrivProtocol (non-standard OID) + SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 101) KEY_SIZE = 24 diff --git a/pysnmp/proto/secmod/eso/priv/aes256.py b/pysnmp/proto/secmod/eso/priv/aes256.py index 94a255ff..7ca42504 100644 --- a/pysnmp/proto/secmod/eso/priv/aes256.py +++ b/pysnmp/proto/secmod/eso/priv/aes256.py @@ -12,7 +12,8 @@ class AesBlumenthal256(aesbase.AbstractAesBlumenthal): http://tools.ietf.org/html/draft-blumenthal-aes-usm-04 """ - SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 2) # cusmAESCfb256PrivProtocol + # cusmAESCfb256PrivProtocol + SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 2) KEY_SIZE = 32 @@ -27,5 +28,6 @@ class Aes256(aesbase.AbstractAesReeder): Known to be used by many vendors including Cisco and others. """ - SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 102) # cusmAESCfb256PrivProtocol (non-standard OID) + # cusmAESCfb256PrivProtocol (non-standard OID) + SERVICE_ID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 102) KEY_SIZE = 32 diff --git a/pysnmp/proto/secmod/eso/priv/aesbase.py b/pysnmp/proto/secmod/eso/priv/aesbase.py index 0c2e5d17..3af30df0 100644 --- a/pysnmp/proto/secmod/eso/priv/aesbase.py +++ b/pysnmp/proto/secmod/eso/priv/aesbase.py @@ -24,19 +24,25 @@ class AbstractAesBlumenthal(aes.Aes): def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) - localPrivKey = localkey.localizeKey(privKey, snmpEngineID, hashAlgo) + localPrivKey = localkey.localizeKey( + privKey, snmpEngineID, hashAlgo) - # now extend this key if too short by repeating steps that includes the hashPassphrase step - for count in range(1, int(ceil(self.KEY_SIZE * 1.0 / len(localPrivKey)))): + # now extend this key if too short by repeating steps that includes + # the hashPassphrase step + rounds = int(ceil(self.KEY_SIZE * 1.0 / len(localPrivKey))) + + for _ in range(1, rounds): localPrivKey += hashAlgo(localPrivKey).digest() return localPrivKey[:self.KEY_SIZE] @@ -64,14 +70,16 @@ class AbstractAesReeder(aes.Aes): def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) localPrivKey = localkey.localizeKey(privKey, snmpEngineID, hashAlgo) diff --git a/pysnmp/proto/secmod/eso/priv/des3.py b/pysnmp/proto/secmod/eso/priv/des3.py index da84475b..8d193084 100644 --- a/pysnmp/proto/secmod/eso/priv/des3.py +++ b/pysnmp/proto/secmod/eso/priv/des3.py @@ -34,7 +34,8 @@ class Des3(base.AbstractEncryptionService): https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00 """ - SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 3) # usm3DESEDEPrivProtocol + # usm3DESEDEPrivProtocol + SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 3) KEY_SIZE = 32 local_int = random.randrange(0, 0xffffffff) @@ -42,28 +43,34 @@ class Des3(base.AbstractEncryptionService): def hashPassphrase(self, authProtocol, privKey): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) + return localkey.hashPassphrase(privKey, hashAlgo) # 2.1 def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) + localPrivKey = localkey.localizeKey(privKey, snmpEngineID, hashAlgo) # now extend this key if too short by repeating steps that includes the hashPassphrase step @@ -75,7 +82,7 @@ class Des3(base.AbstractEncryptionService): return localPrivKey[:self.KEY_SIZE] # 5.1.1.1 - def __getEncryptionKey(self, privKey, snmpEngineBoots): + def _getEncryptionKey(self, privKey, snmpEngineBoots): # 5.1.1.1.1 des3Key = privKey[:24] preIV = privKey[24:32] @@ -94,39 +101,46 @@ class Des3(base.AbstractEncryptionService): ] if self.local_int == 0xffffffff: self.local_int = 0 + else: self.local_int += 1 # salt not yet hashed XXX + iv = map(lambda x, y: x ^ y, salt, preIV.asNumbers()) + return (des3Key.asOctets(), univ.OctetString(salt).asOctets(), - univ.OctetString(map(lambda x, y: x ^ y, salt, preIV.asNumbers())).asOctets()) + univ.OctetString(iv).asOctets()) @staticmethod - def __getDecryptionKey(privKey, salt): + def _getDecryptionKey(privKey, salt): + iv = map( + lambda x, y: x ^ y, salt.asNumbers(), privKey[24:32].asNumbers()) + return (privKey[:24].asOctets(), - univ.OctetString(map(lambda x, y: x ^ y, salt.asNumbers(), privKey[24:32].asNumbers())).asOctets()) + univ.OctetString(iv).asOctets()) # 5.1.1.2 def encryptData(self, encryptKey, privParameters, dataToEncrypt): snmpEngineBoots, snmpEngineTime, salt = privParameters - des3Key, salt, iv = self.__getEncryptionKey( + des3Key, salt, iv = self._getEncryptionKey( encryptKey, snmpEngineBoots ) privParameters = univ.OctetString(salt) - plaintext = dataToEncrypt + univ.OctetString((0,) * (8 - len(dataToEncrypt) % 8)).asOctets() + plaintext = dataToEncrypt + plaintext += univ.OctetString( + (0,) * (8 - len(dataToEncrypt) % 8)).asOctets() try: ciphertext = des3.encrypt(plaintext, des3Key, iv) except PysnmpCryptoError: raise error.StatusInformation( - errorIndication=errind.unsupportedPrivProtocol - ) + errorIndication=errind.unsupportedPrivProtocol) return univ.OctetString(ciphertext), privParameters @@ -136,15 +150,13 @@ class Des3(base.AbstractEncryptionService): if len(salt) != 8: raise error.StatusInformation( - errorIndication=errind.decryptionError - ) + errorIndication=errind.decryptionError) - des3Key, iv = self.__getDecryptionKey(decryptKey, salt) + des3Key, iv = self._getDecryptionKey(decryptKey, salt) if len(encryptedData) % 8 != 0: raise error.StatusInformation( - errorIndication=errind.decryptionError - ) + errorIndication=errind.decryptionError) ciphertext = encryptedData.asOctets() @@ -153,7 +165,6 @@ class Des3(base.AbstractEncryptionService): except PysnmpCryptoError: raise error.StatusInformation( - errorIndication=errind.unsupportedPrivProtocol - ) + errorIndication=errind.unsupportedPrivProtocol) return plaintext diff --git a/pysnmp/proto/secmod/rfc2576.py b/pysnmp/proto/secmod/rfc2576.py index ba11b0fe..92b5eac2 100644 --- a/pysnmp/proto/secmod/rfc2576.py +++ b/pysnmp/proto/secmod/rfc2576.py @@ -4,9 +4,6 @@ # Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> # License: http://snmplabs.com/pysnmp/license.html # -from pyasn1.codec.ber import encoder -from pyasn1.error import PyAsn1Error - from pysnmp import debug from pysnmp.carrier.asyncore.dgram import udp from pysnmp.carrier.asyncore.dgram import udp6 @@ -15,6 +12,9 @@ from pysnmp.proto import error from pysnmp.proto.secmod import base from pysnmp.smi.error import NoSuchInstanceError +from pyasn1.codec.ber import encoder +from pyasn1.error import PyAsn1Error + class SnmpV1SecurityModel(base.AbstractSecurityModel): SECURITY_MODEL_ID = 1 @@ -26,60 +26,69 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): # in here. def __init__(self): - self.__transportBranchId = self.__paramsBranchId = self.__communityBranchId = self.__securityBranchId = -1 + self._transportBranchId = -1 + self._paramsBranchId = -1 + self._communityBranchId = -1 + self._securityBranchId = -1 + base.AbstractSecurityModel.__init__(self) def _sec2com(self, snmpEngine, securityName, contextEngineId, contextName): - snmpTargetParamsSecurityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + + snmpTargetParamsSecurityName, = mibBuilder.importSymbols( 'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityName') - if self.__paramsBranchId != snmpTargetParamsSecurityName.branchVersionId: - snmpTargetParamsSecurityModel, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + + if self._paramsBranchId != snmpTargetParamsSecurityName.branchVersionId: + snmpTargetParamsSecurityModel, = mibBuilder.importSymbols( 'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityModel') - self.__nameToModelMap = {} + self._nameToModelMap = {} nextMibNode = snmpTargetParamsSecurityName while True: try: - nextMibNode = snmpTargetParamsSecurityName.getNextNode(nextMibNode.name) + nextMibNode = snmpTargetParamsSecurityName.getNextNode( + nextMibNode.name) except NoSuchInstanceError: break instId = nextMibNode.name[len(snmpTargetParamsSecurityName.name):] - mibNode = snmpTargetParamsSecurityModel.getNode(snmpTargetParamsSecurityModel.name + instId) + mibNode = snmpTargetParamsSecurityModel.getNode( + snmpTargetParamsSecurityModel.name + instId) try: - if mibNode.syntax not in self.__nameToModelMap: - self.__nameToModelMap[nextMibNode.syntax] = set() + if mibNode.syntax not in self._nameToModelMap: + self._nameToModelMap[nextMibNode.syntax] = set() - self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax) + self._nameToModelMap[nextMibNode.syntax].add(mibNode.syntax) except PyAsn1Error: debug.logger & debug.FLAG_SM and debug.logger( - '_sec2com: table entries %r/%r hashing failed' % ( - nextMibNode.syntax, mibNode.syntax) - ) + '_sec2com: table entries %r/%r hashing ' + 'failed' % (nextMibNode.syntax, mibNode.syntax)) continue - self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId + self._paramsBranchId = snmpTargetParamsSecurityName.branchVersionId # invalidate next map as it include this one - self.__securityBranchId = -1 + self._securityBranchId = -1 - snmpCommunityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-COMMUNITY-MIB', - 'snmpCommunityName') - if self.__securityBranchId != snmpCommunityName.branchVersionId: + snmpCommunityName, = mibBuilder.importSymbols( + 'SNMP-COMMUNITY-MIB', 'snmpCommunityName') + + if self._securityBranchId != snmpCommunityName.branchVersionId: (snmpCommunitySecurityName, snmpCommunityContextEngineId, - snmpCommunityContextName) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpCommunityContextName) = mibBuilder.importSymbols( 'SNMP-COMMUNITY-MIB', 'snmpCommunitySecurityName', 'snmpCommunityContextEngineID', 'snmpCommunityContextName' ) - self.__securityMap = {} + self._securityMap = {} nextMibNode = snmpCommunityName @@ -92,54 +101,55 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): instId = nextMibNode.name[len(snmpCommunityName.name):] - _securityName = snmpCommunitySecurityName.getNode(snmpCommunitySecurityName.name + instId).syntax + _securityName = snmpCommunitySecurityName.getNode( + snmpCommunitySecurityName.name + instId).syntax _contextEngineId = snmpCommunityContextEngineId.getNode( snmpCommunityContextEngineId.name + instId).syntax - _contextName = snmpCommunityContextName.getNode(snmpCommunityContextName.name + instId).syntax + _contextName = snmpCommunityContextName.getNode( + snmpCommunityContextName.name + instId).syntax + + key = _securityName, _contextEngineId, _contextName try: - self.__securityMap[(_securityName, - _contextEngineId, - _contextName)] = nextMibNode.syntax + self._securityMap[key] = nextMibNode.syntax except PyAsn1Error: debug.logger & debug.FLAG_SM and debug.logger( - '_sec2com: table entries %r/%r/%r hashing failed' % ( - _securityName, _contextEngineId, _contextName) - ) + '_sec2com: table entries %r/%r/%r hashing failed' % key) continue - self.__securityBranchId = snmpCommunityName.branchVersionId + self._securityBranchId = snmpCommunityName.branchVersionId debug.logger & debug.FLAG_SM and debug.logger( - '_sec2com: built securityName to communityName map, version %s: %s' % ( - self.__securityBranchId, self.__securityMap)) + '_sec2com: built securityName to communityName map, version ' + '%s: %s' % (self._securityBranchId, self._securityMap)) + + key = securityName, contextEngineId, contextName try: - return self.__securityMap[(securityName, - contextEngineId, - contextName)] + return self._securityMap[key] except KeyError: raise error.StatusInformation( - errorIndication=errind.unknownCommunityName - ) + errorIndication=errind.unknownCommunityName) def _com2sec(self, snmpEngine, communityName, transportInformation): - snmpTargetAddrTAddress, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + + snmpTargetAddrTAddress, = mibBuilder.importSymbols( 'SNMP-TARGET-MIB', 'snmpTargetAddrTAddress') - if self.__transportBranchId != snmpTargetAddrTAddress.branchVersionId: + + if self._transportBranchId != snmpTargetAddrTAddress.branchVersionId: (SnmpTagValue, snmpTargetAddrTDomain, - snmpTargetAddrTagList) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpTargetAddrTagList) = mibBuilder.importSymbols( 'SNMP-TARGET-MIB', 'SnmpTagValue', 'snmpTargetAddrTDomain', - 'snmpTargetAddrTagList' - ) + 'snmpTargetAddrTagList') - self.__emptyTag = SnmpTagValue('') + self._emptyTag = SnmpTagValue('') - self.__transportToTagMap = {} + self._transportToTagMap = {} nextMibNode = snmpTargetAddrTagList @@ -151,56 +161,64 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): break instId = nextMibNode.name[len(snmpTargetAddrTagList.name):] - targetAddrTDomain = snmpTargetAddrTDomain.getNode(snmpTargetAddrTDomain.name + instId).syntax - targetAddrTAddress = snmpTargetAddrTAddress.getNode(snmpTargetAddrTAddress.name + instId).syntax + + targetAddrTDomain = snmpTargetAddrTDomain.getNode( + snmpTargetAddrTDomain.name + instId).syntax + targetAddrTAddress = snmpTargetAddrTAddress.getNode( + snmpTargetAddrTAddress.name + instId).syntax targetAddrTDomain = tuple(targetAddrTDomain) - if targetAddrTDomain[:len(udp.SNMP_UDP_DOMAIN)] == udp.SNMP_UDP_DOMAIN: - SnmpUDPAddress, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMPv2-TM', - 'SnmpUDPAddress') + if (targetAddrTDomain[:len(udp.SNMP_UDP_DOMAIN)] == + udp.SNMP_UDP_DOMAIN): + SnmpUDPAddress, = mibBuilder.importSymbols( + 'SNMPv2-TM', 'SnmpUDPAddress') targetAddrTAddress = tuple(SnmpUDPAddress(targetAddrTAddress)) - elif targetAddrTDomain[:len(udp6.SNMP_UDP6_DOMAIN)] == udp6.SNMP_UDP6_DOMAIN: - TransportAddressIPv6, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + + elif (targetAddrTDomain[:len(udp6.SNMP_UDP6_DOMAIN)] == + udp6.SNMP_UDP6_DOMAIN): + TransportAddressIPv6, = mibBuilder.importSymbols( 'TRANSPORT-ADDRESS-MIB', 'TransportAddressIPv6') + targetAddrTAddress = tuple(TransportAddressIPv6(targetAddrTAddress)) targetAddr = targetAddrTDomain, targetAddrTAddress - targetAddrTagList = snmpTargetAddrTagList.getNode(snmpTargetAddrTagList.name + instId).syntax - if targetAddr not in self.__transportToTagMap: - self.__transportToTagMap[targetAddr] = set() + targetAddrTagList = snmpTargetAddrTagList.getNode( + snmpTargetAddrTagList.name + instId).syntax + + if targetAddr not in self._transportToTagMap: + self._transportToTagMap[targetAddr] = set() try: if targetAddrTagList: - self.__transportToTagMap[targetAddr].update( + self._transportToTagMap[targetAddr].update( [SnmpTagValue(x) - for x in targetAddrTagList.asOctets().split()] - ) + for x in targetAddrTagList.asOctets().split()]) else: - self.__transportToTagMap[targetAddr].add(self.__emptyTag) + self._transportToTagMap[targetAddr].add(self._emptyTag) except PyAsn1Error: debug.logger & debug.FLAG_SM and debug.logger( '_com2sec: table entries %r/%r hashing failed' % ( - targetAddr, targetAddrTagList) - ) + targetAddr, targetAddrTagList)) continue - self.__transportBranchId = snmpTargetAddrTAddress.branchVersionId + self._transportBranchId = snmpTargetAddrTAddress.branchVersionId - debug.logger & debug.FLAG_SM and debug.logger('_com2sec: built transport-to-tag map version %s: %s' % ( - self.__transportBranchId, self.__transportToTagMap)) + debug.logger & debug.FLAG_SM and debug.logger( + '_com2sec: built transport-to-tag map version %s: ' + '%s' % (self._transportBranchId, self._transportToTagMap)) - snmpTargetParamsSecurityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpTargetParamsSecurityName, = mibBuilder.importSymbols( 'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityName') - if self.__paramsBranchId != snmpTargetParamsSecurityName.branchVersionId: - snmpTargetParamsSecurityModel, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + if self._paramsBranchId != snmpTargetParamsSecurityName.branchVersionId: + snmpTargetParamsSecurityModel, = mibBuilder.importSymbols( 'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityModel') - self.__nameToModelMap = {} + self._nameToModelMap = {} nextMibNode = snmpTargetParamsSecurityName @@ -213,43 +231,44 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): instId = nextMibNode.name[len(snmpTargetParamsSecurityName.name):] - mibNode = snmpTargetParamsSecurityModel.getNode(snmpTargetParamsSecurityModel.name + instId) + mibNode = snmpTargetParamsSecurityModel.getNode( + snmpTargetParamsSecurityModel.name + instId) try: - if nextMibNode.syntax not in self.__nameToModelMap: - self.__nameToModelMap[nextMibNode.syntax] = set() + if nextMibNode.syntax not in self._nameToModelMap: + self._nameToModelMap[nextMibNode.syntax] = set() - self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax) + self._nameToModelMap[nextMibNode.syntax].add(mibNode.syntax) except PyAsn1Error: debug.logger & debug.FLAG_SM and debug.logger( - '_com2sec: table entries %r/%r hashing failed' % ( - nextMibNode.syntax, mibNode.syntax) - ) + '_com2sec: table entries %r/%r hashing ' + 'failed' % (nextMibNode.syntax, mibNode.syntax)) continue - self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId + self._paramsBranchId = snmpTargetParamsSecurityName.branchVersionId # invalidate next map as it include this one - self.__communityBranchId = -1 + self._communityBranchId = -1 debug.logger & debug.FLAG_SM and debug.logger( - '_com2sec: built securityName to securityModel map, version %s: %s' % ( - self.__paramsBranchId, self.__nameToModelMap)) + '_com2sec: built securityName to securityModel map, version ' + '%s: %s' % (self._paramsBranchId, self._nameToModelMap)) + + snmpCommunityName, = mibBuilder.importSymbols( + 'SNMP-COMMUNITY-MIB', 'snmpCommunityName') - snmpCommunityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-COMMUNITY-MIB', - 'snmpCommunityName') - if self.__communityBranchId != snmpCommunityName.branchVersionId: + if self._communityBranchId != snmpCommunityName.branchVersionId: (snmpCommunitySecurityName, snmpCommunityContextEngineId, snmpCommunityContextName, - snmpCommunityTransportTag) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpCommunityTransportTag) = mibBuilder.importSymbols( 'SNMP-COMMUNITY-MIB', 'snmpCommunitySecurityName', 'snmpCommunityContextEngineID', 'snmpCommunityContextName', 'snmpCommunityTransportTag' ) - self.__communityToTagMap = {} - self.__tagAndCommunityToSecurityMap = {} + self._communityToTagMap = {} + self._tagAndCommunityToSecurityMap = {} nextMibNode = snmpCommunityName @@ -262,100 +281,125 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): instId = nextMibNode.name[len(snmpCommunityName.name):] - securityName = snmpCommunitySecurityName.getNode(snmpCommunitySecurityName.name + instId).syntax + securityName = snmpCommunitySecurityName.getNode( + snmpCommunitySecurityName.name + instId).syntax contextEngineId = snmpCommunityContextEngineId.getNode( snmpCommunityContextEngineId.name + instId).syntax - contextName = snmpCommunityContextName.getNode(snmpCommunityContextName.name + instId).syntax + contextName = snmpCommunityContextName.getNode( + snmpCommunityContextName.name + instId).syntax - transportTag = snmpCommunityTransportTag.getNode(snmpCommunityTransportTag.name + instId).syntax + transportTag = snmpCommunityTransportTag.getNode( + snmpCommunityTransportTag.name + instId).syntax _tagAndCommunity = transportTag, nextMibNode.syntax try: - if _tagAndCommunity not in self.__tagAndCommunityToSecurityMap: - self.__tagAndCommunityToSecurityMap[_tagAndCommunity] = set() + if _tagAndCommunity not in self._tagAndCommunityToSecurityMap: + self._tagAndCommunityToSecurityMap[_tagAndCommunity] = set() - self.__tagAndCommunityToSecurityMap[_tagAndCommunity].add( - (securityName, contextEngineId, contextName) - ) + self._tagAndCommunityToSecurityMap[_tagAndCommunity].add( + (securityName, contextEngineId, contextName)) - if nextMibNode.syntax not in self.__communityToTagMap: - self.__communityToTagMap[nextMibNode.syntax] = set() + if nextMibNode.syntax not in self._communityToTagMap: + self._communityToTagMap[nextMibNode.syntax] = set() - self.__communityToTagMap[nextMibNode.syntax].add(transportTag) + self._communityToTagMap[nextMibNode.syntax].add(transportTag) except PyAsn1Error: debug.logger & debug.FLAG_SM and debug.logger( - '_com2sec: table entries %r/%r hashing failed' % ( - _tagAndCommunity, nextMibNode.syntax) - ) + '_com2sec: table entries %r/%r hashing ' + 'failed' % (_tagAndCommunity, nextMibNode.syntax)) continue - self.__communityBranchId = snmpCommunityName.branchVersionId + self._communityBranchId = snmpCommunityName.branchVersionId debug.logger & debug.FLAG_SM and debug.logger( - '_com2sec: built communityName to tag map (securityModel %s), version %s: %s' % ( - self.SECURITY_MODEL_ID, self.__communityBranchId, self.__communityToTagMap)) + '_com2sec: built communityName to tag map ' + '(securityModel %s), version %s: ' + '%s' % (self.SECURITY_MODEL_ID, self._communityBranchId, + self._communityToTagMap)) debug.logger & debug.FLAG_SM and debug.logger( - '_com2sec: built tag & community to securityName map (securityModel %s), version %s: %s' % ( - self.SECURITY_MODEL_ID, self.__communityBranchId, self.__tagAndCommunityToSecurityMap)) - - if communityName in self.__communityToTagMap: - if transportInformation in self.__transportToTagMap: - tags = self.__transportToTagMap[transportInformation].intersection( - self.__communityToTagMap[communityName]) - elif self.__emptyTag in self.__communityToTagMap[communityName]: - tags = [self.__emptyTag] + '_com2sec: built tag & community to securityName map ' + '(securityModel %s), version %s: ' + '%s' % (self.SECURITY_MODEL_ID, self._communityBranchId, + self._tagAndCommunityToSecurityMap)) + + if communityName in self._communityToTagMap: + if transportInformation in self._transportToTagMap: + tags = self._transportToTagMap[transportInformation].intersection( + self._communityToTagMap[communityName]) + + elif self._emptyTag in self._communityToTagMap[communityName]: + tags = [self._emptyTag] + else: - raise error.StatusInformation(errorIndication=errind.unknownCommunityName) + raise error.StatusInformation( + errorIndication=errind.unknownCommunityName) candidateSecurityNames = [] - for x in [self.__tagAndCommunityToSecurityMap[(t, communityName)] for t in tags]: + securityNamesSets = [ + self._tagAndCommunityToSecurityMap[(t, communityName)] + for t in tags + ] + + for x in securityNamesSets: candidateSecurityNames.extend(list(x)) - # 5.2.1 (row selection in snmpCommunityTable) - # Picks first match but favors entries already in targets table if candidateSecurityNames: - candidateSecurityNames.sort( - key=lambda x, m=self.__nameToModelMap, v=self.SECURITY_MODEL_ID: ( - not int(x[0] in m and v in m[x[0]]), str(x[0])) - ) + candidateSecurityNames.sort(key=self._orderSecurityNames) + chosenSecurityName = candidateSecurityNames[0] # min() + debug.logger & debug.FLAG_SM and debug.logger( - '_com2sec: securityName candidates for communityName \'%s\' are %s; choosing securityName \'%s\'' % ( - communityName, candidateSecurityNames, chosenSecurityName[0])) + '_com2sec: securityName candidates for communityName %s ' + 'are %s; choosing securityName ' + '%s' % (communityName, candidateSecurityNames, + chosenSecurityName[0])) + return chosenSecurityName - raise error.StatusInformation(errorIndication=errind.unknownCommunityName) + raise error.StatusInformation( + errorIndication=errind.unknownCommunityName) + + # 5.2.1 (row selection in snmpCommunityTable) + # Picks first match but favors entries already in targets table + def _orderSecurityNames(self, securityName): + return (not int(securityName[0] in self._nameToModelMap and + self.SECURITY_MODEL_ID in self._nameToModelMap[securityName[0]]), + str(securityName[0])) def generateRequestMsg(self, snmpEngine, messageProcessingModel, globalData, maxMessageSize, securityModel, securityEngineId, securityName, securityLevel, scopedPDU): msg, = globalData + contextEngineId, contextName, pdu = scopedPDU # rfc2576: 5.2.3 - communityName = self._sec2com(snmpEngine, securityName, - contextEngineId, contextName) + communityName = self._sec2com( + snmpEngine, securityName, contextEngineId, contextName) debug.logger & debug.FLAG_SM and debug.logger( - 'generateRequestMsg: using community %r for securityModel %r, securityName %r, contextEngineId %r contextName %r' % ( - communityName, securityModel, securityName, contextEngineId, contextName)) + 'generateRequestMsg: using community %r for securityModel %r, ' + 'securityName %r, contextEngineId %r contextName ' + '%r' % (communityName, securityModel, securityName, + contextEngineId, contextName)) securityParameters = communityName msg.setComponentByPosition(1, securityParameters) msg.setComponentByPosition(2) msg.getComponentByPosition(2).setComponentByType( - pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, + matchConstraints=False) - debug.logger & debug.FLAG_MP and debug.logger('generateRequestMsg: %s' % (msg.prettyPrint(),)) + debug.logger & debug.FLAG_MP and debug.logger( + 'generateRequestMsg: %s' % (msg.prettyPrint(),)) try: return securityParameters, encoder.encode(msg) @@ -363,7 +407,9 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): except PyAsn1Error as exc: debug.logger & debug.FLAG_MP and debug.logger( 'generateRequestMsg: serialization failure: %s' % exc) - raise error.StatusInformation(errorIndication=errind.serializationError) + + raise error.StatusInformation( + errorIndication=errind.serializationError) def generateResponseMsg(self, snmpEngine, messageProcessingModel, globalData, maxMessageSize, securityModel, @@ -371,21 +417,26 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): scopedPDU, securityStateReference): # rfc2576: 5.2.2 msg, = globalData + contextEngineId, contextName, pdu = scopedPDU + cachedSecurityData = self._cache.pop(securityStateReference) + communityName = cachedSecurityData['communityName'] debug.logger & debug.FLAG_SM and debug.logger( - 'generateResponseMsg: recovered community %r by securityStateReference %s' % ( - communityName, securityStateReference)) + 'generateResponseMsg: recovered community %r by ' + 'securityStateReference ' + '%s' % (communityName, securityStateReference)) msg.setComponentByPosition(1, communityName) msg.setComponentByPosition(2) msg.getComponentByPosition(2).setComponentByType( - pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, + matchConstraints=False) - debug.logger & debug.FLAG_MP and debug.logger('generateResponseMsg: %s' % (msg.prettyPrint(),)) + debug.logger & debug.FLAG_MP and debug.logger( + 'generateResponseMsg: %s' % (msg.prettyPrint(),)) try: return communityName, encoder.encode(msg) @@ -393,11 +444,14 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): except PyAsn1Error as exc: debug.logger & debug.FLAG_MP and debug.logger( 'generateResponseMsg: serialization failure: %s' % exc) + raise error.StatusInformation(errorIndication=errind.serializationError) def processIncomingMsg(self, snmpEngine, messageProcessingModel, maxMessageSize, securityParameters, securityModel, securityLevel, wholeMsg, msg): + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder + # rfc2576: 5.2.1 communityName, transportInformation = securityParameters @@ -407,6 +461,7 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): snmpEngine.observer.storeExecutionContext( snmpEngine, 'rfc2576.processIncomingMsg:writable', scope ) + snmpEngine.observer.clearExecutionContext( snmpEngine, 'rfc2576.processIncomingMsg:writable' ) @@ -418,16 +473,17 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): ) except error.StatusInformation: - snmpInBadCommunityNames, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( + snmpInBadCommunityNames, = mibBuilder.importSymbols( '__SNMPv2-MIB', 'snmpInBadCommunityNames') snmpInBadCommunityNames.syntax += 1 + raise error.StatusInformation( errorIndication=errind.unknownCommunityName, communityName=communityName ) - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', - 'snmpEngineID') + snmpEngineID, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') securityEngineID = snmpEngineID.syntax @@ -440,24 +496,31 @@ class SnmpV1SecurityModel(base.AbstractSecurityModel): contextEngineId=contextEngineId, contextName=contextName) ) + snmpEngine.observer.clearExecutionContext( snmpEngine, 'rfc2576.processIncomingMsg' ) debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: looked up securityName %r securityModel %r contextEngineId %r contextName %r by communityName %r AND transportInformation %r' % ( - securityName, self.SECURITY_MODEL_ID, contextEngineId, contextName, communityName, transportInformation)) + 'processIncomingMsg: looked up securityName %r securityModel %r ' + 'contextEngineId %r contextName %r by communityName %r ' + 'AND transportInformation ' + '%r' % (securityName, self.SECURITY_MODEL_ID, contextEngineId, + contextName, communityName, transportInformation)) stateReference = self._cache.push(communityName=communityName) scopedPDU = (contextEngineId, contextName, msg.getComponentByPosition(2).getComponent()) + maxSizeResponseScopedPDU = maxMessageSize - 128 + securityStateReference = stateReference debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: generated maxSizeResponseScopedPDU %s securityStateReference %s' % ( - maxSizeResponseScopedPDU, securityStateReference)) + 'processIncomingMsg: generated maxSizeResponseScopedPDU ' + '%s securityStateReference ' + '%s' % (maxSizeResponseScopedPDU, securityStateReference)) return (securityEngineID, securityName, scopedPDU, maxSizeResponseScopedPDU, securityStateReference) diff --git a/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py b/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py index df3db63f..c3578682 100644 --- a/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py +++ b/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py @@ -41,11 +41,13 @@ class HmacMd5(base.AbstractAuthenticationService): # should be in the substrate. Also, it pre-sets digest placeholder # so we hash wholeMsg out of the box. # Yes, that's ugly but that's rfc... - l = wholeMsg.find(TWELVE_ZEROS) - if l == -1: + ln = wholeMsg.find(TWELVE_ZEROS) + + if ln == -1: raise error.ProtocolError('Cant locate digest placeholder') - wholeHead = wholeMsg[:l] - wholeTail = wholeMsg[l + 12:] + + wholeHead = wholeMsg[:ln] + wholeTail = wholeMsg[ln + 12:] # 6.3.1.1 @@ -56,15 +58,13 @@ class HmacMd5(base.AbstractAuthenticationService): # 6.3.1.2c k1 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD)) # 6.3.1.2d --> no-op # 6.3.1.2e k2 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD)) # 6.3.1.3 # noinspection PyDeprecation,PyCallingNonCallable @@ -83,15 +83,16 @@ class HmacMd5(base.AbstractAuthenticationService): # 6.3.2.1 & 2 if len(authParameters) != 12: raise error.StatusInformation( - errorIndication=errind.authenticationError - ) + errorIndication=errind.authenticationError) # 6.3.2.3 - l = wholeMsg.find(authParameters.asOctets()) - if l == -1: + ln = wholeMsg.find(authParameters.asOctets()) + if ln == -1: raise error.ProtocolError('Cant locate digest in wholeMsg') - wholeHead = wholeMsg[:l] - wholeTail = wholeMsg[l + 12:] + + wholeHead = wholeMsg[:ln] + wholeTail = wholeMsg[ln + 12:] + authenticatedWholeMsg = wholeHead + TWELVE_ZEROS + wholeTail # 6.3.2.4a @@ -101,15 +102,13 @@ class HmacMd5(base.AbstractAuthenticationService): # 6.3.2.4c k1 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD)) # 6.3.2.4d --> no-op # 6.3.2.4e k2 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD)) # 6.3.2.5a # noinspection PyDeprecation,PyCallingNonCallable @@ -125,7 +124,6 @@ class HmacMd5(base.AbstractAuthenticationService): # 6.3.2.6 if mac != authParameters: raise error.StatusInformation( - errorIndication=errind.authenticationFailure - ) + errorIndication=errind.authenticationFailure) return authenticatedWholeMsg diff --git a/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py b/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py index 4d5498d1..76c35af0 100644 --- a/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py +++ b/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py @@ -42,11 +42,12 @@ class HmacSha(base.AbstractAuthenticationService): # should be in the substrate. Also, it pre-sets digest placeholder # so we hash wholeMsg out of the box. # Yes, that's ugly but that's rfc... - l = wholeMsg.find(TWELVE_ZEROS) - if l == -1: + ln = wholeMsg.find(TWELVE_ZEROS) + if ln == -1: raise error.ProtocolError('Cant locate digest placeholder') - wholeHead = wholeMsg[:l] - wholeTail = wholeMsg[l + 12:] + + wholeHead = wholeMsg[:ln] + wholeTail = wholeMsg[ln + 12:] # 7.3.1.2a extendedAuthKey = authKey.asNumbers() + FORTY_FOUR_ZEROS @@ -55,15 +56,13 @@ class HmacSha(base.AbstractAuthenticationService): # 7.3.1.2c k1 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD)) # 7.3.1.2d -- no-op # 7.3.1.2e k2 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD)) # 7.3.1.3 d1 = sha1(k1.asOctets() + wholeMsg).digest() @@ -80,15 +79,16 @@ class HmacSha(base.AbstractAuthenticationService): # 7.3.2.1 & 2 if len(authParameters) != 12: raise error.StatusInformation( - errorIndication=errind.authenticationError - ) + errorIndication=errind.authenticationError) # 7.3.2.3 - l = wholeMsg.find(authParameters.asOctets()) - if l == -1: + ln = wholeMsg.find(authParameters.asOctets()) + if ln == -1: raise error.ProtocolError('Cant locate digest in wholeMsg') - wholeHead = wholeMsg[:l] - wholeTail = wholeMsg[l + 12:] + + wholeHead = wholeMsg[:ln] + wholeTail = wholeMsg[ln + 12:] + authenticatedWholeMsg = wholeHead + TWELVE_ZEROS + wholeTail # 7.3.2.4a @@ -98,15 +98,13 @@ class HmacSha(base.AbstractAuthenticationService): # 7.3.2.4c k1 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.IPAD)) # 7.3.2.4d --> no-op # 7.3.2.4e k2 = univ.OctetString( - map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD) - ) + map(lambda x, y: x ^ y, extendedAuthKey, self.OPAD)) # 7.3.2.5a d1 = sha1(k1.asOctets() + authenticatedWholeMsg).digest() @@ -120,7 +118,6 @@ class HmacSha(base.AbstractAuthenticationService): # 7.3.2.6 if mac != authParameters: raise error.StatusInformation( - errorIndication=errind.authenticationFailure - ) + errorIndication=errind.authenticationFailure) return authenticatedWholeMsg diff --git a/pysnmp/proto/secmod/rfc3414/localkey.py b/pysnmp/proto/secmod/rfc3414/localkey.py index 144342fa..bc4faa91 100644 --- a/pysnmp/proto/secmod/rfc3414/localkey.py +++ b/pysnmp/proto/secmod/rfc3414/localkey.py @@ -12,9 +12,12 @@ from pyasn1.type import univ def hashPassphrase(passphrase, hashFunc): passphrase = univ.OctetString(passphrase).asOctets() + hasher = hashFunc() + ringBuffer = passphrase * (64 // len(passphrase) + 1) ringBufferLen = len(ringBuffer) + count = 0 mark = 0 @@ -25,9 +28,11 @@ def hashPassphrase(passphrase, hashFunc): mark = e else: - hasher.update( - ringBuffer[mark:ringBufferLen] + ringBuffer[0:e - ringBufferLen] - ) + chunk = ringBuffer[mark:ringBufferLen] + chunk += ringBuffer[0:e - ringBufferLen] + + hasher.update(chunk) + mark = e - ringBufferLen count += 1 @@ -36,11 +41,13 @@ def hashPassphrase(passphrase, hashFunc): def passwordToKey(passphrase, snmpEngineId, hashFunc): - return localizeKey(hashPassphrase(passphrase, hashFunc), snmpEngineId, hashFunc) + return localizeKey( + hashPassphrase(passphrase, hashFunc), snmpEngineId, hashFunc) def localizeKey(passKey, snmpEngineId, hashFunc): passKey = univ.OctetString(passKey).asOctets() + # noinspection PyDeprecation,PyCallingNonCallable return hashFunc(passKey + snmpEngineId.asOctets() + passKey).digest() diff --git a/pysnmp/proto/secmod/rfc3414/priv/des.py b/pysnmp/proto/secmod/rfc3414/priv/des.py index 5128a662..10058aeb 100644 --- a/pysnmp/proto/secmod/rfc3414/priv/des.py +++ b/pysnmp/proto/secmod/rfc3414/priv/des.py @@ -38,32 +38,39 @@ class Des(base.AbstractEncryptionService): def hashPassphrase(self, authProtocol, privKey): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) + return localkey.hashPassphrase(privKey, hashAlgo) def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) + localPrivKey = localkey.localizeKey(privKey, snmpEngineID, hashAlgo) + return localPrivKey[:self.KEY_SIZE] # 8.1.1.1 - def __getEncryptionKey(self, privKey, snmpEngineBoots): + def _getEncryptionKey(self, privKey, snmpEngineBoots): desKey = privKey[:8] preIV = privKey[8:16] @@ -77,42 +84,47 @@ class Des(base.AbstractEncryptionService): self.local_int >> 16 & 0xff, self.local_int >> 8 & 0xff, self.local_int & 0xff] + if self.local_int == 0xffffffff: self.local_int = 0 + else: self.local_int += 1 + iv = map(lambda x, y: x ^ y, salt, preIV.asNumbers()) + return (desKey.asOctets(), univ.OctetString(salt).asOctets(), - univ.OctetString(map(lambda x, y: x ^ y, salt, preIV.asNumbers())).asOctets()) + univ.OctetString(iv).asOctets()) @staticmethod - def __getDecryptionKey(privKey, salt): - return (privKey[:8].asOctets(), - univ.OctetString(map(lambda x, y: x ^ y, salt.asNumbers(), privKey[8:16].asNumbers())).asOctets()) + def _getDecryptionKey(privKey, salt): + iv = map(lambda x, y: x ^ y, salt.asNumbers(), + privKey[8:16].asNumbers()) + + return privKey[:8].asOctets(), univ.OctetString(iv).asOctets() # 8.2.4.1 def encryptData(self, encryptKey, privParameters, dataToEncrypt): snmpEngineBoots, snmpEngineTime, salt = privParameters # 8.3.1.1 - desKey, salt, iv = self.__getEncryptionKey( - encryptKey, snmpEngineBoots - ) + desKey, salt, iv = self._getEncryptionKey(encryptKey, snmpEngineBoots) # 8.3.1.2 privParameters = univ.OctetString(salt) # 8.1.1.2 - plaintext = dataToEncrypt + univ.OctetString((0,) * (8 - len(dataToEncrypt) % 8)).asOctets() + plaintext = dataToEncrypt + plaintext += univ.OctetString( + (0,) * (8 - len(dataToEncrypt) % 8)).asOctets() try: ciphertext = des.encrypt(plaintext, desKey, iv) except PysnmpCryptoError: raise error.StatusInformation( - errorIndication=errind.unsupportedPrivProtocol - ) + errorIndication=errind.unsupportedPrivProtocol) # 8.3.1.3 & 4 return univ.OctetString(ciphertext), privParameters @@ -124,19 +136,17 @@ class Des(base.AbstractEncryptionService): # 8.3.2.1 if len(salt) != 8: raise error.StatusInformation( - errorIndication=errind.decryptionError - ) + errorIndication=errind.decryptionError) # 8.3.2.2 no-op # 8.3.2.3 - desKey, iv = self.__getDecryptionKey(decryptKey, salt) + desKey, iv = self._getDecryptionKey(decryptKey, salt) # 8.3.2.4 -> 8.1.1.3 if len(encryptedData) % 8 != 0: raise error.StatusInformation( - errorIndication=errind.decryptionError - ) + errorIndication=errind.decryptionError) try: # 8.3.2.6 @@ -144,5 +154,4 @@ class Des(base.AbstractEncryptionService): except PysnmpCryptoError: raise error.StatusInformation( - errorIndication=errind.unsupportedPrivProtocol - ) + errorIndication=errind.unsupportedPrivProtocol) diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py index f9bf056b..0a8f54e5 100644 --- a/pysnmp/proto/secmod/rfc3414/service.py +++ b/pysnmp/proto/secmod/rfc3414/service.py @@ -38,15 +38,26 @@ from pysnmp.smi.error import NoSuchInstanceError class UsmSecurityParameters(rfc1155.TypeCoercionHackMixIn, univ.Sequence): componentType = namedtype.NamedTypes( - namedtype.NamedType('msgAuthoritativeEngineId', univ.OctetString()), - namedtype.NamedType('msgAuthoritativeEngineBoots', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), - namedtype.NamedType('msgAuthoritativeEngineTime', - univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), - namedtype.NamedType('msgUserName', - univ.OctetString().subtype(subtypeSpec=constraint.ValueSizeConstraint(0, 32))), - namedtype.NamedType('msgAuthenticationParameters', univ.OctetString()), - namedtype.NamedType('msgPrivacyParameters', univ.OctetString()) + namedtype.NamedType( + 'msgAuthoritativeEngineId', univ.OctetString()), + namedtype.NamedType( + 'msgAuthoritativeEngineBoots', + univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), + namedtype.NamedType( + 'msgAuthoritativeEngineTime', + univ.Integer().subtype( + subtypeSpec=constraint.ValueRangeConstraint(0, 2147483647))), + namedtype.NamedType( + 'msgUserName', + univ.OctetString().subtype( + subtypeSpec=constraint.ValueSizeConstraint(0, 32))), + namedtype.NamedType( + 'msgAuthenticationParameters', + univ.OctetString()), + namedtype.NamedType( + 'msgPrivacyParameters', + univ.OctetString()) ) @@ -56,10 +67,14 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): AUTH_SERVICES = { hmacmd5.HmacMd5.SERVICE_ID: hmacmd5.HmacMd5(), hmacsha.HmacSha.SERVICE_ID: hmacsha.HmacSha(), - hmacsha2.HmacSha2.SHA224_SERVICE_ID: hmacsha2.HmacSha2(hmacsha2.HmacSha2.SHA224_SERVICE_ID), - hmacsha2.HmacSha2.SHA256_SERVICE_ID: hmacsha2.HmacSha2(hmacsha2.HmacSha2.SHA256_SERVICE_ID), - hmacsha2.HmacSha2.SHA384_SERVICE_ID: hmacsha2.HmacSha2(hmacsha2.HmacSha2.SHA384_SERVICE_ID), - hmacsha2.HmacSha2.SHA512_SERVICE_ID: hmacsha2.HmacSha2(hmacsha2.HmacSha2.SHA512_SERVICE_ID), + hmacsha2.HmacSha2.SHA224_SERVICE_ID: hmacsha2.HmacSha2( + hmacsha2.HmacSha2.SHA224_SERVICE_ID), + hmacsha2.HmacSha2.SHA256_SERVICE_ID: hmacsha2.HmacSha2( + hmacsha2.HmacSha2.SHA256_SERVICE_ID), + hmacsha2.HmacSha2.SHA384_SERVICE_ID: hmacsha2.HmacSha2( + hmacsha2.HmacSha2.SHA384_SERVICE_ID), + hmacsha2.HmacSha2.SHA512_SERVICE_ID: hmacsha2.HmacSha2( + hmacsha2.HmacSha2.SHA512_SERVICE_ID), noauth.NoAuth.SERVICE_ID: noauth.NoAuth(), } @@ -76,21 +91,23 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): def __init__(self): AbstractSecurityModel.__init__(self) - self.__securityParametersSpec = UsmSecurityParameters() - self.__timeline = {} - self.__timelineExpQueue = {} - self.__expirationTimer = 0 - self.__paramsBranchId = -1 + self._securityParametersSpec = UsmSecurityParameters() + self._timeline = {} + self._timelineExpQueue = {} + self._expirationTimer = 0 + self._paramsBranchId = -1 - def __sec2usr(self, snmpEngine, securityName, securityEngineID=None): + def _sec2usr(self, snmpEngine, securityName, securityEngineID=None): mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder - usmUserEngineID, = mibBuilder.importSymbols('SNMP-USER-BASED-SM-MIB', - 'usmUserEngineID') - if self.__paramsBranchId != usmUserEngineID.branchVersionId: + + usmUserEngineID, = mibBuilder.importSymbols( + 'SNMP-USER-BASED-SM-MIB', 'usmUserEngineID') + + if self._paramsBranchId != usmUserEngineID.branchVersionId: usmUserName, usmUserSecurityName = mibBuilder.importSymbols( 'SNMP-USER-BASED-SM-MIB', 'usmUserName', 'usmUserSecurityName') - self.__securityToUserMap = {} + self._securityToUserMap = {} nextMibNode = usmUserEngineID @@ -99,108 +116,138 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): nextMibNode = usmUserEngineID.getNextNode(nextMibNode.name) except NoSuchInstanceError: - self.__paramsBranchId = usmUserEngineID.branchVersionId + self._paramsBranchId = usmUserEngineID.branchVersionId + debug.logger & debug.FLAG_SM and debug.logger( - '_sec2usr: built snmpEngineId + securityName to userName map, version %s: %r' % ( - self.__paramsBranchId, self.__securityToUserMap)) + '_sec2usr: built snmpEngineId + securityName to ' + 'userName map, version %s: %r' % ( + self._paramsBranchId, self._securityToUserMap)) break instId = nextMibNode.name[len(usmUserSecurityName.name):] - __engineID = usmUserEngineID.getNode(usmUserEngineID.name + instId).syntax - __userName = usmUserName.getNode(usmUserName.name + instId).syntax - __securityName = usmUserSecurityName.getNode(usmUserSecurityName.name + instId).syntax + _engineID = usmUserEngineID.getNode( + usmUserEngineID.name + instId).syntax + _userName = usmUserName.getNode( + usmUserName.name + instId).syntax + _securityName = usmUserSecurityName.getNode( + usmUserSecurityName.name + instId).syntax - k = __engineID, __securityName + k = _engineID, _securityName # first (lesser) securityName wins - if k not in self.__securityToUserMap: - self.__securityToUserMap[k] = __userName + if k not in self._securityToUserMap: + self._securityToUserMap[k] = _userName if securityEngineID is None: - snmpEngineID, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineID, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') securityEngineID = snmpEngineID.syntax try: - userName = self.__securityToUserMap[(securityEngineID, securityName)] + userName = self._securityToUserMap[(securityEngineID, securityName)] + except KeyError: debug.logger & debug.FLAG_SM and debug.logger( - '_sec2usr: no entry exists for snmpEngineId %r, securityName %r' % (securityEngineID, securityName)) + '_sec2usr: no entry exists for snmpEngineId %r, securityName ' + '%r' % (securityEngineID, securityName)) raise NoSuchInstanceError() # emulate MIB lookup debug.logger & debug.FLAG_SM and debug.logger( - '_sec2usr: using userName %r for snmpEngineId %r, securityName %r' % ( - userName, securityEngineID, securityName)) + '_sec2usr: using userName %r for snmpEngineId %r, securityName ' + '%r' % (userName, securityEngineID, securityName)) return userName @staticmethod - def __getUserInfo(mibInstrumController, securityEngineID, userName): - usmUserEntry, = mibInstrumController.mibBuilder.importSymbols( - 'SNMP-USER-BASED-SM-MIB', 'usmUserEntry' - ) + def _getUserInfo(mibInstrumController, securityEngineID, userName): + mibBuilder = mibInstrumController.mibBuilder + + usmUserEntry, = mibBuilder.importSymbols( + 'SNMP-USER-BASED-SM-MIB', 'usmUserEntry') + tblIdx = usmUserEntry.getInstIdFromIndices(securityEngineID, userName) + # Get userName & securityName usmUserName = usmUserEntry.getNode(usmUserEntry.name + (2,) + tblIdx).syntax usmUserSecurityName = usmUserEntry.getNode(usmUserEntry.name + (3,) + tblIdx).syntax + # Get protocols usmUserAuthProtocol = usmUserEntry.getNode(usmUserEntry.name + (5,) + tblIdx).syntax usmUserPrivProtocol = usmUserEntry.getNode(usmUserEntry.name + (8,) + tblIdx).syntax + # Get keys - pysnmpUsmKeyEntry, = mibInstrumController.mibBuilder.importSymbols( - 'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry' - ) - pysnmpUsmKeyAuthLocalized = pysnmpUsmKeyEntry.getNode(pysnmpUsmKeyEntry.name + (1,) + tblIdx).syntax - pysnmpUsmKeyPrivLocalized = pysnmpUsmKeyEntry.getNode(pysnmpUsmKeyEntry.name + (2,) + tblIdx).syntax + pysnmpUsmKeyEntry, = mibBuilder.importSymbols( + 'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry') + + pysnmpUsmKeyAuthLocalized = pysnmpUsmKeyEntry.getNode( + pysnmpUsmKeyEntry.name + (1,) + tblIdx).syntax + pysnmpUsmKeyPrivLocalized = pysnmpUsmKeyEntry.getNode( + pysnmpUsmKeyEntry.name + (2,) + tblIdx).syntax + return (usmUserName, usmUserSecurityName, usmUserAuthProtocol, pysnmpUsmKeyAuthLocalized, usmUserPrivProtocol, pysnmpUsmKeyPrivLocalized) - def __cloneUserInfo(self, snmpEngine, securityEngineID, userName): + def _cloneUserInfo(self, snmpEngine, securityEngineID, userName): mibInstrumController = snmpEngine.msgAndPduDsp.mibInstrumController + mibBuilder = mibInstrumController.mibBuilder + + snmpEngineID, = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') - snmpEngineID, = mibInstrumController.mibBuilder.importSymbols( - '__SNMP-FRAMEWORK-MIB', 'snmpEngineID' - ) # Proto entry - usmUserEntry, = mibInstrumController.mibBuilder.importSymbols( - 'SNMP-USER-BASED-SM-MIB', 'usmUserEntry' - ) + usmUserEntry, = mibBuilder.importSymbols( + 'SNMP-USER-BASED-SM-MIB', 'usmUserEntry') + tblIdx1 = usmUserEntry.getInstIdFromIndices( - snmpEngineID.syntax, userName - ) + snmpEngineID.syntax, userName) + # Get proto protocols - usmUserName = usmUserEntry.getNode(usmUserEntry.name + (2,) + tblIdx1) - usmUserSecurityName = usmUserEntry.getNode(usmUserEntry.name + (3,) + tblIdx1) - usmUserCloneFrom = usmUserEntry.getNode(usmUserEntry.name + (4,) + tblIdx1) - usmUserAuthProtocol = usmUserEntry.getNode(usmUserEntry.name + (5,) + tblIdx1) - usmUserPrivProtocol = usmUserEntry.getNode(usmUserEntry.name + (8,) + tblIdx1) + usmUserName = usmUserEntry.getNode( + usmUserEntry.name + (2,) + tblIdx1) + usmUserSecurityName = usmUserEntry.getNode( + usmUserEntry.name + (3,) + tblIdx1) + usmUserCloneFrom = usmUserEntry.getNode( + usmUserEntry.name + (4,) + tblIdx1) + usmUserAuthProtocol = usmUserEntry.getNode( + usmUserEntry.name + (5,) + tblIdx1) + usmUserPrivProtocol = usmUserEntry.getNode( + usmUserEntry.name + (8,) + tblIdx1) + # Get proto keys - pysnmpUsmKeyEntry, = mibInstrumController.mibBuilder.importSymbols( - 'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry' - ) - pysnmpUsmKeyAuth = pysnmpUsmKeyEntry.getNode(pysnmpUsmKeyEntry.name + (3,) + tblIdx1) - pysnmpUsmKeyPriv = pysnmpUsmKeyEntry.getNode(pysnmpUsmKeyEntry.name + (4,) + tblIdx1) + pysnmpUsmKeyEntry, = mibBuilder.importSymbols( + 'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry') + + pysnmpUsmKeyAuth = pysnmpUsmKeyEntry.getNode( + pysnmpUsmKeyEntry.name + (3,) + tblIdx1) + pysnmpUsmKeyPriv = pysnmpUsmKeyEntry.getNode( + pysnmpUsmKeyEntry.name + (4,) + tblIdx1) # Create new row from proto values - tblIdx2 = usmUserEntry.getInstIdFromIndices(securityEngineID, userName) + tblIdx2 = usmUserEntry.getInstIdFromIndices( + securityEngineID, userName) # New inactive row mibInstrumController.writeMibObjects( - (usmUserEntry.name + (13,) + tblIdx2, 5), snmpEngine=snmpEngine - ) + (usmUserEntry.name + (13,) + tblIdx2, 5), snmpEngine=snmpEngine) # Set user&securityNames - usmUserEntry.getNode(usmUserEntry.name + (2,) + tblIdx2).syntax = usmUserName.syntax - usmUserEntry.getNode(usmUserEntry.name + (3,) + tblIdx2).syntax = usmUserSecurityName.syntax + usmUserEntry.getNode( + usmUserEntry.name + (2,) + tblIdx2).syntax = usmUserName.syntax + usmUserEntry.getNode( + usmUserEntry.name + (3,) + tblIdx2).syntax = usmUserSecurityName.syntax # Store a reference to original row - usmUserEntry.getNode(usmUserEntry.name + (4,) + tblIdx2).syntax = usmUserCloneFrom.syntax.clone(tblIdx1) + usmUserEntry.getNode( + usmUserEntry.name + (4,) + tblIdx2).syntax = usmUserCloneFrom.syntax.clone(tblIdx1) # Set protocols - usmUserEntry.getNode(usmUserEntry.name + (5,) + tblIdx2).syntax = usmUserAuthProtocol.syntax - usmUserEntry.getNode(usmUserEntry.name + (8,) + tblIdx2).syntax = usmUserPrivProtocol.syntax + usmUserEntry.getNode( + usmUserEntry.name + (5,) + tblIdx2).syntax = usmUserAuthProtocol.syntax + usmUserEntry.getNode( + usmUserEntry.name + (8,) + tblIdx2).syntax = usmUserPrivProtocol.syntax # Activate row mibInstrumController.writeMibObjects( @@ -208,98 +255,124 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): ) # Localize and set keys - pysnmpUsmKeyEntry, = mibInstrumController.mibBuilder.importSymbols( - 'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry' - ) + pysnmpUsmKeyEntry, = mibBuilder.importSymbols( + 'PYSNMP-USM-MIB', 'pysnmpUsmKeyEntry') pysnmpUsmKeyAuthLocalized = pysnmpUsmKeyEntry.getNode( - pysnmpUsmKeyEntry.name + (1,) + tblIdx2 - ) + pysnmpUsmKeyEntry.name + (1,) + tblIdx2) + if usmUserAuthProtocol.syntax in self.AUTH_SERVICES: localizeKey = self.AUTH_SERVICES[usmUserAuthProtocol.syntax].localizeKey - localAuthKey = localizeKey(pysnmpUsmKeyAuth.syntax, - securityEngineID) + localAuthKey = localizeKey( + pysnmpUsmKeyAuth.syntax, securityEngineID) + else: raise error.StatusInformation( - errorIndication=errind.unsupportedAuthProtocol - ) + errorIndication=errind.unsupportedAuthProtocol) + if localAuthKey is not None: pysnmpUsmKeyAuthLocalized.syntax = pysnmpUsmKeyAuthLocalized.syntax.clone(localAuthKey) + pysnmpUsmKeyPrivLocalized = pysnmpUsmKeyEntry.getNode( - pysnmpUsmKeyEntry.name + (2,) + tblIdx2 - ) + pysnmpUsmKeyEntry.name + (2,) + tblIdx2) + if usmUserPrivProtocol.syntax in self.PRIV_SERVICES: localizeKey = self.PRIV_SERVICES[usmUserPrivProtocol.syntax].localizeKey - localPrivKey = localizeKey(usmUserAuthProtocol.syntax, - pysnmpUsmKeyPriv.syntax, - securityEngineID) + localPrivKey = localizeKey( + usmUserAuthProtocol.syntax, pysnmpUsmKeyPriv.syntax, + securityEngineID) + else: - raise error.StatusInformation(errorIndication=errind.unsupportedPrivProtocol) + raise error.StatusInformation( + errorIndication=errind.unsupportedPrivProtocol) + if localPrivKey is not None: pysnmpUsmKeyPrivLocalized.syntax = pysnmpUsmKeyPrivLocalized.syntax.clone(localPrivKey) + return (usmUserName.syntax, usmUserSecurityName.syntax, usmUserAuthProtocol.syntax, pysnmpUsmKeyAuthLocalized.syntax, usmUserPrivProtocol.syntax, pysnmpUsmKeyPrivLocalized.syntax) - def __generateRequestOrResponseMsg(self, snmpEngine, - messageProcessingModel, - globalData, maxMessageSize, - securityModel, securityEngineID, - securityName, securityLevel, - scopedPDU, securityStateReference): + def _generateRequestOrResponseMsg(self, snmpEngine, + messageProcessingModel, + globalData, maxMessageSize, + securityModel, securityEngineID, + securityName, securityLevel, + scopedPDU, securityStateReference): + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder - snmpEngineID = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax + + snmpEngineID = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax # 3.1.1 if securityStateReference is not None: # 3.1.1a cachedSecurityData = self._cache.pop(securityStateReference) + usmUserName = cachedSecurityData['msgUserName'] + if 'usmUserSecurityName' in cachedSecurityData: usmUserSecurityName = cachedSecurityData['usmUserSecurityName'] + else: usmUserSecurityName = usmUserName + if 'usmUserAuthProtocol' in cachedSecurityData: usmUserAuthProtocol = cachedSecurityData['usmUserAuthProtocol'] + else: usmUserAuthProtocol = noauth.NoAuth.SERVICE_ID + if 'usmUserAuthKeyLocalized' in cachedSecurityData: usmUserAuthKeyLocalized = cachedSecurityData['usmUserAuthKeyLocalized'] + else: usmUserAuthKeyLocalized = None + if 'usmUserPrivProtocol' in cachedSecurityData: usmUserPrivProtocol = cachedSecurityData['usmUserPrivProtocol'] + else: usmUserPrivProtocol = nopriv.NoPriv.SERVICE_ID + if 'usmUserPrivKeyLocalized' in cachedSecurityData: usmUserPrivKeyLocalized = cachedSecurityData['usmUserPrivKeyLocalized'] + else: usmUserPrivKeyLocalized = None + securityEngineID = snmpEngineID - debug.logger & debug.FLAG_SM and debug.logger('__generateRequestOrResponseMsg: user info read from cache') + + debug.logger & debug.FLAG_SM and debug.logger( + '__generateRequestOrResponseMsg: user info read from cache') + elif securityName: # 3.1.1b try: (usmUserName, usmUserSecurityName, usmUserAuthProtocol, usmUserAuthKeyLocalized, usmUserPrivProtocol, - usmUserPrivKeyLocalized) = self.__getUserInfo( + usmUserPrivKeyLocalized) = self._getUserInfo( snmpEngine.msgAndPduDsp.mibInstrumController, securityEngineID, - self.__sec2usr(snmpEngine, securityName, securityEngineID) + self._sec2usr(snmpEngine, securityName, securityEngineID) ) - debug.logger & debug.FLAG_SM and debug.logger('__generateRequestOrResponseMsg: read user info') + debug.logger & debug.FLAG_SM and debug.logger( + '__generateRequestOrResponseMsg: read user info') except NoSuchInstanceError: - pysnmpUsmDiscovery, = mibBuilder.importSymbols('__PYSNMP-USM-MIB', 'pysnmpUsmDiscovery') + pysnmpUsmDiscovery, = mibBuilder.importSymbols( + '__PYSNMP-USM-MIB', 'pysnmpUsmDiscovery') + reportUnknownName = not pysnmpUsmDiscovery.syntax + if not reportUnknownName: try: (usmUserName, usmUserSecurityName, usmUserAuthProtocol, usmUserAuthKeyLocalized, usmUserPrivProtocol, - usmUserPrivKeyLocalized) = self.__cloneUserInfo( - snmpEngine, - securityEngineID, - self.__sec2usr(snmpEngine, securityName) + usmUserPrivKeyLocalized) = self._cloneUserInfo( + snmpEngine, securityEngineID, + self._sec2usr(snmpEngine, securityName) ) except NoSuchInstanceError: @@ -307,31 +380,40 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): if reportUnknownName: raise error.StatusInformation( - errorIndication=errind.unknownSecurityName - ) + errorIndication=errind.unknownSecurityName) - debug.logger & debug.FLAG_SM and debug.logger('__generateRequestOrResponseMsg: clone user info') + debug.logger & debug.FLAG_SM and debug.logger( + '__generateRequestOrResponseMsg: clone user info') except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( '__generateRequestOrResponseMsg: %s' % exc) - snmpInGenErrs, = mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInGenErrs') + + snmpInGenErrs, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpInGenErrs') snmpInGenErrs.syntax += 1 - raise error.StatusInformation( - errorIndication=errind.invalidMsg - ) + + raise error.StatusInformation(errorIndication=errind.invalidMsg) + else: # empty username used for engineID discovery usmUserName = usmUserSecurityName = null usmUserAuthProtocol = noauth.NoAuth.SERVICE_ID usmUserPrivProtocol = nopriv.NoPriv.SERVICE_ID + usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None - debug.logger & debug.FLAG_SM and debug.logger('__generateRequestOrResponseMsg: use empty USM data') + + debug.logger & debug.FLAG_SM and debug.logger( + '__generateRequestOrResponseMsg: use empty USM data') # noinspection PyUnboundLocalVariable debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: local usmUserName %r usmUserSecurityName %r usmUserAuthProtocol %s usmUserPrivProtocol %s securityEngineID %r securityName %r' % ( - usmUserName, usmUserSecurityName, usmUserAuthProtocol, usmUserPrivProtocol, securityEngineID, securityName)) + '__generateRequestOrResponseMsg: local usmUserName %r ' + 'usmUserSecurityName %r usmUserAuthProtocol %s ' + 'usmUserPrivProtocol %s securityEngineID %r ' + 'securityName %r' % ( + usmUserName, usmUserSecurityName, usmUserAuthProtocol, + usmUserPrivProtocol, securityEngineID, securityName)) msg = globalData @@ -340,22 +422,21 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): if (usmUserAuthProtocol == noauth.NoAuth.SERVICE_ID or usmUserPrivProtocol == nopriv.NoPriv.SERVICE_ID): raise error.StatusInformation( - errorIndication=errind.unsupportedSecurityLevel - ) + errorIndication=errind.unsupportedSecurityLevel) # 3.1.3 if securityLevel == 3 or securityLevel == 2: if usmUserAuthProtocol == noauth.NoAuth.SERVICE_ID: raise error.StatusInformation( - errorIndication=errind.unsupportedSecurityLevel - ) + errorIndication=errind.unsupportedSecurityLevel) - securityParameters = self.__securityParametersSpec + securityParameters = self._securityParametersSpec scopedPDUData = msg.setComponentByPosition(3).getComponentByPosition(3) + scopedPDUData.setComponentByPosition( - 0, scopedPDU, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, scopedPDU, verifyConstraints=False, matchTags=False, + matchConstraints=False) snmpEngineBoots = snmpEngineTime = 0 @@ -364,161 +445,180 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): # 3.1.6.b if pdu.tagSet in rfc3411.UNCONFIRMED_CLASS_PDUS: - (snmpEngineBoots, - snmpEngineTime) = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots', 'snmpEngineTime') + snmpEngineBoots, snmpEngineTime = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots', + 'snmpEngineTime') snmpEngineBoots = snmpEngineBoots.syntax snmpEngineTime = snmpEngineTime.syntax.clone() debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: read snmpEngineBoots, snmpEngineTime from LCD') + '__generateRequestOrResponseMsg: read snmpEngineBoots, ' + 'snmpEngineTime from LCD') # 3.1.6a - elif securityEngineID in self.__timeline: + elif securityEngineID in self._timeline: (snmpEngineBoots, snmpEngineTime, latestReceivedEngineTime, - latestUpdateTimestamp) = self.__timeline[securityEngineID] + latestUpdateTimestamp) = self._timeline[securityEngineID] debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: read snmpEngineBoots, snmpEngineTime from timeline') + '__generateRequestOrResponseMsg: read snmpEngineBoots, ' + 'snmpEngineTime from timeline') # 3.1.6.c else: debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: assuming zero snmpEngineBoots, snmpEngineTime') + '__generateRequestOrResponseMsg: assuming zero ' + 'snmpEngineBoots, snmpEngineTime') debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: use snmpEngineBoots %s snmpEngineTime %s for securityEngineID %r' % ( + '__generateRequestOrResponseMsg: use snmpEngineBoots %s ' + 'snmpEngineTime %s for securityEngineID %r' % ( snmpEngineBoots, snmpEngineTime, securityEngineID)) # 3.1.4a if securityLevel == 3: if usmUserPrivProtocol in self.PRIV_SERVICES: privHandler = self.PRIV_SERVICES[usmUserPrivProtocol] + else: raise error.StatusInformation( - errorIndication=errind.encryptionError - ) + errorIndication=errind.encryptionError) debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: scopedPDU %s' % scopedPDU.prettyPrint()) + '__generateRequestOrResponseMsg: scopedPDU ' + '%s' % scopedPDU.prettyPrint()) try: dataToEncrypt = encoder.encode(scopedPDU) except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: scopedPDU serialization error: %s' % exc) + '__generateRequestOrResponseMsg: scopedPDU serialization ' + 'error: %s' % exc) raise error.StatusInformation( - errorIndication=errind.serializationError - ) + errorIndication=errind.serializationError) debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: scopedPDU encoded into %s' % debug.hexdump(dataToEncrypt)) + '__generateRequestOrResponseMsg: scopedPDU encoded into ' + '%s' % debug.hexdump(dataToEncrypt)) # noinspection PyUnboundLocalVariable - (encryptedData, - privParameters) = privHandler.encryptData( + encryptedData, privParameters = privHandler.encryptData( usmUserPrivKeyLocalized, - (snmpEngineBoots, snmpEngineTime, None), dataToEncrypt - ) + (snmpEngineBoots, snmpEngineTime, None), + dataToEncrypt) securityParameters.setComponentByPosition( - 5, privParameters, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 5, privParameters, verifyConstraints=False, matchTags=False, + matchConstraints=False) + scopedPDUData.setComponentByPosition( - 1, encryptedData, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, encryptedData, verifyConstraints=False, matchTags=False, + matchConstraints=False) debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: scopedPDU ciphered into %s' % debug.hexdump(encryptedData)) + '__generateRequestOrResponseMsg: scopedPDU ciphered into ' + '%s' % debug.hexdump(encryptedData)) # 3.1.4b elif securityLevel == 1 or securityLevel == 2: securityParameters.setComponentByPosition(5, '') - debug.logger & debug.FLAG_SM and debug.logger('__generateRequestOrResponseMsg: %s' % scopedPDUData.prettyPrint()) + debug.logger & debug.FLAG_SM and debug.logger( + '__generateRequestOrResponseMsg: %s' % scopedPDUData.prettyPrint()) # 3.1.5 securityParameters.setComponentByPosition( - 0, securityEngineID, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 0, securityEngineID, verifyConstraints=False, matchTags=False, + matchConstraints=False) + securityParameters.setComponentByPosition( - 1, snmpEngineBoots, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 1, snmpEngineBoots, verifyConstraints=False, matchTags=False, + matchConstraints=False) + securityParameters.setComponentByPosition( - 2, snmpEngineTime, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 2, snmpEngineTime, verifyConstraints=False, matchTags=False, + matchConstraints=False) # 3.1.7 securityParameters.setComponentByPosition( - 3, usmUserName, verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 3, usmUserName, verifyConstraints=False, matchTags=False, + matchConstraints=False) # 3.1.8a if securityLevel == 3 or securityLevel == 2: if usmUserAuthProtocol in self.AUTH_SERVICES: authHandler = self.AUTH_SERVICES[usmUserAuthProtocol] + else: raise error.StatusInformation( - errorIndication=errind.authenticationFailure - ) + errorIndication=errind.authenticationFailure) # extra-wild hack to facilitate BER substrate in-place re-write securityParameters.setComponentByPosition( - 4, '\x00' * authHandler.digestLength - ) + 4, '\x00' * authHandler.digestLength) debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: %s' % (securityParameters.prettyPrint(),)) + '__generateRequestOrResponseMsg: ' + '%s' % (securityParameters.prettyPrint(),)) try: - msg.setComponentByPosition(2, encoder.encode(securityParameters), verifyConstraints=False) + msg.setComponentByPosition( + 2, encoder.encode(securityParameters), + verifyConstraints=False) except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: securityParameters serialization error: %s' % exc) + '__generateRequestOrResponseMsg: securityParameters ' + 'serialization error: %s' % exc) + raise error.StatusInformation( - errorIndication=errind.serializationError - ) + errorIndication=errind.serializationError) debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: auth outgoing msg: %s' % msg.prettyPrint()) + '__generateRequestOrResponseMsg: auth outgoing msg: ' + '%s' % msg.prettyPrint()) try: wholeMsg = encoder.encode(msg) except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: msg serialization error: %s' % exc) + '__generateRequestOrResponseMsg: msg serialization ' + 'error: %s' % exc) + raise error.StatusInformation( - errorIndication=errind.serializationError - ) + errorIndication=errind.serializationError) # noinspection PyUnboundLocalVariable authenticatedWholeMsg = authHandler.authenticateOutgoingMsg( - usmUserAuthKeyLocalized, wholeMsg - ) + usmUserAuthKeyLocalized, wholeMsg) # 3.1.8b else: securityParameters.setComponentByPosition( - 4, '', verifyConstraints=False, matchTags=False, matchConstraints=False - ) + 4, '', verifyConstraints=False, matchTags=False, + matchConstraints=False) debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: %s' % (securityParameters.prettyPrint(),)) + '__generateRequestOrResponseMsg: ' + '%s' % (securityParameters.prettyPrint(),)) try: - msg.setComponentByPosition(2, encoder.encode(securityParameters), verifyConstraints=False, matchTags=False, matchConstraints=False) + msg.setComponentByPosition( + 2, encoder.encode(securityParameters), verifyConstraints=False, + matchTags=False, matchConstraints=False) except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: secutiryParameters serialization error: %s' % exc) + '__generateRequestOrResponseMsg: securityParameters ' + 'serialization error: %s' % exc) + raise error.StatusInformation( - errorIndication=errind.serializationError - ) + errorIndication=errind.serializationError) try: debug.logger & debug.FLAG_SM and debug.logger( @@ -527,13 +627,16 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( - '__generateRequestOrResponseMsg: msg serialization error: %s' % exc) + '__generateRequestOrResponseMsg: msg serialization error: ' + '%s' % exc) + raise error.StatusInformation( - errorIndication=errind.serializationError - ) + errorIndication=errind.serializationError) - debug.logger & debug.FLAG_SM and debug.logger('__generateRequestOrResponseMsg: %s outgoing msg: %s' % ( - securityLevel > 1 and "authenticated" or "plain", debug.hexdump(authenticatedWholeMsg))) + debug.logger & debug.FLAG_SM and debug.logger( + '__generateRequestOrResponseMsg: %s outgoing msg: ' + '%s' % (securityLevel > 1 and "authenticated" or + "plain", debug.hexdump(authenticatedWholeMsg))) # 3.1.9 return msg.getComponentByPosition(2), authenticatedWholeMsg @@ -542,88 +645,99 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): globalData, maxMessageSize, securityModel, securityEngineID, securityName, securityLevel, scopedPDU): - return self.__generateRequestOrResponseMsg(snmpEngine, - messageProcessingModel, - globalData, - maxMessageSize, - securityModel, - securityEngineID, - securityName, - securityLevel, - scopedPDU, - None) + + return self._generateRequestOrResponseMsg( + snmpEngine, messageProcessingModel, globalData, + maxMessageSize, securityModel, securityEngineID, + securityName, securityLevel, scopedPDU, None) def generateResponseMsg(self, snmpEngine, messageProcessingModel, globalData, maxMessageSize, securityModel, securityEngineID, securityName, securityLevel, scopedPDU, securityStateReference): - return self.__generateRequestOrResponseMsg( + + return self._generateRequestOrResponseMsg( snmpEngine, messageProcessingModel, globalData, maxMessageSize, securityModel, securityEngineID, - securityName, securityLevel, scopedPDU, securityStateReference + securityName, securityLevel, scopedPDU, + securityStateReference ) # 3.2 def processIncomingMsg(self, snmpEngine, messageProcessingModel, maxMessageSize, securityParameters, securityModel, securityLevel, wholeMsg, msg): + mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder # 3.2.9 -- moved up here to be able to report # maxSizeResponseScopedPDU on error # (48 - maximum SNMPv3 header length) - maxSizeResponseScopedPDU = int(maxMessageSize) - len(securityParameters) - 48 + maxSizeResponseScopedPDU = (int(maxMessageSize) - + len(securityParameters) - 48) debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: securityParameters %s' % debug.hexdump(securityParameters)) + 'processIncomingMsg: securityParameters ' + '%s' % debug.hexdump(securityParameters)) # 3.2.1 securityParameters, rest = decoder.decode( - securityParameters, asn1Spec=self.__securityParametersSpec - ) + securityParameters, asn1Spec=self._securityParametersSpec) - debug.logger & debug.FLAG_SM and debug.logger('processIncomingMsg: %s' % (securityParameters.prettyPrint(),)) + debug.logger & debug.FLAG_SM and debug.logger( + 'processIncomingMsg: %s' % (securityParameters.prettyPrint(),)) if eoo.endOfOctets.isSameTypeWith(securityParameters): raise error.StatusInformation(errorIndication=errind.parseError) # 3.2.2 msgAuthoritativeEngineId = securityParameters.getComponentByPosition(0) + securityStateReference = self._cache.push( msgUserName=securityParameters.getComponentByPosition(3) ) debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: cache write securityStateReference %s by msgUserName %s' % ( - securityStateReference, securityParameters.getComponentByPosition(3))) + 'processIncomingMsg: cache write securityStateReference %s by ' + 'msgUserName %s' % (securityStateReference, + securityParameters.getComponentByPosition(3))) scopedPduData = msg.getComponentByPosition(3) # Used for error reporting - contextEngineId = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax + contextEngineId = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax contextName = null - snmpEngineID = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax + snmpEngineID = mibBuilder.importSymbols( + '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax # 3.2.3 if (msgAuthoritativeEngineId != snmpEngineID and - msgAuthoritativeEngineId not in self.__timeline): + msgAuthoritativeEngineId not in self._timeline): + if (msgAuthoritativeEngineId and 4 < len(msgAuthoritativeEngineId) < 33): # 3.2.3a - cloned user when request was sent debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: non-synchronized securityEngineID %r' % (msgAuthoritativeEngineId,)) + 'processIncomingMsg: non-synchronized securityEngineID ' + '%r' % (msgAuthoritativeEngineId,)) + else: # 3.2.3b debug.logger & debug.FLAG_SM and debug.logger( 'processIncomingMsg: peer requested snmpEngineID discovery') + usmStatsUnknownEngineIDs, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownEngineIDs') usmStatsUnknownEngineIDs.syntax += 1 + debug.logger & debug.FLAG_SM and debug.logger( 'processIncomingMsg: null or malformed msgAuthoritativeEngineId') + pysnmpUsmDiscoverable, = mibBuilder.importSymbols( '__PYSNMP-USM-MIB', 'pysnmpUsmDiscoverable') + if pysnmpUsmDiscoverable.syntax: debug.logger & debug.FLAG_SM and debug.logger( 'processIncomingMsg: starting snmpEngineID discovery procedure') @@ -631,10 +745,11 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): # Report original contextName if scopedPduData.getName() != 'plaintext': debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: scopedPduData not plaintext %s' % scopedPduData.prettyPrint()) + 'processIncomingMsg: scopedPduData not plaintext ' + '%s' % scopedPduData.prettyPrint()) + raise error.StatusInformation( - errorIndication=errind.unknownEngineID - ) + errorIndication=errind.unknownEngineID) # 7.2.6.a.1 scopedPdu = scopedPduData.getComponent() @@ -653,16 +768,18 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): maxSizeResponseScopedPDU=maxSizeResponseScopedPDU ) else: - debug.logger & debug.FLAG_SM and debug.logger('processIncomingMsg: will not discover EngineID') + debug.logger & debug.FLAG_SM and debug.logger( + 'processIncomingMsg: will not discover EngineID') + # free securityStateReference XXX raise error.StatusInformation( - errorIndication=errind.unknownEngineID - ) + errorIndication=errind.unknownEngineID) msgUserName = securityParameters.getComponentByPosition(3) debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: read from securityParams msgAuthoritativeEngineId %r msgUserName %r' % ( + 'processIncomingMsg: read from securityParams ' + 'msgAuthoritativeEngineId %r msgUserName %r' % ( msgAuthoritativeEngineId, msgUserName)) if msgUserName: @@ -673,16 +790,17 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): usmUserAuthProtocol, usmUserAuthKeyLocalized, usmUserPrivProtocol, - usmUserPrivKeyLocalized) = self.__getUserInfo( + usmUserPrivKeyLocalized) = self._getUserInfo( snmpEngine.msgAndPduDsp.mibInstrumController, msgAuthoritativeEngineId, msgUserName ) - debug.logger & debug.FLAG_SM and debug.logger('processIncomingMsg: read user info from LCD') + debug.logger & debug.FLAG_SM and debug.logger( + 'processIncomingMsg: read user info from LCD') except NoSuchInstanceError: debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: unknown securityEngineID %r msgUserName %r' % ( - msgAuthoritativeEngineId, msgUserName)) + 'processIncomingMsg: unknown securityEngineID %r ' + 'msgUserName %r' % (msgAuthoritativeEngineId, msgUserName)) usmStatsUnknownUserNames, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames') @@ -701,10 +819,15 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): ) except PyAsn1Error as exc: - debug.logger & debug.FLAG_SM and debug.logger('processIncomingMsg: %s' % exc) - snmpInGenErrs, = mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInGenErrs') + debug.logger & debug.FLAG_SM and debug.logger( + 'processIncomingMsg: %s' % exc) + + snmpInGenErrs, = mibBuilder.importSymbols( + '__SNMPv2-MIB', 'snmpInGenErrs') snmpInGenErrs.syntax += 1 + raise error.StatusInformation(errorIndication=errind.invalidMsg) + else: # empty username used for engineID discovery usmUserName = usmUserSecurityName = null @@ -713,11 +836,14 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: now have usmUserName %r usmUserSecurityName %r usmUserAuthProtocol %r usmUserPrivProtocol %r for msgUserName %r' % ( - usmUserName, usmUserSecurityName, usmUserAuthProtocol, usmUserPrivProtocol, msgUserName)) + 'processIncomingMsg: now have usmUserName %r usmUserSecurityName ' + '%r usmUserAuthProtocol %r usmUserPrivProtocol %r for msgUserName ' + '%r' % (usmUserName, usmUserSecurityName, usmUserAuthProtocol, + usmUserPrivProtocol, msgUserName)) # 3.2.11 (moved up here to let Reports be authenticated & encrypted) self._cache.pop(securityStateReference) + securityStateReference = self._cache.push( msgUserName=securityParameters.getComponentByPosition(3), usmUserSecurityName=usmUserSecurityName, @@ -743,21 +869,24 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): privKey=usmUserPrivKeyLocalized) ) snmpEngine.observer.clearExecutionContext( - snmpEngine, 'rfc3414.processIncomingMsg' - ) + snmpEngine, 'rfc3414.processIncomingMsg') # 3.2.5 if msgAuthoritativeEngineId == snmpEngineID: # Authoritative SNMP engine: make sure securityLevel is sufficient badSecIndication = None + if securityLevel == 3: if usmUserAuthProtocol == noauth.NoAuth.SERVICE_ID: badSecIndication = 'authPriv wanted while auth not expected' + if usmUserPrivProtocol == nopriv.NoPriv.SERVICE_ID: badSecIndication = 'authPriv wanted while priv not expected' + elif securityLevel == 2: if usmUserAuthProtocol == noauth.NoAuth.SERVICE_ID: badSecIndication = 'authNoPriv wanted while auth not expected' + if usmUserPrivProtocol != nopriv.NoPriv.SERVICE_ID: # 4 (discovery phase always uses authenticated messages) if msgAuthoritativeEngineBoots or msgAuthoritativeEngineTime: @@ -766,15 +895,20 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): elif securityLevel == 1: if usmUserAuthProtocol != noauth.NoAuth.SERVICE_ID: badSecIndication = 'noAuthNoPriv wanted while auth expected' + if usmUserPrivProtocol != nopriv.NoPriv.SERVICE_ID: badSecIndication = 'noAuthNoPriv wanted while priv expected' + if badSecIndication: usmStatsUnsupportedSecLevels, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnsupportedSecLevels') + usmStatsUnsupportedSecLevels.syntax += 1 + debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: reporting inappropriate security level for user %s: %s' % ( - msgUserName, badSecIndication)) + 'processIncomingMsg: reporting inappropriate security ' + 'level for user %s: %s' % (msgUserName, badSecIndication)) + raise error.StatusInformation( errorIndication=errind.unsupportedSecurityLevel, oid=usmStatsUnsupportedSecLevels.name, @@ -791,22 +925,23 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): if securityLevel == 3 or securityLevel == 2: if usmUserAuthProtocol in self.AUTH_SERVICES: authHandler = self.AUTH_SERVICES[usmUserAuthProtocol] + else: raise error.StatusInformation( - errorIndication=errind.authenticationFailure - ) + errorIndication=errind.authenticationFailure) try: authHandler.authenticateIncomingMsg( usmUserAuthKeyLocalized, securityParameters.getComponentByPosition(4), - wholeMsg - ) + wholeMsg) except error.StatusInformation: usmStatsWrongDigests, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsWrongDigests') + usmStatsWrongDigests.syntax += 1 + raise error.StatusInformation( errorIndication=errind.authenticationFailure, oid=usmStatsWrongDigests.name, @@ -819,62 +954,81 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): maxSizeResponseScopedPDU=maxSizeResponseScopedPDU ) - debug.logger & debug.FLAG_SM and debug.logger('processIncomingMsg: incoming msg authenticated') + debug.logger & debug.FLAG_SM and debug.logger( + 'processIncomingMsg: incoming msg authenticated') # synchronize time with authed peer - self.__timeline[msgAuthoritativeEngineId] = ( + self._timeline[msgAuthoritativeEngineId] = ( securityParameters.getComponentByPosition(1), securityParameters.getComponentByPosition(2), securityParameters.getComponentByPosition(2), int(time.time()) ) - timerResolution = snmpEngine.transportDispatcher is None and 1.0 or snmpEngine.transportDispatcher.getTimerResolution() - expireAt = int(self.__expirationTimer + 300 / timerResolution) - if expireAt not in self.__timelineExpQueue: - self.__timelineExpQueue[expireAt] = [] - self.__timelineExpQueue[expireAt].append(msgAuthoritativeEngineId) + timerResolution = (snmpEngine.transportDispatcher is None and 1.0 or + snmpEngine.transportDispatcher.getTimerResolution()) + + expireAt = int(self._expirationTimer + 300 / timerResolution) + + if expireAt not in self._timelineExpQueue: + self._timelineExpQueue[expireAt] = [] + + self._timelineExpQueue[expireAt].append(msgAuthoritativeEngineId) debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: store timeline for securityEngineID %r' % (msgAuthoritativeEngineId,)) + 'processIncomingMsg: store timeline for securityEngineID ' + '%r' % (msgAuthoritativeEngineId,)) # 3.2.7 if securityLevel == 3 or securityLevel == 2: if msgAuthoritativeEngineId == snmpEngineID: # Authoritative SNMP engine: use local notion (SF bug #1649032) - (snmpEngineBoots, - snmpEngineTime) = mibBuilder.importSymbols( + snmpEngineBoots, snmpEngineTime = mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots', 'snmpEngineTime') + snmpEngineBoots = snmpEngineBoots.syntax snmpEngineTime = snmpEngineTime.syntax.clone() + idleTime = 0 + debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: read snmpEngineBoots (%s), snmpEngineTime (%s) from LCD' % ( + 'processIncomingMsg: read snmpEngineBoots (%s), ' + 'snmpEngineTime (%s) from LCD' % ( snmpEngineBoots, snmpEngineTime)) + else: # Non-authoritative SNMP engine: use cached estimates - if msgAuthoritativeEngineId in self.__timeline: + if msgAuthoritativeEngineId in self._timeline: (snmpEngineBoots, snmpEngineTime, latestReceivedEngineTime, - latestUpdateTimestamp) = self.__timeline[ + latestUpdateTimestamp) = self._timeline[ msgAuthoritativeEngineId ] + # time passed since last talk with this SNMP engine idleTime = int(time.time()) - latestUpdateTimestamp + debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: read timeline snmpEngineBoots %s snmpEngineTime %s for msgAuthoritativeEngineId %r, idle time %s secs' % ( - snmpEngineBoots, snmpEngineTime, msgAuthoritativeEngineId, idleTime)) + 'processIncomingMsg: read timeline snmpEngineBoots %s ' + 'snmpEngineTime %s for msgAuthoritativeEngineId %r, ' + 'idle time %s secs' % (snmpEngineBoots, snmpEngineTime, + msgAuthoritativeEngineId, + idleTime)) else: raise error.ProtocolError('Peer SNMP engine info missing') # 3.2.7a if msgAuthoritativeEngineId == snmpEngineID: + if (snmpEngineBoots == 2147483647 or snmpEngineBoots != msgAuthoritativeEngineBoots or - abs(idleTime + int(snmpEngineTime) - int(msgAuthoritativeEngineTime)) > 150): + (abs(idleTime + int(snmpEngineTime) + - int(msgAuthoritativeEngineTime))) > 150): + usmStatsNotInTimeWindows, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsNotInTimeWindows') usmStatsNotInTimeWindows.syntax += 1 + raise error.StatusInformation( errorIndication=errind.notInTimeWindow, oid=usmStatsNotInTimeWindows.name, @@ -886,6 +1040,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): msgUserName=msgUserName, maxSizeResponseScopedPDU=maxSizeResponseScopedPDU ) + # 3.2.7b else: # 3.2.7b.1 @@ -893,48 +1048,60 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): if (msgAuthoritativeEngineBoots > snmpEngineBoots or msgAuthoritativeEngineBoots == snmpEngineBoots and msgAuthoritativeEngineTime > latestReceivedEngineTime): - self.__timeline[msgAuthoritativeEngineId] = ( + self._timeline[msgAuthoritativeEngineId] = ( msgAuthoritativeEngineBoots, msgAuthoritativeEngineTime, msgAuthoritativeEngineTime, int(time.time()) ) - timerResolution = snmpEngine.transportDispatcher is None and 1.0 or snmpEngine.transportDispatcher.getTimerResolution() - expireAt = int(self.__expirationTimer + 300 / timerResolution) - if expireAt not in self.__timelineExpQueue: - self.__timelineExpQueue[expireAt] = [] - self.__timelineExpQueue[expireAt].append(msgAuthoritativeEngineId) + timerResolution = ( + snmpEngine.transportDispatcher is None and 1.0 or + snmpEngine.transportDispatcher.getTimerResolution()) + + expireAt = int(self._expirationTimer + 300 / timerResolution) + + if expireAt not in self._timelineExpQueue: + self._timelineExpQueue[expireAt] = [] + + self._timelineExpQueue[expireAt].append(msgAuthoritativeEngineId) debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: stored timeline msgAuthoritativeEngineBoots %s msgAuthoritativeEngineTime %s for msgAuthoritativeEngineId %r' % ( - msgAuthoritativeEngineBoots, msgAuthoritativeEngineTime, msgAuthoritativeEngineId)) + 'processIncomingMsg: stored timeline ' + 'msgAuthoritativeEngineBoots %s ' + 'msgAuthoritativeEngineTime %s for ' + 'msgAuthoritativeEngineId ' + '%r' % (msgAuthoritativeEngineBoots, + msgAuthoritativeEngineTime, + msgAuthoritativeEngineId)) # 3.2.7b.2 if (snmpEngineBoots == 2147483647 or msgAuthoritativeEngineBoots < snmpEngineBoots or msgAuthoritativeEngineBoots == snmpEngineBoots and - abs(idleTime + int(snmpEngineTime) - int(msgAuthoritativeEngineTime)) > 150): + (abs(idleTime + int(snmpEngineTime) + - int(msgAuthoritativeEngineTime))) > 150): + raise error.StatusInformation( errorIndication=errind.notInTimeWindow, - msgUserName=msgUserName - ) + msgUserName=msgUserName) # 3.2.8a if securityLevel == 3: if usmUserPrivProtocol in self.PRIV_SERVICES: privHandler = self.PRIV_SERVICES[usmUserPrivProtocol] + else: raise error.StatusInformation( errorIndication=errind.decryptionError, - msgUserName=msgUserName - ) + msgUserName=msgUserName) + encryptedPDU = scopedPduData.getComponentByPosition(1) + if encryptedPDU is None: # no ciphertext raise error.StatusInformation( errorIndication=errind.decryptionError, - msgUserName=msgUserName - ) + msgUserName=msgUserName) try: decryptedData = privHandler.decryptData( @@ -942,15 +1109,17 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): (securityParameters.getComponentByPosition(1), securityParameters.getComponentByPosition(2), securityParameters.getComponentByPosition(5)), - encryptedPDU - ) + encryptedPDU) + debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: PDU deciphered into %s' % debug.hexdump(decryptedData)) + 'processIncomingMsg: PDU deciphered into ' + '%s' % debug.hexdump(decryptedData)) except error.StatusInformation: usmStatsDecryptionErrors, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsDecryptionErrors') usmStatsDecryptionErrors.syntax += 1 + raise error.StatusInformation( errorIndication=errind.decryptionError, oid=usmStatsDecryptionErrors.name, @@ -962,31 +1131,32 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): msgUserName=msgUserName, maxSizeResponseScopedPDU=maxSizeResponseScopedPDU ) - scopedPduSpec = scopedPduData.setComponentByPosition(0).getComponentByPosition(0) + scopedPduSpec = scopedPduData.setComponentByPosition( + 0).getComponentByPosition(0) + try: scopedPDU, rest = decoder.decode(decryptedData, asn1Spec=scopedPduSpec) except PyAsn1Error as exc: debug.logger & debug.FLAG_SM and debug.logger( 'processIncomingMsg: scopedPDU decoder failed %s' % exc) + raise error.StatusInformation( errorIndication=errind.decryptionError, - msgUserName=msgUserName - ) + msgUserName=msgUserName) if eoo.endOfOctets.isSameTypeWith(scopedPDU): raise error.StatusInformation( errorIndication=errind.decryptionError, - msgUserName=msgUserName - ) + msgUserName=msgUserName) + else: # 3.2.8b scopedPDU = scopedPduData.getComponentByPosition(0) if scopedPDU is None: # no plaintext raise error.StatusInformation( errorIndication=errind.decryptionError, - msgUserName=msgUserName - ) + msgUserName=msgUserName) debug.logger & debug.FLAG_SM and debug.logger( 'processIncomingMsg: scopedPDU decoded %s' % scopedPDU.prettyPrint()) @@ -995,7 +1165,8 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): securityName = usmUserSecurityName debug.logger & debug.FLAG_SM and debug.logger( - 'processIncomingMsg: cached msgUserName %s info by securityStateReference %s' % ( + 'processIncomingMsg: cached msgUserName %s info by ' + 'securityStateReference %s' % ( msgUserName, securityStateReference)) # Delayed to include details @@ -1003,6 +1174,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): usmStatsUnknownUserNames, = mibBuilder.importSymbols( '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames') usmStatsUnknownUserNames.syntax += 1 + raise error.StatusInformation( errorIndication=errind.unknownSecurityName, oid=usmStatsUnknownUserNames.name, @@ -1021,14 +1193,18 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): return (msgAuthoritativeEngineId, securityName, scopedPDU, maxSizeResponseScopedPDU, securityStateReference) - def __expireTimelineInfo(self): - if self.__expirationTimer in self.__timelineExpQueue: - for engineIdKey in self.__timelineExpQueue[self.__expirationTimer]: - if engineIdKey in self.__timeline: - del self.__timeline[engineIdKey] - debug.logger & debug.FLAG_SM and debug.logger('__expireTimelineInfo: expiring %r' % (engineIdKey,)) - del self.__timelineExpQueue[self.__expirationTimer] - self.__expirationTimer += 1 + def _expireTimelineInfo(self): + if self._expirationTimer in self._timelineExpQueue: + + for engineIdKey in self._timelineExpQueue[self._expirationTimer]: + if engineIdKey in self._timeline: + del self._timeline[engineIdKey] + debug.logger & debug.FLAG_SM and debug.logger( + '__expireTimelineInfo: expiring %r' % (engineIdKey,)) + + del self._timelineExpQueue[self._expirationTimer] + + self._expirationTimer += 1 def receiveTimerTick(self, snmpEngine, timeNow): - self.__expireTimelineInfo() + self._expireTimelineInfo() diff --git a/pysnmp/proto/secmod/rfc3826/priv/aes.py b/pysnmp/proto/secmod/rfc3826/priv/aes.py index 56f69280..d000f8ed 100644 --- a/pysnmp/proto/secmod/rfc3826/priv/aes.py +++ b/pysnmp/proto/secmod/rfc3826/priv/aes.py @@ -38,66 +38,85 @@ class Aes(base.AbstractEncryptionService): local_int = random.randrange(0, 0xffffffffffffffff) # 3.1.2.1 - def __getEncryptionKey(self, privKey, snmpEngineBoots, snmpEngineTime): - salt = [self.local_int >> 56 & 0xff, - self.local_int >> 48 & 0xff, - self.local_int >> 40 & 0xff, - self.local_int >> 32 & 0xff, - self.local_int >> 24 & 0xff, - self.local_int >> 16 & 0xff, - self.local_int >> 8 & 0xff, - self.local_int & 0xff] + def _getEncryptionKey(self, privKey, snmpEngineBoots, snmpEngineTime): + salt = [ + self.local_int >> 56 & 0xff, + self.local_int >> 48 & 0xff, + self.local_int >> 40 & 0xff, + self.local_int >> 32 & 0xff, + self.local_int >> 24 & 0xff, + self.local_int >> 16 & 0xff, + self.local_int >> 8 & 0xff, + self.local_int & 0xff + ] if self.local_int == 0xffffffffffffffff: self.local_int = 0 + else: self.local_int += 1 - return self.__getDecryptionKey(privKey, snmpEngineBoots, snmpEngineTime, salt) + ( - univ.OctetString(salt).asOctets(),) + key, iv = self._getDecryptionKey( + privKey, snmpEngineBoots, snmpEngineTime, salt) + + return key, iv, univ.OctetString(salt).asOctets() + + def _getDecryptionKey(self, privKey, snmpEngineBoots, + snmpEngineTime, salt): - def __getDecryptionKey(self, privKey, snmpEngineBoots, - snmpEngineTime, salt): snmpEngineBoots, snmpEngineTime, salt = ( - int(snmpEngineBoots), int(snmpEngineTime), salt - ) + int(snmpEngineBoots), int(snmpEngineTime), salt) + + iv = [ + snmpEngineBoots >> 24 & 0xff, + snmpEngineBoots >> 16 & 0xff, + snmpEngineBoots >> 8 & 0xff, + snmpEngineBoots & 0xff, + snmpEngineTime >> 24 & 0xff, + snmpEngineTime >> 16 & 0xff, + snmpEngineTime >> 8 & 0xff, + snmpEngineTime & 0xff + ] - iv = [snmpEngineBoots >> 24 & 0xff, - snmpEngineBoots >> 16 & 0xff, - snmpEngineBoots >> 8 & 0xff, - snmpEngineBoots & 0xff, - snmpEngineTime >> 24 & 0xff, - snmpEngineTime >> 16 & 0xff, - snmpEngineTime >> 8 & 0xff, - snmpEngineTime & 0xff] + salt + iv += salt - return privKey[:self.KEY_SIZE].asOctets(), univ.OctetString(iv).asOctets() + key = privKey[:self.KEY_SIZE].asOctets() + iv = univ.OctetString(iv).asOctets() + + return key, iv def hashPassphrase(self, authProtocol, privKey): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) + return localkey.hashPassphrase(privKey, hashAlgo) def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.SERVICE_ID: hashAlgo = md5 + elif authProtocol == hmacsha.HmacSha.SERVICE_ID: hashAlgo = sha1 + elif authProtocol in hmacsha2.HmacSha2.HASH_ALGORITHM: hashAlgo = hmacsha2.HmacSha2.HASH_ALGORITHM[authProtocol] + else: raise error.ProtocolError( - 'Unknown auth protocol %s' % (authProtocol,) - ) + 'Unknown auth protocol %s' % (authProtocol,)) + localPrivKey = localkey.localizeKey(privKey, snmpEngineID, hashAlgo) + return localPrivKey[:self.KEY_SIZE] # 3.2.4.1 @@ -105,21 +124,20 @@ class Aes(base.AbstractEncryptionService): snmpEngineBoots, snmpEngineTime, salt = privParameters # 3.3.1.1 - aesKey, iv, salt = self.__getEncryptionKey( - encryptKey, snmpEngineBoots, snmpEngineTime - ) + aesKey, iv, salt = self._getEncryptionKey( + encryptKey, snmpEngineBoots, snmpEngineTime) # 3.3.1.3 # PyCrypto seems to require padding - dataToEncrypt = dataToEncrypt + univ.OctetString((0,) * (16 - len(dataToEncrypt) % 16)).asOctets() + padding = univ.OctetString((0,) * (16 - len(dataToEncrypt) % 16)) + dataToEncrypt += padding try: - ciphertext = aes.encrypt(dataToEncrypt, aesKey, iv) + ciphertext = aes.encrypt(dataToEncrypt.asOctets(), aesKey, iv) except PysnmpCryptoError: raise error.StatusInformation( - errorIndication=errind.unsupportedPrivProtocol - ) + errorIndication=errind.unsupportedPrivProtocol) # 3.3.1.4 return univ.OctetString(ciphertext), univ.OctetString(salt) @@ -131,16 +149,15 @@ class Aes(base.AbstractEncryptionService): # 3.3.2.1 if len(salt) != 8: raise error.StatusInformation( - errorIndication=errind.decryptionError - ) + errorIndication=errind.decryptionError) # 3.3.2.3 - aesKey, iv = self.__getDecryptionKey( - decryptKey, snmpEngineBoots, snmpEngineTime, salt - ) + aesKey, iv = self._getDecryptionKey( + decryptKey, snmpEngineBoots, snmpEngineTime, salt) # PyCrypto seems to require padding - encryptedData = encryptedData + univ.OctetString((0,) * (16 - len(encryptedData) % 16)).asOctets() + padding = univ.OctetString((0,) * (16 - len(encryptedData) % 16)) + encryptedData += padding try: # 3.3.2.4-6 @@ -148,5 +165,4 @@ class Aes(base.AbstractEncryptionService): except PysnmpCryptoError: raise error.StatusInformation( - errorIndication=errind.unsupportedPrivProtocol - ) + errorIndication=errind.unsupportedPrivProtocol) diff --git a/pysnmp/proto/secmod/rfc7860/auth/hmacsha2.py b/pysnmp/proto/secmod/rfc7860/auth/hmacsha2.py index 11dd79b3..267db682 100644 --- a/pysnmp/proto/secmod/rfc7860/auth/hmacsha2.py +++ b/pysnmp/proto/secmod/rfc7860/auth/hmacsha2.py @@ -19,19 +19,26 @@ except ImportError: sha224 = sha256 = sha384 = sha512 = NotAvailable() -from pyasn1.type import univ from pysnmp.proto.secmod.rfc3414.auth import base from pysnmp.proto.secmod.rfc3414 import localkey from pysnmp.proto import errind, error +from pyasn1.type import univ # 7.2.4 class HmacSha2(base.AbstractAuthenticationService): - SHA224_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 4) # usmHMAC128SHA224AuthProtocol - SHA256_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 5) # usmHMAC192SHA256AuthProtocol - SHA384_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 6) # usmHMAC256SHA384AuthProtocol - SHA512_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 7) # usmHMAC384SHA512AuthProtocol + # usmHMAC128SHA224AuthProtocol + SHA224_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 4) + + # usmHMAC192SHA256AuthProtocol + SHA256_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 5) + + # usmHMAC256SHA384AuthProtocol + SHA384_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 6) + + # usmHMAC384SHA512AuthProtocol + SHA512_SERVICE_ID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 7) KEY_LENGTH = { SHA224_SERVICE_ID: 28, @@ -59,39 +66,43 @@ class HmacSha2(base.AbstractAuthenticationService): def __init__(self, oid): if oid not in self.HASH_ALGORITHM: - raise error.ProtocolError('No SHA-2 authentication algorithm %s available' % (oid,)) - self.__hashAlgo = self.HASH_ALGORITHM[oid] - self.__digestLength = self.DIGEST_LENGTH[oid] - self.__placeHolder = univ.OctetString((0,) * self.__digestLength).asOctets() + raise error.ProtocolError( + 'No SHA-2 authentication algorithm %s available' % (oid,)) + + self._hashAlgo = self.HASH_ALGORITHM[oid] + self._digestLength = self.DIGEST_LENGTH[oid] + self._placeHolder = univ.OctetString( + (0,) * self._digestLength).asOctets() def hashPassphrase(self, authKey): - return localkey.hashPassphrase(authKey, self.__hashAlgo) + return localkey.hashPassphrase(authKey, self._hashAlgo) def localizeKey(self, authKey, snmpEngineID): - return localkey.localizeKey(authKey, snmpEngineID, self.__hashAlgo) + return localkey.localizeKey(authKey, snmpEngineID, self._hashAlgo) @property def digestLength(self): - return self.__digestLength + return self._digestLength # 7.3.1 def authenticateOutgoingMsg(self, authKey, wholeMsg): # 7.3.1.1 - location = wholeMsg.find(self.__placeHolder) + location = wholeMsg.find(self._placeHolder) if location == -1: - raise error.ProtocolError('Can\'t locate digest placeholder') + raise error.ProtocolError('Cannot locate digest placeholder') + wholeHead = wholeMsg[:location] - wholeTail = wholeMsg[location + self.__digestLength:] + wholeTail = wholeMsg[location + self._digestLength:] # 7.3.1.2, 7.3.1.3 try: - mac = hmac.new(authKey.asOctets(), wholeMsg, self.__hashAlgo) + mac = hmac.new(authKey.asOctets(), wholeMsg, self._hashAlgo) except errind.ErrorIndication as exc: raise error.StatusInformation(errorIndication=exc) # 7.3.1.4 - mac = mac.digest()[:self.__digestLength] + mac = mac.digest()[:self._digestLength] # 7.3.1.5 & 6 return wholeHead + mac + wholeTail @@ -99,33 +110,32 @@ class HmacSha2(base.AbstractAuthenticationService): # 7.3.2 def authenticateIncomingMsg(self, authKey, authParameters, wholeMsg): # 7.3.2.1 & 2 - if len(authParameters) != self.__digestLength: + if len(authParameters) != self._digestLength: raise error.StatusInformation( - errorIndication=errind.authenticationError - ) + errorIndication=errind.authenticationError) # 7.3.2.3 location = wholeMsg.find(authParameters.asOctets()) if location == -1: - raise error.ProtocolError('Can\'t locate digest in wholeMsg') + raise error.ProtocolError('Cannot locate digest in wholeMsg') + wholeHead = wholeMsg[:location] - wholeTail = wholeMsg[location + self.__digestLength:] - authenticatedWholeMsg = wholeHead + self.__placeHolder + wholeTail + wholeTail = wholeMsg[location + self._digestLength:] + authenticatedWholeMsg = wholeHead + self._placeHolder + wholeTail # 7.3.2.4 try: - mac = hmac.new(authKey.asOctets(), authenticatedWholeMsg, self.__hashAlgo) + mac = hmac.new(authKey.asOctets(), authenticatedWholeMsg, self._hashAlgo) except errind.ErrorIndication as exc: raise error.StatusInformation(errorIndication=exc) # 7.3.2.5 - mac = mac.digest()[:self.__digestLength] + mac = mac.digest()[:self._digestLength] # 7.3.2.6 if mac != authParameters: raise error.StatusInformation( - errorIndication=errind.authenticationFailure - ) + errorIndication=errind.authenticationFailure) return authenticatedWholeMsg |