def prettyIn(self, bits): if type(bits) not in (types.TupleType, types.ListType): return str(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] = octets[d] | 0x01 << (7-m) return string.join(map(lambda x: chr(x), octets))
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)) del self.__stateReferenceIndex[stateReference] cacheEntry, expireAt = cacheInfo del self.__expirationQueue[expireAt]['stateReference'][stateReference] return cacheEntry
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, )) return localkey.hashPassphrase(privKey, hashAlgo)
def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.serviceID: localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID) while ceil(self.keySize // len(localPrivKey)): # noinspection PyDeprecation,PyCallingNonCallable localPrivKey = localPrivKey + md5(localPrivKey).digest() elif authProtocol == hmacsha.HmacSha.serviceID: localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID) while ceil(self.keySize // len(localPrivKey)): localPrivKey = localPrivKey + sha1(localPrivKey).digest() else: raise error.ProtocolError( 'Unknown auth protocol %s' % (authProtocol,) ) return localPrivKey[:self.keySize]
def pushByMsgId(self, msgId, **msgInfo): if msgId in self.__msgIdIndex: raise error.ProtocolError('Cache dup for msgId=%s at %s' % (msgId, self)) expireAt = self.__expirationTimer + 600 self.__msgIdIndex[msgId] = msgInfo, expireAt self.__sendPduHandleIdx[msgInfo['sendPduHandle']] = msgId # 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 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 authenticateIncomingMsg(self, authKey, authParameters, wholeMsg): # 6.3.2.1 & 2 if len(authParameters) != 12: raise error.StatusInformation( errorIndication=errind.authenticationError) # 6.3.2.3 ln = wholeMsg.find(authParameters.asOctets()) if ln == -1: raise error.ProtocolError('Cant locate digest in wholeMsg') wholeHead = wholeMsg[:ln] wholeTail = wholeMsg[ln + 12:] authenticatedWholeMsg = wholeHead + TWELVE_ZEROS + wholeTail # 6.3.2.4a extendedAuthKey = authKey.asNumbers() + FORTY_EIGHT_ZEROS # 6.3.2.4b --> no-op # 6.3.2.4c k1 = univ.OctetString( 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)) # 6.3.2.5a # noinspection PyDeprecation,PyCallingNonCallable d1 = md5(k1.asOctets() + authenticatedWholeMsg).digest() # 6.3.2.5b # noinspection PyDeprecation,PyCallingNonCallable d2 = md5(k2.asOctets() + d1).digest() # 6.3.2.5c mac = d2[:12] # 6.3.2.6 if mac != authParameters: raise error.StatusInformation( errorIndication=errind.authenticationFailure) return authenticatedWholeMsg
def authenticateIncomingMsg(self, authKey, authParameters, wholeMsg): # 7.3.2.1 & 2 if len(authParameters) != 12: raise error.StatusInformation( errorIndication=errind.authenticationError ) # 7.3.2.3 l = wholeMsg.find(authParameters.asOctets()) if l == -1: raise error.ProtocolError('Cant locate digest in wholeMsg') wholeHead = wholeMsg[:l] wholeTail = wholeMsg[l + 12:] authenticatedWholeMsg = wholeHead + _twelveZeros + wholeTail # 7.3.2.4a extendedAuthKey = authKey.asNumbers() + _fortyFourZeros # 7.3.2.4b --> noop # 7.3.2.4c k1 = univ.OctetString( map(lambda x, y: x ^ y, extendedAuthKey, self.__ipad) ) # 7.3.2.4d --> noop # 7.3.2.4e k2 = univ.OctetString( map(lambda x, y: x ^ y, extendedAuthKey, self.__opad) ) # 7.3.2.5a d1 = sha1(k1.asOctets() + authenticatedWholeMsg).digest() # 7.3.2.5b d2 = sha1(k2.asOctets() + d1).digest() # 7.3.2.5c mac = d2[:12] # 7.3.2.6 if mac != authParameters: raise error.StatusInformation( errorIndication=errind.authenticationFailure ) return authenticatedWholeMsg
def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.serviceID: localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID) # now extend this key if too short by repeating steps that includes the hashPassphrase step while len(localPrivKey) < self.keySize: newKey = localkey.hashPassphraseMD5(localPrivKey) localPrivKey += localkey.localizeKeyMD5(newKey, snmpEngineID) elif authProtocol == hmacsha.HmacSha.serviceID: localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID) while len(localPrivKey) < self.keySize: newKey = localkey.hashPassphraseSHA(localPrivKey) localPrivKey += localkey.localizeKeySHA(newKey, snmpEngineID) else: raise error.ProtocolError('Unknown auth protocol %s' % (authProtocol, )) return localPrivKey[:self.keySize]
def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.serviceID: localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID) localPrivKey = localPrivKey + localkey.localizeKeyMD5( localPrivKey, snmpEngineID ) elif authProtocol == hmacsha.HmacSha.serviceID: localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID) localPrivKey = localPrivKey + localkey.localizeKeySHA( localPrivKey, snmpEngineID ) else: raise error.ProtocolError( 'Unknown auth protocol %s' % (authProtocol,) ) return localPrivKey[:32]
def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.serviceID: localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID) for count in range(1, int(ceil(self.keySize * 1.0 / len(localPrivKey)))): # noinspection PyDeprecation,PyCallingNonCallable localPrivKey += md5(localPrivKey).digest() elif authProtocol == hmacsha.HmacSha.serviceID: localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID) # RFC mentions this algo generates 480bit key, but only up to 256 bits are used for count in range(1, int(ceil(self.keySize * 1.0 / len(localPrivKey)))): localPrivKey += sha1(localPrivKey).digest() else: raise error.ProtocolError( 'Unknown auth protocol %s' % (authProtocol,) ) return localPrivKey[:self.keySize]
def _cachePushByMsgId(self, msgId, **msgInfo): if self.__msgIdIndex.has_key(msgId): raise error.ProtocolError('Cache dup for msgId=%s at %s' % (msgId, self)) expireAt = self.__expirationTimer + 50 self.__msgIdIndex[msgId] = (msgInfo, expireAt) self.__sendPduHandleIdx[msgInfo['sendPduHandle']] = msgId # Schedule to expire if not self.__expirationQueue.has_key(expireAt): self.__expirationQueue[expireAt] = {} if not self.__expirationQueue[expireAt].has_key('msgId'): self.__expirationQueue[expireAt]['msgId'] = {} self.__expirationQueue[expireAt]['msgId'][msgId] = 1 self.__expireCaches()
def __verifyAccess(self, name, syntax, idx, viewType, acCtx): snmpEngine = acCtx execCtx = snmpEngine.observer.getExecutionContext( 'rfc3412.receiveMessage:request') (securityModel, securityName, securityLevel, contextName, pduType) = (execCtx['securityModel'], execCtx['securityName'], execCtx['securityLevel'], execCtx['contextName'], execCtx['pdu'].getTagSet()) try: snmpEngine.accessControlModel[self.acmID].isAccessAllowed( snmpEngine, securityModel, securityName, securityLevel, viewType, contextName, name) # Map ACM errors onto SMI ones except error.StatusInformation: statusInformation = sys.exc_info()[1] debug.logger & debug.flagApp and debug.logger( '__verifyAccess: name %s, statusInformation %s' % (name, statusInformation)) errorIndication = statusInformation['errorIndication'] # 3.2.5... if (errorIndication == errind.noSuchView or errorIndication == errind.noAccessEntry or errorIndication == errind.noGroupName): raise pysnmp.smi.error.AuthorizationError(name=name, idx=idx) elif errorIndication == errind.otherError: raise pysnmp.smi.error.GenError(name=name, idx=idx) elif errorIndication == errind.noSuchContext: snmpUnknownContexts, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( '__SNMP-TARGET-MIB', 'snmpUnknownContexts') snmpUnknownContexts.syntax += 1 # Request REPORT generation raise pysnmp.smi.error.GenError(name=name, idx=idx, oid=snmpUnknownContexts.name, val=snmpUnknownContexts.syntax) elif errorIndication == errind.notInView: return 1 else: raise error.ProtocolError('Unknown ACM error %s' % errorIndication) else: # rfc2576: 4.1.2.1 if (securityModel == 1 and syntax is not None and self._counter64Type == syntax.getTagSet() and self._getNextRequestType == pduType): # This will cause MibTree to skip this OID-value raise pysnmp.smi.error.NoAccessError(name=name, idx=idx)
def _sendNotification(self, snmpEngine, notificationTarget, notificationName, additionalVarBinds=(), cbFun=None, cbCtx=None, contextName=null, instanceIndex=None): if self.snmpContext is None: raise error.ProtocolError('SNMP context not specified') # # Here we first expand trap OID into associated OBJECTS # and then look them up at context-specific MIB # mibViewController = snmpEngine.getUserContext('mibViewController') if not mibViewController: mibViewController = view.MibViewController(snmpEngine.getMibBuilder()) snmpEngine.setUserContext(mibViewController=mibViewController) # Support the following syntax: # '1.2.3.4' # (1,2,3,4) # ('MIB', 'symbol') if isinstance(notificationName, (tuple, list)) and \ notificationName and isinstance(notificationName[0], str): notificationName = rfc1902.ObjectIdentity(*notificationName) else: notificationName = rfc1902.ObjectIdentity(notificationName) varBinds = rfc1902.NotificationType( notificationName, instanceIndex=instanceIndex ).resolveWithMib(mibViewController) mibInstrumController = self.snmpContext.getMibInstrum(contextName) varBinds = varBinds[:1] + mibInstrumController.readVars(varBinds[1:]) return self.sendVarBinds(snmpEngine, notificationTarget, self.snmpContext.contextEngineId, contextName, varBinds + list(additionalVarBinds), _sendNotificationCbFun, (cbFun, cbCtx))
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, )) localPrivKey = localkey.localizeKey(privKey, snmpEngineID, hashAlgo) return localPrivKey[:self.KEY_SIZE]
def registerContextEngineId(self, contextEngineId, pduTypes, processPdu): """Register application with dispatcher""" # 4.3.2 -> noop # 4.3.3 for pduType in pduTypes: k = (contextEngineId, pduType) if k in self.__appsRegistration: raise error.ProtocolError( 'Duplicate registration %r/%s' % (contextEngineId, pduType) ) # 4.3.4 self.__appsRegistration[k] = processPdu debug.logger & debug.flagDsp and debug.logger( 'registerContextEngineId: contextEngineId %r pduTypes %s' % (contextEngineId, pduTypes))
def pushByStateRef(self, stateReference, **msgInfo): if stateReference in self.__stateReferenceIndex: 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 prettyOut(self, value): names = [] octets = tuple(map(None, str(value))) i = 0 while i < len(octets): v = ord(octets[i]) j = 7 while j >= 0: if v & (0x01<<j): name = self.__namedValues.getName(i*8+7-j) if name is None: raise error.ProtocolError( 'Unknown named value %s' % v ) names.append(name) j = j - 1 i = i + 1 return string.join(map(lambda x: str(x), names), ', ')
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)) msgInfo, expireAt = cacheInfo del self.__sendPduHandleIdx[msgInfo['sendPduHandle']] del self.__msgIdIndex[msgId] cacheEntry, expireAt = cacheInfo del self.__expirationQueue[expireAt]['msgId'][msgId] return cacheEntry
def prettyOut(self, value): names = [] ints = self.__class__(value).asNumbers() i = 0 while i < len(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: raise error.ProtocolError( 'Unknown named value %s' % v ) names.append(name) j = j - 1 i = i + 1 return ', '.join([ str(x) for x in names ])
def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.serviceID: hashAlgo = md5 elif authProtocol == hmacsha.HmacSha.serviceID: hashAlgo = sha1 elif authProtocol in hmacsha2.HmacSha2.hashAlgorithms: hashAlgo = hmacsha2.HmacSha2.hashAlgorithms[authProtocol] else: raise error.ProtocolError('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 while len(localPrivKey) < self.keySize: # this is the difference between reeder and bluementhal newKey = localkey.hashPassphrase(localPrivKey, hashAlgo) localPrivKey += localkey.localizeKey(newKey, snmpEngineID, hashAlgo) return localPrivKey[:self.keySize]
def authenticateIncomingMsg(self, authKey, authParameters, wholeMsg): # 7.3.2.1 & 2 if len(authParameters) != 12: raise error.StatusInformation( errorIndication='authenticationError') # 7.3.2.3 l = string.find(wholeMsg, str(authParameters)) if l == -1: raise error.ProtocolError('Cant locate digest in wholeMsg') wholeHead = wholeMsg[:l] wholeTail = wholeMsg[l + 12:] authenticatedWholeMsg = '%s%s%s' % (wholeHead, _twelveZeros, wholeTail) # 7.3.2.4a extendedAuthKey = map(ord, str(authKey) + _fortyFourZeros) # 7.3.2.4b --> noop # 7.3.2.4c k1 = string.join( map(lambda x, y: chr(x ^ y), extendedAuthKey, self.__ipad), '') # 7.3.2.4d --> noop # 7.3.2.4e k2 = string.join( map(lambda x, y: chr(x ^ y), extendedAuthKey, self.__opad), '') # 7.3.2.5a d1 = sha1(k1 + authenticatedWholeMsg).digest() # 7.3.2.5b d2 = sha1(k2 + d1).digest() # 7.3.2.5c mac = d2[:12] # 7.3.2.6 if mac != authParameters: raise error.StatusInformation( errorIndication='authenticationFailure') return authenticatedWholeMsg
def localizeKey(self, authProtocol, privKey, snmpEngineID): if authProtocol == hmacmd5.HmacMd5.serviceID: hashAlgo = md5 elif authProtocol == hmacsha.HmacSha.serviceID: hashAlgo = sha1 elif authProtocol in hmacsha2.HmacSha2.hashAlgorithms: hashAlgo = hmacsha2.HmacSha2.hashAlgorithms[authProtocol] else: raise error.ProtocolError('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 for count in range(1, int(ceil(self.keySize * 1.0 / len(localPrivKey)))): localPrivKey += hashAlgo(localPrivKey).digest() return localPrivKey[:self.keySize]
def authenticateOutgoingMsg(self, authKey, wholeMsg): # 7.3.1.1 location = wholeMsg.find(self.__placeHolder) if location == -1: raise error.ProtocolError('Can\'t locate digest placeholder') wholeHead = wholeMsg[:location] wholeTail = wholeMsg[location + self.__digestLength:] # 7.3.1.2, 7.3.1.3 try: mac = hmac.new(authKey.asOctets(), wholeMsg, self.__hashAlgo) except errind.ErrorIndication: raise error.StatusInformation(errorIndication=sys.exc_info()[1]) # 7.3.1.4 mac = mac.digest()[:self.__digestLength] # 7.3.1.5 & 6 return wholeHead + mac + wholeTail
def authenticateOutgoingMsg(self, authKey, wholeMsg): # Here we expect calling secmod to indicate where the digest # 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(_twelveZeros) if l == -1: raise error.ProtocolError('Cant locate digest placeholder') wholeHead = wholeMsg[:l] wholeTail = wholeMsg[l + 12:] # 6.3.1.1 # 6.3.1.2a extendedAuthKey = authKey.asNumbers() + _fortyEightZeros # 6.3.1.2b --> no-op # 6.3.1.2c k1 = univ.OctetString( 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) ) # 6.3.1.3 # noinspection PyDeprecation,PyCallingNonCallable d1 = md5(k1.asOctets() + wholeMsg).digest() # 6.3.1.4 # noinspection PyDeprecation,PyCallingNonCallable d2 = md5(k2.asOctets() + d1).digest() mac = d2[:12] # 6.3.1.5 & 6 return wholeHead + mac + wholeTail
def processPdu(self, snmpEngine, messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, PDU, maxSizeResponseScopedPDU, stateReference): # Agent-side API complies with SMIv2 if messageProcessingModel == 0: origPdu = PDU PDU = rfc2576.v1ToV2(PDU) else: origPdu = None # 3.2.1 if (PDU.tagSet not in rfc3411.readClassPDUs and PDU.tagSet not in rfc3411.writeClassPDUs): raise error.ProtocolError('Unexpected PDU class %s' % PDU.tagSet) # 3.2.2 --> no-op # 3.2.4 rspPDU = v2c.apiPDU.getResponse(PDU) statusInformation = {} self.__pendingReqs[stateReference] = (messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, rspPDU, origPdu, maxSizeResponseScopedPDU, statusInformation) # 3.2.5 varBinds = v2c.apiPDU.getVarBinds(PDU) debug.logger & debug.flagApp and debug.logger( 'processPdu: stateReference %s, varBinds %s' % (stateReference, varBinds)) self.initiateMgmtOperation(snmpEngine, stateReference, contextName, PDU)
def authenticateOutgoingMsg(self, authKey, wholeMsg): # Here we expect calling secmod to indicate where the digest # 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 = string.find(wholeMsg, _twelveZeros) if l == -1: raise error.ProtocolError('Cant locate digest placeholder') wholeHead = wholeMsg[:l] wholeTail = wholeMsg[l + 12:] # 6.3.1.1 # 6.3.1.2a extendedAuthKey = map(ord, str(authKey) + _fortyEightZeros) # 6.3.1.2b --> noop # 6.3.1.2c k1 = string.join( map(lambda x, y: chr(x ^ y), extendedAuthKey, self.__ipad), '') # 6.3.1.2d --> noop # 6.3.1.2e k2 = string.join( map(lambda x, y: chr(x ^ y), extendedAuthKey, self.__opad), '') # 6.3.1.3 d1 = md5(k1 + wholeMsg).digest() # 6.3.1.4 d2 = md5(k2 + d1).digest() mac = d2[:12] # 6.3.1.5 & 6 return '%s%s%s' % (wholeHead, mac, wholeTail)
def authenticateOutgoingMsg(self, authKey, wholeMsg): # 7.3.1.1 # Here we expect calling secmod to indicate where the digest # 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... ln = wholeMsg.find(TWELVE_ZEROS) if ln == -1: raise error.ProtocolError('Cant locate digest placeholder') wholeHead = wholeMsg[:ln] wholeTail = wholeMsg[ln + 12:] # 7.3.1.2a extendedAuthKey = authKey.asNumbers() + FORTY_FOUR_ZEROS # 7.3.1.2b -- no-op # 7.3.1.2c k1 = univ.OctetString( 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)) # 7.3.1.3 d1 = sha1(k1.asOctets() + wholeMsg).digest() # 7.3.1.4 d2 = sha1(k2.asOctets() + d1).digest() mac = d2[:12] # 7.3.1.5 & 6 return wholeHead + mac + wholeTail
def sendVarBinds(self, snmpEngine, notificationTarget, contextEngineId, contextName, varBinds=(), cbFun=None, cbCtx=None): debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationTarget %s, contextEngineId %s, contextName "%s", varBinds %s' % (notificationTarget, contextEngineId or '<default>', contextName, varBinds)) if contextName: __SnmpAdminString, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-FRAMEWORK-MIB', 'SnmpAdminString') contextName = __SnmpAdminString(contextName) # 3.3 ( notifyTag, notifyType ) = config.getNotificationInfo( snmpEngine, notificationTarget ) notificationHandle = getNextHandle() debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, notifyTag %s, notifyType %s' % (notificationHandle, notifyTag, notifyType)) varBinds = [ (v2c.ObjectIdentifier(x),y) for x,y in varBinds ] # 3.3.2 & 3.3.3 snmpTrapOID, sysUpTime = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpTrapOID', 'sysUpTime') for idx in range(len(varBinds)): if idx and varBinds[idx][0] == sysUpTime.getName(): if varBinds[0][0] == sysUpTime.getName(): varBinds[0] = varBinds[idx] else: varBinds.insert(0, varBinds[idx]) del varBinds[idx] if varBinds[0][0] != sysUpTime.getName(): varBinds.insert(0, (v2c.ObjectIdentifier(sysUpTime.getName()), sysUpTime.getSyntax().clone())) if len(varBinds) < 2 or varBinds[1][0] != snmpTrapOID.getName(): varBinds.insert(1, (v2c.ObjectIdentifier(snmpTrapOID.getName()), snmpTrapOID.getSyntax())) debug.logger & debug.flagApp and debug.logger('sendVarBinds: final varBinds %s' % (varBinds,)) for targetAddrName in config.getTargetNames(snmpEngine, notifyTag): ( transportDomain, transportAddress, timeout, retryCount, params ) = config.getTargetAddr(snmpEngine, targetAddrName) ( messageProcessingModel, securityModel, securityName, securityLevel ) = config.getTargetParams(snmpEngine, params) # 3.3.1 XXX # XXX filtering's yet to be implemented # filterProfileName = config.getNotifyFilterProfile(params) # ( filterSubtree, # filterMask, # filterType ) = config.getNotifyFilter(filterProfileName) debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s' % (notificationHandle, notifyTag, transportDomain, transportAddress, securityModel, securityName, securityLevel)) for varName, varVal in varBinds: if varName in (sysUpTime.name, snmpTrapOID.name): continue try: snmpEngine.accessControlModel[self.acmID].isAccessAllowed( snmpEngine, securityModel, securityName, securityLevel, 'notify', contextName, varName ) debug.logger & debug.flagApp and debug.logger('sendVarBinds: ACL succeeded for OID %s securityName %s' % (varName, securityName)) except error.StatusInformation: debug.logger & debug.flagApp and debug.logger('sendVarBinds: ACL denied access for OID %s securityName %s, droppping notification' % (varName, securityName)) return # 3.3.4 if notifyType == 1: pdu = v2c.SNMPv2TrapPDU() elif notifyType == 2: pdu = v2c.InformRequestPDU() else: raise error.ProtocolError('Unknown notify-type %r', notifyType) v2c.apiPDU.setDefaults(pdu) v2c.apiPDU.setVarBinds(pdu, varBinds) # 3.3.5 try: sendRequestHandle = self.sendPdu(snmpEngine, targetAddrName, contextEngineId, contextName, pdu, self.processResponseVarBinds, (notificationHandle, cbFun, cbCtx)) except error.StatusInformation: statusInformation = sys.exc_info()[1] debug.logger & debug.flagApp and debug.logger('sendVarBinds: sendRequestHandle %s: sendPdu() failed with %r' % (sendRequestHandle, statusInformation)) if notificationHandle not in self.__pendingNotifications or \ not self.__pendingNotifications[notificationHandle]: if notificationHandle in self.__pendingNotifications: del self.__pendingNotifications[notificationHandle] cbFun(snmpEngine, notificationHandle, statusInformation['errorIndication'], 0, 0, (), cbCtx) return notificationHandle debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, sendRequestHandle %s, timeout %d' % (notificationHandle, sendRequestHandle, timeout)) if notifyType == 2: if notificationHandle not in self.__pendingNotifications: self.__pendingNotifications[notificationHandle] = set() self.__pendingNotifications[notificationHandle].add(sendRequestHandle) debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, sendRequestHandle %s, notification(s) sent' % (notificationHandle, sendRequestHandle)) return notificationHandle
def processResponsePdu(self, snmpEngine, messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, PDU, statusInformation, sendPduHandle, cbInfo): sendRequestHandle, cbFun, cbCtx = cbInfo # 3.3.6d if sendPduHandle not in self.__pendingReqs: raise error.ProtocolError('Missing sendPduHandle %s' % sendPduHandle) ( origTransportDomain, origTransportAddress, origMessageProcessingModel, origSecurityModel, origSecurityName, origSecurityLevel, origContextEngineId, origContextName, origPdu, origTimeout, origRetryCount, origRetries ) = self.__pendingReqs.pop(sendPduHandle) snmpEngine.transportDispatcher.jobFinished(id(self)) if statusInformation: debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendRequestHandle %s, sendPduHandle %s statusInformation %s' % (sendRequestHandle, sendPduHandle, statusInformation)) if origRetries == origRetryCount: debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendRequestHandle %s, sendPduHandle %s retry count %d exceeded' % (sendRequestHandle, sendPduHandle, origRetries)) cbFun(snmpEngine, sendRequestHandle, statusInformation['errorIndication'], None, cbCtx) return # Convert timeout in seconds into timeout in timer ticks timeoutInTicks = float(origTimeout)/100/snmpEngine.transportDispatcher.getTimerResolution() # User-side API assumes SMIv2 if messageProcessingModel == 0: reqPDU = rfc2576.v2ToV1(origPdu) pduVersion = 0 else: reqPDU = origPdu pduVersion = 1 # 3.3.6a try: sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu( snmpEngine, origTransportDomain, origTransportAddress, origMessageProcessingModel, origSecurityModel, origSecurityName, origSecurityLevel, origContextEngineId, origContextName, pduVersion, reqPDU, 1, # expectResponse timeoutInTicks, self.processResponsePdu, (sendRequestHandle, cbFun, cbCtx) ) except error.StatusInformation: statusInformation = sys.exc_info()[1] debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendRequestHandle %s: sendPdu() failed with %r ' % (sendRequestHandle, statusInformation)) cbFun(snmpEngine, sendRequestHandle, statusInformation['errorIndication'], None, cbCtx) return snmpEngine.transportDispatcher.jobStarted(id(self)) debug.logger & debug.flagApp and debug.logger('processResponsePdu: sendRequestHandle %s, sendPduHandle %s, timeout %d, retry %d of %d' % (sendRequestHandle, sendPduHandle, origTimeout, origRetries, origRetryCount)) # 3.3.6b self.__pendingReqs[sendPduHandle] = ( origTransportDomain, origTransportAddress, origMessageProcessingModel, origSecurityModel, origSecurityName, origSecurityLevel, origContextEngineId, origContextName, origPdu, origTimeout, origRetryCount, origRetries + 1 ) return # 3.3.6c # User-side API assumes SMIv2 if messageProcessingModel == 0: PDU = rfc2576.v1ToV2(PDU, origPdu) cbFun(snmpEngine, sendRequestHandle, None, PDU, cbCtx)