def process_exception(self, request, exception):
        """
        Arguments:
            request - a Django request
            exception - An Exception
        Returns:
            None if the exception is not a StatusMessageException
            an HttpResponseTaxii if it is
        """

        if not isinstance(exception, StatusMessageException):
            return None  # This class only handles StatusMessageExceptions

        version = None

        a = request.META.get('HTTP_ACCEPT', None)
        if a:
            a = a.lower()
        if a not in ('application/xml', None):  # This application doesn't know how to handle this
            # print "accept: ", a
            r = HttpResponse()
            r.status_code = 406  # Unacceptable
            return r

        xta = request.META.get('HTTP_X_TAXII_ACCEPT', None)
        if xta is None:  # Can respond with whatever we want. try to use the X-TAXII-Content-Type header to pick
            xtct = request.META.get('HTTP_X_TAXII_CONTENT_TYPE', None)
            if xtct == VID_TAXII_XML_10:
                sm = exception.to_status_message_10()
                version = VID_TAXII_SERVICES_10
            else:  # Well, we tried - use TAXII XML 1.1 as a default
                sm = exception.to_status_message_11()
                version = VID_TAXII_SERVICES_11
        elif xta == VID_TAXII_XML_10:
            sm = exception.to_status_message_10()
            version = VID_TAXII_SERVICES_10
        elif xta == VID_TAXII_XML_11:
            sm = exception.to_status_message_11()
            version = VID_TAXII_SERVICES_11
        else:
            # For now, just pretend X-TAXII-Accept was TAXII 1.1
            # Not 100% sure what the right response is... HTTP Unacceptable?
            # Squash the exception argument and create a new one for unknown HTTP Accept?
            sm = exception.to_status_message_11()
            version = VID_TAXII_SERVICES_11

        response_headers = handlers.get_headers(version, request.is_secure())
        return handlers.HttpResponseTaxii(sm.to_xml(pretty_print=True), response_headers)
def service_router(request, path, do_validate=True):
    """
    Takes in a request, path, and TAXII Message,
    and routes the taxii_message to the Service Handler.
    """

    if request.method != 'POST':
        raise StatusMessageException('0', ST_BAD_MESSAGE, 'Request method was not POST!')

    xtct = request.META.get('HTTP_X_TAXII_CONTENT_TYPE', None)
    if not xtct:
        raise StatusMessageException('0', ST_BAD_MESSAGE, 'The X-TAXII-Content-Type Header was not present.')

    parse_tuple = xtct_map.get(xtct)
    if not parse_tuple:
        raise StatusMessageException('0', ST_BAD_MESSAGE, 'The X-TAXII-Content-Type Header is not supported.')

    if do_validate:
        msg = None  # None means no error, a non-None value means an error happened
        try:
            result = parse_tuple.validator.validate_string(request.body)
            if not result.valid:
                if settings.DEBUG is True:
                    msg = 'Request was not schema valid: %s' % [err for err in result.error_log]
                else:
                    msg = PV_ERR
        except XMLSyntaxError as e:
            if settings.DEBUG is True:
                msg = 'Request was not well-formed XML: %s' % str(e)
            else:
                msg = PV_ERR

        if msg is not None:
            raise StatusMessageException('0', ST_BAD_MESSAGE, msg)

    try:
        taxii_message = parse_tuple.parser(request.body)
    except tm11.UnsupportedQueryException as e:
        # TODO: Is it possible to give the real message id?
        # TODO: Is it possible to indicate which query aspects are supported?
        # This might require a change in how libtaxii works
        raise StatusMessageException('0',
                                     ST_UNSUPPORTED_QUERY)

    service = handlers.get_service_from_path(request.path)
    handler = service.get_message_handler(taxii_message)
    module_name, class_name = handler.handler.rsplit('.', 1)

    try:
        module = import_module(module_name)
        handler_class = getattr(module, class_name)
    except Exception as e:
        type, value, tb = sys.exc_info()
        raise type, ("Error importing handler: %s" % handler.handler, type, value), tb

    handler_class.validate_headers(request, taxii_message.message_id)
    handler_class.validate_message_is_supported(taxii_message)

    try:
        response_message = handler_class.handle_message(service, taxii_message, request)
    except StatusMessageException:
        raise  # The handler_class has intentionally raised this
    except Exception as e:  # Something else happened
        msg = "There was a failure while executing the message handler"
        if settings.DEBUG:  # Add the stacktrace
            msg += "\r\n" + traceback.format_exc()

        raise StatusMessageException(taxii_message.message_id,
                                     ST_FAILURE,
                                     msg)

    try:
        response_message.message_type
    except AttributeError as e:
        msg = "The message handler (%s) did not return a TAXII Message!" % handler_class
        if settings.DEBUG:
            msg += ("\r\n The returned value was: %s (class=%s)" %
                    (response_message, response_message.__class__.__name__))

        raise StatusMessageException(taxii_message.message_id,
                                     ST_FAILURE,
                                     msg)

    if response_message.__module__ == 'libtaxii.messages_11':
        vid = VID_TAXII_SERVICES_11
    elif response_message.__module__ == 'libtaxii.messages_10':
        vid = VID_TAXII_SERVICES_10
    else:
        raise ValueError("Unknown response message module")

    response_headers = handlers.get_headers(vid, request.is_secure())

    return handlers.HttpResponseTaxii(response_message.to_xml(pretty_print=True), response_headers)
Example #3
0
def service_router(request, path, do_validate=True):
    """
    Takes in a request, path, and TAXII Message,
    and routes the taxii_message to the Service Handler.
    """

    if request.method != 'POST':
        raise StatusMessageException('0', ST_BAD_MESSAGE,
                                     'Request method was not POST!')

    xtct = request.META.get('HTTP_X_TAXII_CONTENT_TYPE', None)
    if not xtct:
        raise StatusMessageException(
            '0', ST_BAD_MESSAGE,
            'The X-TAXII-Content-Type Header was not present.')

    parse_tuple = xtct_map.get(xtct)
    if not parse_tuple:
        raise StatusMessageException(
            '0', ST_BAD_MESSAGE,
            'The X-TAXII-Content-Type Header is not supported.')

    if do_validate:
        msg = None  # None means no error, a non-None value means an error happened
        try:
            result = parse_tuple.validator.validate_string(request.body)
            if not result.valid:
                if settings.DEBUG is True:
                    msg = 'Request was not schema valid: %s' % [
                        err for err in result.error_log
                    ]
                else:
                    msg = PV_ERR
        except XMLSyntaxError as e:
            if settings.DEBUG is True:
                msg = 'Request was not well-formed XML: %s' % str(e)
            else:
                msg = PV_ERR

        if msg is not None:
            raise StatusMessageException('0', ST_BAD_MESSAGE, msg)

    try:
        taxii_message = parse_tuple.parser(request.body)
    except tm11.UnsupportedQueryException as e:
        # TODO: Is it possible to give the real message id?
        # TODO: Is it possible to indicate which query aspects are supported?
        # This might require a change in how libtaxii works
        raise StatusMessageException('0', ST_UNSUPPORTED_QUERY)

    service = handlers.get_service_from_path(request.path)
    handler = service.get_message_handler(taxii_message)
    module_name, class_name = handler.handler.rsplit('.', 1)

    try:
        module = import_module(module_name)
        handler_class = getattr(module, class_name)
    except Exception as e:
        type, value, tb = sys.exc_info()
        raise type, ("Error importing handler: %s" % handler.handler, type,
                     value), tb

    handler_class.validate_headers(request, taxii_message.message_id)
    handler_class.validate_message_is_supported(taxii_message)

    try:
        response_message = handler_class.handle_message(
            service, taxii_message, request)
    except StatusMessageException:
        raise  # The handler_class has intentionally raised this
    except Exception as e:  # Something else happened
        msg = "There was a failure while executing the message handler"
        if settings.DEBUG:  # Add the stacktrace
            msg += "\r\n" + traceback.format_exc()

        raise StatusMessageException(taxii_message.message_id, ST_FAILURE, msg)

    try:
        response_message.message_type
    except AttributeError as e:
        msg = "The message handler (%s) did not return a TAXII Message!" % handler_class
        if settings.DEBUG:
            msg += ("\r\n The returned value was: %s (class=%s)" %
                    (response_message, response_message.__class__.__name__))

        raise StatusMessageException(taxii_message.message_id, ST_FAILURE, msg)

    if response_message.__module__ == 'libtaxii.messages_11':
        vid = VID_TAXII_SERVICES_11
    elif response_message.__module__ == 'libtaxii.messages_10':
        vid = VID_TAXII_SERVICES_10
    else:
        raise ValueError("Unknown response message module")

    response_headers = handlers.get_headers(vid, request.is_secure())

    return handlers.HttpResponseTaxii(
        response_message.to_xml(pretty_print=True), response_headers)