<commit_before>#! /usr/bin/python
# pylint: disable=line-too-long,no-member

# Copyright 2015 F-Secure Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you
# may not use this file except in compliance with the License.  You
# may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.  See the License for the specific language governing
# permissions and limitations under the License.

"""mqtt_fuzz.py

Performs MQTT sessions as a client with a fuzzed PDU once in a while.
"""

from __future__ import division
from twisted.internet.protocol import Protocol, ClientFactory
import itertools
import time
import binascii
import fuzzpool
import random
import uuid
import calendar
import argparse
import os


class MQTTFuzzProtocol(Protocol):
    '''Implementation of a pseudo-MQTT protocol that conducts predefined MQTT
    sessions by replaying a series of stored MQTT control packets.'''

    def dataReceived(self, data):
        """Callback. If we receive data from the remote peer, print it out

        :param data: Data received from remote peer

        """
        print "%s:%s:Server -> Fuzzer: %s" % (calendar.timegm(time.gmtime()), self.session_id, binascii.b2a_base64(data))

    def connectionMade(self):
        """Callback. We have connected to the MQTT server, so start banging away

        """
        print "%s:%s:Connected to server" % (calendar.timegm(time.gmtime()), self.session_id)
        self.send_next_pdu()

    def send_next_pdu(self):
        """Send a PDU and schedule the next PDU

        """
        from twisted.internet import reactor

        try:
            self.send_pdu(self.current_session.next())
            reactor.callLater(self.send_delay / 1000, self.send_next_pdu)
        except StopIteration:
            # We have sent all the PDUs of this session. Tear down
            # connection. It will trigger a reconnection in the factory.
            print "%s:%s:End of session, initiating disconnect." % (calendar.timegm(time.gmtime()), self.session_id)
            self.transport.loseConnection()

    def send_pdu(self, pdutype):
        """Send either a valid case or a fuzz case

        :param pdutype: Message type (Directory from which the message will be sent)

        """
        from twisted.internet import reactor

        try:
            # 1 in 10, send a fuzz case, otherwise a valid case
            if random.randint(1, 10) < self.fuzz_ratio:
                print "%s:%s:Sending fuzzed %s" % (calendar.timegm(time.gmtime()), self.session_id, pdutype)
                data = self.fuzzdata.get_next_fuzzcase(os.path.join(self.validcases_path, pdutype))
            else:
                print "%s:%s:Sending valid %s" % (calendar.timegm(time.gmtime()), self.session_id, pdutype)
                data = self.fuzzdata.get_valid_case(os.path.join(self.validcases_path, pdutype))
                print "%s:%s:Fuzzer -> Server: %s" % (calendar.timegm(time.gmtime()), self.session_id, binascii.b2a_base64(data).rstrip())
                self.transport.write(data)
        except (IOError, OSError) as err:
            print "Could not run the fuzzer. Check -validcases and -radamsa options. The error was: %s" % err
            reactor.stop()

class MQTTClientFactory(ClientFactory):
    '''Factory that creates pseudo-MQTT clients'''

    protocol = MQTTFuzzProtocol

    # These are the sessions that we will be running through.
    # If you want to extend the fuzzer with new control packets,
    # copy some raw valid control packets into a directory under valid-cases
    # and refer to that directory by name in one of these sessions here.
    # See readme.txt.
    session_structures = [
        ['connect', 'disconnect'],
        ['connect', 'subscribe', 'disconnect'],
        ['connect', 'subscribe', 'publish', 'disconnect'],
        ['connect', 'subscribe', 'publish', 'publish-ack', 'publish-release', 'publish-complete', 'publish-received', 'publish-complete', 'disconnect'],
        ['connect', 'publish', 'publish-release', 'subscribe', 'publish-received', 'publish-ack', 'disconnect']]

    def __init__(self, fuzz_ratio, send_delay, radamsa_path, validcases_path):
        # We cycle through the sessions again and again
        self.session = itertools.cycle(iter(self.session_structures))

        # Copy the data into this instance so we can use it later
        self.fuzzdata = fuzzpool.FuzzPool(radamsa_path)
        self.fuzz_ratio = fuzz_ratio
        self.send_delay = send_delay
        self.validcases_path = validcases_path<commit_msg>Fixed fuzz case sending<commit_after>#! /usr/bin/python
# pylint: disable=line-too-long,no-member

# Copyright 2015 F-Secure Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you
# may not use this file except in compliance with the License.  You
# may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.  See the License for the specific language governing
# permissions and limitations under the License.

"""mqtt_fuzz.py

Performs MQTT sessions as a client with a fuzzed PDU once in a while.
"""

from __future__ import division
from twisted.internet.protocol import Protocol, ClientFactory
import itertools
import time
import binascii
import fuzzpool
import random
import uuid
import calendar
import argparse
import os


class MQTTFuzzProtocol(Protocol):
    '''Implementation of a pseudo-MQTT protocol that conducts predefined MQTT
    sessions by replaying a series of stored MQTT control packets.'''

    def dataReceived(self, data):
        """Callback. If we receive data from the remote peer, print it out

        :param data: Data received from remote peer

        """
        print "%s:%s:Server -> Fuzzer: %s" % (calendar.timegm(time.gmtime()), self.session_id, binascii.b2a_base64(data))

    def connectionMade(self):
        """Callback. We have connected to the MQTT server, so start banging away

        """
        print "%s:%s:Connected to server" % (calendar.timegm(time.gmtime()), self.session_id)
        self.send_next_pdu()

    def send_next_pdu(self):
        """Send a PDU and schedule the next PDU

        """
        from twisted.internet import reactor

        try:
            self.send_pdu(self.current_session.next())
            reactor.callLater(self.send_delay / 1000, self.send_next_pdu)
        except StopIteration:
            # We have sent all the PDUs of this session. Tear down
            # connection. It will trigger a reconnection in the factory.
            print "%s:%s:End of session, initiating disconnect." % (calendar.timegm(time.gmtime()), self.session_id)
            self.transport.loseConnection()

    def send_pdu(self, pdutype):
        """Send either a valid case or a fuzz case

        :param pdutype: Message type (Directory from which the message will be sent)

        """
        from twisted.internet import reactor

        try:
            # 1 in 10, send a fuzz case, otherwise a valid case
            if random.randint(1, 10) < self.fuzz_ratio:
                print "%s:%s:Sending fuzzed %s" % (calendar.timegm(time.gmtime()), self.session_id, pdutype)
                data = self.fuzzdata.get_next_fuzzcase(os.path.join(self.validcases_path, pdutype))
            else:
                print "%s:%s:Sending valid %s" % (calendar.timegm(time.gmtime()), self.session_id, pdutype)
                data = self.fuzzdata.get_valid_case(os.path.join(self.validcases_path, pdutype))
            print "%s:%s:Fuzzer -> Server: %s" % (calendar.timegm(time.gmtime()), self.session_id, binascii.b2a_base64(data).rstrip())
            self.transport.write(data)
        except (IOError, OSError) as err:
            print "Could not run the fuzzer. Check -validcases and -radamsa options. The error was: %s" % err
            reactor.stop()

class MQTTClientFactory(ClientFactory):
    '''Factory that creates pseudo-MQTT clients'''

    protocol = MQTTFuzzProtocol

    # These are the sessions that we will be running through.
    # If you want to extend the fuzzer with new control packets,
    # copy some raw valid control packets into a directory under valid-cases
    # and refer to that directory by name in one of these sessions here.
    # See readme.txt.
    session_structures = [
        ['connect', 'disconnect'],
        ['connect', 'subscribe', 'disconnect'],
        ['connect', 'subscribe', 'publish', 'disconnect'],
        ['connect', 'subscribe', 'publish', 'publish-ack', 'publish-release', 'publish-complete', 'publish-received', 'publish-complete', 'disconnect'],
        ['connect', 'publish', 'publish-release', 'subscribe', 'publish-received', 'publish-ack', 'disconnect']]

    def __init__(self, fuzz_ratio, send_delay, radamsa_path, validcases_path):
        # We cycle through the sessions again and again
        self.session = itertools.cycle(iter(self.session_structures))

        # Copy the data into this instance so we can use it later
        self.fuzzdata = fuzzpool.FuzzPool(radamsa_path)
        self.fuzz_ratio = fuzz_ratio
        self.send_delay = send_delay
        self.validcases_path = validcases_path
{'fraction_non_alphanumeric': 0.09987489574645537, 'fraction_numerical': 0.0050041701417848205, 'mean_word_length': 3.0648305084745764, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3041495', 'n_tokens_mistral': 2841, 'n_tokens_neox': 2710, 'n_words': 926}