Ejemplo n.º 1
0
    def test_multiwalk_non_containment(self):
        '''
        Running a multiwalk should raise an exception if the agent returns OIDs
        which are not properly increasing.
        '''
        from puresnmp.pdu import GetResponse
        OID = ObjectIdentifier.from_string

        # First case: Returned OIDs are the same
        response = Sequence(
            Integer(1), OctetString(b'public'),
            GetResponse(123, [
                VarBind(oid=OID('1.2.3'), value=Integer(30)),
                VarBind(oid=OID('2.3.4'), value=Integer(40)),
            ]))
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = [to_bytes(response)]
            mck().get_request_id.return_value = 0
            with self.assertRaises(FaultySNMPImplementation):
                list(multiwalk('::1', 'public', [
                    '1.2.3',
                    '2.3.4',
                ]))

        # Second case: Returned OIDs are smaller
        response = Sequence(
            Integer(1), OctetString(b'public'),
            GetResponse(123, [
                VarBind(oid=OID('1.2.2'), value=Integer(30)),
                VarBind(oid=OID('2.3.3'), value=Integer(40)),
            ]))
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = [to_bytes(response)]
            mck().get_request_id.return_value = 0
            with self.assertRaises(FaultySNMPImplementation):
                list(multiwalk('::1', 'public', [
                    '1.2.3',
                    '2.3.4',
                ]))
Ejemplo n.º 2
0
    def test_getnext_increasing_oid_strict(self):
        '''
        When running "getnext" we expect a different OID than the one we passed
        in. If not, this can cause endless-loops in the worst case. Faulty SNMP
        implementations may behave this way!
        '''
        requested_oid = ObjectIdentifier(1, 2, 3, 4)
        response_object = Sequence(
            Integer(1), OctetString(b'public'),
            GetResponse(234, [VarBind(requested_oid, Integer(123))]))
        response_bytes = to_bytes(response_object)

        with patch('puresnmp.api.raw.send') as mck:
            mck.return_value = response_bytes
            with self.assertRaises(FaultySNMPImplementation):
                getnext('::1', 'private', '1.2.3.4')
Ejemplo n.º 3
0
    def test_walk_endless_loop(self):
        '''
        In rare cases, some devices fall into an endless loop by returning the
        requested OID on a "getnext" call during a "walk" operation. A SNMP
        client behaving according to the SNMP spec will fall into an endless
        loop. This test fakes such a case and revents the loop.
        '''
        response_binds = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),  # same OID
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),  # same OID
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),  # same OID
        ]
        response_packets = [
            Sequence(Integer(1), OctetString(b'public'),
                     GetResponse(234, [bind])) for bind in response_binds
        ]
        response_bytes = [to_bytes(packet) for packet in response_packets]

        handler = CapturingHandler()
        logger = getLogger('puresnmp')
        logger.addHandler(handler)
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = response_bytes
            mck().get_request_id.return_value = 0
            result = list(walk('::1', 'private', '1.2', errors='warn'))
        logger.removeHandler(handler)

        # The last OID in the mocked responses is decreasing so we want to read
        # just up to that point.
        expected = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
        ]
        self.assertEqual(result, expected)

        # We also want to make sure that we have a proper warning about this
        handler.assertContains(WARNING, r'.*1.2.5.*')
Ejemplo n.º 4
0
    def test_walk_increasing_oid_lenient(self):
        '''
        We want to be able to allow faulty SNMP implementations to at least try
        to fetch the values in a walk which are not increasing. It should read
        up to the values which are no longer increasing and emit a warning.
        '''
        logger = getLogger('puresnmp')
        handler = CapturingHandler()
        logger.addHandler(handler)

        response_binds = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
            VarBind(ObjectIdentifier(1, 2, 1), Integer(121)),  # non-increasing
        ]
        response_packets = [
            Sequence(Integer(1), OctetString(b'public'),
                     GetResponse(234, [bind])) for bind in response_binds
        ]
        response_bytes = [to_bytes(packet) for packet in response_packets]

        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = response_bytes
            mck().get_request_id.return_value = 0
            result = list(walk('::1', 'private', '1.2', errors='warn'))

        # The last OID in the mocked responses is decreasing so we want to read
        # just up to that point.
        expected = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
        ]
        self.assertEqual(result, expected)

        # We also want to make sure that we have a proper warning about this
        handler.assertContains(WARNING, r'.*1.2.1.*1.2.5.*')
        logger.removeHandler(handler)