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)
def handle_read(self): try: incomingMessage, transportAddress = self._recvfrom( self.socket, 65535) transportAddress = self.normalizeAddress(transportAddress) debug.logger & debug.flagIO 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: if sys.exc_info()[1].args[0] in sockErrors: debug.logger & debug.flagIO and debug.logger( 'handle_read: known socket error %s' % (sys.exc_info()[1], )) sockErrors[sys.exc_info()[1].args[0]] and self.handle_close() return else: raise error.CarrierError('recvfrom() failed: %s' % (sys.exc_info()[1], ))
def sendMessage(self, outgoingMessage, transportAddress): self.__outQueue.append( (outgoingMessage, self.normalizeAddress(transportAddress)) ) debug.logger & debug.FLAG_IO and debug.logger( 'sendMessage: outgoingMessage queued (%d octets) %s' % ( len(outgoingMessage), debug.hexdump(outgoingMessage)))
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())))
def sendMessage(self, outgoingMessage, transportAddress): debug.logger & debug.flagIO and debug.logger('sendMessage: %s transportAddress %r outgoingMessage %s' % ( (self.transport is None and "queuing" or "sending"), transportAddress, debug.hexdump(outgoingMessage) )) if self.transport is None: self._writeQ.append((outgoingMessage, transportAddress)) else: try: self.transport.sendto(outgoingMessage, self.normalizeAddress(transportAddress)) except Exception: raise error.CarrierError(';'.join(traceback.format_exception(*sys.exc_info())))
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], ))
def sendMessage(self, outgoingMessage, transportAddress): debug.logger & debug.flagIO and debug.logger( 'startProtocol: %s transportAddress %r outgoingMessage %s' % ((self.transport is None and "queuing" or "sending"), transportAddress, debug.hexdump(outgoingMessage))) if self.transport is None: self._writeQ.append((outgoingMessage, transportAddress)) else: try: self.transport.write(outgoingMessage, transportAddress) except Exception: raise error.CarrierError('Twisted exception: %s' % (sys.exc_info()[1], ))
def sendMessage(self, outgoingMessage, transportAddress): debug.logger & debug.FLAG_IO and debug.logger( 'startProtocol: %s transportAddress %r outgoingMessage ' '%s' % ((self.transport is None and "queuing" or "sending"), transportAddress, debug.hexdump(outgoingMessage))) if not self.transport: self._writeQ.append((outgoingMessage, transportAddress)) else: try: self.transport.write(outgoingMessage, transportAddress) except Exception as exc: raise error.CarrierError('Twisted exception: %s' % exc)
def handle_write(self): outgoingMessage, transportAddress = self.__outQueue.pop(0) debug.logger & debug.flagIO and debug.logger( "handle_write: transportAddress %r -> %r outgoingMessage (%d octets) %s" % (self.__getsockname(), transportAddress, len(outgoingMessage), 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]))
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]))
def handle_read(self): try: incomingMessage, transportAddress = self.socket.recvfrom(65535) transportAddress = self.normalizeAddress(transportAddress) debug.logger & debug.flagIO and debug.logger( "handle_read: transportAddress %r -> %r incomingMessage (%d octets) %s" % (transportAddress, self.__getsockname(), len(incomingMessage), debug.hexdump(incomingMessage)) ) if not incomingMessage: self.handle_close() return else: self._cbFun(self, transportAddress, incomingMessage) return except socket.error: if sys.exc_info()[1].args[0] in sockErrors: debug.logger & debug.flagIO and debug.logger( "handle_read: known socket error %s" % (sys.exc_info()[1],) ) sockErrors[sys.exc_info()[1].args[0]] and self.handle_close() return else: raise error.CarrierError("recvfrom() failed: %s" % (sys.exc_info()[1],))
def handle_write(self): outgoingMessage, transportAddress = self.__outQueue.pop(0) debug.logger & debug.FLAG_IO and debug.logger( 'handle_write: transportAddress %r -> %r outgoingMessage (%d ' 'octets) %s' % (transportAddress.getLocalAddress(), transportAddress, len(outgoingMessage), debug.hexdump(outgoingMessage))) if not transportAddress: debug.logger & debug.FLAG_IO and debug.logger( 'handle_write: missing dst address, loosing outgoing msg') return try: self._sendto(self.socket, outgoingMessage, transportAddress) except socket.error as exc: if exc.args[0] in SOCK_ERRORS: debug.logger & debug.FLAG_IO and debug.logger( 'handle_write: ignoring socket error %s' % exc) else: raise error.CarrierError( 'sendto() failed for %s: %s' % (transportAddress, exc))
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)
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
def sendMessage(self, outgoingMessage, transportAddress): debug.logger & debug.flagIO and debug.logger('startProtocol: %s transportAddress %r outgoingMessage %s' % ((self.transport is None and "queuing" or "sending"), transportAddress, debug.hexdump(outgoingMessage))) if self.transport is None: self._writeQ.append((outgoingMessage, transportAddress)) else: try: self.transport.write(outgoingMessage, transportAddress) except Exception: raise error.CarrierError('Twisted exception: %s' % (sys.exc_info()[1],))
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],))
def sendMessage(self, outgoingMessage, transportAddress): self.__outQueue.append( (outgoingMessage, self.normalizeAddress(transportAddress))) debug.logger & debug.flagIO and debug.logger( 'sendMessage: outgoingMessage queued (%d octets) %s' % (len(outgoingMessage), debug.hexdump(outgoingMessage)))
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._cache.pop(securityStateReference) usmUserName = cachedSecurityData['msgUserName'] 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, 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 = errind.unknownSecurityName ) debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: clone user info') 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') debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: local user usmUserName %r usmUserAuthProtocol %s usmUserPrivProtocol %s securityEngineID %r securityName %r' % (usmUserName, 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 ( # request type check added securityLevel == 3 or securityLevel == 2 ): 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 ) = 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 %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()) dataToEncrypt = encoder.encode(scopedPDU) debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: scopedPDU encoded into %s' % debug.hexdump(dataToEncrypt)) ( 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(),)) msg.setComponentByPosition( 2, encoder.encode(securityParameters), verifyConstraints=False ) debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: auth outgoing msg: %s' % msg.prettyPrint()) wholeMsg = encoder.encode(msg) 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(),)) msg.setComponentByPosition( 2, encoder.encode(securityParameters), verifyConstraints=False ) debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: plain outgoing msg: %s' % msg.prettyPrint()) authenticatedWholeMsg = encoder.encode(msg) 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 )
def processIncomingMsg( self, snmpEngine, messageProcessingModel, maxMessageSize, securityParameters, securityModel, securityLevel, wholeMsg, msg # XXX ): # 3.2.9 -- moved up here to be able to report # maxSizeResponseScopedPDU on error # (48 - maximum SNMPv3 header length) maxSizeResponseScopedPDU = 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, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInASNParseErrs') snmpInASNParseErrs.syntax = snmpInASNParseErrs.syntax + 1 raise error.StatusInformation( errorIndication=errind.parseError ) debug.logger & debug.flagSM and debug.logger('processIncomingMsg: %s' % (securityParameters.prettyPrint(),)) # 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 = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax contextName = null # 3.2.3 if msgAuthoritativeEngineID not in self.__timeline: debug.logger & debug.flagSM and debug.logger('processIncomingMsg: unknown securityEngineID %r' % (msgAuthoritativeEngineID,)) if not msgAuthoritativeEngineID: # 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') # 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 ) snmpEngineID = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')[0].syntax 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: ( 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, msgAuthoritativeEngineID, 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 %r msgUserName %r' % (msgAuthoritativeEngineID, msgUserName)) if __reportUnknownName: usmStatsUnknownUserNames, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames') usmStatsUnknownUserNames.syntax = 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 ) 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 usmUserSecurityName %s usmUserAuthProtocol %s usmUserPrivProtocol %s for msgUserName %s' % (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), usmUserAuthProtocol=usmUserAuthProtocol, usmUserAuthKeyLocalized=usmUserAuthKeyLocalized, usmUserPrivProtocol=usmUserPrivProtocol, usmUserPrivKeyLocalized=usmUserPrivKeyLocalized ) # 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: __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, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-USER-BASED-SM-MIB', 'usmStatsUnsupportedSecLevels') usmStatsUnsupportedSecLevels.syntax = 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: 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 = 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') if msgAuthoritativeEngineID: # 3.2.3a moved down here to execute only for authed msg self.__timeline[msgAuthoritativeEngineID] = ( securityParameters.getComponentByPosition(1), securityParameters.getComponentByPosition(2), securityParameters.getComponentByPosition(2), int(time.time()) ) expireAt = int(self.__expirationTimer + 300 / snmpEngine.transportDispatcher.getTimerResolution()) 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 ) = 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 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') 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 = 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 if msgAuthoritativeEngineBoots > snmpEngineBoots or \ msgAuthoritativeEngineBoots == snmpEngineBoots and \ msgAuthoritativeEngineTime > latestReceivedEngineTime: self.__timeline[msgAuthoritativeEngineID] = ( msgAuthoritativeEngineBoots, msgAuthoritativeEngineTime, msgAuthoritativeEngineTime, int(time.time()) ) expireAt = int(self.__expirationTimer + 300 / snmpEngine.transportDispatcher.getTimerResolution()) 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, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-USER-BASED-SM-MIB', 'usmStatsDecryptionErrors') usmStatsDecryptionErrors.syntax = 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 ) 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, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-USER-BASED-SM-MIB', 'usmStatsUnknownUserNames') usmStatsUnknownUserNames.syntax = 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 )
def sendMessage(self, outgoingMessage, transportAddress): self.__outQueue.append( (outgoingMessage, transportAddress) ) self.set_writable(True) LOGGER.debug('sendMessage: outgoingMessage queued (%d octets) %s' % (len(outgoingMessage), debug.hexdump(outgoingMessage)))
def handle_write(self): if not self.__outQueue: self.set_writable(False) return outgoingMessage, transportAddress = self.__outQueue.pop(0) LOGGER.debug('handle_write: transportAddress %r -> %r outgoingMessage (%d octets) %s' % (self.__getsockname(), transportAddress, len(outgoingMessage), debug.hexdump(outgoingMessage))) if not transportAddress: LOGGER.debug('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: LOGGER.debug('handle_write: ignoring socket error %s' % (sys.exc_info()[1],)) else: raise error.CarrierError('sendto() failed for %s: %s' % (transportAddress, sys.exc_info()[1]))
def handle_read(self): try: incomingMessage, transportAddress = self.socket.recvfrom(65535) transportAddress = self.normalizeAddress(transportAddress) LOGGER.debug('handle_read: transportAddress %r -> %r incomingMessage (%d octets) %s' % (transportAddress, self.__getsockname(), len(incomingMessage), debug.hexdump(incomingMessage))) if not incomingMessage: # must do something, but don't know what return else: self._cbFun(self, transportAddress, incomingMessage) return except socket.error: if sys.exc_info()[1].args[0] in sockErrors: LOGGER.debug('handle_read: known socket error %s' % (sys.exc_info()[1],)) sockErrors[sys.exc_info()[1].args[0]] and self.handle_close() return else: raise error.CarrierError('recvfrom() failed: %s' % (sys.exc_info()[1],))
def sendMessage(self, outgoingMessage, transportAddress): self.__outQueue.append((outgoingMessage, transportAddress)) debug.logger & debug.flagIO and debug.logger( "sendMessage: outgoingMessage queued (%d octets) %s" % (len(outgoingMessage), debug.hexdump(outgoingMessage)) )