Exemplo n.º 1
0
    def test_td_coap(self):
        for pcap_name in self.get_pcaps():
            expected_verdict = None
            if 'PASS' in pcap_name:
                expected_verdict = 'pass'
            elif 'FAIL' in pcap_name:
                expected_verdict = 'fail'
            elif 'INCONCLUSIVE' in pcap_name:
                expected_verdict = 'inconclusive'
            else:
                if default_expected_verdict_if_none_specified == "error":
                    raise Exception("No verdict in name with pcap filename " +
                                    pcap_name)
                else:
                    expected_verdict = default_expected_verdict_if_none_specified
            analyzer = Analyzer('tat_coap')

            test_case = self.__get_test_case_from_full_path(pcap_name)
            if test_case is None:
                logging.info(
                    "Ignored file " + pcap_name +
                    " because we couldn't determine the relevant test case.")
                continue

            logging.info("Testing " + test_case + "\n With file " + pcap_name)

            tc_name, verdict, rev_frames, log, partial_verdicts, exception_info = analyzer.analyse(
                pcap_name, test_case)
            assert verdict == expected_verdict, log

            logging.info(test_case + " PASSED.")
Exemplo n.º 2
0
def get_test_steps(tc: str) -> list_of(OrderedDict):
    """
    Get an OrderedDict representing the different steps of a test case

    :param tc: The id of the test case
    :type tc: str

    :return: The steps of a TC as a list of OrderedDict
    :rtype: [OrderedDict]
    """

    # The return list of OrderedDict
    steps = []

    # Get the test case informations
    raw_tcs = Analyzer('tat_coap').get_implemented_testcases([tc], True)
    assert len(raw_tcs) == 1

    # Parse the documentation with yaml reader and get it as dictionnary
    doc_reader = YamlReader(raw_tcs[0][3], raw_text=True)
    doc_dict = doc_reader.as_dict

    # For every step, put its informations inside the steps dict
    for step_id, step in enumerate(doc_dict[tc]['seq']):
        step_dict = OrderedDict()
        step_dict['_type'] = 'step'
        step_dict['step_id'] = step_id
        step_dict['step_type'], step_dict['step_info'] = step.popitem()
        steps.append(step_dict)

    # Return the step list of this tc
    return steps
Exemplo n.º 3
0
def analyze_capture(filename, protocol, testcase_id, output_filename):
    """
    Analyses network traces (.pcap file) based on the test cases checks.
    """
    assert filename
    assert protocol
    assert testcase_id

    if os.path.isfile(filename) is False and os.path.isfile(
            os.path.join(TMPDIR, filename)):
        filename = os.path.join(TMPDIR, filename)

    logger.info("Analyzing PCAP file %s, for testcase: %s" %
                (filename, testcase_id))

    if protocol.lower() not in ALLOWED_PROTOCOLS_FOR_ANALYSIS:
        raise NotImplementedError(
            'Protocol %s not among the allowed analysis test suites' %
            protocol)

    analysis_results = Analyzer('tat_' + protocol.lower()).analyse(
        filename, testcase_id)
    logger.info('Analysis finished. Got [%s]' % str(analysis_results[1]))

    if output_filename and type(output_filename) is str:
        # save analysis response
        results_to_be_saved = analysis_results[:
                                               -1]  # drop the last returned value (exceptions list)
        _dump_json_to_file(json.dumps(results_to_be_saved), output_filename)
        logger.info('Results saved at: %s' % output_filename)

    return analysis_results
Exemplo n.º 4
0
def get_test_cases(
    testcase_id: optional(str) = None,
    verbose: bool = False
) -> OrderedDict:
    """
    Function to get the implemented test cases

    :param testcase_id: The id of the single test case if one wanted
    :param verbose: True if we want a verbose response
    :type testcase_id: str
    :type verbose: bool

    :return: The implemented test cases using doc.f-interop.eu format
    :rtype: OrderedDict
    """

    test_cases = OrderedDict()
    tc_query = [] if not testcase_id else [testcase_id]
    raw_tcs = Analyzer('tat_coap').get_implemented_testcases(
        tc_query,
        verbose
    )

    # Build the clean results list
    for raw_tc in raw_tcs:

        tc_basic = OrderedDict()
        tc_basic['_type'] = 'tc_basic'
        tc_basic['id'] = raw_tc[0]
        tc_basic['objective'] = raw_tc[1]

        tc_implementation = OrderedDict()
        tc_implementation['_type'] = 'tc_implementation'
        tc_implementation['implementation'] = raw_tc[2]

        # Tuple, basic + implementation
        test_cases[raw_tc[0]] = OrderedDict()
        test_cases[raw_tc[0]]['tc_basic'] = tc_basic
        test_cases[raw_tc[0]]['tc_implementation'] = tc_implementation

    # If a single element is asked
    if testcase_id:
        test_cases = test_cases[raw_tcs[0][0]]

    # Return the results
    return test_cases
Exemplo n.º 5
0
def get_test_cases(testcase_id: optional(str) = None) -> OrderedDict:
    """
    Function to get the test cases from files if not initialized

    Or directly from the global storage variable, can retrieve a single test
    case if wanted but doesn't use the analysis function, cf the remark

    :param testcase_id: The id of the single test case if one wanted
    :type testcase_id: str

    :return: The implemented test cases
    :rtype: OrderedDict
    """

    # New way by analyzer tool
    test_cases = OrderedDict()
    tc_query = [] if not testcase_id else [testcase_id]
    raw_tcs = Analyzer('tat_coap').get_implemented_testcases(tc_query)

    # Build the clean results list
    for raw_tc in raw_tcs:

        tc_basic = OrderedDict()
        tc_basic['_type'] = 'tc_basic'
        tc_basic['id'] = raw_tc[0]
        tc_basic['objective'] = raw_tc[1]

        tc_implementation = OrderedDict()
        tc_implementation['_type'] = 'tc_implementation'
        tc_implementation['implementation'] = raw_tc[2]

        # Tuple, basic + implementation
        test_cases[raw_tc[0]] = OrderedDict()
        test_cases[raw_tc[0]]['tc_basic'] = tc_basic
        test_cases[raw_tc[0]]['tc_implementation'] = tc_implementation

    # If a single element is asked
    if testcase_id:
        test_cases = test_cases[raw_tcs[0][0]]

    # Return the results
    return test_cases
Exemplo n.º 6
0
    def do_POST(self):

        # The job counter
        global job_id
        job_id += 1

        # ########################## ttproto API ########################### #

        # POST handler for the analyzer_testCaseAnalyze uri
        # It will allow users to analyze a pcap file corresponding to a TC
        #
        # \param pcap_file => The pcap file that we want to analyze
        # \param token => The token previously provided
        # \param testcase_id => The id of the corresponding test case
        # The pcap_file or the token is required, having both is also forbidden
        #
        if self.path == '/api/v1/analyzer_testCaseAnalyze':

            # Send the header
            self.send_response(200)
            self.send_header('Content-Type', 'application/json;charset=utf-8')
            self.end_headers()

            # Bind the stdout to the http output
            os.dup2(self.wfile.fileno(), sys.stdout.fileno())

            # Get the content type
            try:
                content_type = cgi.parse_header(self.headers['Content-Type'])
            except TypeError:
                self.api_error(
                    "Non empty POST datas and format of 'multipart/form-data' expected"
                )
                return

            # Get post values
            form = cgi.FieldStorage(fp=self.rfile,
                                    headers=self.headers,
                                    keep_blank_values=True,
                                    environ={
                                        'REQUEST_METHOD': 'POST',
                                        'CONTENT_TYPE': content_type[0]
                                    })

            # Check that we have the two values
            if any((
                    len(form) != 2,
                    'testcase_id' not in form,
                    all((  # None of the two required => Error
                        'pcap_file' not in form, 'token' not in form)),
                    all((  # Both of them => Error
                        'pcap_file' in form, 'token' in form)))):
                self.api_error(
                    'Expected POST=([pcap_file={file}|token={text}], testcase_id={text})'
                )
                return

            # Get the test case and its informations
            testcase_id = form.getvalue('testcase_id')
            if not type(testcase_id) == str:
                self.api_error(
                    'The value of the testcase_id should be a string from text input'
                )
                return

            # Try to get the test case
            try:
                test_case = get_test_cases(testcase_id)
            except FileNotFoundError:
                self.api_error('Test case %s not found' % testcase_id)
                return

            # Get the token
            token = form.getvalue('token')

            # Get analysis results from the token
            if token:

                # Just get the path
                pcap_path = os.path.join(TMPDIR, token + '.dump')

            # Get analysis results from the pcap file
            else:

                # Check headers
                if any((len(content_type) == 0, content_type[0] is None,
                        content_type[0] != 'multipart/form-data')):
                    self.api_error(
                        "POST format of 'multipart/form-data' expected, no file input 'pcap_file' found"
                    )
                    return

                # Get the same token or generate a new one
                token = get_token(token)

                # Get and check the pcap file entered
                pcap_file = form.getvalue('pcap_file')

                # Path to save the file
                pcap_path = os.path.join(TMPDIR, token + '.dump')

                # Write the pcap file to a temporary destination
                try:
                    with open(pcap_path, 'wb') as f:
                        f.write(pcap_file)
                except:
                    self.api_error("Couldn't write the temporary file %s" %
                                   pcap_path)
                    return

                # Get the dissection from analysis tool
                try:
                    dissection = Dissector(pcap_path).dissect()
                except pure_pcapy.PcapError:
                    self.api_error(
                        "Expected 'pcap_file' to be a non empty pcap file")
                except:
                    self.api_error("Couldn't read the temporary file %s" %
                                   pcap_path)
                    return

                # Save the json dissection result into a file
                json_save = os.path.join(TMPDIR, token + '.json')
                try:
                    with open(json_save, 'w') as f:
                        json.dump(dissection, f)
                except:
                    self.api_error("Couldn't write the json file")
                    return

            # Get the result of the analysis
            analysis_results = Analyzer('tat_coap').analyse(
                pcap_path, testcase_id)

            # self.log_message("###############################################")
            # self.log_message("Verdict description is : %s", analysis_results[0][3])
            # self.log_message("###############################################")

            # print(analysis_results)

            # Error for some test cases that the analysis doesn't manage to get
            try:
                assert type(analysis_results) == tuple
                assert len(analysis_results) == 5
                assert type(analysis_results[0]) == str
                assert type(analysis_results[1]) == str
                assert type(analysis_results[2]) == list
                assert type(analysis_results[3]) == str
                assert type(analysis_results[5]) == list
                for exception_tuple in analysis_results[5]:
                    assert type(exception_tuple) == tuple
                    assert len(exception_tuple) == 3
                    assert isinstance(exception_tuple[0], type)
                    assert isinstance(exception_tuple[1], Exception)
                    assert isinstance(exception_tuple[2], object)
                assert analysis_results[0] == test_case['tc_basic']['id']
            except AssertionError:
                self.api_error(
                    'Problem with the analyse of TC %s, wrong result received'
                    % testcase_id)
                return

            # Only take the first
            verdict = OrderedDict()
            verdict['_type'] = 'verdict'
            verdict['verdict'] = analysis_results[1]
            verdict['description'] = analysis_results[3]
            verdict['review_frames'] = analysis_results[2]

            token_res = OrderedDict()
            token_res['_type'] = 'token'
            token_res['value'] = token

            # Prepare the result to return
            json_result = OrderedDict()
            json_result['_type'] = 'response'
            json_result['ok'] = True
            json_result['content'] = [
                token_res, test_case['tc_basic'], verdict
            ]

            # Here we will analyze the pcap file and get the results as json
            print(json.dumps(json_result))
            return

        # POST handler for the analyzer_allMightyAnalyze uri
        # It will allow users to analyze a pcap file without giving
        # a corresponding test case
        #
        # \param pcap_file => The pcap file that we want to analyze
        # \param token => The token previously provided
        # The pcap_file or the token is required, having both is also forbidden
        #
        elif self.path == '/api/v1/analyzer_allMightyAnalyze':

            # Send the header
            self.send_response(200)
            self.send_header('Content-Type', 'application/json;charset=utf-8')
            self.end_headers()

            # Bind the stdout to the http output
            os.dup2(self.wfile.fileno(), sys.stdout.fileno())

            # Not implemented for the moment
            self.api_error(
                "This method is not implemented yet, please come back later")
            return

        # POST handler for the dissector_dissectFile uri
        # It will allow users to analyze a pcap file corresponding to a TC
        #
        # \param pcap_file => The pcap file that we want to dissect
        # \param protocol_selection => The protocol name
        #
        elif self.path == '/api/v1/dissector_dissectFile':

            # Send the header
            self.send_response(200)
            self.send_header('Content-Type', 'application/json;charset=utf-8')
            self.end_headers()

            # Bind the stdout to the http output
            os.dup2(self.wfile.fileno(), sys.stdout.fileno())

            # Get the content type
            try:
                content_type = cgi.parse_header(self.headers['Content-Type'])
            except TypeError:
                self.api_error(
                    "Non empty POST datas and format of 'multipart/form-data' expected"
                )
                return

            # Check headers
            if any((len(content_type) == 0, content_type[0] is None,
                    content_type[0] != 'multipart/form-data')):
                self.api_error(
                    "POST format of 'multipart/form-data' expected, no file input 'pcap_file' found"
                )
                return

            # Get post values
            form = cgi.FieldStorage(fp=self.rfile,
                                    headers=self.headers,
                                    environ={
                                        'REQUEST_METHOD': 'POST',
                                        'CONTENT_TYPE': content_type[0]
                                    })

            # Check the parameters passed
            if any((len(form) != 2, 'pcap_file'
                    not in form, 'protocol_selection' not in form)):
                self.api_error(
                    'Expected POST=(pcap_file={file}, protocol_selection={text})'
                )
                return

            # Check the protocol_selection value
            protocol_selection = form.getvalue('protocol_selection')
            if not type(protocol_selection) == str:
                self.api_error(
                    'Expected protocol_selection post value to be a text (eq string)'
                )
                return

            # In function of the protocol asked
            prot = get_protocol(protocol_selection)
            if prot is None:
                self.api_error('Unknown protocol %s' % protocol_selection)
                return

            # Generate a new token
            token = get_token()

            # Get the pcap file
            pcap_file = form.getvalue('pcap_file')

            # Path to save the file
            pcap_path = os.path.join(TMPDIR, token + '.dump')

            # Write the pcap file to a temporary destination
            try:
                with open(pcap_path, 'wb') as f:
                    f.write(pcap_file)
            except:
                self.api_error("Couldn't write the temporary file")
                return

            # Prepare the result to return
            json_result = OrderedDict()
            json_result['_type'] = 'response'
            json_result['ok'] = True

            token_res = OrderedDict()
            token_res['_type'] = 'token'
            token_res['value'] = token

            # Get the dissection from dissector tool
            try:
                dissection = Dissector(pcap_path).dissect(eval(prot['name']))
            except TypeError as e:
                self.api_error('Dissector error: ' + str(e))
                return
            except pure_pcapy.PcapError:
                self.api_error(
                    "Expected 'pcap_file' to be a non empty pcap file")
                return
            except:
                self.api_error(
                    "Couldn't read the temporary file %s and protocol is %s" %
                    (pcap_path, prot['name']))
                return

            # Save the json dissection result into a file
            json_save = os.path.join(TMPDIR, token + '.json')
            try:
                with open(json_save, 'w') as f:
                    json.dump(dissection, f)
            except:
                self.api_error("Couldn't write the json file")
                return

            # Add the token to the results
            dissection.insert(0, token_res)

            # The json result to return
            json_result['content'] = dissection

            # Here we will analyze the pcap file and get the results as json
            print(json.dumps(json_result))
            return

        # ######################## End of API part ######################### #

        # DEPRECATED
        # elif (self.path == "/submit"):

        #     if os.fork():
        #         # close the socket right now(because the
        #         # requesthandler may do a shutdown(), which triggers a
        #         # SIGCHLD in the child process)
        #         self.connection.close()
        #         return

        #     parser = BytesFeedParser()
        #     ct = self.headers.get("Content-Type")
        #     if not ct.startswith("multipart/form-data;"):
        #         self.send_error(400)
        #         return

        #     parser.feed(bytes("Content-Type: %s\r\n\r\n" % ct, "ascii"))
        #     parser.feed(self.rfile.read(int(self.headers['Content-Length'])))
        #     msg = parser.close()

        #     # agree checkbox is selected
        #     for part in msg.get_payload():
        #         if isinstance(part, email.message.Message):
        #             disposition = part.get("content-disposition")
        #             if disposition and 'name="agree"' in disposition:
        #                 agree = True
        #                 break
        #     else:
        #         agree = False

        #     # urifilter checkbox is selected
        #     for part in msg.get_payload():
        #         if isinstance(part, email.message.Message):
        #             disposition = part.get("content-disposition")
        #             if disposition and 'name="urifilter"' in disposition:
        #                 urifilter = True
        #                 break
        #     else:
        #         urifilter = False

        #     # content of the regex box
        #     for part in msg.get_payload():
        #         if isinstance(part, email.message.Message):
        #             disposition = part.get("content-disposition")
        #             if disposition and 'name="regex"' in disposition:
        #                 regex = part.get_payload()
        #                 if not regex:
        #                     regex = None
        #                 break
        #     else:
        #         regex = None

        #     # profile radio buttons
        #     for part in msg.get_payload():
        #         if isinstance(part, email.message.Message):
        #             disposition = part.get("content-disposition")
        #             if disposition and 'name="profile"' in disposition:
        #                 profile = part.get_payload()
        #                 break
        #     else:
        #         profile = "client"

        #     # receive the pcap file
        #     for part in msg.get_payload():
        #         if isinstance(part, email.message.Message):
        #             disposition = part.get("content-disposition")
        #             if disposition and 'name="file"' in disposition:
        #                 mo = re.search('filename="([^"]*)"', disposition)

        #                 orig_filename = mo.group(1) if mo else None

        #                 timestamp = time.strftime("%y%m%d_%H%M%S")

        #                 pcap_file = os.path.join(
        #                         (DATADIR if agree else TMPDIR),
        #                         "%s_%04d.dump" % (timestamp, job_id)
        #                 )
        #                 self.log_message("uploading %s(urifilter=%r, regex=%r)", pcap_file, urifilter, regex)
        #                 with open(pcap_file, "wb") as fd:
        #                     # FIXME: using hidden API(._payload) because it seems that there is something broken with the encoding when getting the payload using .get_payload()
        #                     fd.write(part._payload.encode("ascii", errors="surrogateescape"))

        #                 break
        #     else:
        #         self.send_error(400)
        #         return

        #     self.send_response(200)
        #     self.send_header("Content-Type", "text/html;charset=utf-8")
        #     self.end_headers()

        #     out = UTF8Wrapper(self.wfile)

        #     self.wfile.flush()

        #     os.dup2(self.wfile.fileno(), sys.stdout.fileno())

        #     try:
        #         exceptions = []
        #         analysis.analyse_file_html(pcap_file, orig_filename, urifilter, exceptions, regex, profile)
        #         for tc in exceptions:
        #             self.log_message("exception in %s", type(tc).__name__, append=tc.exception)
        #     except pure_pcapy.PcapError:
        #         print("Bad file format!")

        #     shutdown()

        # If we didn't manage to bind the request
        else:
            self.send_error(404)
            return
Exemplo n.º 7
0
    def do_POST(self):

        # The job counter
        global job_id
        job_id += 1

        # ########################## ttproto API ########################### #

        # POST handler for the analyzer_testCaseAnalyze uri
        # It will allow users to analyze a pcap file corresponding to a TC
        #
        # \param pcap_file => The pcap file that we want to analyze
        # \param token => The token previously provided
        # \param testcase_id => The id of the corresponding test case
        # The pcap_file or the token is required, having both is also forbidden
        #
        if self.path == '/api/v1/analyzer_testCaseAnalyze':

            # Send the header
            self.send_response(200)
            self.send_header('Content-Type', 'application/json;charset=utf-8')
            self.end_headers()

            # Bind the stdout to the http output
            os.dup2(self.wfile.fileno(), sys.stdout.fileno())

            # Get the content type
            try:
                content_type = cgi.parse_header(self.headers['Content-Type'])
            except TypeError:
                self.api_error(
                    "Non empty POST datas and format of 'multipart/form-data' expected"
                )
                return

            # Get post values
            form = cgi.FieldStorage(
                fp=self.rfile,
                headers=self.headers,
                keep_blank_values=True,
                environ={
                    'REQUEST_METHOD': 'POST',
                    'CONTENT_TYPE': content_type[0]
                })

            # Check that we have the two values
            if any((
                len(form) != 2,
                'testcase_id' not in form,
                all((  # None of the two required => Error
                    'pcap_file' not in form,
                    'token' not in form
                )),
                all((  # Both of them => Error
                    'pcap_file' in form,
                    'token' in form
                ))
            )):
                self.api_error(
                    'Expected POST=([pcap_file={file}|token={text}], testcase_id={text})'
                )
                return

            # Get the test case and its informations
            testcase_id = form.getvalue('testcase_id')
            if not type(testcase_id) == str:
                self.api_error('The value of the testcase_id should be a string from text input')
                return

            # Try to get the test case
            try:
                test_case = get_test_cases(testcase_id)
            except FileNotFoundError:
                self.api_error('Test case %s not found' % testcase_id)
                return

            # Get the token
            token = form.getvalue('token')

            # Get analysis results from the token
            if token:

                # Just get the path
                pcap_path = os.path.join(
                    TMPDIR,
                    token + '.dump'
                )

            # Get analysis results from the pcap file
            else:

                # Check headers
                if any((
                    len(content_type) == 0,
                    content_type[0] is None,
                    content_type[0] != 'multipart/form-data'
                )):
                    self.api_error(
                        "POST format of 'multipart/form-data' expected, no file input 'pcap_file' found"
                    )
                    return

                # Get the same token or generate a new one
                token = get_token(token)

                # Get and check the pcap file entered
                pcap_file = form.getvalue('pcap_file')

                # Path to save the file
                pcap_path = os.path.join(
                    TMPDIR,
                    token + '.dump'
                )

                # Write the pcap file to a temporary destination
                try:
                    with open(pcap_path, 'wb') as f:
                        f.write(pcap_file)
                except:
                    self.api_error(
                        "Couldn't write the temporary file %s"
                        %
                        pcap_path
                    )
                    return

                # Get the dissection from analysis tool
                try:
                    dissection = Dissector(pcap_path).dissect()
                except pure_pcapy.PcapError:
                    self.api_error(
                        "Expected 'pcap_file' to be a non empty pcap file"
                    )
                except:
                    self.api_error(
                        "Couldn't read the temporary file %s"
                        %
                        pcap_path
                    )
                    return

                # Save the json dissection result into a file
                json_save = os.path.join(
                    TMPDIR,
                    token + '.json'
                )
                try:
                    with open(json_save, 'w') as f:
                        json.dump(dissection, f)
                except:
                    self.api_error("Couldn't write the json file")
                    return

            # Get the result of the analysis
            analysis_results = Analyzer('tat_coap').analyse(
                                pcap_path,
                                testcase_id
                            )

            self.log_message("Analysis result: " + str(analysis_results))

            # Error for some test cases that the analysis doesn't manage to get
            try:
                assert type(analysis_results[4]) is list
                if len(analysis_results[4]) != 0:
                    assert type(analysis_results[4][0]) is tuple
                assert type(analysis_results) == tuple
                assert len(analysis_results) == 6
                assert type(analysis_results[0]) == str
                assert type(analysis_results[1]) == str
                assert type(analysis_results[2]) == list
                assert type(analysis_results[3]) == str
                assert type(analysis_results[5]) == list
                for exception_tuple in analysis_results[5]:
                    assert type(exception_tuple) == tuple
                    assert len(exception_tuple) == 3
                    assert isinstance(exception_tuple[0], type)
                    assert isinstance(exception_tuple[1], Exception)
                    assert isinstance(exception_tuple[2], object)
                assert analysis_results[0] == test_case['tc_basic']['id']
            except AssertionError:
                self.api_error(
                    'Problem with the analyse of TC %s, wrong result received'
                    %
                    testcase_id
                )
                return

            # Only take the first
            verdict = OrderedDict()
            verdict['_type'] = 'verdict'
            verdict['verdict'] = analysis_results[1]
            verdict['description'] = analysis_results[3]
            verdict['review_frames'] = analysis_results[2]
            verdict['partial_verdicts'] = analysis_results[4]

            token_res = OrderedDict()
            token_res['_type'] = 'token'
            token_res['value'] = token

            # Prepare the result to return
            json_result = OrderedDict()
            json_result['_type'] = 'response'
            json_result['ok'] = True
            json_result['content'] = [
                token_res,
                test_case['tc_basic'],
                verdict
            ]
            self.log_message("Analysis response sent: " + str((analysis_results[4])))

            self.log_message("Analysis response sent: " + str(json.dumps(json_result)))

            # Here we will analyze the pcap file and get the results as json
            print(json.dumps(json_result))
            return



        # POST handler for the analyzer_allMightyAnalyze uri
        # It will allow users to analyze a pcap file without giving
        # a corresponding test case
        #
        # \param pcap_file => The pcap file that we want to analyze
        # \param token => The token previously provided
        # The pcap_file or the token is required, having both is also forbidden
        #
        elif self.path == '/api/v1/analyzer_allMightyAnalyze':

            # Send the header
            self.send_response(200)
            self.send_header('Content-Type', 'application/json;charset=utf-8')
            self.end_headers()

            # Bind the stdout to the http output
            os.dup2(self.wfile.fileno(), sys.stdout.fileno())

            # Not implemented for the moment
            self.api_error(
                "This method is not implemented yet, please come back later"
            )
            return

        # POST handler for the dissector_dissectFile uri
        # It will allow users to analyze a pcap file corresponding to a TC
        #
        # \param pcap_file => The pcap file that we want to dissect
        # \param protocol_selection => The protocol name
        #
        elif self.path == '/api/v1/dissector_dissectFile':

            # Send the header
            self.send_response(200)
            self.send_header('Content-Type', 'application/json;charset=utf-8')
            self.end_headers()

            # Bind the stdout to the http output
            os.dup2(self.wfile.fileno(), sys.stdout.fileno())

            # Get the content type
            try:
                content_type = cgi.parse_header(self.headers['Content-Type'])
            except TypeError:
                self.api_error(
                    "Non empty POST datas and format of 'multipart/form-data' expected"
                )
                return

            # Check headers
            if any((
                len(content_type) == 0,
                content_type[0] is None,
                content_type[0] != 'multipart/form-data'
            )):
                self.api_error(
                    "POST format of 'multipart/form-data' expected, no file input 'pcap_file' found"
                )
                return

            # Get post values
            form = cgi.FieldStorage(
                fp=self.rfile,
                headers=self.headers,
                environ={
                    'REQUEST_METHOD': 'POST',
                    'CONTENT_TYPE': content_type[0]
                })

            # Check the parameters passed
            if any((
                len(form) != 2,
                'pcap_file' not in form,
                'protocol_selection' not in form
            )):
                self.api_error(
                    'Expected POST=(pcap_file={file}, protocol_selection={text})'
                )
                return

            # Check the protocol_selection value
            protocol_selection = form.getvalue('protocol_selection')
            if not type(protocol_selection) == str:
                self.api_error('Expected protocol_selection post value to be a text (eq string)')
                return

            # In function of the protocol asked
            prot = get_protocol(protocol_selection)
            if prot is None:
                self.api_error('Unknown protocol %s' % protocol_selection)
                return

            # Generate a new token
            token = get_token()

            # Get the pcap file
            pcap_file = form.getvalue('pcap_file')

            # Path to save the file
            pcap_path = os.path.join(
                TMPDIR,
                token + '.dump'
            )

            # Write the pcap file to a temporary destination
            try:
                with open(pcap_path, 'wb') as f:
                    f.write(pcap_file)
            except:
                self.api_error("Couldn't write the temporary file")
                return

            # Prepare the result to return
            json_result = OrderedDict()
            json_result['_type'] = 'response'
            json_result['ok'] = True

            token_res = OrderedDict()
            token_res['_type'] = 'token'
            token_res['value'] = token

            # Get the dissection from dissector tool
            try:
                dissection = Dissector(pcap_path).dissect(eval(prot['name']))
            except TypeError as e:
                self.api_error('Dissector error: ' + str(e))
                return
            except pure_pcapy.PcapError:
                self.api_error(
                    "Expected 'pcap_file' to be a non empty pcap file"
                )
                return
            except:
                self.api_error(
                    "Couldn't read the temporary file %s and protocol is %s"
                    %
                    (
                        pcap_path,
                        prot['name']
                    )
                )
                return

            # Save the json dissection result into a file
            json_save = os.path.join(
                TMPDIR,
                token + '.json'
            )
            try:
                with open(json_save, 'w') as f:
                    json.dump(dissection, f)
            except:
                self.api_error("Couldn't write the json file")
                return

            # Add the token to the results
            dissection.insert(0, token_res)

            # The json result to return
            json_result['content'] = dissection

            # Here we will analyze the pcap file and get the results as json
            print(json.dumps(json_result))
            return

        # If we didn't manage to bind the request
        else:
            self.send_error(404)
            return
Exemplo n.º 8
0
class CoAPAnalyzerTestCase(unittest.TestCase):
    """
    Test class for the analyzer tool
    """

    # #################### Tests parameters #########################

    # Test env (only tat_coap for the moment)
    TEST_ENV = 'tat_coap'
    TEST_DIR = './tests/test_dumps/coap_core/'
    UNKNOWN_TEST_ENV = 'unknown'
    TEST_CASE_ID = 'TD_COAP_CORE_01'
    TEST_CASE_ID_WHICH_BUGGED_IN_THE_PAST = 'TD_COAP_CORE_24'
    UNKNOWN_TEST_CASE_ID = 'TD_COAP_CORE_42'

    # Create a struct checker object
    struct_validator = StructureValidator()

    # #################### Init and deinit functions #########################
    def setUp(self):
        """
            Initialize the analyzer instance
        """
        self.analyzer = Analyzer(self.TEST_ENV)

    # #################### Tests functions #########################

    # ##### __init__
    def test___init__(self):

        # Initialize the analyzer with a correct test env
        analyzer = Analyzer(self.TEST_ENV)

    def test___init___unknown_test_env(self):

        # Initialize the analyzer with an unknown test env
        with self.assertRaises(NotADirectoryError):
            analyzer = Analyzer(self.UNKNOWN_TEST_ENV)

    # ##### get_implemented_testcases
    def test_get_implemented_testcases(self):

        # Get implemented test cases and check their values
        tcs = self.analyzer.get_implemented_testcases()
        self.struct_validator.check_tc_from_analyzer(tcs)

    def test_get_implemented_testcases_with_none_value(self):

        # Get implemented test cases and check their values
        tcs = self.analyzer.get_implemented_testcases(None)
        self.struct_validator.check_tc_from_analyzer(tcs)

    def test_get_implemented_testcases_single_test_case(self):

        # Get implemented test cases and check their values
        tcs = self.analyzer.get_implemented_testcases([self.TEST_CASE_ID])
        self.struct_validator.check_tc_from_analyzer(tcs)
        self.assertEqual(len(tcs), 1)
        self.assertEqual(tcs[0][0], self.TEST_CASE_ID)

    def test_get_implemented_testcases_verbose_mode(self):

        # Get implemented test cases and check their values
        tcs = self.analyzer.get_implemented_testcases(verbose=True)
        self.struct_validator.check_tc_from_analyzer(tcs)

        # Check that they have the extra informations (the source code)
        for tc in tcs:
            self.assertGreater(len(tc[2]), 0)

    def test_get_implemented_testcases_single_test_case_which_bugged(self):

        if self.TEST_CASE_ID_WHICH_BUGGED_IN_THE_PAST:
            # Get implemented test cases and check their values
            tcs = self.analyzer.get_implemented_testcases(
                [self.TEST_CASE_ID_WHICH_BUGGED_IN_THE_PAST])
            self.struct_validator.check_tc_from_analyzer(tcs)
            self.assertEqual(len(tcs), 1)
            self.assertEqual(tcs[0][0],
                             self.TEST_CASE_ID_WHICH_BUGGED_IN_THE_PAST)

    def test_get_implemented_testcases_unknown_test_case(self):

        # Get implemented test cases and check their values
        with self.assertRaises(FileNotFoundError):
            tcs = self.analyzer.get_implemented_testcases(
                [self.UNKNOWN_TEST_CASE_ID])

    def test_get_implemented_testcases_str_instead_of_list(self):

        # Get implemented test cases and check their values
        with self.assertRaises(InputParameterError):
            tcs = self.analyzer.get_implemented_testcases(self.TEST_CASE_ID)

    # ##### analyse
    def test_analyse_basic_pass_PCAPs(self):
        dir = self.TEST_DIR
        print('looking for test dumps for testing the test cases: %s' % dir)
        for tc in self.analyzer.get_implemented_testcases():
            filename = path.join(dir, tc[0] + '_PASS.pcap')
            print('Testcase found %s , dump file %s for test exist: %s' %
                  (str(tc[0]), filename, path.isfile(filename)))
            # check if there's a pcap_pass_test for the testcase
            if path.isfile(filename):
                tc_name, verdict, rev_frames, log, partial_verdicts, exception_info = self.analyzer.analyse(
                    filename, tc[0])

                # I apologize to you future reader for the utterly ugly way of unpacking the exception info :)
                exc_str = ''
                if exception_info:
                    counter = 0
                    for i in exception_info:
                        counter += 1
                        exc_str += '\nException n:%s' % counter
                        exc_str += '\n\ttype: %s ' % i[0]
                        exc_str += '\n\texception: %s' % i[1]
                        exc_str += '\n\ttracelog: %s' % i[2]
                        exc_str += '\n'

                self.assertTrue(
                    verdict == 'pass',
                    msg='%s implementation got verdict: %s expected PASS \n '
                    'details: \n %s \n'
                    'errors: \n %s \n'
                    'logs: \n %s \n' %
                    (tc_name, str(verdict).upper(),
                     json.dumps(partial_verdicts, indent=4) if log else "",
                     exc_str if exc_str else "No exception registered", log))

                print('Testcase %s , got verdict: %s' %
                      (str(tc[0]), str(verdict).upper()))
Exemplo n.º 9
0
    def test___init___unknown_test_env(self):

        # Initialize the analyzer with an unknown test env
        with self.assertRaises(NotADirectoryError):
            analyzer = Analyzer(self.UNKNOWN_TEST_ENV)
Exemplo n.º 10
0
    def test___init__(self):

        # Initialize the analyzer with a correct test env
        analyzer = Analyzer(self.TEST_ENV)
Exemplo n.º 11
0
 def setUp(self):
     """
         Initialize the analyzer instance
     """
     self.analyzer = Analyzer(self.TEST_ENV)