Example #1
0
    def processIncomingMsg(
        self,
        snmpEngine,
        messageProcessingModel,
        maxMessageSize,
        securityParameters,
        securityModel,
        securityLevel,
        wholeMsg,
        msg
        ):
        # rfc2576: 5.2.1
        ( communityName, transportInformation ) = securityParameters

        scope = dict(communityName=communityName, 
                     transportInformation=transportInformation)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine,
            'rfc2576.processIncomingMsg:writable',
            scope
        )

        try:
            securityName, contextEngineId, contextName = self._com2sec(
                snmpEngine,
                scope.get('communityName', communityName),
                scope.get('transportInformation', transportInformation)
            )
        except error.StatusInformation:
            snmpInBadCommunityNames, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInBadCommunityNames')
            snmpInBadCommunityNames.syntax = snmpInBadCommunityNames.syntax+1
            raise error.StatusInformation(
                errorIndication = errind.unknownCommunityName
            )

        snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')

        securityEngineID = snmpEngineID.syntax
       
        debug.logger & debug.flagSM and debug.logger('processIncomingMsg: looked up securityName %r securityModel %r contextEngineId %r contextName %r by communityName %r AND transportInformation %r' % (securityName, self.securityModelID, 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.flagSM and debug.logger('processIncomingMsg: generated maxSizeResponseScopedPDU %s securityStateReference %s' % (maxSizeResponseScopedPDU, securityStateReference))
        
        return ( securityEngineID,
                 securityName,
                 scopedPDU,
                 maxSizeResponseScopedPDU,
                 securityStateReference )
Example #2
0
    def __init__(self, sock=None, sockMap=None):
        asyncore.dispatcher.__init__(self)
        if sock is None:
            if self.sockFamily is None:
                raise error.CarrierError(
                    'Address family %s not supported' % self.__class__.__name__
                )
            if self.sockType is None:
                raise error.CarrierError(
                    'Socket type %s not supported' % self.__class__.__name__
                )
            try:
                sock = socket.socket(self.sockFamily, self.sockType)
            except socket.error:
                raise error.CarrierError('socket() failed: %s' % sys.exc_info()[1])

            try:
                for b in socket.SO_RCVBUF, socket.SO_SNDBUF:
                    bsize = sock.getsockopt(socket.SOL_SOCKET, b)
                    if bsize < self.bufferSize:
                        sock.setsockopt(socket.SOL_SOCKET, b, self.bufferSize)
                        debug.logger & debug.flagIO and debug.logger('%s: socket %d buffer size increased from %d to %d for buffer %d' % (self.__class__.__name__, sock.fileno(), bsize, self.bufferSize, b))
            except Exception:
                debug.logger & debug.flagIO and debug.logger('%s: socket buffer size option mangling failure for buffer: %s' % (self.__class__.__name__, sys.exc_info()[1]))

        # The socket map is managed by the AsyncoreDispatcher on
        # which this transport is registered. Here we just prepare
        # socket and postpone transport registration at dispatcher
        # till AsyncoreDispatcher invokes registerSocket()

        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.setblocking(0)
        self.set_socket(sock)
Example #3
0
    def generateResponseMsg(
        self,
        snmpEngine,
        messageProcessingModel,
        globalData,
        maxMessageSize,
        securityModel,
        securityEngineID,
        securityName,
        securityLevel,
        scopedPDU,
        securityStateReference
        ):
        # rfc2576: 5.2.2
        msg, = globalData
        contextEngineId, contextName, pdu = scopedPDU
        cachedSecurityData = self._cache.pop(securityStateReference)
        communityName = cachedSecurityData['communityName']

        debug.logger & debug.flagSM and debug.logger('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
            )
        
        debug.logger & debug.flagMP and debug.logger('generateResponseMsg: %s' % (msg.prettyPrint(),))

        wholeMsg = encoder.encode(msg)
        return ( communityName, wholeMsg )
Example #4
0
    def processResponseVarBinds(self,
                                snmpEngine,
                                sendRequestHandle,
                                errorIndication,
                                PDU,
                                cbCtx):
        targetName, contextEngineId, contextName, reqPDU, cbFun, cbCtx = cbCtx

        if errorIndication:
            cbFun(snmpEngine,
                  sendRequestHandle,
                  errorIndication,
                  0, 0, (),
                  cbCtx)
            return
        
        varBindTable = v2c.apiPDU.getVarBindTable(reqPDU, PDU)

        if v2c.apiPDU.getErrorStatus(PDU):
            errorIndication, varBinds = None, ()
        elif not varBindTable:
            errorIndication, varBinds = errind.emptyResponse, ()
        else:
            errorIndication, varBinds = getNextVarBinds(
                varBindTable[-1], v2c.apiPDU.getVarBinds(reqPDU)
            )
        
        if not cbFun(snmpEngine,
                     sendRequestHandle,
                     errorIndication,
                     v2c.apiPDU.getErrorStatus(PDU),
                     v2c.apiPDU.getErrorIndex(PDU, muteErrors=True),
                     varBindTable,    
                     cbCtx):
            debug.logger & debug.flagApp and debug.logger('processResponseVarBinds: sendRequestHandle %s, app says to stop walking' % sendRequestHandle)
            return  # app says enough

        if not varBinds:
            return # no more objects available

        v2c.apiPDU.setRequestID(reqPDU, v2c.getNextRequestID())
        v2c.apiPDU.setVarBinds(reqPDU, varBinds)

        try:
            self.sendPdu(snmpEngine,
                         targetName,
                         contextEngineId,
                         contextName,
                         reqPDU,
                         self.processResponseVarBinds,
                         (targetName, contextEngineId, contextName,
                          reqPDU, cbFun, cbCtx))
            
        except StatusInformation:
            statusInformation = sys.exc_info()[1]
            debug.logger & debug.flagApp and debug.logger('sendVarBinds: sendPduHandle %s: sendPdu() failed with %r' % (sendRequestHandle, statusInformation))
            cbFun(snmpEngine,
                  sendRequestHandle,
                  statusInformation['errorIndication'],
                  0, 0, (), cbCtx)
Example #5
0
    def generateResponseMsg(self, snmpEngine, messageProcessingModel,
                            globalData, maxMessageSize, securityModel,
                            securityEngineID, securityName, securityLevel,
                            scopedPDU, securityStateReference):
        # rfc2576: 5.2.2
        msg, = globalData
        contextEngineId, contextName, pdu = scopedPDU
        cachedSecurityData = self._cache.pop(securityStateReference)
        communityName = cachedSecurityData['communityName']

        debug.logger & debug.flagSM and debug.logger('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
        )

        debug.logger & debug.flagMP and debug.logger('generateResponseMsg: %s' % (msg.prettyPrint(),))

        try:
            return communityName, encoder.encode(msg)

        except PyAsn1Error:
            debug.logger & debug.flagMP and debug.logger('generateResponseMsg: serialization failure: %s' % sys.exc_info()[1])
            raise error.StatusInformation(errorIndication=errind.serializationError)
Example #6
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)

        debug.logger & debug.flagSM and debug.logger('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
        )

        debug.logger & debug.flagMP and debug.logger('generateRequestMsg: %s' % (msg.prettyPrint(),))

        try:
            return securityParameters, encoder.encode(msg)

        except PyAsn1Error:
            debug.logger & debug.flagMP and debug.logger('generateRequestMsg: serialization failure: %s' % sys.exc_info()[1])
            raise error.StatusInformation(errorIndication=errind.serializationError)
Example #7
0
    def handle_read(self):
        try:
            incomingMessage, transportAddress = self._recvfrom(self.socket, 65535)

            transportAddress = self.normalizeAddress(transportAddress)

            debug.logger & debug.FLAG_IO and debug.logger(
                'handle_read: transportAddress %r -> %r incomingMessage (%d '
                'octets) %s' % (transportAddress, transportAddress.getLocalAddress(),
                                len(incomingMessage), debug.hexdump(incomingMessage)))

            if not incomingMessage:
                self.handle_close()
                return

            else:
                self._cbFun(self, transportAddress, incomingMessage)
                return

        except socket.error as exc:
            if exc.args[0] in SOCK_ERRORS:
                debug.logger & debug.FLAG_IO and debug.logger(
                    'handle_read: known socket error %s' % exc)
                SOCK_ERRORS[exc.args[0]] and self.handle_close()
                return

            else:
                raise error.CarrierError('recvfrom() failed: %s' % exc)
Example #8
0
    def exportSymbols(self, modName, *anonymousSyms, **namedSyms):
        if modName not in self.mibSymbols:
            self.mibSymbols[modName] = {}
        mibSymbols = self.mibSymbols[modName]

        for symObj in anonymousSyms:
            debug.logger & debug.flagBld and debug.logger(
                'exportSymbols: anonymous symbol %s::__pysnmp_%ld' % (modName, self._autoName))
            mibSymbols['__pysnmp_%ld' % self._autoName] = symObj
            self._autoName += 1
        for symName, symObj in namedSyms.items():
            if symName in mibSymbols:
                raise error.SmiError(
                    'Symbol %s already exported at %s' % (symName, modName)
                )

            if symName != self.moduleID and \
                    not isinstance(symObj, classTypes):
                label = symObj.getLabel()
                if label:
                    symName = label
                else:
                    symObj.setLabel(symName)

            mibSymbols[symName] = symObj

            debug.logger & debug.flagBld and debug.logger('exportSymbols: symbol %s::%s' % (modName, symName))

        self.lastBuildId += 1
Example #9
0
    def exportSymbols(self, modName, *anonymousSyms, **namedSyms):
        if not self.mibSymbols.has_key(modName):
            self.mibSymbols[modName] = {}
        mibSymbols = self.mibSymbols[modName]
        
        for symObj in anonymousSyms:
            debug.logger & debug.flagBld and debug.logger('exportSymbols: anonymous symbol %s::__pysnmp_%ld'  % (modName, self._autoName))
            mibSymbols['__pysnmp_%ld' % self._autoName] = symObj
            self._autoName = self._autoName + 1
        for symName, symObj in namedSyms.items():
            if mibSymbols.has_key(symName):
                raise error.SmiError(
                    'Symbol %s already exported at %s' % (symName, modName)
                    )

            if hasattr(symObj, 'label'):
                symName = symObj.label or symName # class
            if type(symObj) == types.InstanceType:
                symName = symObj.getLabel() or symName # class instance
            
            mibSymbols[symName] = symObj
            
            debug.logger & debug.flagBld and debug.logger('exportSymbols: symbol %s::%s' % (modName, symName))
            
        self.lastBuildId = self.lastBuildId + 1
Example #10
0
    def sendPdu(self, snmpEngine, targetName, contextEngineId,
                contextName, pdu, cbFun=None, cbCtx=None):
        (transportDomain, transportAddress, timeout,
         retryCount, params) = config.getTargetAddr(snmpEngine, targetName)

        (messageProcessingModel, securityModel, securityName,
         securityLevel) = config.getTargetParams(snmpEngine, params)

        # User-side API assumes SMIv2
        if messageProcessingModel == 0:
            reqPDU = rfc2576.v2ToV1(pdu)
            pduVersion = 0

        else:
            reqPDU = pdu
            pduVersion = 1

        # 3.3.5
        if reqPDU.tagSet in rfc3411.CONFIRMED_CLASS_PDUS:
            # Convert timeout in seconds into timeout in timer ticks
            timeoutInTicks = (float(timeout) / 100 /
                              snmpEngine.transportDispatcher.getTimerResolution())

            sendRequestHandle = getNextHandle()

            # 3.3.6a
            sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                snmpEngine, transportDomain, transportAddress,
                messageProcessingModel, securityModel, securityName,
                securityLevel, contextEngineId, contextName,
                pduVersion, reqPDU, True, timeoutInTicks,
                self.processResponsePdu, (sendRequestHandle, cbFun, cbCtx)
            )

            debug.logger & debug.FLAG_APP and debug.logger(
                'sendPdu: sendPduHandle %s, timeout %d' % (sendPduHandle, timeout))

            # 3.3.6b
            self.__pendingReqs[sendPduHandle] = (
                transportDomain, transportAddress, messageProcessingModel,
                securityModel, securityName, securityLevel, contextEngineId,
                contextName, pdu, timeout, retryCount, 0, 0
            )

            snmpEngine.transportDispatcher.jobStarted(id(self))

        else:
            snmpEngine.msgAndPduDsp.sendPdu(
                snmpEngine, transportDomain, transportAddress,
                messageProcessingModel, securityModel,
                securityName, securityLevel, contextEngineId,
                contextName, pduVersion, reqPDU, False
            )

            sendRequestHandle = None

            debug.logger & debug.FLAG_APP and debug.logger('sendPdu: message sent')

        return sendRequestHandle
Example #11
0
    def returnResponsePdu(
        self,
        snmpEngine,
        messageProcessingModel,
        securityModel,
        securityName,
        securityLevel,
        contextEngineId,
        contextName,
        pduVersion,
        PDU,
        maxSizeResponseScopedPDU,
        stateReference,
        statusInformation,
    ):
        """PDU dispatcher -- prepare and serialize a response"""
        # 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)

        debug.logger & debug.flagDsp and debug.logger(
            "returnResponsePdu: PDU %s" % (PDU and PDU.prettyPrint() or "<empty>",)
        )

        # 4.1.2.2
        try:
            (destTransportDomain, destTransportAddress, outgoingMessage) = mpHandler.prepareResponseMessage(
                snmpEngine,
                messageProcessingModel,
                securityModel,
                securityName,
                securityLevel,
                contextEngineId,
                contextName,
                pduVersion,
                PDU,
                maxSizeResponseScopedPDU,
                stateReference,
                statusInformation,
            )
            debug.logger & debug.flagDsp and debug.logger("returnResponsePdu: MP suceeded")
        except error.StatusInformation:
            # 4.1.2.3
            raise

        # Handle oversized messages XXX transport constrains?
        snmpEngineMaxMessageSize, = self.mibInstrumController.mibBuilder.importSymbols(
            "__SNMP-FRAMEWORK-MIB", "snmpEngineMaxMessageSize"
        )
        if snmpEngineMaxMessageSize.syntax and len(outgoingMessage) > snmpEngineMaxMessageSize.syntax:
            snmpSilentDrops, = self.mibInstrumController.mibBuilder.importSymbols("__SNMPv2-MIB", "snmpSilentDrops")
            snmpSilentDrops.syntax = snmpSilentDrops.syntax + 1
            raise error.StatusInformation(errorIndication=errind.tooBig)

        # 4.1.2.4
        snmpEngine.transportDispatcher.sendMessage(outgoingMessage, destTransportDomain, destTransportAddress)
 def flipFlopFsm(self, fsmTable, inputNameVals, acInfo):
     self.__indexMib()
     debug.logger & debug.flagIns and debug.logger('flipFlopFsm: inputNameVals %r' % (inputNameVals,))
     mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso')
     outputNameVals = []
     state, status = 'start', 'ok'
     origExc = None
     while 1:
         k = (state, status)
         if k in fsmTable:
             fsmState = fsmTable[k]
         else:
             k = ('*', status)
             if k in fsmTable:
                 fsmState = fsmTable[k]
             else:
                 raise error.SmiError(
                     'Unresolved FSM state %s, %s' % (state, status)
                     )
         debug.logger & debug.flagIns and debug.logger('flipFlopFsm: state %s status %s -> fsmState %s' % (state, status, fsmState))
         state = fsmState
         status = 'ok'
         if state == 'stop':
             break
         idx = 0
         for name, val in inputNameVals:
             f = getattr(mibTree, state, None)
             if f is None:
                 raise error.SmiError(
                     'Unsupported state handler %s at %s' % (state, self)
                     )
             try:
                 # Convert to tuple to avoid ObjectName instantiation
                 # on subscription
                 rval = f(tuple(name), val, idx, acInfo)
             except error.SmiError:
                 exc_t, exc_v, exc_tb = sys.exc_info()
                 debug.logger & debug.flagIns and debug.logger('flipFlopFsm: fun %s exception %s for %s=%r with traceback: %s' % (f, exc_t, name, val, traceback.format_exception(exc_t, exc_v, exc_tb)))
                 if origExc is None:  # Take the first exception
                     origExc, origTraceback = exc_v, exc_tb
                 status = 'err'
                 break
             else:
                 debug.logger & debug.flagIns and debug.logger('flipFlopFsm: fun %s suceeded for %s=%r' % (f, name, val))
                 if rval is not None:
                     outputNameVals.append((rval[0], rval[1]))
             idx = idx + 1
     if origExc:
         if sys.version_info[0] <= 2:
             raise origExc
         else:
             try:
                 raise origExc.with_traceback(origTraceback)
             finally:
                 # Break cycle between locals and traceback object
                 # (seems to be irrelevant on Py3 but just in case)
                 del origTraceback
     return outputNameVals
Example #13
0
    def processResponseVarBinds(self, snmpEngine, sendRequestHandle,
                                errorIndication, PDU, cbCtx):
        (targetName, nonRepeaters, maxRepetitions,
         contextEngineId, contextName, reqPDU, cbFun, cbCtx) = cbCtx

        if errorIndication:
            cbFun(snmpEngine, sendRequestHandle, errorIndication,
                  0, 0, (), cbCtx)
            return

        varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, PDU)

        if v2c.apiBulkPDU.getErrorStatus(PDU):
            errorIndication, varBinds = None, ()

        elif not varBindTable:
            errorIndication, varBinds = errind.emptyResponse, ()

        else:
            errorIndication, varBinds = v2c.apiBulkPDU.getNextVarBinds(varBindTable[-1])
            nonRepeaters = v2c.apiBulkPDU.getNonRepeaters(reqPDU)

            if nonRepeaters:
                varBinds = v2c.apiBulkPDU.getVarBinds(reqPDU)[:int(nonRepeaters)] + varBinds[int(nonRepeaters):]

        if not cbFun(
                snmpEngine, sendRequestHandle, errorIndication,
                v2c.apiBulkPDU.getErrorStatus(PDU),
                v2c.apiBulkPDU.getErrorIndex(PDU, muteErrors=True),
                varBindTable, cbCtx):

            debug.logger & debug.FLAG_APP and debug.logger(
                'processResponseVarBinds: sendRequestHandle %s, app says to stop walking' % sendRequestHandle)

            return  # app says it's enough

        if not varBinds:
            return  # no more objects available

        v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID())
        v2c.apiBulkPDU.setVarBinds(reqPDU, varBinds)

        try:
            self.sendPdu(
                snmpEngine, targetName, contextEngineId, contextName, reqPDU,
                self.processResponseVarBinds,
                (targetName, nonRepeaters, maxRepetitions,
                    contextEngineId, contextName, reqPDU, cbFun, cbCtx))

        except StatusInformation as exc:
            statusInformation = exc

            debug.logger & debug.FLAG_APP and debug.logger(
                'processResponseVarBinds: sendPduHandle %s: _sendPdu() failed '
                'with %r' % (sendRequestHandle, statusInformation))

            cbFun(snmpEngine, sendRequestHandle,
                  statusInformation['errorIndication'], 0, 0, (), cbCtx)
 def startProtocol(self):
     debug.logger & debug.flagIO and debug.logger('startProtocol: invoked')
     while self._writeQ:
         outgoingMessage, transportAddress = self._writeQ.pop(0)
         debug.logger & debug.flagIO and debug.logger('startProtocol: transportAddress %r outgoingMessage %s' % (transportAddress, debug.hexdump(outgoingMessage)))
         try:
             self.transport.write(outgoingMessage, transportAddress)
         except Exception:
             raise error.CarrierError('Twisted exception: %s' % (sys.exc_info()[1],))
Example #15
0
 def startProtocol(self):
     debug.logger & debug.flagIO and debug.logger('startProtocol: invoked')
     while self._writeQ:
         outgoingMessage, transportAddress = self._writeQ.pop(0)
         debug.logger & debug.flagIO and debug.logger('startProtocol: transportAddress %s outgoingMessage %s' % (transportAddress, repr(outgoingMessage)))
         try:
             self.transport.write(outgoingMessage, transportAddress)
         except Exception, why:
             raise error.CarrierError('Twisted exception: %s' % (why,))
Example #16
0
 def getMibInstrum(self, contextName):
     contextName = univ.OctetString(contextName).asOctets()
     if contextName not in self.contextNames:
         debug.logger & debug.flagIns and debug.logger('getMibInstrum: contextName \"%s\" not registered' % contextName)
         raise error.PySnmpError(
             'Missing contextName %s' % contextName
             )
     else:
         debug.logger & debug.flagIns and debug.logger('getMibInstrum: contextName \"%s\", mibInstum %s' % (contextName, self.contextNames[contextName]))
         return self.contextNames[contextName]
Example #17
0
 def handle_write(self):
     outgoingMessage, transportAddress = self.__outQueue.pop()
     debug.logger & debug.flagIO and debug.logger('handle_write: transportAddress %r outgoingMessage %r' % (transportAddress, outgoingMessage))
     try:
         self.socket.sendto(outgoingMessage, transportAddress)
     except socket.error:
         if sys.exc_info()[1].args[0] in sockErrors:
             debug.logger & debug.flagIO and debug.logger('handle_write: ignoring socket error %s' % (sys.exc_info()[1],))
         else:
             raise socket.error(sys.exc_info()[1])
Example #18
0
    def loadModules(self, *modNames, **userCtx):
        # Build a list of available modules
        if not modNames:
            modNames = {}
            for mibSource in self.__mibSources:
                for modName in mibSource.listdir():
                    modNames[modName] = None
            modNames = list(modNames.keys())
        if not modNames:
            raise error.SmiError(
                'No MIB module to load at %s' % (self,)
                )
        
        for modName in modNames:
            for mibSource in self.__mibSources:
                debug.logger & debug.flagBld and debug.logger('loadModules: trying %s at %s' % (modName, mibSource))
                try:
                    modData, sfx = mibSource.read(modName)
                except IOError:
                    debug.logger & debug.flagBld and debug.logger('loadModules: read %s from %s failed: %s' % (modName, mibSource, sys.exc_info()[1]))
                    continue

                modPath = mibSource.fullPath(modName, sfx)
                
                if modPath in self.__modPathsSeen:
                    debug.logger & debug.flagBld and debug.logger('loadModules: seen %s' % modPath)
                    break
                else:
                    self.__modPathsSeen[modPath] = 1

                debug.logger & debug.flagBld and debug.logger('loadModules: evaluating %s' % modPath)

                g = { 'mibBuilder': self,
                      'userCtx': userCtx }

                try:
                    exec(modData, g)
                except Exception:
                    del self.__modPathsSeen[modPath]
                    raise error.SmiError(
                        'MIB module \"%s\" load error: %s' % (modPath, sys.exc_info()[1])
                        )

                self.__modSeen[modName] = modPath

                debug.logger & debug.flagBld and debug.logger('loadModules: loaded %s' % modPath)

                break

            if modName not in self.__modSeen:
                raise error.SmiError(
                    'MIB file \"%s\" not found in search path' % (modName and modName + ".py[co]")
                    )

        return self
Example #19
0
    def loadModule(self, modName, **userCtx):
        """Load and execute MIB modules as Python code"""
        for mibSource in self._mibSources:
            debug.logger & debug.FLAG_BLD and debug.logger(
                'loadModule: trying %s at %s' % (modName, mibSource))

            try:
                codeObj, sfx = mibSource.read(modName)

            except IOError as exc:
                debug.logger & debug.FLAG_BLD and debug.logger(
                    'loadModule: read %s from %s failed: '
                    '%s' % (modName, mibSource, exc))
                continue

            modPath = mibSource.fullPath(modName, sfx)

            if modPath in self._modPathsSeen:
                debug.logger & debug.FLAG_BLD and debug.logger(
                    'loadModule: seen %s' % modPath)
                break

            else:
                self._modPathsSeen.add(modPath)

            debug.logger & debug.FLAG_BLD and debug.logger(
                'loadModule: evaluating %s' % modPath)

            g = {'mibBuilder': self,
                 'userCtx': userCtx}

            try:
                exec(codeObj, g)

            except Exception:
                self._modPathsSeen.remove(modPath)
                raise error.MibLoadError(
                    'MIB module "%s" load error: '
                    '%s' % (modPath, traceback.format_exception(*sys.exc_info())))

            self._modSeen[modName] = modPath

            debug.logger & debug.FLAG_BLD and debug.logger(
                'loadModule: loaded %s' % modPath)

            break

        if modName not in self._modSeen:
            raise error.MibNotFoundError(
                'MIB file "%s" not found in search path '
                '(%s)' % (modName and modName + ".py[co]", ', '.join(
                    [str(x) for x in self._mibSources])))

        return self
Example #20
0
 def connection_made(self, transport):
     self.transport = transport
     debug.logger & debug.flagIO and debug.logger('connection_made: invoked')
     while self._writeQ:
         outgoingMessage, transportAddress = self._writeQ.pop(0)
         debug.logger & debug.flagIO and debug.logger('connection_made: transportAddress %r outgoingMessage %s' %
                                                      (transportAddress, debug.hexdump(outgoingMessage)))
         try:
             self.transport.sendto(outgoingMessage, self.normalizeAddress(transportAddress))
         except Exception:
             raise error.CarrierError(';'.join(traceback.format_exception(*sys.exc_info())))
Example #21
0
    def read(self, f):
        pycTime = pyTime = -1

        for pycSfx, pycSfxLen, pycMode in self.__sfx[imp.PY_COMPILED]:
            try:
                pycData = self._getData(f + pycSfx, pycMode)
            except IOError:
                why = sys.exc_info()[1]
                if ENOENT == -1 or why.errno == ENOENT:
                    debug.logger & debug.flagBld and debug.logger(
                        'file %s access error: %s' % (f + pycSfx, why)
                    )
                else:
                    raise error.MibLoadError('MIB file %s access error: %s' % (f + pycSfx, why))
            else:
                if self.__magic == pycData[:4]:
                    pycData = pycData[4:]
                    pycTime = struct.unpack('<L', pycData[:4])[0]
                    pycData = pycData[4:]
                    debug.logger & debug.flagBld and debug.logger(
                        'file %s mtime %d' % (f + pycSfx, pycTime)
                    )
                    break
                else:
                    debug.logger & debug.flagBld and debug.logger(
                        'bad magic in %s' % (f + pycSfx,)
                    )

        for pySfx, pySfxLen, pyMode in self.__sfx[imp.PY_SOURCE]:
            try:
                pyTime = self._getTimestamp(f + pySfx)
            except IOError:
                why = sys.exc_info()[1]
                if ENOENT == -1 or why.errno == ENOENT:
                    debug.logger & debug.flagBld and debug.logger(
                        'file %s access error: %s' % (f + pySfx, why)
                    )
                else:
                    raise error.MibLoadError('MIB file %s access error: %s' % (f + pySfx, why))
            else:
                debug.logger & debug.flagBld and debug.logger(
                    'file %s mtime %d' % (f + pySfx, pyTime)
                )
                break

        if pycTime != -1 and pycTime >= pyTime:
            # noinspection PyUnboundLocalVariable
            return marshal.loads(pycData), pycSfx
        if pyTime != -1:
            # noinspection PyUnboundLocalVariable
            return self._getData(f + pySfx, pyMode), pySfx

        raise IOError(ENOENT, 'No suitable module found', f)
Example #22
0
 def handle_write(self):
     outgoingMessage, transportAddress = self.__outQueue.pop()
     debug.logger & debug.flagIO and debug.logger(
         "handle_write: transportAddress %s outgoingMessage %s" % (transportAddress, repr(outgoingMessage))
     )
     try:
         self.socket.sendto(outgoingMessage, transportAddress)
     except socket.error, why:
         if sockErrors.has_key(why[0]):
             debug.logger & debug.flagIO and debug.logger("handle_write: ignoring socket error %s" % (why,))
         else:
             raise socket.error, why
Example #23
0
    def loadModules(self, *modNames):
        # Build a list of available modules
        if not modNames:
            modNames = {}
            for mibPath in self.__mibPaths:
                try:
                    for modName in os.listdir(mibPath):
                        if modName == '__init__.py' or modName[-3:] != '.py':
                            continue
                        modNames[modName[:-3]] = None
                except OSError:
                    continue
            modNames = modNames.keys()
        if not modNames:
            raise error.SmiError(
                'No MIB module to load at %s' % (self,)
                )
        for modName in modNames:
            for mibPath in self.__mibPaths:
                modPath = os.path.join(
                    mibPath, modName + '.py'
                    )

                debug.logger & debug.flagBld and debug.logger('loadModules: trying %s' % modPath)

                try:
                    open(modPath).close()
                except IOError, why:
                    debug.logger & debug.flagBld and debug.logger('loadModules: open() %s' % why)
                    continue

                if self.__modPathsSeen.has_key(modPath):
                    debug.logger & debug.flagBld and debug.logger('loadModules: seen %s' % modPath)
                    continue
                else:
                    self.__modPathsSeen[modPath] = 1

                g = { 'mibBuilder': self }

                try:
                    execfile(modPath, g)
                except StandardError, why:
                    del self.__modPathsSeen[modPath]
                    raise error.SmiError(
                        'MIB module \"%s\" load error: %s' % (modPath, why)
                        )

                self.__modSeen[modName] = modPath

                debug.logger & debug.flagBld and debug.logger('loadModules: loaded %s' % modPath)

                break
Example #24
0
 def handle_write(self):
     outgoingMessage, transportAddress = self.__outQueue.pop()
     debug.logger & debug.flagIO and debug.logger('handle_write: transportAddress %r -> %r outgoingMessage %s' % (self.socket.getsockname(), transportAddress, debug.hexdump(outgoingMessage)))
     if not transportAddress:
         debug.logger & debug.flagIO and debug.logger('handle_write: missing dst address, loosing outgoing msg')
         return
     try:
         self.socket.sendto(outgoingMessage, transportAddress)
     except socket.error:
         if sys.exc_info()[1].args[0] in sockErrors:
             debug.logger & debug.flagIO and debug.logger('handle_write: ignoring socket error %s' % (sys.exc_info()[1],))
         else:
             raise error.CarrierError('sendto() failed for %s: %s' % (transportAddress, sys.exc_info()[1]))
Example #25
0
    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:
            usmUserName, usmUserSecurityName = mibBuilder.importSymbols(
                'SNMP-USER-BASED-SM-MIB', 'usmUserName', 'usmUserSecurityName')

            self.__securityToUserMap = {}

            nextMibNode = usmUserEngineID

            while True:
                try:
                    nextMibNode = usmUserEngineID.getNextNode(nextMibNode.name)

                except NoSuchInstanceError:
                    self.__paramsBranchId = usmUserEngineID.branchVersionId
                    debug.logger & debug.flagSM and debug.logger(
                        '_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

                k = __engineID, __securityName

                # first (lesser) securityName wins
                if k not in self.__securityToUserMap:
                    self.__securityToUserMap[k] = __userName

        if securityEngineID is None:
            snmpEngineID, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
            securityEngineID = snmpEngineID.syntax

        try:
            userName = self.__securityToUserMap[(securityEngineID, securityName)]
        except KeyError:
            debug.logger & debug.flagSM and debug.logger(
                '_sec2usr: no entry exists for snmpEngineId %r, securityName %r' % (securityEngineID, securityName))
            raise NoSuchInstanceError()  # emulate MIB lookup

        debug.logger & debug.flagSM and debug.logger(
            '_sec2usr: using userName %r for snmpEngineId %r, securityName %r' % (
                userName, securityEngineID, securityName))

        return userName
Example #26
0
 def flipFlopFsm(self, fsmTable, inputNameVals, acInfo):
     self.__indexMib()
     debug.logger & debug.flagIns and debug.logger('flipFlopFsm: inputNameVals %r' % (inputNameVals,))
     mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso')
     outputNameVals = []
     state, status = 'start', 'ok'
     myErr = None
     while 1:
         k = (state, status)
         if k in fsmTable:
             fsmState = fsmTable[k]
         else:
             k = ('*', status)
             if k in fsmTable:
                 fsmState = fsmTable[k]
             else:
                 raise error.SmiError(
                     'Unresolved FSM state %s, %s' % (state, status)
                     )
         debug.logger & debug.flagIns and debug.logger('flipFlopFsm: state %s status %s -> fsmState %s' % (state, status, fsmState))
         state = fsmState
         status = 'ok'
         if state == 'stop':
             break
         idx = 0
         for name, val in inputNameVals:
             f = getattr(mibTree, state, None)
             if f is None:
                 raise error.SmiError(
                     'Unsupported state handler %s at %s' % (state, self)
                     )
             try:
                 # Convert to tuple to avoid ObjectName instantiation
                 # on subscription
                 rval = f(tuple(name), val, idx, acInfo)
             except error.SmiError:
                 debug.logger & debug.flagIns and debug.logger('flipFlopFsm: fun %s failed %s for %s=%r' % (f, sys.exc_info()[1], name, val))
                 if myErr is None:  # Take the first exception
                     myErr = sys.exc_info()[1]
                 status = 'err'
                 break
             else:
                 debug.logger & debug.flagIns and debug.logger('flipFlopFsm: fun %s suceeded for %s=%r' % (f, name, val))
                 if rval is not None:
                     outputNameVals.append((rval[0], rval[1]))
             idx = idx + 1
     if myErr:
         raise myErr
     return outputNameVals
Example #27
0
    def returnResponsePdu(
        self,
        snmpEngine,
        messageProcessingModel,
        securityModel,
        securityName,
        securityLevel,
        contextEngineId,
        contextName,
        pduVersion,
        PDU,
        maxSizeResponseScopedPDU,
        stateReference,
        statusInformation
        ):
        """PDU dispatcher -- prepare and serialize a response"""
        # Extract input values and initialize defaults
        mpHandler = snmpEngine.messageProcessingSubsystems.get(
            int(messageProcessingModel)
            )
        if mpHandler is None:
            raise error.StatusInformation(
                errorIndication='unsupportedMsgProcessingModel'
                )

        debug.logger & debug.flagDsp and debug.logger('returnResponsePdu: PDU %s' % (PDU and PDU.prettyPrint() or "<empty>",))

        # 4.1.2.2
        try:
            ( destTransportDomain,
              destTransportAddress,
              outgoingMessage ) = mpHandler.prepareResponseMessage(
                snmpEngine,
                messageProcessingModel,
                securityModel,
                securityName,
                securityLevel,
                contextEngineId,
                contextName,
                pduVersion,
                PDU,
                maxSizeResponseScopedPDU,
                stateReference,
                statusInformation
                )
            debug.logger & debug.flagDsp and debug.logger('returnResponsePdu: MP suceeded')
        except error.StatusInformation, statusInformation:
            # 4.1.2.3
            raise
Example #28
0
    def loadModules(self, *modNames, **userCtx):
        # Build a list of available modules
        if not modNames:
            modNames = {}
            for mibSource in self.__mibSources:
                for modName in mibSource.listdir():
                    modNames[modName] = None
            modNames = list(modNames.keys())
        if not modNames:
            raise error.MibNotFoundError(
                'No MIB module to load at %s' % (self,)
            )

        for modName in modNames:
            try:
                self.loadModule(modName, **userCtx)
            except error.MibNotFoundError:
                if self.__mibCompiler:
                    debug.logger & debug.flagBld and debug.logger('loadModules: calling MIB compiler for %s' % modName)
                    status = self.__mibCompiler.compile(modName, genTexts=self.loadTexts)
                    errs = '; '.join([hasattr(x, 'error') and str(x.error) or x for x in status.values() if
                                      x in ('failed', 'missing')])
                    if errs:
                        raise error.MibNotFoundError('%s compilation error(s): %s' % (modName, errs))
                    # compilation suceeded, MIB might load now
                    self.loadModule(modName, **userCtx)

        return self
Example #29
0
    def __expireRequest(self, snmpEngine,cachedParams,statusInformation=None):
        processResponsePdu, timeoutAt, cbCtx = cachedParams['expectResponse']
        if statusInformation is None and time.time() < timeoutAt:
            return

        debug.logger & debug.flagDsp and debug.logger('__expireRequest: req cachedParams %s' % cachedParams)

        # Fail timed-out requests        
        if not statusInformation:
            statusInformation = error.StatusInformation(
                errorIndication='requestTimedOut'
                )
        self.releaseStateInformation(
            snmpEngine,
            cachedParams['sendPduHandle'],
            cachedParams['messageProcessingModel']
            )
        processResponsePdu(
            snmpEngine,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            statusInformation,
            cachedParams['sendPduHandle'],
            cbCtx
            )
        return 1
Example #30
0
 def _listdir(self):
     try:
         return self._uniqNames(os.listdir(self._srcName))
     except OSError:
         debug.logger & debug.flagBld and debug.logger(
             'listdir() failed for %s: %s' % (self._srcName, sys.exc_info()[1]))
         return ()
Example #31
0
 def setMibSources(self, *mibSources):
     self.__mibSources = mibSources
     debug.logger & debug.flagBld and debug.logger(
         'setMibPath: new MIB sources %s' % (self.__mibSources, ))
Example #32
0
    def processIncomingMsg(self, snmpEngine, messageProcessingModel,
                           maxMessageSize, securityParameters, securityModel,
                           securityLevel, wholeMsg, msg):
        # rfc2576: 5.2.1
        communityName, transportInformation = securityParameters

        scope = dict(communityName=communityName,
                     transportInformation=transportInformation)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc2576.processIncomingMsg:writable', scope
        )
        snmpEngine.observer.clearExecutionContext(
            snmpEngine, 'rfc2576.processIncomingMsg:writable'
        )

        try:
            securityName, contextEngineId, contextName = self._com2sec(
                snmpEngine, scope.get('communityName', communityName),
                scope.get('transportInformation', transportInformation)
            )

        except error.StatusInformation:
            snmpInBadCommunityNames, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInBadCommunityNames')
            snmpInBadCommunityNames.syntax += 1
            raise error.StatusInformation(errorIndication=errind.unknownCommunityName)

        snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB',
                                                                                              'snmpEngineID')

        securityEngineID = snmpEngineID.syntax

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc2576.processIncomingMsg',
            dict(transportInformation=transportInformation,
                 securityEngineId=securityEngineID,
                 securityName=securityName,
                 communityName=communityName,
                 contextEngineId=contextEngineId,
                 contextName=contextName)
        )
        snmpEngine.observer.clearExecutionContext(
            snmpEngine, 'rfc2576.processIncomingMsg'
        )

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: looked up securityName %r securityModel %r contextEngineId %r contextName %r by communityName %r AND transportInformation %r' % (
                securityName, self.securityModelID, 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.flagSM and debug.logger(
            'processIncomingMsg: generated maxSizeResponseScopedPDU %s securityStateReference %s' % (
                maxSizeResponseScopedPDU, securityStateReference))

        return (securityEngineID, securityName, scopedPDU,
                maxSizeResponseScopedPDU, securityStateReference)
Example #33
0
 def stopProtocol(self):
     debug.logger & debug.flagIO and debug.logger('stopProtocol: invoked')
Example #34
0
    def prepareDataElements(self, snmpEngine, transportDomain,
                            transportAddress, wholeMsg):
        mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        # rfc3412: 7.2.2
        try:
            msg, restOfWholeMsg = decoder.decode(wholeMsg,
                                                 asn1Spec=self._snmpMsgSpec)
        except PyAsn1Error:
            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: %s' % (sys.exc_info()[1], ))
            snmpInASNParseErrs, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1
            raise error.StatusInformation(errorIndication=errind.parseError)

        debug.logger & debug.flagMP and debug.logger(
            'prepareDataElements: %s' % (msg.prettyPrint(), ))

        if eoo.endOfOctets.isSameTypeWith(msg):
            raise error.StatusInformation(errorIndication=errind.parseError)

        # rfc3412: 7.2.3
        msgVersion = msg.getComponentByPosition(0)

        # rfc2576: 5.2.1
        snmpEngineMaxMessageSize, = mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize')
        communityName = msg.getComponentByPosition(1)
        # transportDomain identifies local enpoint
        securityParameters = (communityName, (transportDomain,
                                              transportAddress))
        messageProcessingModel = int(msg.getComponentByPosition(0))
        securityModel = messageProcessingModel + 1
        securityLevel = 1

        # rfc3412: 7.2.4 -- 7.2.5 -> noop

        k = int(securityModel)
        if k in snmpEngine.securityModels:
            smHandler = snmpEngine.securityModels[k]
        else:
            raise error.StatusInformation(
                errorIndication=errind.unsupportedSecurityModel)

        # rfc3412: 7.2.6
        (securityEngineId, securityName, scopedPDU, maxSizeResponseScopedPDU,
         securityStateReference) = smHandler.processIncomingMsg(
             snmpEngine, messageProcessingModel,
             snmpEngineMaxMessageSize.syntax, securityParameters,
             securityModel, securityLevel, wholeMsg, msg)

        debug.logger & debug.flagMP and debug.logger(
            'prepareDataElements: SM returned securityEngineId %r securityName %r'
            % (securityEngineId, securityName))

        # rfc3412: 7.2.6a --> noop

        # rfc3412: 7.2.7
        contextEngineId, contextName, pdu = scopedPDU

        # rfc2576: 5.2.1
        pduVersion = msgVersion
        pduType = pdu.tagSet

        # rfc3412: 7.2.8, 7.2.9 -> noop

        # rfc3412: 7.2.10
        if pduType in rfc3411.responseClassPDUs:
            # get unique PDU request-id
            msgID = pdu.getComponentByPosition(0)

            # 7.2.10a
            try:
                cachedReqParams = self._cache.popByMsgId(int(msgID))
            except error.ProtocolError:
                smHandler.releaseStateInformation(securityStateReference)
                raise error.StatusInformation(
                    errorIndication=errind.dataMismatch)

            # recover original PDU request-id to return to app
            pdu.setComponentByPosition(0, cachedReqParams['reqID'])

            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: unique PDU request-id %s replaced with original ID %s'
                % (msgID, cachedReqParams['reqID']))

            # 7.2.10b
            sendPduHandle = cachedReqParams['sendPduHandle']
        else:
            sendPduHandle = None

        # no error by default
        statusInformation = None

        # rfc3412: 7.2.11 -> noop

        # rfc3412: 7.2.12
        if pduType in rfc3411.responseClassPDUs:
            # rfc3412: 7.2.12a -> noop
            # rfc3412: 7.2.12b
            # noinspection PyUnboundLocalVariable
            if securityModel != cachedReqParams['securityModel'] or \
                    securityName != cachedReqParams['securityName'] or \
                    securityLevel != cachedReqParams['securityLevel'] or \
                    contextEngineId != cachedReqParams['contextEngineId'] or \
                    contextName != cachedReqParams['contextName']:
                smHandler.releaseStateInformation(securityStateReference)
                raise error.StatusInformation(
                    errorIndication=errind.dataMismatch)

            stateReference = None

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc2576.prepareDataElements:response',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     communityName=communityName,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc2576.prepareDataElements:response')

            # rfc3412: 7.2.12c
            smHandler.releaseStateInformation(securityStateReference)

            # rfc3412: 7.2.12d
            return (messageProcessingModel, securityModel, securityName,
                    securityLevel, contextEngineId, contextName, pduVersion,
                    pdu, pduType, sendPduHandle, maxSizeResponseScopedPDU,
                    statusInformation, stateReference)

        # rfc3412: 7.2.13
        if pduType in rfc3411.confirmedClassPDUs:
            # store original PDU request-id and replace it with a unique one
            reqID = pdu.getComponentByPosition(0)
            msgID = self._cache.newMsgID()
            pdu.setComponentByPosition(0, msgID)
            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: received PDU request-id %s replaced with unique ID %s'
                % (reqID, msgID))

            # rfc3412: 7.2.13a
            snmpEngineId, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB',
                                                     'snmpEngineID')
            if securityEngineId != snmpEngineId.syntax:
                smHandler.releaseStateInformation(securityStateReference)
                raise error.StatusInformation(
                    errorIndication=errind.engineIDMismatch)

            # rfc3412: 7.2.13b
            stateReference = self._cache.newStateReference()
            self._cache.pushByStateRef(
                stateReference,
                msgVersion=messageProcessingModel,
                msgID=msgID,
                reqID=reqID,
                contextEngineId=contextEngineId,
                contextName=contextName,
                securityModel=securityModel,
                securityName=securityName,
                securityLevel=securityLevel,
                securityStateReference=securityStateReference,
                msgMaxSize=snmpEngineMaxMessageSize.syntax,
                maxSizeResponseScopedPDU=maxSizeResponseScopedPDU,
                transportDomain=transportDomain,
                transportAddress=transportAddress)

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc2576.prepareDataElements:confirmed',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     communityName=communityName,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc2576.prepareDataElements:confirmed')

            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: cached by new stateReference %s' %
                stateReference)

            # rfc3412: 7.2.13c
            return (messageProcessingModel, securityModel, securityName,
                    securityLevel, contextEngineId, contextName, pduVersion,
                    pdu, pduType, sendPduHandle, maxSizeResponseScopedPDU,
                    statusInformation, stateReference)

        # rfc3412: 7.2.14
        if pduType in rfc3411.unconfirmedClassPDUs:
            # Pass new stateReference to let app browse request details
            stateReference = self._cache.newStateReference()

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc2576.prepareDataElements:unconfirmed',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     communityName=communityName,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc2576.prepareDataElements:unconfirmed')

            # This is not specified explicitly in RFC
            smHandler.releaseStateInformation(securityStateReference)

            return (messageProcessingModel, securityModel, securityName,
                    securityLevel, contextEngineId, contextName, pduVersion,
                    pdu, pduType, sendPduHandle, maxSizeResponseScopedPDU,
                    statusInformation, stateReference)

        smHandler.releaseStateInformation(securityStateReference)
        raise error.StatusInformation(
            errorIndication=errind.unsupportedPDUtype)
Example #35
0
    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

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: securityParameters %s' %
            debug.hexdump(securityParameters))

        # 3.2.1
        try:
            securityParameters, rest = decoder.decode(
                securityParameters, asn1Spec=self.__securityParametersSpec)

        except PyAsn1Error:
            debug.logger & debug.flagSM and debug.logger(
                'processIncomingMsg: %s' % (sys.exc_info()[1], ))
            snmpInASNParseErrs, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1
            raise error.StatusInformation(errorIndication=errind.parseError)

        debug.logger & debug.flagSM 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.flagSM and debug.logger(
            '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
        contextName = null

        snmpEngineID = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB',
                                                'snmpEngineID')[0].syntax

        # 3.2.3
        if msgAuthoritativeEngineId != snmpEngineID and \
                msgAuthoritativeEngineId not in self.__timeline:
            if msgAuthoritativeEngineId and \
                    4 < len(msgAuthoritativeEngineId) < 33:
                # 3.2.3a - cloned user when request was sent
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: unsynchronized securityEngineID %r' %
                    (msgAuthoritativeEngineId, ))
            else:
                # 3.2.3b
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: peer requested snmpEngineID discovery'
                )
                usmStatsUnknownEngineIDs, = mibBuilder.importSymbols(
                    '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownEngineIDs')
                usmStatsUnknownEngineIDs.syntax += 1
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: null or malformed msgAuthoritativeEngineId'
                )
                pysnmpUsmDiscoverable, = mibBuilder.importSymbols(
                    '__PYSNMP-USM-MIB', 'pysnmpUsmDiscoverable')
                if pysnmpUsmDiscoverable.syntax:
                    debug.logger & debug.flagSM and debug.logger(
                        'processIncomingMsg: starting snmpEngineID discovery procedure'
                    )

                    # Report original contextName
                    if scopedPduData.getName() != 'plaintext':
                        debug.logger & debug.flagSM and debug.logger(
                            'processIncomingMsg: scopedPduData not plaintext %s'
                            % scopedPduData.prettyPrint())
                        raise error.StatusInformation(
                            errorIndication=errind.unknownEngineID)

                    # 7.2.6.a.1
                    scopedPdu = scopedPduData.getComponent()
                    contextEngineId = scopedPdu.getComponentByPosition(0)
                    contextName = scopedPdu.getComponentByPosition(1)

                    raise error.StatusInformation(
                        errorIndication=errind.unknownEngineID,
                        oid=usmStatsUnknownEngineIDs.name,
                        val=usmStatsUnknownEngineIDs.syntax,
                        securityStateReference=securityStateReference,
                        securityLevel=securityLevel,
                        contextEngineId=contextEngineId,
                        contextName=contextName,
                        scopedPDU=scopedPdu,
                        maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
                else:
                    debug.logger & debug.flagSM and debug.logger(
                        'processIncomingMsg: will not discover EngineID')
                    # free securityStateReference XXX
                    raise error.StatusInformation(
                        errorIndication=errind.unknownEngineID)

        msgUserName = securityParameters.getComponentByPosition(3)

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: read from securityParams msgAuthoritativeEngineId %r msgUserName %r'
            % (msgAuthoritativeEngineId, msgUserName))

        if msgUserName:
            # 3.2.4
            try:
                (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
                 usmUserAuthKeyLocalized, usmUserPrivProtocol,
                 usmUserPrivKeyLocalized) = self.__getUserInfo(
                     snmpEngine.msgAndPduDsp.mibInstrumController,
                     msgAuthoritativeEngineId, msgUserName)
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: read user info from LCD')

            except NoSuchInstanceError:
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: unknown securityEngineID %r msgUserName %r'
                    % (msgAuthoritativeEngineId, msgUserName))
                usmStatsUnknownUserNames, = mibBuilder.importSymbols(
                    '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames')
                usmStatsUnknownUserNames.syntax += 1
                raise error.StatusInformation(
                    errorIndication=errind.unknownSecurityName,
                    oid=usmStatsUnknownUserNames.name,
                    val=usmStatsUnknownUserNames.syntax,
                    securityStateReference=securityStateReference,
                    securityLevel=securityLevel,
                    contextEngineId=contextEngineId,
                    contextName=contextName,
                    maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: %s' % (sys.exc_info()[1], ))
                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
            usmUserAuthProtocol = noauth.NoAuth.serviceID
            usmUserPrivProtocol = nopriv.NoPriv.serviceID
            usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None

        debug.logger & debug.flagSM and debug.logger(
            '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,
            usmUserAuthProtocol=usmUserAuthProtocol,
            usmUserAuthKeyLocalized=usmUserAuthKeyLocalized,
            usmUserPrivProtocol=usmUserPrivProtocol,
            usmUserPrivKeyLocalized=usmUserPrivKeyLocalized)

        msgAuthoritativeEngineBoots = securityParameters.getComponentByPosition(
            1)
        msgAuthoritativeEngineTime = securityParameters.getComponentByPosition(
            2)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc3414.processIncomingMsg',
            dict(securityEngineId=msgAuthoritativeEngineId,
                 snmpEngineBoots=msgAuthoritativeEngineBoots,
                 snmpEngineTime=msgAuthoritativeEngineTime,
                 userName=usmUserName,
                 securityName=usmUserSecurityName,
                 authProtocol=usmUserAuthProtocol,
                 authKey=usmUserAuthKeyLocalized,
                 privProtocol=usmUserPrivProtocol,
                 privKey=usmUserPrivKeyLocalized))
        snmpEngine.observer.clearExecutionContext(
            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.serviceID:
                    badSecIndication = 'authPriv wanted while auth not expected'
                if usmUserPrivProtocol == nopriv.NoPriv.serviceID:
                    badSecIndication = 'authPriv wanted while priv not expected'
            elif securityLevel == 2:
                if usmUserAuthProtocol == noauth.NoAuth.serviceID:
                    badSecIndication = 'authNoPriv wanted while auth not expected'
                if usmUserPrivProtocol != nopriv.NoPriv.serviceID:
                    # 4 (discovery phase always uses authenticated messages)
                    if msgAuthoritativeEngineBoots or msgAuthoritativeEngineTime:
                        badSecIndication = 'authNoPriv wanted while priv expected'

            elif securityLevel == 1:
                if usmUserAuthProtocol != noauth.NoAuth.serviceID:
                    badSecIndication = 'noAuthNoPriv wanted while auth expected'
                if usmUserPrivProtocol != nopriv.NoPriv.serviceID:
                    badSecIndication = 'noAuthNoPriv wanted while priv expected'
            if badSecIndication:
                usmStatsUnsupportedSecLevels, = mibBuilder.importSymbols(
                    '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnsupportedSecLevels')
                usmStatsUnsupportedSecLevels.syntax += 1
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: reporting inappropriate security level for user %s: %s'
                    % (msgUserName, badSecIndication))
                raise error.StatusInformation(
                    errorIndication=errind.unsupportedSecurityLevel,
                    oid=usmStatsUnsupportedSecLevels.name,
                    val=usmStatsUnsupportedSecLevels.syntax,
                    securityStateReference=securityStateReference,
                    securityLevel=securityLevel,
                    contextEngineId=contextEngineId,
                    contextName=contextName,
                    maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)

        # 3.2.6
        if securityLevel == 3 or securityLevel == 2:
            if usmUserAuthProtocol in self.authServices:
                authHandler = self.authServices[usmUserAuthProtocol]
            else:
                raise error.StatusInformation(
                    errorIndication=errind.authenticationFailure)

            try:
                authHandler.authenticateIncomingMsg(
                    usmUserAuthKeyLocalized,
                    securityParameters.getComponentByPosition(4), 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,
                    val=usmStatsWrongDigests.syntax,
                    securityStateReference=securityStateReference,
                    securityLevel=securityLevel,
                    contextEngineId=contextEngineId,
                    contextName=contextName,
                    maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)

            debug.logger & debug.flagSM and debug.logger(
                'processIncomingMsg: incoming msg authenticated')

            # synchronize time with authed peer
            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)

            debug.logger & debug.flagSM and debug.logger(
                '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(
                    '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots',
                    'snmpEngineTime')
                snmpEngineBoots = snmpEngineBoots.syntax
                snmpEngineTime = snmpEngineTime.syntax.clone()
                idleTime = 0
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: read snmpEngineBoots (%s), snmpEngineTime (%s) from LCD'
                    % (snmpEngineBoots, snmpEngineTime))
            else:
                # Non-authoritative SNMP engine: use cached estimates
                if msgAuthoritativeEngineId in self.__timeline:
                    (snmpEngineBoots, snmpEngineTime, latestReceivedEngineTime,
                     latestUpdateTimestamp
                     ) = self.__timeline[msgAuthoritativeEngineId]
                    # time passed since last talk with this SNMP engine
                    idleTime = int(time.time()) - latestUpdateTimestamp
                    debug.logger & debug.flagSM and debug.logger(
                        '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:
                    usmStatsNotInTimeWindows, = mibBuilder.importSymbols(
                        '__SNMP-USER-BASED-SM-MIB', 'usmStatsNotInTimeWindows')
                    usmStatsNotInTimeWindows.syntax += 1
                    raise error.StatusInformation(
                        errorIndication=errind.notInTimeWindow,
                        oid=usmStatsNotInTimeWindows.name,
                        val=usmStatsNotInTimeWindows.syntax,
                        securityStateReference=securityStateReference,
                        securityLevel=2,
                        contextEngineId=contextEngineId,
                        contextName=contextName,
                        maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
            # 3.2.7b
            else:
                # 3.2.7b.1
                # noinspection PyUnboundLocalVariable
                if msgAuthoritativeEngineBoots > snmpEngineBoots or \
                        msgAuthoritativeEngineBoots == snmpEngineBoots and \
                        msgAuthoritativeEngineTime > latestReceivedEngineTime:
                    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)

                    debug.logger & debug.flagSM and debug.logger(
                        '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:
                    raise error.StatusInformation(
                        errorIndication=errind.notInTimeWindow)

        # 3.2.8a
        if securityLevel == 3:
            if usmUserPrivProtocol in self.privServices:
                privHandler = self.privServices[usmUserPrivProtocol]
            else:
                raise error.StatusInformation(
                    errorIndication=errind.decryptionError)
            encryptedPDU = scopedPduData.getComponentByPosition(1)
            if encryptedPDU is None:  # no ciphertext
                raise error.StatusInformation(
                    errorIndication=errind.decryptionError)

            try:
                decryptedData = privHandler.decryptData(
                    usmUserPrivKeyLocalized,
                    (securityParameters.getComponentByPosition(1),
                     securityParameters.getComponentByPosition(2),
                     securityParameters.getComponentByPosition(5)),
                    encryptedPDU)
                debug.logger & debug.flagSM and debug.logger(
                    '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,
                    val=usmStatsDecryptionErrors.syntax,
                    securityStateReference=securityStateReference,
                    securityLevel=securityLevel,
                    contextEngineId=contextEngineId,
                    contextName=contextName,
                    maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
            scopedPduSpec = scopedPduData.setComponentByPosition(
                0).getComponentByPosition(0)
            try:
                scopedPDU, rest = decoder.decode(decryptedData,
                                                 asn1Spec=scopedPduSpec)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: scopedPDU decoder failed %s' %
                    sys.exc_info()[0])
                raise error.StatusInformation(
                    errorIndication=errind.decryptionError)

            if eoo.endOfOctets.isSameTypeWith(scopedPDU):
                raise error.StatusInformation(
                    errorIndication=errind.decryptionError)
        else:
            # 3.2.8b
            scopedPDU = scopedPduData.getComponentByPosition(0)
            if scopedPDU is None:  # no plaintext
                raise error.StatusInformation(
                    errorIndication=errind.decryptionError)

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: scopedPDU decoded %s' %
            scopedPDU.prettyPrint())

        # 3.2.10
        securityName = usmUserSecurityName

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: cached msgUserName %s info by securityStateReference %s'
            % (msgUserName, securityStateReference))

        # Delayed to include details
        if not msgUserName and not msgAuthoritativeEngineId:
            usmStatsUnknownUserNames, = mibBuilder.importSymbols(
                '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames')
            usmStatsUnknownUserNames.syntax += 1
            raise error.StatusInformation(
                errorIndication=errind.unknownSecurityName,
                oid=usmStatsUnknownUserNames.name,
                val=usmStatsUnknownUserNames.syntax,
                securityStateReference=securityStateReference,
                securityEngineID=msgAuthoritativeEngineId,
                securityLevel=securityLevel,
                contextEngineId=contextEngineId,
                contextName=contextName,
                maxSizeResponseScopedPDU=maxSizeResponseScopedPDU,
                PDU=scopedPDU)

        # 3.2.12
        return (msgAuthoritativeEngineId, securityName, scopedPDU,
                maxSizeResponseScopedPDU, securityStateReference)
Example #36
0
    def prepareOutgoingMessage(self, snmpEngine, transportDomain,
                               transportAddress, messageProcessingModel,
                               securityModel, securityName, securityLevel,
                               contextEngineId, contextName, pduVersion, pdu,
                               expectResponse, sendPduHandle):
        snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
        snmpEngineID = snmpEngineID.syntax

        # 7.1.1b
        msgID = self._cache.newMsgID()

        debug.logger & debug.flagMP and debug.logger(
            'prepareOutgoingMessage: new msgID %s' % msgID)

        k = (transportDomain, transportAddress)
        if k in self.__engineIdCache:
            peerSnmpEngineData = self.__engineIdCache[k]
        else:
            peerSnmpEngineData = None

        debug.logger & debug.flagMP and debug.logger(
            '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
                # probably be done on Agent side (see 7.1.3.d.2,) so this
                # is a sort of workaround.
                if not contextEngineId:
                    contextEngineId = peerSnmpEngineData['securityEngineId']
        # 7.1.5
        if not contextName:
            contextName = self._emptyStr

        debug.logger & debug.flagMP and debug.logger(
            'prepareOutgoingMessage: using contextEngineId %r, contextName %r'
            % (contextEngineId, contextName))

        # 7.1.6
        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)

        # 7.1.7
        msg = self._snmpMsgSpec

        # 7.1.7a
        msg.setComponentByPosition(0,
                                   self.messageProcessingModelID,
                                   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)

        snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.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)

        # 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)

        if pdu.tagSet in rfc3411.confirmedClassPDUs:
            msgFlags |= 0x04

        headerData.setComponentByPosition(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.flagMP and debug.logger(
            'prepareOutgoingMessage: %s' % (msg.prettyPrint(), ))

        if securityModel in snmpEngine.securityModels:
            smHandler = snmpEngine.securityModels[securityModel]
        else:
            raise error.StatusInformation(
                errorIndication=errind.unsupportedSecurityModel)

        # 7.1.9.a
        if pdu.tagSet in rfc3411.unconfirmedClassPDUs:
            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)
                # XXX
                scopedPDU = self.__scopedPDU
                scopedPDU.setComponentByPosition(0,
                                                 self._emptyStr,
                                                 verifyConstraints=False,
                                                 matchTags=False,
                                                 matchConstraints=False)
                scopedPDU.setComponentByPosition(1, contextName)
                scopedPDU.setComponentByPosition(2)

                # Use dead-empty PDU for engine-discovery report
                emptyPdu = pdu.clone()
                pMod.apiPDU.setDefaults(emptyPdu)

                scopedPDU.getComponentByPosition(2).setComponentByType(
                    emptyPdu.tagSet,
                    emptyPdu,
                    verifyConstraints=False,
                    matchTags=False,
                    matchConstraints=False)
                debug.logger & debug.flagMP and debug.logger(
                    'prepareOutgoingMessage: force engineID discovery')
            else:
                securityEngineId = peerSnmpEngineData['securityEngineId']

        debug.logger & debug.flagMP and debug.logger(
            'prepareOutgoingMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r'
            % (securityModel, securityEngineId, securityName, securityLevel))

        # 7.1.9.b
        (securityParameters, wholeMsg) = smHandler.generateRequestMsg(
            snmpEngine, self.messageProcessingModelID, msg,
            snmpEngineMaxMessageSize.syntax, securityModel, securityEngineId,
            securityName, securityLevel, scopedPDU)

        # Message size constraint verification
        if len(wholeMsg) > snmpEngineMaxMessageSize.syntax:
            raise error.StatusInformation(errorIndication=errind.tooBig)

        # 7.1.9.c
        if pdu.tagSet in rfc3411.confirmedClassPDUs:
            # 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)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc3412.prepareOutgoingMessage',
            dict(transportDomain=transportDomain,
                 transportAddress=transportAddress,
                 wholeMsg=wholeMsg,
                 securityModel=securityModel,
                 securityName=securityName,
                 securityLevel=securityLevel,
                 contextEngineId=contextEngineId,
                 contextName=contextName,
                 pdu=pdu))
        snmpEngine.observer.clearExecutionContext(
            snmpEngine, 'rfc3412.prepareOutgoingMessage')

        return transportDomain, transportAddress, wholeMsg
Example #37
0
    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, origDiscoveryRetries) = 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))

            errorIndication = statusInformation['errorIndication']

            if errorIndication in (errind.notInTimeWindow, errind.unknownEngineID):
                origDiscoveryRetries += 1
                origRetries = 0
            else:
                origDiscoveryRetries = 0
                origRetries += 1

            if origRetries > origRetryCount or origDiscoveryRetries > self.__options.get('discoveryRetries', 4):
                debug.logger & debug.flagApp and debug.logger(
                    'processResponsePdu: sendRequestHandle %s, sendPduHandle %s retry count %d exceeded' % (
                        sendRequestHandle, sendPduHandle, origRetries))
                cbFun(snmpEngine, sendRequestHandle, 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, True, 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, origDiscoveryRetries
            )
            return

        # 3.3.6c
        # User-side API assumes SMIv2
        if messageProcessingModel == 0:
            PDU = rfc2576.v1ToV2(PDU, origPdu)

        cbFun(snmpEngine, sendRequestHandle, None, PDU, cbCtx)
Example #38
0
    def prepareDataElements(self, snmpEngine, transportDomain,
                            transportAddress, wholeMsg):
        # 7.2.2
        msg, restOfwholeMsg = decoder.decode(wholeMsg,
                                             asn1Spec=self._snmpMsgSpec)

        debug.logger & debug.flagMP and debug.logger(
            'prepareDataElements: %s' % (msg.prettyPrint(), ))

        if eoo.endOfOctets.isSameTypeWith(msg):
            raise error.StatusInformation(errorIndication=errind.parseError)

        # 7.2.3
        headerData = msg.getComponentByPosition(1)
        msgVersion = messageProcessingModel = msg.getComponentByPosition(0)
        msgID = headerData.getComponentByPosition(0)
        msgFlags, = headerData.getComponentByPosition(2).asNumbers()
        maxMessageSize = headerData.getComponentByPosition(1)
        securityModel = headerData.getComponentByPosition(3)
        securityParameters = msg.getComponentByPosition(2)

        debug.logger & debug.flagMP and debug.logger(
            '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(
                '__SNMP-MPD-MIB', 'snmpUnknownSecurityModels')
            snmpUnknownSecurityModels.syntax += 1
            raise error.StatusInformation(
                errorIndication=errind.unsupportedSecurityModel)

        # 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.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, scopedPDU,
             maxSizeResponseScopedPDU,
             securityStateReference) = smHandler.processIncomingMsg(
                 snmpEngine, messageProcessingModel, maxMessageSize,
                 securityParameters, securityModel, securityLevel, wholeMsg,
                 msg)
            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: SM succeeded')

        except error.StatusInformation:
            statusInformation, origTraceback = sys.exc_info()[1:3]

            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: SM failed, statusInformation %s' %
                statusInformation)

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:sm-failure',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityLevel=securityLevel,
                     securityParameters=securityParameters,
                     statusInformation=statusInformation))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:sm-failure')

            if 'errorIndication' in statusInformation:
                # 7.2.6a
                if 'oid' in statusInformation:
                    # 7.2.6a1
                    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,
                        contextName=contextName,
                        securityModel=securityModel,
                        securityName=securityName,
                        securityLevel=securityLevel,
                        securityStateReference=securityStateReference,
                        reportableFlag=reportableFlag,
                        msgMaxSize=maxMessageSize,
                        maxSizeResponseScopedPDU=maxSizeResponseScopedPDU,
                        transportDomain=transportDomain,
                        transportAddress=transportAddress)

                    # 7.2.6a3
                    try:
                        snmpEngine.msgAndPduDsp.returnResponsePdu(
                            snmpEngine, 3, securityModel, securityName,
                            securityLevel, contextEngineId, contextName, 1,
                            pdu, maxSizeResponseScopedPDU, stateReference,
                            statusInformation)
                    except error.StatusInformation:
                        pass

                    debug.logger & debug.flagMP and debug.logger(
                        'prepareDataElements: error reported')

            # 7.2.6b
            if sys.version_info[0] <= 2:
                raise statusInformation
            else:
                try:
                    raise statusInformation.with_traceback(origTraceback)
                finally:
                    # Break cycle between locals and traceback object
                    # (seems to be irrelevant on Py3 but just in case)
                    del origTraceback
        else:
            # Sniff for 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.internalClassPDUs:
                    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)

                    debug.logger & debug.flagMP and debug.logger(
                        'prepareDataElements: cache securityEngineId %r for %r %r'
                        %
                        (securityEngineId, transportDomain, transportAddress))

        snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
        snmpEngineID = snmpEngineID.syntax

        # 7.2.7 XXX PDU would be parsed here?
        contextEngineId = scopedPDU[0]
        contextName = scopedPDU[1]
        pdu = scopedPDU[2]

        pdu = pdu.getComponent()  # PDUs

        # 7.2.8
        pduVersion = api.protoVersion2c

        # 7.2.9
        pduType = pdu.tagSet

        # 7.2.10
        if (pduType in rfc3411.responseClassPDUs
                or pduType in rfc3411.internalClassPDUs):
            # 7.2.10a
            try:
                cachedReqParams = self._cache.popByMsgId(msgID)
            except error.ProtocolError:
                smHandler.releaseStateInformation(securityStateReference)
                raise error.StatusInformation(
                    errorIndication=errind.dataMismatch)
            # 7.2.10b
            sendPduHandle = cachedReqParams['sendPduHandle']
        else:
            sendPduHandle = None

        debug.logger & debug.flagMP and debug.logger(
            'prepareDataElements: using sendPduHandle %s for msgID %s' %
            (sendPduHandle, msgID))

        # 7.2.11
        if pduType in rfc3411.internalClassPDUs:
            # 7.2.11a
            varBinds = pMod.apiPDU.getVarBinds(pdu)
            if varBinds:
                statusInformation = error.StatusInformation(
                    errorIndication=_snmpErrors.get(
                        varBinds[0][0],
                        errind.ReportPduReceived(
                            varBinds[0][0].prettyPrint())),
                    oid=varBinds[0][0],
                    val=varBinds[0][1],
                    sendPduHandle=sendPduHandle)
            else:
                statusInformation = error.StatusInformation(
                    sendPduHandle=sendPduHandle)

            # 7.2.11b (incomplete implementation)

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:internal',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:internal')

            # 7.2.11c
            smHandler.releaseStateInformation(securityStateReference)

            # 7.2.11d
            # no-op

            # 7.2.11e XXX may need to pass Reports up to app in some cases...
            raise statusInformation

        statusInformation = None  # no errors ahead

        # 7.2.12
        if pduType in rfc3411.responseClassPDUs:
            # 7.2.12a -> no-op

            # 7.2.12b
            # noinspection PyUnboundLocalVariable
            if (securityModel != cachedReqParams['securityModel']
                    or securityName != cachedReqParams['securityName']
                    or securityLevel != cachedReqParams['securityLevel']
                    or contextEngineId != cachedReqParams['contextEngineId']
                    or contextName != cachedReqParams['contextName']):
                smHandler.releaseStateInformation(securityStateReference)
                raise error.StatusInformation(
                    errorIndication=errind.dataMismatch)

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:response',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:response')

            # 7.2.12c
            smHandler.releaseStateInformation(securityStateReference)
            stateReference = None

            # 7.2.12d
            return (messageProcessingModel, securityModel, securityName,
                    securityLevel, contextEngineId, contextName, pduVersion,
                    pdu, pduType, sendPduHandle, maxSizeResponseScopedPDU,
                    statusInformation, stateReference)

        # 7.2.13
        if pduType in rfc3411.confirmedClassPDUs:
            # 7.2.13a
            if securityEngineId != snmpEngineID:
                smHandler.releaseStateInformation(securityStateReference)
                raise error.StatusInformation(
                    errorIndication=errind.engineIDMismatch)

            # 7.2.13b
            stateReference = self._cache.newStateReference()
            self._cache.pushByStateRef(
                stateReference,
                msgVersion=messageProcessingModel,
                msgID=msgID,
                contextEngineId=contextEngineId,
                contextName=contextName,
                securityModel=securityModel,
                securityName=securityName,
                securityLevel=securityLevel,
                securityStateReference=securityStateReference,
                reportableFlag=reportableFlag,
                msgMaxSize=maxMessageSize,
                maxSizeResponseScopedPDU=maxSizeResponseScopedPDU,
                transportDomain=transportDomain,
                transportAddress=transportAddress)

            debug.logger & debug.flagMP and debug.logger(
                'prepareDataElements: new stateReference %s' % stateReference)

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:confirmed',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:confirmed')

            # 7.2.13c
            return (messageProcessingModel, securityModel, securityName,
                    securityLevel, contextEngineId, contextName, pduVersion,
                    pdu, pduType, sendPduHandle, maxSizeResponseScopedPDU,
                    statusInformation, stateReference)

        # 7.2.14
        if pduType in rfc3411.unconfirmedClassPDUs:
            # Pass new stateReference to let app browse request details
            stateReference = self._cache.newStateReference()

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:unconfirmed',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     securityEngineId=securityEngineId,
                     pdu=pdu))
            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.prepareDataElements:unconfirmed')

            # This is not specified explicitly in RFC
            smHandler.releaseStateInformation(securityStateReference)

            return (messageProcessingModel, securityModel, securityName,
                    securityLevel, contextEngineId, contextName, pduVersion,
                    pdu, pduType, sendPduHandle, maxSizeResponseScopedPDU,
                    statusInformation, stateReference)

        smHandler.releaseStateInformation(securityStateReference)
        raise error.StatusInformation(
            errorIndication=errind.unsupportedPDUtype)
Example #39
0
    def prepareResponseMessage(self, snmpEngine, messageProcessingModel,
                               securityModel, securityName, securityLevel,
                               contextEngineId, contextName, pduVersion, pdu,
                               maxSizeResponseScopedPDU, stateReference,
                               statusInformation):
        snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
        snmpEngineID = snmpEngineID.syntax

        # 7.1.2.b
        cachedParams = self._cache.popByStateRef(stateReference)
        msgID = cachedParams['msgID']
        contextEngineId = cachedParams['contextEngineId']
        contextName = cachedParams['contextName']
        securityModel = cachedParams['securityModel']
        securityName = cachedParams['securityName']
        securityLevel = cachedParams['securityLevel']
        securityStateReference = cachedParams['securityStateReference']
        reportableFlag = cachedParams['reportableFlag']
        maxMessageSize = cachedParams['msgMaxSize']
        transportDomain = cachedParams['transportDomain']
        transportAddress = cachedParams['transportAddress']

        debug.logger & debug.flagMP 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

            # 7.1.3b
            if (pdu is None and not reportableFlag or pduType is not None
                    and pduType not in rfc3411.confirmedClassPDUs):
                raise error.StatusInformation(
                    errorIndication=errind.loopTerminated)

            # 7.1.3c
            reportPDU = rfc1905.ReportPDU()
            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)

            # 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 = ""

            # 7.1.3e
            pdu = reportPDU

            debug.logger & debug.flagMP and debug.logger(
                'prepareResponseMessage: prepare report PDU for statusInformation %s'
                % statusInformation)
        # 7.1.4
        if not contextEngineId:
            contextEngineId = snmpEngineID  # XXX impl-dep manner

        # 7.1.5
        if not contextName:
            contextName = self._emptyStr

        debug.logger & debug.flagMP and debug.logger(
            'prepareResponseMessage: using contextEngineId %r, contextName %r'
            % (contextEngineId, contextName))

        # 7.1.6
        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)

        # 7.1.7
        msg = self._snmpMsgSpec

        # 7.1.7a
        msg.setComponentByPosition(0,
                                   self.messageProcessingModelID,
                                   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)

        snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.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)

        # 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)

        if pdu.tagSet in rfc3411.confirmedClassPDUs:  # XXX not needed?
            msgFlags |= 0x04

        headerData.setComponentByPosition(2,
                                          self._msgFlags[msgFlags],
                                          verifyConstraints=False,
                                          matchTags=False,
                                          matchConstraints=False)

        # 7.1.7e
        headerData.setComponentByPosition(3,
                                          securityModel,
                                          verifyConstraints=False,
                                          matchTags=False,
                                          matchConstraints=False)

        debug.logger & debug.flagMP and debug.logger(
            'prepareResponseMessage: %s' % (msg.prettyPrint(), ))

        if securityModel in snmpEngine.securityModels:
            smHandler = snmpEngine.securityModels[securityModel]
        else:
            raise error.StatusInformation(
                errorIndication=errind.unsupportedSecurityModel)

        debug.logger & debug.flagMP and debug.logger(
            'prepareResponseMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r'
            % (securityModel, snmpEngineID, securityName, securityLevel))

        # 7.1.8a
        try:
            (securityParameters, wholeMsg) = smHandler.generateResponseMsg(
                snmpEngine, self.messageProcessingModelID, msg,
                snmpEngineMaxMessageSize.syntax, securityModel, snmpEngineID,
                securityName, securityLevel, scopedPDU, securityStateReference)
        except error.StatusInformation:
            # 7.1.8.b
            raise

        debug.logger & debug.flagMP and debug.logger(
            'prepareResponseMessage: SM finished')

        # Message size constraint verification
        if len(wholeMsg) > min(snmpEngineMaxMessageSize.syntax,
                               maxMessageSize):
            raise error.StatusInformation(errorIndication=errind.tooBig)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc3412.prepareResponseMessage',
            dict(transportDomain=transportDomain,
                 transportAddress=transportAddress,
                 securityModel=securityModel,
                 securityName=securityName,
                 securityLevel=securityLevel,
                 contextEngineId=contextEngineId,
                 contextName=contextName,
                 securityEngineId=snmpEngineID,
                 pdu=pdu))
        snmpEngine.observer.clearExecutionContext(
            snmpEngine, 'rfc3412.prepareResponseMessage')

        return transportDomain, transportAddress, wholeMsg
Example #40
0
    def prepareResponseMessage(self, snmpEngine, messageProcessingModel,
                               securityModel, securityName, securityLevel,
                               contextEngineId, contextName, pduVersion, pdu,
                               maxSizeResponseScopedPDU, stateReference,
                               statusInformation):
        mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        snmpEngineId, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB',
                                                 'snmpEngineID')
        snmpEngineId = snmpEngineId.syntax

        # rfc3412: 7.1.2.b
        if stateReference is None:
            raise error.StatusInformation(errorIndication=errind.nonReportable)

        cachedParams = self._cache.popByStateRef(stateReference)
        msgID = cachedParams['msgID']
        reqID = cachedParams['reqID']
        contextEngineId = cachedParams['contextEngineId']
        contextName = cachedParams['contextName']
        securityModel = cachedParams['securityModel']
        securityName = cachedParams['securityName']
        securityLevel = cachedParams['securityLevel']
        securityStateReference = cachedParams['securityStateReference']
        maxMessageSize = cachedParams['msgMaxSize']
        transportDomain = cachedParams['transportDomain']
        transportAddress = cachedParams['transportAddress']

        debug.logger & debug.flagMP and debug.logger(
            'prepareResponseMessage: cache read msgID %s transportDomain %s transportAddress %s by stateReference %s'
            % (msgID, transportDomain, transportAddress, stateReference))

        # rfc3412: 7.1.3
        if statusInformation:
            # rfc3412: 7.1.3a (N/A)

            # rfc3412: 7.1.3b (always discard)
            raise error.StatusInformation(errorIndication=errind.nonReportable)

        # rfc3412: 7.1.4
        # Since there's no SNMP engine identification in v1/2c,
        # set destination contextEngineId to ours
        if not contextEngineId:
            contextEngineId = snmpEngineId

        # rfc3412: 7.1.5
        if not contextName:
            contextName = null

        # rfc3412: 7.1.6
        scopedPDU = (contextEngineId, contextName, pdu)

        debug.logger & debug.flagMP and debug.logger(
            '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)

        # att: msgId not set back to PDU as it's up to responder app

        # rfc3412: 7.1.7
        globalData = (msg, )

        k = int(securityModel)
        if k in snmpEngine.securityModels:
            smHandler = snmpEngine.securityModels[k]
        else:
            raise error.StatusInformation(
                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(
            snmpEngine, self.messageProcessingModelID, globalData,
            maxMessageSize, securityModel, snmpEngineId, securityName,
            securityLevel, scopedPDU, securityStateReference)

        # recover unique request-id right after PDU serialization
        pdu.setComponentByPosition(0, msgID)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc2576.prepareResponseMessage',
            dict(transportDomain=transportDomain,
                 transportAddress=transportAddress,
                 securityModel=securityModel,
                 securityName=securityName,
                 securityLevel=securityLevel,
                 contextEngineId=contextEngineId,
                 contextName=contextName,
                 securityEngineId=snmpEngineId,
                 communityName=msg.getComponentByPosition(1),
                 pdu=pdu))
        snmpEngine.observer.clearExecutionContext(
            snmpEngine, 'rfc2576.prepareResponseMessage')

        return transportDomain, transportAddress, wholeMsg
Example #41
0
def v1ToV2(v1Pdu, origV2Pdu=None):
    pduType = v1Pdu.tagSet
    v2Pdu = __v1ToV2PduMap[pduType].clone()

    debug.logger & debug.flagPrx and debug.logger(
        'v1ToV2: v1Pdu %s' % v1Pdu.prettyPrint())

    v2VarBinds = []

    # 3.1
    if pduType in rfc3411.notificationClassPDUs:
        # 3.1.1
        sysUpTime = v1.apiTrapPDU.getTimeStamp(v1Pdu)

        # 3.1.2
        genericTrap = v1.apiTrapPDU.getGenericTrap(v1Pdu)
        if genericTrap == 6:
            snmpTrapOIDParam = v1.apiTrapPDU.getEnterprise(v1Pdu) + (
                0, int(v1.apiTrapPDU.getSpecificTrap(v1Pdu)))

        # 3.1.3
        else:
            snmpTrapOIDParam = v2c.ObjectIdentifier(
                __v1ToV2TrapMap[genericTrap])

        # 3.1.4 (XXX snmpTrapCommunity.0 is missing here)
        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("")))
        v2VarBinds.append((v2c.apiTrapPDU.snmpTrapEnterprise,
                           v1.apiTrapPDU.getEnterprise(v1Pdu)))

        varBinds = v1.apiTrapPDU.getVarBinds(v1Pdu)
    else:
        varBinds = v1.apiPDU.getVarBinds(v1Pdu)

    # Translate Var-Binds
    for oid, v1Val in varBinds:
        # 2.1.1.11
        if v1Val.tagSet == v1.NetworkAddress.tagSet:
            v1Val = v1Val.getComponent()
        v2VarBinds.append((oid, __v1ToV2ValueMap[v1Val.tagSet].clone(v1Val)))

    if pduType in rfc3411.responseClassPDUs:
        # 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]
            else:
                v2VarBinds = [(o, rfc1905.noSuchObject) for o, v in v2VarBinds]
            v2c.apiPDU.setErrorStatus(v2Pdu, 0)
            v2c.apiPDU.setErrorIndex(v2Pdu, 0)
        else:
            # partial one-to-one mapping - 4.2.1
            v2c.apiPDU.setErrorStatus(v2Pdu, errorStatus)
            v2c.apiPDU.setErrorIndex(v2Pdu, errorIndex)

            # 4.1.2.1 --> no-op

    elif pduType in rfc3411.confirmedClassPDUs:
        v2c.apiPDU.setErrorStatus(v2Pdu, 0)
        v2c.apiPDU.setErrorIndex(v2Pdu, 0)

    if pduType not in rfc3411.notificationClassPDUs:
        v2c.apiPDU.setRequestID(v2Pdu, int(v1.apiPDU.getRequestID(v1Pdu)))

    v2c.apiPDU.setVarBinds(v2Pdu, v2VarBinds)

    debug.logger & debug.flagPrx and debug.logger(
        'v1ToV2: v2Pdu %s' % v2Pdu.prettyPrint())

    return v2Pdu
Example #42
0
    def returnResponsePdu(self, snmpEngine, messageProcessingModel,
                          securityModel, securityName, securityLevel,
                          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)

        debug.logger & debug.flagDsp and debug.logger(
            'returnResponsePdu: PDU %s' %
            (PDU and PDU.prettyPrint() or "<empty>", ))

        # 4.1.2.2
        try:
            (transportDomain, transportAddress,
             outgoingMessage) = mpHandler.prepareResponseMessage(
                 snmpEngine, messageProcessingModel, securityModel,
                 securityName, securityLevel, contextEngineId, contextName,
                 pduVersion, PDU, maxSizeResponseScopedPDU, stateReference,
                 statusInformation)

            debug.logger & debug.flagDsp and debug.logger(
                'returnResponsePdu: MP suceeded')

        except error.StatusInformation:
            # 4.1.2.3
            raise

        # Handle oversized messages XXX transport constrains?
        snmpEngineMaxMessageSize, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize')
        if (snmpEngineMaxMessageSize.syntax
                and len(outgoingMessage) > snmpEngineMaxMessageSize.syntax):
            snmpSilentDrops, = self.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpSilentDrops')
            snmpSilentDrops.syntax += 1
            raise error.StatusInformation(errorIndication=errind.tooBig)

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc3412.returnResponsePdu',
            dict(transportDomain=transportDomain,
                 transportAddress=transportAddress,
                 outgoingMessage=outgoingMessage,
                 messageProcessingModel=messageProcessingModel,
                 securityModel=securityModel,
                 securityName=securityName,
                 securityLevel=securityLevel,
                 contextEngineId=contextEngineId,
                 contextName=contextName,
                 pdu=PDU))

        # 4.1.2.4
        snmpEngine.transportDispatcher.sendMessage(outgoingMessage,
                                                   transportDomain,
                                                   transportAddress)

        snmpEngine.observer.clearExecutionContext(snmpEngine,
                                                  'rfc3412.returnResponsePdu')
Example #43
0
 def __init__(self, **kwargs):
     SnmpV3Error.__init__(self)
     self.__errorIndication = kwargs
     debug.logger & (debug.flagDsp | debug.flagMP
                     | debug.flagSM) and debug.logger(
                         'StatusInformation: %s' % kwargs)
Example #44
0
    def sendPdu(self,
                snmpEngine,
                transportDomain,
                transportAddress,
                messageProcessingModel,
                securityModel,
                securityName,
                securityLevel,
                contextEngineId,
                contextName,
                pduVersion,
                PDU,
                expectResponse,
                timeout=0,
                cbFun=None,
                cbCtx=None):
        """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)

        debug.logger & debug.flagDsp and debug.logger(
            'sendPdu: securityName %s, PDU\n%s' %
            (securityName, PDU.prettyPrint()))

        # 4.1.1.3
        sendPduHandle = self.__sendPduHandle()
        if expectResponse:
            self.__cache.add(sendPduHandle,
                             messageProcessingModel=messageProcessingModel,
                             sendPduHandle=sendPduHandle,
                             timeout=timeout +
                             snmpEngine.transportDispatcher.getTimerTicks(),
                             cbFun=cbFun,
                             cbCtx=cbCtx)

            debug.logger & debug.flagDsp and debug.logger(
                'sendPdu: current time %d ticks, one tick is %s seconds' %
                (snmpEngine.transportDispatcher.getTimerTicks(),
                 snmpEngine.transportDispatcher.getTimerResolution()))

        debug.logger & debug.flagDsp and debug.logger(
            'sendPdu: new sendPduHandle %s, timeout %s ticks, cbFun %s' %
            (sendPduHandle, timeout, cbFun))

        origTransportDomain = transportDomain
        origTransportAddress = transportAddress

        # 4.1.1.4 & 4.1.1.5
        try:
            (transportDomain, transportAddress,
             outgoingMessage) = mpHandler.prepareOutgoingMessage(
                 snmpEngine, origTransportDomain, origTransportAddress,
                 messageProcessingModel, securityModel, securityName,
                 securityLevel, contextEngineId, contextName, pduVersion, PDU,
                 expectResponse, sendPduHandle)

            debug.logger & debug.flagDsp and debug.logger(
                'sendPdu: MP succeeded')
        except PySnmpError:
            if expectResponse:
                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)

            raise error.PySnmpError('Transport dispatcher not set')

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc3412.sendPdu',
            dict(transportDomain=transportDomain,
                 transportAddress=transportAddress,
                 outgoingMessage=outgoingMessage,
                 messageProcessingModel=messageProcessingModel,
                 securityModel=securityModel,
                 securityName=securityName,
                 securityLevel=securityLevel,
                 contextEngineId=contextEngineId,
                 contextName=contextName,
                 pdu=PDU))

        try:
            snmpEngine.transportDispatcher.sendMessage(outgoingMessage,
                                                       transportDomain,
                                                       transportAddress)
        except PySnmpError:
            if expectResponse:
                self.__cache.pop(sendPduHandle)
            raise

        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)

        return sendPduHandle
Example #45
0
    def prepareOutgoingMessage(self, snmpEngine, transportDomain,
                               transportAddress, messageProcessingModel,
                               securityModel, securityName, securityLevel,
                               contextEngineId, contextName, pduVersion, pdu,
                               expectResponse, sendPduHandle):
        mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        snmpEngineId, = mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB',
                                                 'snmpEngineID')
        snmpEngineId = snmpEngineId.syntax

        # rfc3412: 7.1.1b
        if pdu.tagSet in rfc3411.confirmedClassPDUs:
            # serve unique PDU request-id
            pdu.setComponentByPosition(1)
            msgID = self._cache.newMsgID()
            reqID = pdu.getComponentByPosition(0)
            debug.logger & debug.flagMP and debug.logger(
                '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,
        # set destination contextEngineId to ours
        if not contextEngineId:
            contextEngineId = snmpEngineId

        # rfc3412: 7.1.5
        if not contextName:
            contextName = null

        debug.logger & debug.flagMP and debug.logger(
            'prepareOutgoingMessage: using contextEngineId %r contextName %r' %
            (contextEngineId, contextName))

        # rfc3412: 7.1.6
        scopedPDU = (contextEngineId, contextName, pdu)

        msg = self._snmpMsgSpec
        msg.setComponentByPosition(0, self.messageProcessingModelID)
        msg.setComponentByPosition(2)
        msg.getComponentByPosition(2).setComponentByType(
            pdu.tagSet, pdu, verifyConstraints=False)

        # rfc3412: 7.1.7
        globalData = (msg, )

        k = int(securityModel)
        if k in snmpEngine.securityModels:
            smHandler = snmpEngine.securityModels[k]
        else:
            raise error.StatusInformation(
                errorIndication=errind.unsupportedSecurityModel)

        # rfc3412: 7.1.9.a & rfc2576: 5.2.1 --> no-op

        snmpEngineMaxMessageSize, = mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize')

        # fix unique request-id right prior PDU serialization
        if pdu.tagSet in rfc3411.confirmedClassPDUs:
            # noinspection PyUnboundLocalVariable
            pdu.setComponentByPosition(0, msgID)

        # rfc3412: 7.1.9.b
        (securityParameters, wholeMsg) = smHandler.generateRequestMsg(
            snmpEngine, self.messageProcessingModelID, globalData,
            snmpEngineMaxMessageSize.syntax, securityModel, snmpEngineId,
            securityName, securityLevel, scopedPDU)

        # return original request-id right after PDU serialization
        if pdu.tagSet in rfc3411.confirmedClassPDUs:
            # noinspection PyUnboundLocalVariable
            pdu.setComponentByPosition(0, reqID)

        # rfc3412: 7.1.9.c
        if pdu.tagSet in rfc3411.confirmedClassPDUs:
            # 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)

        communityName = msg.getComponentByPosition(1)  # for observer

        snmpEngine.observer.storeExecutionContext(
            snmpEngine, 'rfc2576.prepareOutgoingMessage',
            dict(transportDomain=transportDomain,
                 transportAddress=transportAddress,
                 wholeMsg=wholeMsg,
                 securityModel=securityModel,
                 securityName=securityName,
                 securityLevel=securityLevel,
                 contextEngineId=contextEngineId,
                 contextName=contextName,
                 communityName=communityName,
                 pdu=pdu))
        snmpEngine.observer.clearExecutionContext(
            snmpEngine, 'rfc2576.prepareOutgoingMessage')

        return transportDomain, transportAddress, wholeMsg
Example #46
0
    def _sec2com(self, snmpEngine, securityName, contextEngineId, contextName):
        snmpTargetParamsSecurityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityName')
        if self.__paramsBranchId != snmpTargetParamsSecurityName.branchVersionId:
            snmpTargetParamsSecurityModel, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityModel')

            self.__nameToModelMap = {}

            nextMibNode = snmpTargetParamsSecurityName

            while 1:
                try:
                    nextMibNode = snmpTargetParamsSecurityName.getNextNode(
                        nextMibNode.name)

                except NoSuchInstanceError:
                    break

                instId = nextMibNode.name[len(snmpTargetParamsSecurityName.name
                                              ):]

                mibNode = snmpTargetParamsSecurityModel.getNode(
                    snmpTargetParamsSecurityModel.name + instId)

                if mibNode.syntax not in self.__nameToModelMap:
                    self.__nameToModelMap[nextMibNode.syntax] = set()

                self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)

            self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId

            # invalidate next map as it include this one
            self.__securityBranchId = -1

        snmpCommunityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-COMMUNITY-MIB', 'snmpCommunityName')
        if self.__securityBranchId != snmpCommunityName.branchVersionId:
            (
                snmpCommunitySecurityName, snmpCommunityContextEngineId,
                snmpCommunityContextName
            ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-COMMUNITY-MIB', 'snmpCommunitySecurityName',
                'snmpCommunityContextEngineID', 'snmpCommunityContextName')

            self.__securityMap = {}

            nextMibNode = snmpCommunityName
            while 1:
                try:
                    nextMibNode = snmpCommunityName.getNextNode(
                        nextMibNode.name)

                except NoSuchInstanceError:
                    break

                instId = nextMibNode.name[len(snmpCommunityName.name):]

                _securityName = snmpCommunitySecurityName.getNode(
                    snmpCommunitySecurityName.name + instId).syntax

                _contextEngineId = snmpCommunityContextEngineId.getNode(
                    snmpCommunityContextEngineId.name + instId).syntax

                _contextName = snmpCommunityContextName.getNode(
                    snmpCommunityContextName.name + instId).syntax

                self.__securityMap[(_securityName, _contextEngineId,
                                    _contextName)] = nextMibNode.syntax

            self.__securityBranchId = snmpCommunityName.branchVersionId

            debug.logger & debug.flagSM and debug.logger(
                '_sec2com: built securityName to communityName map, version %s: %s'
                % (self.__securityBranchId, self.__securityMap))

        try:
            return self.__securityMap[(securityName, contextEngineId,
                                       contextName)]

        except KeyError:
            raise error.StatusInformation(
                errorIndication=errind.unknownCommunityName)
Example #47
0
    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,
                                 snmpTrapCommunity=self.__snmpTrapCommunity)
        else:
            origPdu = None

        errorStatus = 'noError'
        errorIndex = 0
        varBinds = v2c.apiPDU.getVarBinds(PDU)

        debug.logger & debug.flagApp and debug.logger(
            'processPdu: stateReference %s, varBinds %s' %
            (stateReference, varBinds))

        # 3.4
        if PDU.tagSet in rfc3411.confirmedClassPDUs:
            # 3.4.1 --> no-op

            rspPDU = v2c.apiPDU.getResponse(PDU)

            # 3.4.2
            v2c.apiPDU.setErrorStatus(rspPDU, errorStatus)
            v2c.apiPDU.setErrorIndex(rspPDU, errorIndex)
            v2c.apiPDU.setVarBinds(rspPDU, varBinds)

            debug.logger & debug.flagApp and debug.logger(
                'processPdu: stateReference %s, confirm PDU %s' %
                (stateReference, rspPDU.prettyPrint()))

            # Agent-side API complies with SMIv2
            if messageProcessingModel == 0:
                rspPDU = rfc2576.v2ToV1(rspPDU, origPdu)

            statusInformation = {}

            # 3.4.3
            try:
                snmpEngine.msgAndPduDsp.returnResponsePdu(
                    snmpEngine, messageProcessingModel, securityModel,
                    securityName, securityLevel, contextEngineId, contextName,
                    pduVersion, rspPDU, maxSizeResponseScopedPDU,
                    stateReference, statusInformation)

            except error.StatusInformation:
                debug.logger & debug.flagApp and debug.logger(
                    'processPdu: stateReference %s, statusInformation %s' %
                    (stateReference, sys.exc_info()[1]))
                snmpSilentDrops, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMPv2-MIB', 'snmpSilentDrops')
                snmpSilentDrops.syntax += 1

        elif PDU.tagSet in rfc3411.unconfirmedClassPDUs:
            pass
        else:
            raise error.ProtocolError('Unexpected PDU class %s' % PDU.tagSet)

        debug.logger & debug.flagApp and debug.logger(
            'processPdu: stateReference %s, user cbFun %s, cbCtx %s, varBinds %s'
            % (stateReference, self.__cbFun, self.__cbCtx, varBinds))

        if self.__cbFunVer:
            self.__cbFun(snmpEngine, stateReference, contextEngineId,
                         contextName, varBinds, self.__cbCtx)
        else:
            # Compatibility stub (handle legacy cbFun interface)
            try:
                self.__cbFun(snmpEngine, contextEngineId, contextName,
                             varBinds, self.__cbCtx)
            except TypeError:
                self.__cbFunVer = 1
                self.__cbFun(snmpEngine, stateReference, contextEngineId,
                             contextName, varBinds, self.__cbCtx)
Example #48
0
    def _com2sec(self, snmpEngine, communityName, transportInformation):
        snmpTargetAddrTAddress, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-TARGET-MIB', 'snmpTargetAddrTAddress')
        if self.__transportBranchId != snmpTargetAddrTAddress.branchVersionId:
            (
                SnmpTagValue, snmpTargetAddrTDomain, snmpTargetAddrTagList
            ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-TARGET-MIB', 'SnmpTagValue', 'snmpTargetAddrTDomain',
                'snmpTargetAddrTagList')

            self.__emptyTag = SnmpTagValue('')

            self.__transportToTagMap = {}

            nextMibNode = snmpTargetAddrTagList
            while True:
                try:
                    nextMibNode = snmpTargetAddrTagList.getNextNode(
                        nextMibNode.name)
                except NoSuchInstanceError:
                    break
                instId = nextMibNode.name[len(snmpTargetAddrTagList.name):]
                targetAddrTDomain = snmpTargetAddrTDomain.getNode(
                    snmpTargetAddrTDomain.name + instId).syntax
                targetAddrTAddress = snmpTargetAddrTAddress.getNode(
                    snmpTargetAddrTAddress.name + instId).syntax

                targetAddrTDomain = tuple(targetAddrTDomain)

                if targetAddrTDomain[:len(udp.snmpUDPDomain
                                          )] == udp.snmpUDPDomain:
                    SnmpUDPAddress, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                        'SNMPv2-TM', 'SnmpUDPAddress')
                    targetAddrTAddress = tuple(
                        SnmpUDPAddress(targetAddrTAddress))
                elif targetAddrTDomain[:len(udp6.snmpUDP6Domain
                                            )] == udp6.snmpUDP6Domain:
                    TransportAddressIPv6, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                        'TRANSPORT-ADDRESS-MIB', 'TransportAddressIPv6')
                    targetAddrTAddress = tuple(
                        TransportAddressIPv6(targetAddrTAddress))
                elif targetAddrTDomain[:len(unix.snmpLocalDomain
                                            )] == unix.snmpLocalDomain:
                    targetAddrTAddress = str(targetAddrTAddress)
                targetAddr = targetAddrTDomain, targetAddrTAddress
                targetAddrTagList = snmpTargetAddrTagList.getNode(
                    snmpTargetAddrTagList.name + instId).syntax
                if targetAddr not in self.__transportToTagMap:
                    self.__transportToTagMap[targetAddr] = set()
                if targetAddrTagList:
                    self.__transportToTagMap[targetAddr].update([
                        SnmpTagValue(x)
                        for x in targetAddrTagList.asOctets().split()
                    ])
                else:
                    self.__transportToTagMap[targetAddr].add(self.__emptyTag)

            self.__transportBranchId = snmpTargetAddrTAddress.branchVersionId

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built transport-to-tag map version %s: %s' %
                (self.__transportBranchId, self.__transportToTagMap))

        snmpTargetParamsSecurityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityName')
        if self.__paramsBranchId != snmpTargetParamsSecurityName.branchVersionId:
            snmpTargetParamsSecurityModel, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityModel')

            self.__nameToModelMap = {}

            nextMibNode = snmpTargetParamsSecurityName

            while True:
                try:
                    nextMibNode = snmpTargetParamsSecurityName.getNextNode(
                        nextMibNode.name)

                except NoSuchInstanceError:
                    break

                instId = nextMibNode.name[len(snmpTargetParamsSecurityName.name
                                              ):]

                mibNode = snmpTargetParamsSecurityModel.getNode(
                    snmpTargetParamsSecurityModel.name + instId)

                if nextMibNode.syntax not in self.__nameToModelMap:
                    self.__nameToModelMap[nextMibNode.syntax] = set()

                self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)

            self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId

            # invalidate next map as it include this one
            self.__communityBranchId = -1

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built securityName to securityModel map, version %s: %s'
                % (self.__paramsBranchId, self.__nameToModelMap))

        snmpCommunityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-COMMUNITY-MIB', 'snmpCommunityName')
        if self.__communityBranchId != snmpCommunityName.branchVersionId:
            (
                snmpCommunitySecurityName, snmpCommunityContextEngineId,
                snmpCommunityContextName, snmpCommunityTransportTag
            ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-COMMUNITY-MIB', 'snmpCommunitySecurityName',
                'snmpCommunityContextEngineID', 'snmpCommunityContextName',
                'snmpCommunityTransportTag')

            self.__communityToTagMap = {}
            self.__tagAndCommunityToSecurityMap = {}

            nextMibNode = snmpCommunityName
            while True:
                try:
                    nextMibNode = snmpCommunityName.getNextNode(
                        nextMibNode.name)

                except NoSuchInstanceError:
                    break

                instId = nextMibNode.name[len(snmpCommunityName.name):]

                securityName = snmpCommunitySecurityName.getNode(
                    snmpCommunitySecurityName.name + instId).syntax

                contextEngineId = snmpCommunityContextEngineId.getNode(
                    snmpCommunityContextEngineId.name + instId).syntax

                contextName = snmpCommunityContextName.getNode(
                    snmpCommunityContextName.name + instId).syntax

                transportTag = snmpCommunityTransportTag.getNode(
                    snmpCommunityTransportTag.name + instId).syntax

                _tagAndCommunity = transportTag, nextMibNode.syntax

                if _tagAndCommunity not in self.__tagAndCommunityToSecurityMap:
                    self.__tagAndCommunityToSecurityMap[
                        _tagAndCommunity] = set()

                self.__tagAndCommunityToSecurityMap[_tagAndCommunity].add(
                    (securityName, contextEngineId, contextName))

                if nextMibNode.syntax not in self.__communityToTagMap:
                    self.__communityToTagMap[nextMibNode.syntax] = set()

                self.__communityToTagMap[nextMibNode.syntax].add(transportTag)

            self.__communityBranchId = snmpCommunityName.branchVersionId

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built communityName to tag map (securityModel %s), version %s: %s'
                % (self.securityModelID, self.__communityBranchId,
                   self.__communityToTagMap))

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built tag & community to securityName map (securityModel %s), version %s: %s'
                % (self.securityModelID, 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)

            candidateSecurityNames = []

            for x in [
                    self.__tagAndCommunityToSecurityMap[(t, communityName)]
                    for t in tags
            ]:
                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.
                    securityModelID:
                    (not int(x[0] in m and v in m[x[0]]), str(x[0])))
                chosenSecurityName = candidateSecurityNames[0]  # min()
                debug.logger & debug.flagSM and debug.logger(
                    '_com2sec: securityName candidates for communityName \'%s\' are %s; choosing securityName \'%s\''
                    % (communityName, candidateSecurityNames,
                       chosenSecurityName[0]))
                return chosenSecurityName

        raise error.StatusInformation(
            errorIndication=errind.unknownCommunityName)
Example #49
0
    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

        # 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.serviceID
            if 'usmUserAuthKeyLocalized' in cachedSecurityData:
                usmUserAuthKeyLocalized = cachedSecurityData[
                    'usmUserAuthKeyLocalized']
            else:
                usmUserAuthKeyLocalized = None
            if 'usmUserPrivProtocol' in cachedSecurityData:
                usmUserPrivProtocol = cachedSecurityData['usmUserPrivProtocol']
            else:
                usmUserPrivProtocol = nopriv.NoPriv.serviceID
            if 'usmUserPrivKeyLocalized' in cachedSecurityData:
                usmUserPrivKeyLocalized = cachedSecurityData[
                    'usmUserPrivKeyLocalized']
            else:
                usmUserPrivKeyLocalized = None
            securityEngineID = snmpEngineID
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: user info read from cache')
        elif securityName:
            # 3.1.1b
            try:
                (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
                 usmUserAuthKeyLocalized, usmUserPrivProtocol,
                 usmUserPrivKeyLocalized) = self.__getUserInfo(
                     snmpEngine.msgAndPduDsp.mibInstrumController,
                     securityEngineID,
                     self.__sec2usr(snmpEngine, securityName,
                                    securityEngineID))
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: read user info')

            except NoSuchInstanceError:
                pysnmpUsmDiscovery, = mibBuilder.importSymbols(
                    '__PYSNMP-USM-MIB', 'pysnmpUsmDiscovery')
                reportUnknownName = not pysnmpUsmDiscovery.syntax
                if not reportUnknownName:
                    try:
                        (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
                         usmUserAuthKeyLocalized, usmUserPrivProtocol,
                         usmUserPrivKeyLocalized) = self.__cloneUserInfo(
                             snmpEngine.msgAndPduDsp.mibInstrumController,
                             securityEngineID,
                             self.__sec2usr(snmpEngine, securityName))

                    except NoSuchInstanceError:
                        reportUnknownName = True

                if reportUnknownName:
                    raise error.StatusInformation(
                        errorIndication=errind.unknownSecurityName)

                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: clone user info')

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: %s' %
                    (sys.exc_info()[1], ))
                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
            usmUserAuthProtocol = noauth.NoAuth.serviceID
            usmUserPrivProtocol = nopriv.NoPriv.serviceID
            usmUserAuthKeyLocalized = usmUserPrivKeyLocalized = None
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: use empty USM data')

        # noinspection PyUnboundLocalVariable
        debug.logger & debug.flagSM and debug.logger(
            '__generateRequestOrResponseMsg: local usmUserName %r usmUserSecurityName %r usmUserAuthProtocol %s usmUserPrivProtocol %s securityEngineID %r securityName %r'
            % (usmUserName, usmUserSecurityName, usmUserAuthProtocol,
               usmUserPrivProtocol, securityEngineID, securityName))

        msg = globalData

        # 3.1.2
        if securityLevel == 3:
            if usmUserAuthProtocol == noauth.NoAuth.serviceID or \
                    usmUserPrivProtocol == nopriv.NoPriv.serviceID:
                raise error.StatusInformation(
                    errorIndication=errind.unsupportedSecurityLevel)

        # 3.1.3
        if securityLevel == 3 or securityLevel == 2:
            if usmUserAuthProtocol == noauth.NoAuth.serviceID:
                raise error.StatusInformation(
                    errorIndication=errind.unsupportedSecurityLevel)

        securityParameters = self.__securityParametersSpec

        scopedPDUData = msg.setComponentByPosition(3).getComponentByPosition(3)
        scopedPDUData.setComponentByPosition(0,
                                             scopedPDU,
                                             verifyConstraints=False)

        # 3.1.6a
        if securityStateReference is None and securityLevel in (2, 3):
            if securityEngineID in self.__timeline:
                (snmpEngineBoots, snmpEngineTime, latestReceivedEngineTime,
                 latestUpdateTimestamp) = self.__timeline[securityEngineID]
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: read snmpEngineBoots, snmpEngineTime from timeline'
                )
            else:
                # 2.3 XXX is this correct?
                snmpEngineBoots = snmpEngineTime = 0
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: no timeline for securityEngineID %r'
                    % (securityEngineID, ))
        # 3.1.6.b
        elif securityStateReference is not None:  # XXX Report?
            (snmpEngineBoots, snmpEngineTime) = mibBuilder.importSymbols(
                '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots', 'snmpEngineTime')
            snmpEngineBoots = snmpEngineBoots.syntax
            snmpEngineTime = snmpEngineTime.syntax.clone()
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: read snmpEngineBoots, snmpEngineTime from LCD'
            )
        # 3.1.6.c
        else:
            snmpEngineBoots = snmpEngineTime = 0
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: assuming zero snmpEngineBoots, snmpEngineTime'
            )

        debug.logger & debug.flagSM and debug.logger(
            '__generateRequestOrResponseMsg: use snmpEngineBoots %s snmpEngineTime %s for securityEngineID %r'
            % (snmpEngineBoots, snmpEngineTime, securityEngineID))

        # 3.1.4a
        if securityLevel == 3:
            if usmUserPrivProtocol in self.privServices:
                privHandler = self.privServices[usmUserPrivProtocol]
            else:
                raise error.StatusInformation(
                    errorIndication=errind.encryptionError)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: scopedPDU %s' %
                scopedPDU.prettyPrint())

            try:
                dataToEncrypt = encoder.encode(scopedPDU)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: scopedPDU serialization error: %s'
                    % sys.exc_info()[1])
                raise error.StatusInformation(
                    errorIndication=errind.serializationError)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: scopedPDU encoded into %s' %
                debug.hexdump(dataToEncrypt))

            # noinspection PyUnboundLocalVariable
            (encryptedData, privParameters) = privHandler.encryptData(
                usmUserPrivKeyLocalized,
                (snmpEngineBoots, snmpEngineTime, None), dataToEncrypt)

            securityParameters.setComponentByPosition(5,
                                                      privParameters,
                                                      verifyConstraints=False)
            scopedPDUData.setComponentByPosition(1,
                                                 encryptedData,
                                                 verifyConstraints=False)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: scopedPDU ciphered into %s' %
                debug.hexdump(encryptedData))

        # 3.1.4b
        elif securityLevel == 1 or securityLevel == 2:
            securityParameters.setComponentByPosition(5, '')

        debug.logger & debug.flagSM and debug.logger(
            '__generateRequestOrResponseMsg: %s' % scopedPDUData.prettyPrint())

        # 3.1.5
        securityParameters.setComponentByPosition(0,
                                                  securityEngineID,
                                                  verifyConstraints=False)
        securityParameters.setComponentByPosition(1,
                                                  snmpEngineBoots,
                                                  verifyConstraints=False)
        securityParameters.setComponentByPosition(2,
                                                  snmpEngineTime,
                                                  verifyConstraints=False)

        # 3.1.7
        securityParameters.setComponentByPosition(3,
                                                  usmUserName,
                                                  verifyConstraints=False)

        # 3.1.8a
        if securityLevel == 3 or securityLevel == 2:
            if usmUserAuthProtocol in self.authServices:
                authHandler = self.authServices[usmUserAuthProtocol]
            else:
                raise error.StatusInformation(
                    errorIndication=errind.authenticationFailure)

            # extra-wild hack to facilitate BER substrate in-place re-write
            securityParameters.setComponentByPosition(
                4, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: %s' %
                (securityParameters.prettyPrint(), ))

            try:
                msg.setComponentByPosition(2,
                                           encoder.encode(securityParameters),
                                           verifyConstraints=False)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: securityParameters serialization error: %s'
                    % sys.exc_info()[1])
                raise error.StatusInformation(
                    errorIndication=errind.serializationError)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: auth outgoing msg: %s' %
                msg.prettyPrint())

            try:
                wholeMsg = encoder.encode(msg)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: msg serialization error: %s'
                    % sys.exc_info()[1])
                raise error.StatusInformation(
                    errorIndication=errind.serializationError)

            # noinspection PyUnboundLocalVariable
            authenticatedWholeMsg = authHandler.authenticateOutgoingMsg(
                usmUserAuthKeyLocalized, wholeMsg)

        # 3.1.8b
        else:
            securityParameters.setComponentByPosition(4,
                                                      '',
                                                      verifyConstraints=False)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: %s' %
                (securityParameters.prettyPrint(), ))

            try:
                msg.setComponentByPosition(2,
                                           encoder.encode(securityParameters),
                                           verifyConstraints=False)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: secutiryParameters serialization error: %s'
                    % sys.exc_info()[1])
                raise error.StatusInformation(
                    errorIndication=errind.serializationError)

            try:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: plain outgoing msg: %s' %
                    msg.prettyPrint())
                authenticatedWholeMsg = encoder.encode(msg)

            except PyAsn1Error:
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: msg serialization error: %s'
                    % sys.exc_info()[1])
                raise error.StatusInformation(
                    errorIndication=errind.serializationError)

        debug.logger & debug.flagSM 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
Example #50
0
 def addMibSources(self, *mibSources):
     self.__mibSources.extend([s.init() for s in mibSources])
     debug.logger & debug.flagBld and debug.logger('addMibSources: new MIB sources %s' % (self.__mibSources,))
Example #51
0
 def connection_lost(self, exc):
     debug.logger & debug.flagIO and debug.logger('connection_lost: invoked')
Example #52
0
    def sendPdu(self,
                snmpEngine,
                targetName,
                contextEngineId,
                contextName,
                pdu,
                cbFun=None,
                cbCtx=None):
        (transportDomain, transportAddress, timeout, retryCount,
         params) = config.getTargetAddr(snmpEngine, targetName)

        (messageProcessingModel, securityModel, securityName,
         securityLevel) = config.getTargetParams(snmpEngine, params)

        # User-side API assumes SMIv2
        if messageProcessingModel == 0:
            reqPDU = rfc2576.v2ToV1(pdu)
            pduVersion = 0
        else:
            reqPDU = pdu
            pduVersion = 1

        # 3.3.5
        if reqPDU.tagSet in rfc3411.confirmedClassPDUs:
            # Convert timeout in seconds into timeout in timer ticks
            timeoutInTicks = float(
                timeout
            ) / 100 / snmpEngine.transportDispatcher.getTimerResolution()

            sendRequestHandle = getNextHandle()

            # 3.3.6a
            sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                snmpEngine, transportDomain, transportAddress,
                messageProcessingModel, securityModel, securityName,
                securityLevel, contextEngineId, contextName, pduVersion,
                reqPDU, True, timeoutInTicks, self.processResponsePdu,
                (sendRequestHandle, cbFun, cbCtx))

            debug.logger & debug.flagApp and debug.logger(
                'sendPdu: sendPduHandle %s, timeout %d' %
                (sendPduHandle, timeout))

            # 3.3.6b
            self.__pendingReqs[sendPduHandle] = (transportDomain,
                                                 transportAddress,
                                                 messageProcessingModel,
                                                 securityModel, securityName,
                                                 securityLevel,
                                                 contextEngineId, contextName,
                                                 pdu, timeout, retryCount, 0,
                                                 0)
            snmpEngine.transportDispatcher.jobStarted(id(self))
        else:
            snmpEngine.msgAndPduDsp.sendPdu(
                snmpEngine, transportDomain, transportAddress,
                messageProcessingModel, securityModel, securityName,
                securityLevel, contextEngineId, contextName, pduVersion,
                reqPDU, False)

            sendRequestHandle = None

            debug.logger & debug.flagApp and debug.logger(
                'sendPdu: message sent')

        return sendRequestHandle
Example #53
0
 def setMibSources(self, *mibSources):
     self.__mibSources = [s.init() for s in mibSources]
     debug.logger & debug.flagBld and debug.logger('setMibSources: new MIB sources %s' % (self.__mibSources,))
Example #54
0
    def processIncomingMsg(
            self,
            snmpEngine,
            messageProcessingModel,
            maxMessageSize,
            securityParameters,
            securityModel,
            securityLevel,
            wholeMsg,
            msg  # XXX 
    ):
        # 3.2.1
        try:
            securityParameters, rest = decoder.decode(
                securityParameters, asn1Spec=self._securityParametersSpec)
        except PyAsn1Error:
            snmpInASNParseErrs, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax = snmpInASNParseErrs.syntax + 1
            raise error.StatusInformation(errorIndication='parseError')

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: %s' % (securityParameters.prettyPrint(), ))

        # 3.2.9 -- moved up here to be able to report
        # maxSizeResponseScopedPDU on error
        maxSizeResponseScopedPDU = maxMessageSize - 512  # XXX
        if maxSizeResponseScopedPDU < 0:
            maxSizeResponseScopedPDU = 0

        # 3.2.2
        securityEngineID = securityParameters.getComponentByPosition(0)
        securityStateReference = self._cachePush(
            msgUserName=securityParameters.getComponentByPosition(3))

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: cache read securityStateReference %s by msgUserName %s'
            % (securityStateReference,
               securityParameters.getComponentByPosition(3)))

        # Used for error reporting
        contextEngineId = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax
        contextName = ''

        # 3.2.3
        if not self.__timeline.has_key(securityEngineID):
            debug.logger & debug.flagSM and debug.logger(
                'processIncomingMsg: unknown securityEngineID %s' %
                securityEngineID)
            if securityEngineID:
                # 3.2.3a XXX any other way to get auth engine in cache?
                self.__timeline[securityEngineID] = (
                    securityParameters.getComponentByPosition(1),
                    securityParameters.getComponentByPosition(2),
                    securityParameters.getComponentByPosition(2),
                    int(time.time()))

                expireAt = self.__expirationTimer + 300
                if not self.__timelineExpQueue.has_key(expireAt):
                    self.__timelineExpQueue[expireAt] = []
                self.__timelineExpQueue[expireAt].append(securityEngineID)

                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: store timeline for securityEngineID %s'
                    % (securityEngineID, ))
            else:
                # 3.2.3b
                usmStatsUnknownEngineIDs, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownEngineIDs')
                usmStatsUnknownEngineIDs.syntax = usmStatsUnknownEngineIDs.syntax + 1
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: null securityEngineID')
                pysnmpUsmDiscoverable, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__PYSNMP-USM-MIB', 'pysnmpUsmDiscoverable')
                if pysnmpUsmDiscoverable.syntax:
                    debug.logger & debug.flagSM and debug.logger(
                        'processIncomingMsg: request EngineID discovery')
                    raise error.StatusInformation(
                        errorIndication='unknownEngineID',
                        oid=usmStatsUnknownEngineIDs.name,
                        val=usmStatsUnknownEngineIDs.syntax,
                        securityStateReference=securityStateReference,
                        contextEngineId=contextEngineId,
                        contextName=contextName,
                        maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
                else:
                    debug.logger & debug.flagSM and debug.logger(
                        'processIncomingMsg: will not discover EngineID')
                    # free securityStateReference XXX
                    raise error.StatusInformation(
                        errorIndication='unknownEngineID')

        snmpEngineID = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax

        msgAuthoritativeEngineID = securityParameters.getComponentByPosition(0)
        msgUserName = securityParameters.getComponentByPosition(3)

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: read from securityParams msgAuthoritativeEngineID %s msgUserName %s'
            % (msgAuthoritativeEngineID, msgUserName))

        if msgUserName:
            # 3.2.4
            try:
                (usmUserSecurityName, usmUserAuthProtocol,
                 usmUserAuthKeyLocalized, usmUserPrivProtocol,
                 usmUserPrivKeyLocalized) = self.__getUserInfo(
                     snmpEngine.msgAndPduDsp.mibInstrumController,
                     msgAuthoritativeEngineID, msgUserName)
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: read user info from LCD')
            except NoSuchInstanceError:
                pysnmpUsmDiscoverable, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__PYSNMP-USM-MIB', 'pysnmpUsmDiscoverable')
                __reportUnknownName = not pysnmpUsmDiscoverable.syntax
                if not __reportUnknownName:
                    try:
                        (usmUserSecurityName, usmUserAuthProtocol,
                         usmUserAuthKeyLocalized, usmUserPrivProtocol,
                         usmUserPrivKeyLocalized) = self.__cloneUserInfo(
                             snmpEngine.msgAndPduDsp.mibInstrumController,
                             securityEngineID, msgUserName)
                        debug.logger & debug.flagSM and debug.logger(
                            'processIncomingMsg: cloned user info')
                    except NoSuchInstanceError:
                        __reportUnknownName = 1
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: unknown securityEngineID %s msgUserName %s'
                    % (securityEngineID, msgUserName))
                if __reportUnknownName:
                    usmStatsUnknownUserNames, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                        '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames')
                    usmStatsUnknownUserNames.syntax = usmStatsUnknownUserNames.syntax + 1
                    raise error.StatusInformation(
                        errorIndication='unknownSecurityName',
                        oid=usmStatsUnknownUserNames.name,
                        val=usmStatsUnknownUserNames.syntax,
                        securityStateReference=securityStateReference,
                        contextEngineId=contextEngineId,
                        contextName=contextName,
                        maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
        else:
            # empty username used for engineID discovery
            usmUserName = usmUserSecurityName = ''
            usmUserAuthProtocol = usmUserAuthKeyLocalized = None
            usmUserPrivProtocol = usmUserPrivKeyLocalized = None

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: now have usmUserSecurityName %s usmUserAuthProtocol %s usmUserPrivProtocol %s for msgUserName %s'
            % (usmUserSecurityName, usmUserAuthProtocol, usmUserPrivProtocol,
               msgUserName))

        # 3.2.5
        __reportError = 0
        if securityLevel == 3:
            if not usmUserAuthProtocol or not usmUserPrivProtocol:
                __reportError = 1
            elif securityLevel == 2:
                if not usmUserAuthProtocol:
                    __reportError = 1
        if __reportError:
            usmStatsUnsupportedSecLevels, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnsupportedSecLevels')
            usmStatsUnsupportedSecLevels.syntax = usmStatsUnsupportedSecLevels.syntax + 1
            raise error.StatusInformation(
                errorIndication='unsupportedSecurityLevel',
                oid=usmStatsUnknownEngineIDs.name,
                val=usmStatsUnknownEngineIDs.syntax,
                securityStateReference=securityStateReference,
                contextEngineId=contextEngineId,
                contextName=contextName,
                maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)

        # 3.2.6
        if securityLevel == 3 or securityLevel == 2:
            authHandler = self.authServices.get(usmUserAuthProtocol)
            if authHandler is None:
                raise error.StatusInformation(
                    errorIndication='authenticationFailure')
            try:
                authenticatedWholeMsg = authHandler.authenticateIncomingMsg(
                    usmUserAuthKeyLocalized,
                    securityParameters.getComponentByPosition(4), wholeMsg)
            except error.StatusInformation:
                usmStatsWrongDigests, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-USER-BASED-SM-MIB', 'usmStatsWrongDigests')
                usmStatsWrongDigests.syntax = usmStatsWrongDigests.syntax + 1
                raise error.StatusInformation(
                    errorIndication='authenticationFailure',
                    oid=usmStatsWrongDigests.name,
                    val=usmStatsWrongDigests.syntax,
                    securityStateReference=securityStateReference,
                    contextEngineId=contextEngineId,
                    contextName=contextName,
                    maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)

            debug.logger & debug.flagSM and debug.logger(
                'processIncomingMsg: incoming msg authed')
        # 3.2.7
        if securityLevel == 3 or securityLevel == 2:
            if msgAuthoritativeEngineID == snmpEngineID:
                # Authoritative SNMP engine: use local notion (SF bug #1649032)
                (
                    snmpEngineBoots, snmpEngineTime
                ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots',
                    'snmpEngineTime')
                snmpEngineBoots = snmpEngineBoots.syntax
                snmpEngineTime = snmpEngineTime.syntax.clone()
                idleTime = 0
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: read snmpEngineBoots (%s), snmpEngineTime (%s) from LCD'
                    % (snmpEngineBoots, snmpEngineTime))
            else:
                # Non-authoritative SNMP engine: use cached estimates
                if self.__timeline.has_key(securityEngineID):
                    (snmpEngineBoots, snmpEngineTime, latestReceivedEngineTime,
                     latestUpdateTimestamp
                     ) = self.__timeline[msgAuthoritativeEngineID]
                    # time passed since last talk with this SNMP engine
                    idleTime = int(time.time()) - latestUpdateTimestamp
                    debug.logger & debug.flagSM and debug.logger(
                        'processIncomingMsg: read timeline snmpEngineBoots %s snmpEngineTime %s for msgAuthoritativeEngineID %s, idle time %s secs'
                        % (snmpEngineBoots, snmpEngineTime,
                           msgAuthoritativeEngineID, idleTime))
                else:
                    raise error.ProtocolError('Peer SNMP engine info missing')

            msgAuthoritativeEngineBoots = securityParameters.getComponentByPosition(
                1)
            msgAuthoritativeEngineTime = securityParameters.getComponentByPosition(
                2)

            # 3.2.7a
            if msgAuthoritativeEngineID == snmpEngineID:
                if snmpEngineBoots == 2147483647 or \
                   snmpEngineBoots != msgAuthoritativeEngineBoots or \
                   abs(idleTime + int(snmpEngineTime) - \
                       int(msgAuthoritativeEngineTime)) > 150:
                    usmStatsNotInTimeWindows, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                        '__SNMP-USER-BASED-SM-MIB', 'usmStatsNotInTimeWindows')
                    usmStatsNotInTimeWindows.syntax = usmStatsNotInTimeWindows.syntax + 1
                    raise error.StatusInformation(
                        errorIndication='notInTimeWindow',
                        oid=usmStatsNotInTimeWindows.name,
                        val=usmStatsNotInTimeWindows.syntax,
                        securityStateReference=securityStateReference,
                        securityLevel=2,
                        contextEngineId=contextEngineId,
                        contextName=contextName,
                        maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
            # 3.2.7b
            else:
                # 3.2.7b.1
                if msgAuthoritativeEngineBoots > snmpEngineBoots or \
                   msgAuthoritativeEngineBoots == snmpEngineBoots and \
                   msgAuthoritativeEngineTime > latestReceivedEngineTime:
                    self.__timeline[msgAuthoritativeEngineID] = (
                        msgAuthoritativeEngineBoots,
                        msgAuthoritativeEngineTime, msgAuthoritativeEngineTime,
                        int(time.time()))
                    debug.logger & debug.flagSM and debug.logger(
                        'processIncomingMsg: stored timeline msgAuthoritativeEngineBoots %s msgAuthoritativeEngineTime %s for msgAuthoritativeEngineID %s'
                        %
                        (msgAuthoritativeEngineBoots,
                         msgAuthoritativeEngineTime, msgAuthoritativeEngineID))

                # 3.2.7b.2
                if snmpEngineBoots == 2147483647 or \
                   msgAuthoritativeEngineBoots < snmpEngineBoots or \
                   msgAuthoritativeEngineBoots == snmpEngineBoots and \
                   abs(idleTime + int(snmpEngineTime) - \
                       int(msgAuthoritativeEngineTime)) > 150:
                    raise error.StatusInformation(
                        errorIndication='notInTimeWindow')

        scopedPduData = msg.getComponentByPosition(3)

        # 3.2.8a
        if securityLevel == 3:
            privHandler = self.privServices.get(usmUserPrivProtocol)
            if privHandler is None:
                raise error.StatusInformation(
                    errorIndication='decryptionError')
            encryptedPDU = scopedPduData.getComponentByPosition(1)
            if encryptedPDU is None:  # no ciphertext
                raise error.StatusInformation(
                    errorIndication='decryptionError')

            try:
                decryptedData = privHandler.decryptData(
                    usmUserPrivKeyLocalized,
                    (securityParameters.getComponentByPosition(1),
                     securityParameters.getComponentByPosition(2),
                     securityParameters.getComponentByPosition(5)),
                    encryptedPDU)
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: PDU deciphered')
            except error.StatusInformation:
                usmStatsDecryptionErrors, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-USER-BASED-SM-MIB', 'usmStatsDecryptionErrors')
                usmStatsDecryptionErrors.syntax = usmStatsDecryptionErrors.syntax + 1
                raise error.StatusInformation(
                    errorIndication='decryptionError',
                    oid=usmStatsDecryptionErrors.name,
                    val=usmStatsDecryptionErrors.syntax,
                    securityStateReference=securityStateReference,
                    contextEngineId=contextEngineId,
                    contextName=contextName,
                    maxSizeResponseScopedPDU=maxSizeResponseScopedPDU)
            scopedPduSpec = scopedPduData.setComponentByPosition(
                0).getComponentByPosition(0)
            try:
                scopedPDU, rest = decoder.decode(decryptedData,
                                                 asn1Spec=scopedPduSpec)
            except PyAsn1Error as why:
                debug.logger & debug.flagSM and debug.logger(
                    'processIncomingMsg: PDU decoder failed %s' % why)
                raise error.StatusInformation(
                    errorIndication='decryptionError')
        else:
            # 3.2.8b
            scopedPDU = scopedPduData.getComponentByPosition(0)
            if scopedPDU is None:  # no plaintext
                raise error.StatusInformation(
                    errorIndication='decryptionError')

        # 3.2.10
        securityName = usmUserSecurityName

        # 3.2.11
        self._cachePop(securityStateReference)
        securityStateReference = self._cachePush(
            msgUserName=securityParameters.getComponentByPosition(3),
            usmUserAuthProtocol=usmUserAuthProtocol,
            usmUserAuthKeyLocalized=usmUserAuthKeyLocalized,
            usmUserPrivProtocol=usmUserPrivProtocol,
            usmUserPrivKeyLocalized=usmUserPrivKeyLocalized)

        debug.logger & debug.flagSM and debug.logger(
            'processIncomingMsg: cached msgUserName %s info by securityStateReference %s'
            % (msgUserName, securityStateReference))

        # Delayed to include details
        if not msgUserName and not securityEngineID:
            usmStatsUnknownUserNames, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames')
            usmStatsUnknownUserNames.syntax = usmStatsUnknownUserNames.syntax + 1
            raise error.StatusInformation(
                errorIndication='unknownSecurityName',
                oid=usmStatsUnknownUserNames.name,
                val=usmStatsUnknownUserNames.syntax,
                securityStateReference=securityStateReference,
                securityEngineID=securityEngineID,
                contextEngineId=contextEngineId,
                contextName=contextName,
                maxSizeResponseScopedPDU=maxSizeResponseScopedPDU,
                PDU=scopedPDU)

        # 3.2.12
        return (securityEngineID, securityName, scopedPDU,
                maxSizeResponseScopedPDU, securityStateReference)
Example #55
0
    def _com2sec(self, snmpEngine, communityName, transportInformation):
        snmpTargetAddrTAddress, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-TARGET-MIB', 'snmpTargetAddrTAddress')
        if self.__transportBranchId != snmpTargetAddrTAddress.branchVersionId:
            (
                SnmpTagValue, snmpTargetAddrTDomain, snmpTargetAddrTagList
            ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-TARGET-MIB', 'SnmpTagValue', 'snmpTargetAddrTDomain',
                'snmpTargetAddrTagList')

            self.__emptyTag = SnmpTagValue('')

            self.__transportToTagMap = {}

            nextMibNode = snmpTargetAddrTagList
            while 1:
                try:
                    nextMibNode = snmpTargetAddrTagList.getNextNode(
                        nextMibNode.name)
                except NoSuchInstanceError:
                    break
                instId = nextMibNode.name[len(snmpTargetAddrTagList.name):]
                targetAddrTDomain = snmpTargetAddrTDomain.getNode(
                    snmpTargetAddrTDomain.name + instId).syntax
                targetAddrTAddress = snmpTargetAddrTAddress.getNode(
                    snmpTargetAddrTAddress.name + instId).syntax

                targetAddrTDomain = tuple(targetAddrTDomain)

                if targetAddrTDomain[:len(udp.snmpUDPDomain
                                          )] == udp.snmpUDPDomain:
                    SnmpUDPAddress, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                        'SNMPv2-TM', 'SnmpUDPAddress')
                    targetAddrTAddress = tuple(
                        SnmpUDPAddress(targetAddrTAddress))
                elif targetAddrTDomain[:len(udp6.snmpUDP6Domain
                                            )] == udp6.snmpUDP6Domain:
                    TransportAddressIPv6, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                        'TRANSPORT-ADDRESS-MIB', 'TransportAddressIPv6')
                    targetAddrTAddress = tuple(
                        TransportAddressIPv6(targetAddrTAddress))
                elif targetAddrTDomain[:len(unix.snmpLocalDomain
                                            )] == unix.snmpLocalDomain:
                    targetAddrTAddress = str(targetAddrTAddress)
                targetAddr = targetAddrTDomain, targetAddrTAddress
                targetAddrTagList = snmpTargetAddrTagList.getNode(
                    snmpTargetAddrTagList.name + instId).syntax
                if targetAddr not in self.__transportToTagMap:
                    self.__transportToTagMap[targetAddr] = set()
                if targetAddrTagList:
                    self.__transportToTagMap[targetAddr].update([
                        SnmpTagValue(x)
                        for x in targetAddrTagList.asOctets().split()
                    ])
                else:
                    self.__transportToTagMap[targetAddr].add(self.__emptyTag)

            self.__transportBranchId = snmpTargetAddrTAddress.branchVersionId

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built transport-to-tag map version %s: %s' %
                (self.__transportBranchId, self.__transportToTagMap))

        snmpTargetParamsSecurityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityName')
        if self.__paramsBranchId != snmpTargetParamsSecurityName.branchVersionId:
            snmpTargetParamsSecurityModel, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-TARGET-MIB', 'snmpTargetParamsSecurityModel')

            self.__nameToModelMap = {}

            nextMibNode = snmpTargetParamsSecurityName

            while 1:
                try:
                    nextMibNode = snmpTargetParamsSecurityName.getNextNode(
                        nextMibNode.name)
                except NoSuchInstanceError:
                    break

                instId = nextMibNode.name[len(snmpTargetParamsSecurityName.name
                                              ):]

                mibNode = snmpTargetParamsSecurityModel.getNode(
                    snmpTargetParamsSecurityModel.name + instId)

                if nextMibNode.syntax not in self.__nameToModelMap:
                    self.__nameToModelMap[nextMibNode.syntax] = set()

                self.__nameToModelMap[nextMibNode.syntax].add(mibNode.syntax)

            self.__paramsBranchId = snmpTargetParamsSecurityName.branchVersionId

            # invalidate next map as it include this one
            self.__communityBranchId = -1

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built securityName to securityModel map, version %s: %s'
                % (self.__paramsBranchId, self.__nameToModelMap))

        snmpCommunityName, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            'SNMP-COMMUNITY-MIB', 'snmpCommunityName')
        if self.__communityBranchId != snmpCommunityName.branchVersionId:
            (
                snmpCommunitySecurityName, snmpCommunityContextEngineId,
                snmpCommunityContextName, snmpCommunityTransportTag
            ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-COMMUNITY-MIB', 'snmpCommunitySecurityName',
                'snmpCommunityContextEngineID', 'snmpCommunityContextName',
                'snmpCommunityTransportTag')

            self.__communityToTagMap = {}
            self.__tagAndCommunityToSecurityMap = {}

            nextMibNode = snmpCommunityName
            while 1:
                try:
                    nextMibNode = snmpCommunityName.getNextNode(
                        nextMibNode.name)
                except NoSuchInstanceError:
                    break

                instId = nextMibNode.name[len(snmpCommunityName.name):]

                securityName = snmpCommunitySecurityName.getNode(
                    snmpCommunitySecurityName.name + instId).syntax

                # Filter community table by security model
                # *if* there are conflicting security names
                if securityName in self.__nameToModelMap and \
                     self.securityModelID not in self.__nameToModelMap[securityName]:
                    continue

                contextEngineId = snmpCommunityContextEngineId.getNode(
                    snmpCommunityContextEngineId.name + instId).syntax

                contextName = snmpCommunityContextName.getNode(
                    snmpCommunityContextName.name + instId).syntax

                transportTag = snmpCommunityTransportTag.getNode(
                    snmpCommunityTransportTag.name + instId).syntax

                self.__tagAndCommunityToSecurityMap[(
                    transportTag, nextMibNode.syntax)] = (securityName,
                                                          contextEngineId,
                                                          contextName)

                if nextMibNode.syntax not in self.__communityToTagMap:
                    self.__communityToTagMap[nextMibNode.syntax] = set()

                self.__communityToTagMap[nextMibNode.syntax].add(transportTag)

            self.__communityBranchId = snmpCommunityName.branchVersionId

            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built communityName to tag map (securityModel %s), version %s: %s'
                % (self.securityModelID, self.__communityBranchId,
                   self.__communityToTagMap))
            debug.logger & debug.flagSM and debug.logger(
                '_com2sec: built tag & community to securityName map (securityModel %s), version %s: %s'
                % (self.securityModelID, self.__communityBranchId,
                   self.__tagAndCommunityToSecurityMap))

        if communityName in self.__communityToTagMap:
            if self.__emptyTag in self.__communityToTagMap[communityName]:
                return self.__tagAndCommunityToSecurityMap[(self.__emptyTag,
                                                            communityName)]

            if transportInformation in self.__transportToTagMap:
                tags = self.__transportToTagMap[
                    transportInformation].intersection(
                        self.__communityToTagMap[communityName])
                if tags:
                    return self.__tagAndCommunityToSecurityMap[(tags.pop(),
                                                                communityName)]

        raise error.StatusInformation()
Example #56
0
    def __generateRequestOrResponseMsg(self, snmpEngine,
                                       messageProcessingModel, globalData,
                                       maxMessageSize, securityModel,
                                       securityEngineID, securityName,
                                       securityLevel, scopedPDU,
                                       securityStateReference):
        snmpEngineID = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax
        # 3.1.1
        if securityStateReference is not None:
            # 3.1.1a
            cachedSecurityData = self._cachePop(securityStateReference)
            usmUserName = cachedSecurityData['msgUserName']
            usmUserAuthProtocol = cachedSecurityData.get('usmUserAuthProtocol')
            usmUserAuthKeyLocalized = cachedSecurityData.get(
                'usmUserAuthKeyLocalized')
            usmUserPrivProtocol = cachedSecurityData.get('usmUserPrivProtocol')
            usmUserPrivKeyLocalized = cachedSecurityData.get(
                'usmUserPrivKeyLocalized')
            securityEngineID = snmpEngineID
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: user info read from cache')
        elif securityName:
            # 3.1.1b
            try:
                (usmUserName, usmUserAuthProtocol, usmUserAuthKeyLocalized,
                 usmUserPrivProtocol,
                 usmUserPrivKeyLocalized) = self.__getUserInfo(
                     snmpEngine.msgAndPduDsp.mibInstrumController,
                     securityEngineID, securityName)
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: read user info')
            except NoSuchInstanceError:
                pysnmpUsmDiscovery, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                    '__PYSNMP-USM-MIB', 'pysnmpUsmDiscovery')
                __reportUnknownName = not pysnmpUsmDiscovery.syntax
                if not __reportUnknownName:
                    try:
                        (usmUserName, usmUserAuthProtocol,
                         usmUserAuthKeyLocalized, usmUserPrivProtocol,
                         usmUserPrivKeyLocalized) = self.__cloneUserInfo(
                             snmpEngine.msgAndPduDsp.mibInstrumController,
                             securityEngineID, securityName)
                    except NoSuchInstanceError:
                        __reportUnknownName = 1

                if __reportUnknownName:
                    raise error.StatusInformation(
                        errorIndication='unknownSecurityName')
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: clone user info')
        else:
            # empty username used for engineID discovery
            usmUserName = usmUserSecurityName = ''
            usmUserAuthProtocol = usmUserAuthKeyLocalized = None
            usmUserPrivProtocol = usmUserPrivKeyLocalized = None
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: use empty USM data')

        debug.logger & debug.flagSM and debug.logger(
            '__generateRequestOrResponseMsg: local user usmUserName %s usmUserAuthProtocol %s usmUserPrivProtocol %s by securityEngineID %s securityName %s'
            % (usmUserName, usmUserAuthProtocol, usmUserPrivProtocol,
               securityEngineID, securityName))

        msg = globalData

        # 3.1.2
        if securityLevel == 3:
            if not usmUserAuthProtocol or not usmUserPrivProtocol:
                raise error.StatusInformation(
                    errorIndication='unsupportedSecurityLevel')

        # 3.1.3
        if securityLevel == 3 or securityLevel == 2:
            if not usmUserAuthProtocol:
                raise error.StatusInformation(
                    errorIndication='unsupportedSecurityLevel')

        securityParameters = UsmSecurityParameters()

        scopedPDUData = msg.setComponentByPosition(3).getComponentByPosition(3)
        scopedPDUData.setComponentByPosition(0, scopedPDU)

        # 3.1.6a
        if securityStateReference is None and (  # request type check added
                securityLevel == 3 or securityLevel == 2):
            if self.__timeline.has_key(securityEngineID):
                (snmpEngineBoots, snmpEngineTime, latestReceivedEngineTime,
                 latestUpdateTimestamp) = self.__timeline[securityEngineID]
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: read snmpEngineBoots, snmpEngineTime from timeline'
                )
            else:
                # 2.3 XXX is this correct?
                snmpEngineBoots = snmpEngineTime = 0
                debug.logger & debug.flagSM and debug.logger(
                    '__generateRequestOrResponseMsg: no timeline for securityEngineID %s'
                    % securityEngineID)
        # 3.1.6.b
        elif securityStateReference is not None:  # XXX Report?
            (
                snmpEngineBoots, snmpEngineTime
            ) = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots', 'snmpEngineTime')
            snmpEngineBoots = snmpEngineBoots.syntax
            snmpEngineTime = snmpEngineTime.syntax.clone()
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: read snmpEngineBoots, snmpEngineTime from LCD'
            )
        # 3.1.6.c
        else:
            snmpEngineBoots = snmpEngineTime = 0
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: assuming zero snmpEngineBoots, snmpEngineTime'
            )

        debug.logger & debug.flagSM and debug.logger(
            '__generateRequestOrResponseMsg: use snmpEngineBoots %s snmpEngineTime %s for securityEngineID %s'
            % (snmpEngineBoots, snmpEngineTime, securityEngineID))

        # 3.1.4a
        if securityLevel == 3:
            privHandler = self.privServices.get(usmUserPrivProtocol)
            if privHandler is None:
                raise error.StatusInformation(
                    errorIndication='encryptionError')
            dataToEncrypt = encoder.encode(scopedPDU)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: scopedPDU encoded')

            try:
                (encryptedData, privParameters) = privHandler.encryptData(
                    usmUserPrivKeyLocalized,
                    (snmpEngineBoots, snmpEngineTime, None), dataToEncrypt)
            except error.StatusInformation as statusInformation:
                raise

            securityParameters.setComponentByPosition(5, privParameters)
            scopedPDUData.setComponentByPosition(1, encryptedData)

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: scopedPDU ciphered')

        # 3.1.4b
        elif securityLevel == 1 or securityLevel == 2:
            securityParameters.setComponentByPosition(5, '')

        debug.logger & debug.flagSM and debug.logger(
            '__generateRequestOrResponseMsg: %s' % scopedPDUData.prettyPrint())

        # 3.1.5
        securityParameters.setComponentByPosition(0, securityEngineID)
        securityParameters.setComponentByPosition(1, snmpEngineBoots)
        securityParameters.setComponentByPosition(2, snmpEngineTime)

        # 3.1.7
        securityParameters.setComponentByPosition(3, usmUserName)

        # 3.1.8a
        if securityLevel == 3 or securityLevel == 2:
            authHandler = self.authServices.get(usmUserAuthProtocol)
            if authHandler is None:
                raise error.StatusInformation(
                    errorIndication='authenticationFailure')

            # extra-wild hack to facilitate BER substrate in-place re-write
            securityParameters.setComponentByPosition(
                4, '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: %s' %
                (securityParameters.prettyPrint(), ))

            msg.setComponentByPosition(2, encoder.encode(securityParameters))

            wholeMsg = encoder.encode(msg)

            try:
                authenticatedWholeMsg = authHandler.authenticateOutgoingMsg(
                    usmUserAuthKeyLocalized, wholeMsg)
            except error.StatusInformation as statusInformation:
                raise

            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: auth outgoing msg')
        # 3.1.8b
        else:
            securityParameters.setComponentByPosition(4, '')
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: %s' %
                (securityParameters.prettyPrint(), ))
            msg.setComponentByPosition(2, encoder.encode(securityParameters))
            authenticatedWholeMsg = encoder.encode(msg)
            debug.logger & debug.flagSM and debug.logger(
                '__generateRequestOrResponseMsg: plain outgoing msg')

        # 3.1.9
        return (msg.getComponentByPosition(2), authenticatedWholeMsg)
Example #57
0
    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()))

        sendRequestHandle = -1

        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]
                    if cbFun:
                        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
Example #58
0
    def receiveMessage(self, snmpEngine, transportDomain, transportAddress,
                       wholeMsg):
        """Message dispatcher -- de-serialize message into PDU"""
        # 4.2.1.1
        snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts')
        snmpInPkts.syntax += 1

        # 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.syntax += 1
            return null  # n.b the whole buffer gets dropped

        debug.logger & debug.flagDsp and debug.logger(
            'receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        try:
            mpHandler = snmpEngine.messageProcessingSubsystems[int(
                messageProcessingModel)]

        except KeyError:
            snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax += 1
            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            (messageProcessingModel, securityModel, securityName,
             securityLevel, contextEngineId, contextName, pduVersion, PDU,
             pduType, sendPduHandle, maxSizeResponseScopedPDU,
             statusInformation,
             stateReference) = mpHandler.prepareDataElements(
                 snmpEngine, transportDomain, transportAddress, wholeMsg)

            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: MP succeded')

        except error.StatusInformation:
            statusInformation = sys.exc_info()[1]
            if 'sendPduHandle' in statusInformation:
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: MP failed, statusInformation %s, forcing a retry'
                    % statusInformation)
                self.__expireRequest(
                    statusInformation['sendPduHandle'],
                    self.__cache.pop(statusInformation['sendPduHandle']),
                    snmpEngine, statusInformation)
            return restOfWholeMsg

        except PyAsn1Error:
            debug.logger & debug.flagMP and debug.logger('receiveMessage: %s' %
                                                         (sys.exc_info()[1], ))
            snmpInASNParseErrs, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1

            return restOfWholeMsg

        debug.logger & debug.flagDsp 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.flagDsp 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.syntax += 1

                # 4.2.2.1.2.b
                statusInformation = {
                    'errorIndication': errind.unknownPDUHandler,
                    'oid': snmpUnknownPDUHandlers.name,
                    'val': snmpUnknownPDUHandlers.syntax
                }

                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: unhandled PDU type')

                # 4.2.2.1.2.c
                try:
                    (destTransportDomain, destTransportAddress,
                     outgoingMessage) = mpHandler.prepareResponseMessage(
                         snmpEngine, messageProcessingModel, securityModel,
                         securityName, securityLevel, contextEngineId,
                         contextName, pduVersion, PDU,
                         maxSizeResponseScopedPDU, stateReference,
                         statusInformation)

                    snmpEngine.transportDispatcher.sendMessage(
                        outgoingMessage, destTransportDomain,
                        destTransportAddress)

                except PySnmpError:
                    debug.logger & debug.flagDsp and debug.logger(
                        'receiveMessage: report failed, statusInformation %s' %
                        sys.exc_info()[1])

                else:
                    debug.logger & debug.flagDsp and debug.logger(
                        'receiveMessage: reporting succeeded')

                # 4.2.2.1.2.d
                return restOfWholeMsg

            else:
                snmpEngine.observer.storeExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request',
                    dict(transportDomain=transportDomain,
                         transportAddress=transportAddress,
                         wholeMsg=wholeMsg,
                         messageProcessingModel=messageProcessingModel,
                         securityModel=securityModel,
                         securityName=securityName,
                         securityLevel=securityLevel,
                         contextEngineId=contextEngineId,
                         contextName=contextName,
                         pdu=PDU))

                # pass transport info to app (legacy)
                if stateReference is not None:
                    self.__transportInfo[stateReference] = (transportDomain,
                                                            transportAddress)

                # 4.2.2.1.3
                processPdu(snmpEngine, messageProcessingModel, securityModel,
                           securityName, securityLevel, contextEngineId,
                           contextName, pduVersion, PDU,
                           maxSizeResponseScopedPDU, stateReference)

                snmpEngine.observer.clearExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request')

                # legacy
                if stateReference is not None:
                    del self.__transportInfo[stateReference]

                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: processPdu succeeded')
                return restOfWholeMsg
        else:
            # 4.2.2.2 (response)

            # 4.2.2.2.1
            cachedParams = self.__cache.pop(sendPduHandle)

            # 4.2.2.2.2
            if cachedParams is None:
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1
                return restOfWholeMsg

            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: cache read by sendPduHandle %s' %
                sendPduHandle)

            # 4.2.2.2.3
            # no-op ? XXX

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     wholeMsg=wholeMsg,
                     messageProcessingModel=messageProcessingModel,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     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'])

            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response')

            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: processResponsePdu succeeded')

            return restOfWholeMsg
Example #59
0
def v2ToV1(v2Pdu, origV1Pdu=None):
    debug.logger & debug.flagPrx and debug.logger(
        'v2ToV1: v2Pdu %s' % v2Pdu.prettyPrint())

    pduType = v2Pdu.tagSet

    if pduType in __v2ToV1PduMap:
        v1Pdu = __v2ToV1PduMap[pduType].clone()
    else:
        raise error.ProtocolError('Unsupported PDU type')

    v2VarBinds = v2c.apiPDU.getVarBinds(v2Pdu)
    v1VarBinds = []

    # 3.2
    if pduType in rfc3411.notificationClassPDUs:
        # 3.2.1
        snmpTrapOID, snmpTrapOIDParam = v2VarBinds[1]
        if snmpTrapOID != v2c.apiTrapPDU.snmpTrapOID:
            raise error.ProtocolError('Second OID not snmpTrapOID')
        snmpTrapOID, snmpTrapOIDParam = v2VarBinds[1]
        if snmpTrapOIDParam in __v2ToV1TrapMap:
            for oid, val in v2VarBinds:
                if oid == v2c.apiTrapPDU.snmpTrapEnterprise:
                    v1.apiTrapPDU.setEnterprise(v1Pdu, val)
                    break
            else:
                # snmpTraps
                v1.apiTrapPDU.setEnterprise(v1Pdu, (1, 3, 6, 1, 6, 3, 1, 1, 5))
        else:
            if snmpTrapOIDParam[-2] == 0:
                v1.apiTrapPDU.setEnterprise(v1Pdu, snmpTrapOIDParam[:-2])
            else:
                v1.apiTrapPDU.setEnterprise(v1Pdu, snmpTrapOIDParam[:-1])

        # 3.2.2
        for oid, val in v2VarBinds:
            # snmpTrapAddress
            if oid == v2c.apiTrapPDU.snmpTrapAddress:
                v1.apiTrapPDU.setAgentAddr(v1Pdu, val)
                break
        else:
            v1.apiTrapPDU.setAgentAddr(v1Pdu, v1.IpAddress('0.0.0.0'))

        # 3.2.3
        if snmpTrapOIDParam in __v2ToV1TrapMap:
            v1.apiTrapPDU.setGenericTrap(v1Pdu,
                                         __v2ToV1TrapMap[snmpTrapOIDParam])
        else:
            v1.apiTrapPDU.setGenericTrap(v1Pdu, 6)

        # 3.2.4
        if snmpTrapOIDParam in __v2ToV1TrapMap:
            v1.apiTrapPDU.setSpecificTrap(v1Pdu, __zeroInt)
        else:
            v1.apiTrapPDU.setSpecificTrap(v1Pdu, snmpTrapOIDParam[-1])

        # 3.2.5
        v1.apiTrapPDU.setTimeStamp(v1Pdu, v2VarBinds[0][1])

        __v2VarBinds = []
        for oid, val in v2VarBinds[2:]:
            if oid in __v2ToV1TrapMap or \
                    oid in (v2c.apiTrapPDU.sysUpTime,
                            v2c.apiTrapPDU.snmpTrapAddress,
                            v2c.apiTrapPDU.snmpTrapEnterprise):
                continue
            __v2VarBinds.append((oid, val))
        v2VarBinds = __v2VarBinds

        # 3.2.6 --> done below

    else:
        v1.apiPDU.setErrorStatus(v1Pdu, __zeroInt)
        v1.apiPDU.setErrorIndex(v1Pdu, __zeroInt)

    if pduType in rfc3411.responseClassPDUs:
        idx = len(v2VarBinds) - 1
        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)
                    v1.apiPDU.setErrorIndex(v1Pdu, idx + 1)
                    break
                elif origV1Pdu.tagSet == v1.GetNextRequestPDU.tagSet:
                    raise error.StatusInformation(idx=idx, pdu=v2Pdu)
                else:
                    raise error.ProtocolError('Counter64 on the way')

            # 4.1.2.2.1&2
            if val.tagSet in (v2c.NoSuchObject.tagSet,
                              v2c.NoSuchInstance.tagSet,
                              v2c.EndOfMibView.tagSet):
                v1.apiPDU.setErrorStatus(v1Pdu, 2)
                v1.apiPDU.setErrorIndex(v1Pdu, idx + 1)

            idx -= 1

        # 4.1.2.3.1
        v2ErrorStatus = v2c.apiPDU.getErrorStatus(v2Pdu)
        if v2ErrorStatus:
            v1.apiPDU.setErrorStatus(v1Pdu,
                                     __v2ToV1ErrorMap.get(v2ErrorStatus, 5))
            v1.apiPDU.setErrorIndex(
                v1Pdu, v2c.apiPDU.getErrorIndex(v2Pdu, muteErrors=True))

    elif pduType in rfc3411.confirmedClassPDUs:
        v1.apiPDU.setErrorStatus(v1Pdu, 0)
        v1.apiPDU.setErrorIndex(v1Pdu, 0)

    # Translate Var-Binds
    if pduType in rfc3411.responseClassPDUs and \
            v1.apiPDU.getErrorStatus(v1Pdu):
        v1VarBinds = v1.apiPDU.getVarBinds(origV1Pdu)
    else:
        for oid, v2Val in v2VarBinds:
            v1VarBinds.append(
                (oid, __v2ToV1ValueMap[v2Val.tagSet].clone(v2Val)))

    if pduType in rfc3411.notificationClassPDUs:
        v1.apiTrapPDU.setVarBinds(v1Pdu, v1VarBinds)
    else:
        v1.apiPDU.setVarBinds(v1Pdu, v1VarBinds)

        v1.apiPDU.setRequestID(v1Pdu, v2c.apiPDU.getRequestID(v2Pdu))

    debug.logger & debug.flagPrx and debug.logger(
        'v2ToV1: v1Pdu %s' % v1Pdu.prettyPrint())

    return v1Pdu
Example #60
0
    def __init__(self,
                 snmpEngineID=None,
                 maxMessageSize=65507,
                 msgAndPduDsp=None):
        self.cache = {}

        self.observer = observer.MetaObserver()

        if msgAndPduDsp is None:
            self.msgAndPduDsp = MsgAndPduDispatcher()
        else:
            self.msgAndPduDsp = msgAndPduDsp
        self.messageProcessingSubsystems = {
            SnmpV1MessageProcessingModel.messageProcessingModelID:
            SnmpV1MessageProcessingModel(),
            SnmpV2cMessageProcessingModel.messageProcessingModelID:
            SnmpV2cMessageProcessingModel(),
            SnmpV3MessageProcessingModel.messageProcessingModelID:
            SnmpV3MessageProcessingModel()
        }
        self.securityModels = {
            SnmpV1SecurityModel.securityModelID: SnmpV1SecurityModel(),
            SnmpV2cSecurityModel.securityModelID: SnmpV2cSecurityModel(),
            SnmpUSMSecurityModel.securityModelID: SnmpUSMSecurityModel()
        }
        self.accessControlModel = {
            void.Vacm.accessModelID: void.Vacm(),
            rfc3415.Vacm.accessModelID: rfc3415.Vacm()
        }

        self.transportDispatcher = None

        if self.msgAndPduDsp.mibInstrumController is None:
            raise error.PySnmpError('MIB instrumentation does not yet exist')
        snmpEngineMaxMessageSize, = self.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize')
        snmpEngineMaxMessageSize.syntax = snmpEngineMaxMessageSize.syntax.clone(
            maxMessageSize)
        snmpEngineBoots, = self.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots')
        snmpEngineBoots.syntax += 1
        origSnmpEngineID, = self.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
            '__SNMP-FRAMEWORK-MIB', 'snmpEngineID')

        if snmpEngineID is None:
            self.snmpEngineID = origSnmpEngineID.syntax
        else:
            origSnmpEngineID.syntax = origSnmpEngineID.syntax.clone(
                snmpEngineID)
            self.snmpEngineID = origSnmpEngineID.syntax

            debug.logger & debug.flagApp and debug.logger(
                'SnmpEngine: using custom SNMP Engine ID: %s' %
                self.snmpEngineID.prettyPrint())

            # Attempt to make some of snmp Engine settings persistent.
            # This should probably be generalized as a non-volatile MIB store.

            persistentPath = os.path.join(tempfile.gettempdir(), '__pysnmp',
                                          self.snmpEngineID.prettyPrint())

            debug.logger & debug.flagApp and debug.logger(
                'SnmpEngine: using persistent directory: %s' % persistentPath)

            if not os.path.exists(persistentPath):
                try:
                    os.makedirs(persistentPath)
                except OSError:
                    return

            f = os.path.join(persistentPath, 'boots')
            try:
                snmpEngineBoots.syntax = snmpEngineBoots.syntax.clone(
                    open(f).read())
            except Exception:
                pass

            try:
                snmpEngineBoots.syntax += 1
            except Exception:
                snmpEngineBoots.syntax = snmpEngineBoots.syntax.clone(1)

            try:
                fd, fn = tempfile.mkstemp(dir=persistentPath)
                os.write(fd, str2octs(snmpEngineBoots.syntax.prettyPrint()))
                os.close(fd)
                os.rename(fn, f)
            except Exception:
                debug.logger & debug.flagApp and debug.logger(
                    'SnmpEngine: could not stored SNMP Engine Boots: %s' %
                    sys.exc_info()[1])
            else:
                debug.logger & debug.flagApp and debug.logger(
                    'SnmpEngine: stored SNMP Engine Boots: %s' %
                    snmpEngineBoots.syntax.prettyPrint())