Example #1
0
def subscription_service(request):
    """Handles TAXII Subscription Service requests."""
    logger = logging.getLogger("TAXIIApplication.taxii.views.subscription_service")
    logger.debug('Entering subscription service')

    resp = handlers.validate_taxii_request(request)
    if resp: return resp # if validation failed, return the response

    try:
        taxii_message = tm_version.get_message_from_xml(request.body)
    except Exception as ex:
        logger.debug('Unable to parse inbound message: %s', str(ex))
        m = tm.StatusMessage(tm.generate_message_id(), '0', status_type=tm.ST_BAD_MESSAGE, message='Message received could not be parsed')
        return handlers.create_taxii_response(m, use_https=request.is_secure())

    logger.debug('Message received TAXII message with id [%s] and type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))

    if taxii_message.message_type != tm_version.MSG_MANAGE_FEED_SUBSCRIPTION_REQUEST:
        logger.info('TAXII message with id [%s] was not Subscription Managment request [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
        m = tm_version.StatusMessage(tm.generate_message_id(), taxii_message.message_id, status_type=tm.ST_FAILURE, message='Message sent to feed managment service did not have a feed_managmen_request message type')
        return handlers.create_taxii_response(m, use_https=request.is_secure())

    resp = handlers.feed_subscription_get_content(request, taxii_message)

    logger.debug("We send the response to the client")
    return resp
Example #2
0
def inbox_service(request, inbox_name):
    """Handles TAXII Inbox Service requests."""
    logger = logging.getLogger('yeti.taxii_services.views.inbox_service')
    logger.debug('Entering Inbox service')
    
    resp = handlers.validate_taxii_request(request)
    if resp: return resp # if validation failed, return the response
    
    try:
        taxii_message = tm11.get_message_from_xml(request.body)
    except Exception as ex:
        logger.debug('Unable to parse inbound message: %s', ex.message)
        m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_BAD_MESSAGE, message='Message received could not be parsed')
        return handlers.create_taxii_response(m, use_https=request.is_secure())
    
    logger.debug('Inbox [%s] received TAXII message with id [%s] and type [%s]', 
                 make_safe(inbox_name), make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
    
    if taxii_message.message_type != tm11.MSG_INBOX_MESSAGE:
        logger.info('TAXII message with id [%s] was not Inbox type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
        m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_FAILURE, message='Message sent to Inbox service did not have an inbox Message type')
        return handlers.create_taxii_response(m, use_https=request.is_secure())
    
    resp = handlers.inbox_add_content(request, inbox_name, taxii_message)
    return resp
Example #3
0
def poll_service(request):
    """Handles TAXII Poll Service requests."""
    logger = logging.getLogger("yeti.taxii_services.views.poll_service")
    logger.debug('Entering poll service')
    
    resp = handlers.validate_taxii_request(request)
    if resp: return resp # if validation failed, return the response
    
    try:
        taxii_message = tm11.get_message_from_xml(request.body)
    except tm11.UnsupportedQueryException as e:
        logger.debug('Unsupported query found in TAXII Message')
        m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_UNSUPPORTED_QUERY, message='The message used an unsupported query format')
        return handlers.create_taxii_response(m, use_https=request.is_secure())
    except Exception as ex:
        logger.debug('Unable to parse inbound message: %s', ex.message)
        m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_BAD_MESSAGE, message='Message received could not be parsed')
        return handlers.create_taxii_response(m, use_https=request.is_secure())
    
    logger.debug('Poll service received TAXII message with id [%s] and type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
    
    if taxii_message.message_type != tm11.MSG_POLL_REQUEST:
        logger.info('TAXII message with id [%s] was not Poll request [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
        m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_FAILURE, message='Message sent to Poll service did not have a poll request message type')
        return handlers.create_taxii_response(m, use_https=request.is_secure())    
    
    resp = handlers.poll_get_content(request, taxii_message)
    return resp
Example #4
0
def poll_get_content(request, taxii_message):
    """Returns a Poll response for a given Poll Request Message"""
    logger = logging.getLogger('taxii_services.utils.handlers.poll_get_content')
    logger.debug('Polling data from data collection [%s] - begin_ts: %s, end_ts: %s', 
                 make_safe(taxii_message.collection_name), taxii_message.exclusive_begin_timestamp_label, taxii_message.inclusive_end_timestamp_label)
    
    try:
        data_collection = DataCollection.objects.get(name=taxii_message.collection_name)
    except:
        logger.debug('Attempting to poll unknown data collection [%s]', make_safe(taxii_message.collection_name))
        m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_NOT_FOUND, message='Data collection does not exist [%s]' % (make_safe(taxii_message.collection_name)))
        return create_taxii_response(m, use_https=request.is_secure())
    
    # build query for poll results
    query_params = {}
    if taxii_message.exclusive_begin_timestamp_label:
        query_params['timestamp_label__gt'] = taxii_message.exclusive_begin_timestamp_label
    
    current_datetime = datetime.datetime.now(tzutc())
    if taxii_message.inclusive_end_timestamp_label and (taxii_message.inclusive_end_timestamp_label < current_datetime):
        query_params['timestamp_label__lte'] = taxii_message.inclusive_end_timestamp_label
    else:
        query_params['timestamp_label__lte'] = current_datetime
    
    if taxii_message.poll_parameters.content_bindings:
        query_params['content_binding__in'] = taxii_message.content_bindings
    
    content_blocks = data_collection.content_blocks.filter(**query_params).order_by('timestamp_label')
    logger.debug('Returned [%d] content blocks from data collection [%s]', len(content_blocks), make_safe(data_collection.name))
    
    # TAXII Poll Requests have exclusive begin timestamp label fields, while Poll Responses
    # have *inclusive* begin timestamp label fields. To satisfy this, we add one millisecond
    # to the Poll Request's begin timestamp label. 
    #
    # This will be addressed in future versions of TAXII
    inclusive_begin_ts = None
    if taxii_message.exclusive_begin_timestamp_label:
        inclusive_begin_ts = taxii_message.exclusive_begin_timestamp_label + datetime.timedelta(milliseconds=1)
    
    # build poll response
    poll_response_message = tm11.PollResponse(tm11.generate_message_id(), 
                                            taxii_message.message_id, 
                                            collection_name=data_collection.name, 
                                            exclusive_begin_timestamp_label=inclusive_begin_ts, 
                                            inclusive_end_timestamp_label=query_params['timestamp_label__lte'],
                                            record_count=tm11.RecordCount(len(content_blocks), False))
    
    if taxii_message.poll_parameters.response_type == tm11.RT_FULL:
        for content_block in content_blocks:
            cb = tm11.ContentBlock(tm11.ContentBinding(content_block.content_binding.binding_id), content_block.content, content_block.timestamp_label)
            
            if content_block.padding:
                cb.padding = content_block.padding
            
            poll_response_message.content_blocks.append(cb)
    
    return create_taxii_response(poll_response_message, use_https=request.is_secure())
Example #5
0
def inbox_add_content(request, inbox_name, taxii_message):
    """Adds content to inbox and associated data collections"""
    logger = logging.getLogger('taxii_services.utils.handlers.inbox_add_content')
    logger.debug('Adding content to inbox [%s]', make_safe(inbox_name))
    
    if len(taxii_message.destination_collection_names) > 0:
        logger.debug('Client specified a Destination Collection Name, which is not supported by YETI.')
        m = tm11.StatusMessage(tm11.generate_message_id(), 
                               taxii_message.message_id, 
                               status_type=tm11.ST_DESTINATION_COLLECTION_ERROR, 
                               message='Destination Collection Names are not allowed')
        return create_taxii_response(m, use_https=request.is_secure())
    
    try:
        inbox = Inbox.objects.get(name=inbox_name)
    except:
        logger.debug('Attempting to push content to unknown inbox [%s]', make_safe(inbox_name))
        m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_NOT_FOUND, message='Inbox does not exist [%s]' % (make_safe(inbox_name)))
        return create_taxii_response(m, use_https=request.is_secure())
    
    logger.debug('TAXII message [%s] contains [%d] content blocks', make_safe(taxii_message.message_id), len(taxii_message.content_blocks))
    for content_block in taxii_message.content_blocks:
        try:
            content_binding_id = ContentBindingId.objects.get(binding_id=content_block.content_binding)
        except:
            logger.debug('TAXII message [%s] contained unrecognized content binding [%s]', make_safe(taxii_message.message_id), make_safe(content_block.content_binding))
            continue # cannot proceed - move on to the next content block
            
        if content_binding_id not in inbox.supported_content_bindings.all():
            logger.debug('Inbox [%s] does not accept content with binding id [%s]', make_safe(inbox_name), make_safe(content_block.content_binding))
        else:
            c = ContentBlock()
            c.message_id = taxii_message.message_id
            c.content_binding = content_binding_id
            c.content = content_block.content
            
            if content_block.padding: 
                c.padding = content_block.padding
            
            if request.user.is_authenticated():
                c.submitted_by = request.user
            
            c.save()
            inbox.content_blocks.add(c) # add content block to inbox
            
            for data_collection in inbox.data_collections.all():
                if content_binding_id in data_collection.supported_content_bindings.all():
                    data_collection.content_blocks.add(c)
                    data_collection.save()
                else:
                    logger.debug('Inbox [%s] received data using content binding [%s] - '
                                 'associated data collection [%s] does not support this binding.',
                                 make_safe(inbox_name), make_safe(content_block.content_binding), make_safe(data_collection.name))
    
    inbox.save()
    m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type = tm11.ST_SUCCESS)
    return create_taxii_response(m, use_https=request.is_secure())
Example #6
0
    def log(self, event):
        # converts from conpot log format to STIX compatible xml
        stix_package = self.stix_transformer.transform(event)

        # wrapping the stix message in a TAXII envelope
        content_block = ContentBlock(libtaxii.CB_STIX_XML_11,
                                     stix_package.encode('utf-8'))
        inbox_message = InboxMessage(message_id=generate_message_id(),
                                     content_blocks=[content_block])
        inbox_xml = inbox_message.to_xml()

        # the actual call to the TAXII web service
        response = self.client.callTaxiiService2(self.host, self.inbox_path,
                                                 libtaxii.VID_TAXII_XML_11,
                                                 inbox_xml, self.port)
        response_message = libtaxii.get_message_from_http_response(
            response, '0')

        if response_message.status_type != libtaxii.messages.ST_SUCCESS:
            logger.error(
                'Error while transmitting message to TAXII server: {0}'.format(
                    response_message.message))
            return False
        else:
            return True
Example #7
0
def main():
    parser = scripts.get_base_parser("Poll Fulfillment Client", path="/services/query_example/")
    parser.add_argument("--collection", dest="collection", default="default_queryable", help="Data Collection that this Fulfillment request applies to. Defaults to 'default_queryable'.")
    parser.add_argument("--result_id", dest="result_id", required=True, help="The result_id being requested.")
    parser.add_argument("--result_part_number", dest="result_part_number", default=1, help="The part number being requested. Defaults to '1'.")

    args = parser.parse_args()

    poll_fulf_req = tm11.PollFulfillmentRequest(message_id=tm11.generate_message_id(),
                              collection_name=args.collection,
                              result_id=args.result_id,
                              result_part_number=args.result_part_number)
    
    print "Request:\n"
    if args.xml_output is False:
        print poll_fulf_req.to_text()
    else:
        print poll_fulf_req.to_xml(pretty_print=True)
    
    client = scripts.create_client(args)
    resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, poll_fulf_req.to_xml(pretty_print=True), args.port)
    r = t.get_message_from_http_response(resp, '0')
    
    print "Response:\n"
    if args.xml_output is False:
        print r.to_text()
    else:
        print r.to_xml(pretty_print=True)
Example #8
0
def main():
    parser = argparse.ArgumentParser(description="Inbox Client")
    parser.add_argument("--host", dest="host", default="localhost", help="Host where the Inbox Service is hosted. Defaults to localhost.")
    parser.add_argument("--port", dest="port", default="8080", help="Port where the Inbox Service is hosted. Defaults to 8080.")
    parser.add_argument("--path", dest="path", default="/services/inbox/default/", help="Path where the Inbox Service is hosted. Defaults to /services/inbox/default/.")
    parser.add_argument("--content-binding", dest="content_binding", default=t.CB_STIX_XML_10, help="Content binding of the Content Block to send. Defaults to %s" % t.CB_STIX_XML_10 )
    parser.add_argument("--content-file", dest="content_file", default=stix_watchlist, help="Content of the Content Block to send. Defaults to a STIX watchlist.")

    args = parser.parse_args()

    if args.content_file is stix_watchlist:
        c = StringIO.StringIO(stix_watchlist)
    else:
        c = open(args.content_file, 'r')
    
    cb = tm11.ContentBlock(tm11.ContentBinding(args.content_binding), c.read())
    c.close()

    inbox_message = tm11.InboxMessage(message_id = tm11.generate_message_id(), content_blocks=[cb])
    inbox_xml = inbox_message.to_xml()

    print "Inbox Message: \r\n", inbox_xml
    client = tc.HttpClient()
    client.setProxy('noproxy')
    resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, inbox_xml, args.port)
    response_message = t.get_message_from_http_response(resp, '0')
    print "Response Message: \r\n", response_message.to_xml()
 def create_request_message(self, args):
     poll_fulf_req = tm11.PollFulfillmentRequest(
         message_id=tm11.generate_message_id(),
         collection_name=args.collection,
         result_id=args.result_id,
         result_part_number=args.result_part_number)
     return poll_fulf_req
Example #10
0
    def push(s, collection, content, path="/"):

        msg_id=tm11.generate_message_id()
        content = tm11.ContentBlock(tm11.ContentBinding(t.CB_STIX_XML_11), 
                                    content)

        # Create inbox request
        req = tm11.InboxMessage(message_id=msg_id,
                                destination_collection_names=[collection],
                                content_blocks=[content])

        # Convert to XML for request body
        req_xml = req.to_xml()

        # Create HTTP client
        client = tc.HttpClient()
        client.setProxy('noproxy') 

        # Call TAXII service, using the body
        resp = client.callTaxiiService2(s.host, path, t.VID_TAXII_XML_11,
                                        req_xml, s.port)

        # Get response
        resp = t.get_message_from_http_response(resp, '0')

        if resp.status_type != tm11.ST_SUCCESS:
            print("%s: %s" % (resp.status_type, resp.message))
Example #11
0
def main():
    parser = scripts.get_base_parser("Inbox Client", path="/services/inbox/default/")
    parser.add_argument("--content-binding", dest="content_binding", default=t.CB_STIX_XML_11, help="Content binding of the Content Block to send. Defaults to %s" % t.CB_STIX_XML_11 )
    parser.add_argument("--subtype", dest="subtype", default=None, help="The subtype of the Content Binding. Defaults to None")
    parser.add_argument("--content-file", dest="content_file", default=stix_watchlist, help="Content of the Content Block to send. Defaults to a STIX watchlist.")
    
    args = parser.parse_args()

    if args.content_file is stix_watchlist:
        c = StringIO.StringIO(stix_watchlist)
    else:
        c = open(args.content_file, 'r')
    
    cb = tm11.ContentBlock(tm11.ContentBinding(args.content_binding), c.read())
    c.close()
    if args.subtype is not None:
        cb.subtypes.append(args.subtype)

    inbox_message = tm11.InboxMessage(message_id = tm11.generate_message_id(), content_blocks=[cb])
    inbox_xml = inbox_message.to_xml(pretty_print=True)

    print "Inbox Message: \r\n", inbox_xml
    client = scripts.create_client(args)
    resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, inbox_xml, args.port)
    response_message = t.get_message_from_http_response(resp, '0')
    print "Response Message: \r\n", response_message.to_xml(pretty_print=True)
Example #12
0
    def create_request_message(self, args):
        try:
            if args.begin_ts:
                begin_ts = dateutil.parser.parse(args.begin_ts)
                if not begin_ts.tzinfo:
                    raise ValueError
            else:
                begin_ts = None

            if args.end_ts:
                end_ts = dateutil.parser.parse(args.end_ts)
                if not end_ts.tzinfo:
                    raise ValueError
            else:
                end_ts = None
        except ValueError:
            print("Unable to parse timestamp value. Timestamp should include both date and time " \
                  "information along with a timezone or UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). " \
                  "Aborting poll.")
            sys.exit()

        create_kwargs = {'message_id': tm11.generate_message_id(),
                         'collection_name': args.collection,
                         'exclusive_begin_timestamp_label': begin_ts,
                         'inclusive_end_timestamp_label': end_ts}

        if args.subscription_id:
            create_kwargs['subscription_id'] = args.subscription_id
        else:
            create_kwargs['poll_parameters'] = tm11.PollRequest.PollParameters()
        poll_req = tm11.PollRequest(**create_kwargs)
        return poll_req
Example #13
0
 def create_fulfillment_request(collection, result_id, part_number):
     return PollFulfillmentRequest(
         message_id=generate_message_id(),
         collection_name=collection,
         result_id=result_id,
         result_part_number=part_number,
     )
Example #14
0
    def create_request_message(self, args):
        try:
            if args.begin_ts:
                begin_ts = dateutil.parser.parse(args.begin_ts)
                if not begin_ts.tzinfo:
                    raise ValueError
            else:
                begin_ts = None

            if args.end_ts:
                end_ts = dateutil.parser.parse(args.end_ts)
                if not end_ts.tzinfo:
                    raise ValueError
            else:
                end_ts = None
        except ValueError:
            print("Unable to parse timestamp value. Timestamp should include both date and time " \
                  "information along with a timezone or UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). " \
                  "Aborting poll.")
            sys.exit()

        create_kwargs = {
            'message_id': tm11.generate_message_id(),
            'collection_name': args.collection,
            'exclusive_begin_timestamp_label': begin_ts,
            'inclusive_end_timestamp_label': end_ts
        }

        if args.subscription_id:
            create_kwargs['subscription_id'] = args.subscription_id
        else:
            create_kwargs['poll_parameters'] = tm11.PollRequest.PollParameters(
            )
        poll_req = tm11.PollRequest(**create_kwargs)
        return poll_req
Example #15
0
    def handle_manage_collection_subscription_request(s, msg):

        print(msg.to_xml(True))
        
        # Create poll response.
        msg_id=tm11.generate_message_id()
        cn=msg.collection_name
        resp_id=msg.message_id
        action=msg.action
        query=msg.subscription_parameters.query
        subs_id=msg.subscription_id
        inbox=msg.push_parameters.inbox_address

        if query:
            print(query.to_xml())

        if action == tm11.ACT_SUBSCRIBE:

            subs_id = s.subscribe(collection=cn, query=query, 
                                  inbox=inbox)

            si = tm11.ManageCollectionSubscriptionResponse.SubscriptionInstance(
                subscription_id=subs_id,
                status=tm11.SS_ACTIVE
            )

            resp = tm11.ManageCollectionSubscriptionResponse(
                message_id=msg_id,
                collection_name=cn,
                in_response_to=resp_id,
                subscription_instances=[si]
            )

            # Send response
            s.respond(resp.to_xml())
Example #16
0
 def _get_inbox_message(self, cb):
     return tm11.InboxMessage(
         message_id=tm11.generate_message_id(),
         destination_collection_names=[self._collection_name],
         subscription_information=self._subscription_information,
         content_blocks=[cb],
     )
Example #17
0
def envio_informacion(data_feed, host, path, port):
    #Given the host, port and path of a TAXII client we sent the data_feed to that client.
    logger = logging.getLogger('TAXIIApplication.rest.tasks.envio_informacion')
    logger.debug('Get the subscription methods')
    logger.debug('The parameters are: ')
    logger.debug('Host: ' + host)
    logger.debug('Path: ' + path)
    logger.debug('Port: ' + str(port))
    logger.debug('Data Feed name:' + data_feed.name)

    content_blocks = data_feed.content_blocks

    content = []
    for content_block in content_blocks.all():
	cb = tm11.ContentBlock(tm11.ContentBinding(content_block.content_binding.binding_id), content_block.content)
        content.append(cb)

    subInfo = tm11.InboxMessage.SubscriptionInformation(collection_name = data_feed.title + ' ' + ORGANIZATION_NAME, subscription_id = 1)
    inbox_message = tm11.InboxMessage(message_id = tm11.generate_message_id(), content_blocks=content, subscription_information = subInfo)

    inbox_xml = inbox_message.to_xml()
    logger.debug('The message to be sent is: '+ inbox_xml)

    client = tc.HttpClient()
    client.setProxy('noproxy')

    resp = client.callTaxiiService2(host, path, t.VID_TAXII_XML_10, inbox_xml, port)
    response_message = t.get_message_from_http_response(resp, '0')
    logger.debug('The response message was: ' + response_message.to_xml())
Example #18
0
def push_11(taxii_client, stix_file_doc):
    if stix_file_doc.version.startswith('2'):
        try:
            content = stix_file_doc.get_slide_12()
        except Exception as e:
            traceback.print_exc()
            raise e
    else:
        with open(stix_file_doc.origin_path, 'r', encoding='utf-8') as fp:
            content = fp.read()

    auth_credentials_dict, cert_fd, key_fd = _get_auth_credentials_dict(
        taxii_client)
    taxii_client._client.set_auth_credentials(auth_credentials_dict)
    try:
        subscription_information = tm11.SubscriptionInformation(
            collection_name=taxii_client._collection_name,
            subscription_id='subscripiton_id')
        cb = tm11.ContentBlock(const.CB_STIX_XML_11, content)
        im = tm11.InboxMessage(
            message_id=tm11.generate_message_id(),
            destination_collection_names=[taxii_client._collection_name],
            subscription_information=subscription_information,
            content_blocks=[cb])

        http_resp = taxii_client._client.call_taxii_service2(
            taxii_client._address,
            taxii_client._path,
            const.VID_TAXII_XML_11,
            im.to_xml(),
            port=taxii_client._port)
        taxii_message = libtaxii.get_message_from_http_response(
            http_resp, im.message_id)
        if taxii_message.status_type != 'SUCCESS':
            raise Exception('taxii_message.status_type is not SUCCESS')
        return 'Success !!'
    except Exception as e:
        traceback.print_exc()
        raise e
    finally:
        if cert_fd is not None:
            try:
                os.close(cert_fd)
            except Exception:
                pass
        if key_fd is not None:
            try:
                os.close(key_fd)
            except Exception:
                pass
        if 'cert_file' in auth_credentials_dict:
            try:
                os.remove(auth_credentials_dict['cert_file'])
            except Exception:
                pass
        if 'key_file' in auth_credentials_dict:
            try:
                os.remove(auth_credentials_dict['key_file'])
            except Exception:
                pass
Example #19
0
 def create_fulfillment_request(collection, result_id, part_number):
     return PollFulfillmentRequest(
         message_id=generate_message_id(),
         collection_name=collection,
         result_id=result_id,
         result_part_number=part_number,
     )
Example #20
0
    def get_discovery_service(
            self, taxii_message: DiscoveryRequest) -> DiscoveryResponse:
        """
        Handle discovery request.
        Args:
            taxii_message: The discovery request message.

        Returns:
            The discovery response.
        """

        if taxii_message.message_type != MSG_DISCOVERY_REQUEST:
            raise ValueError('Invalid message, invalid Message Type')

        discovery_service_url = self.get_url()

        discovery_response = DiscoveryResponse(generate_message_id(),
                                               taxii_message.message_id)

        for instance in self.service_instances:
            instance_type = instance['type']
            instance_path = instance['path']
            taxii_service_instance = ServiceInstance(
                instance_type,
                'urn:taxii.mitre.org:services:1.1',
                'urn:taxii.mitre.org:protocol:http:1.0',
                f'{discovery_service_url}/{instance_path}',
                ['urn:taxii.mitre.org:message:xml:1.1'],
                available=True)
            discovery_response.service_instances.append(taxii_service_instance)

        return discovery_response
Example #21
0
    def get_collections(
        self, taxii_message: CollectionInformationRequest
    ) -> CollectionInformationResponse:
        """
        Handle collection management request.
        Args:
            taxii_message: The collection request message.

        Returns:
            The collection management response.
        """
        taxii_feeds = list(self.collections.keys())
        url = self.get_url()

        if taxii_message.message_type != MSG_COLLECTION_INFORMATION_REQUEST:
            raise ValueError('Invalid message, invalid Message Type')

        collection_info_response = CollectionInformationResponse(
            generate_message_id(), taxii_message.message_id)

        for feed in taxii_feeds:
            collection_info = CollectionInformation(
                feed, f'{feed} Data Feed', ['urn:stix.mitre.org:xml:1.1.1'],
                True)
            polling_instance = PollingServiceInstance(
                'urn:taxii.mitre.org:protocol:http:1.0',
                f'{url}/taxii-poll-service',
                ['urn:taxii.mitre.org:message:xml:1.1'])
            collection_info.polling_service_instances.append(polling_instance)
            collection_info_response.collection_informations.append(
                collection_info)

        return collection_info_response
Example #22
0
 def inner(request, *args, **kwargs):
     if not taxii_services.settings.AUTH_REQUIRED:
         return func(request, *args, **kwargs)
     elif request.user.is_authenticated():
         return func(request, *args, **kwargs)
     
     m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm.ST_UNAUTHORIZED, message='You are not authorized to access this URL.')
     return handlers.create_taxii_response(m)
Example #23
0
    def handle_discovery_request(s, msg):
        
        # Create poll response.
        resp = tm11.DiscoveryResponse(message_id=tm11.generate_message_id(),
                                      in_response_to=msg.message_id)

        # Send response
        s.respond(resp.to_xml())
Example #24
0
    def poll_11(self):
        auth_credentials_dict = self._get_auth_credentials_dict()
        self._client.set_auth_credentials(auth_credentials_dict)
        try:
            poll_parameters = tm11.PollParameters()
            poll_request = tm11.PollRequest(
                message_id=tm11.generate_message_id(),
                collection_name=self._collection_name,
                exclusive_begin_timestamp_label=self._start,
                inclusive_end_timestamp_label=self._end,
                poll_parameters=poll_parameters,
            )
            last_requested = datetime.datetime.now(pytz.utc)

            http_resp = self._client.call_taxii_service2(
                self._address,
                self._path,
                const.VID_TAXII_XML_11,
                poll_request.to_xml(),
                port=self._port)

            taxii_message = libtaxii.get_message_from_http_response(
                http_resp, poll_request.message_id)

            try:
                if taxii_message.content_blocks is None:
                    return 0
            except AttributeError:
                return 0

            count = 0
            for cb in taxii_message.content_blocks:
                _, stix_file_path = tempfile.mkstemp(suffix='.xml')
                with open(stix_file_path, 'wb+') as fp:
                    fp.write(cb.content)
                try:
                    from ctirs.core.stix.regist import regist
                    if self._community is not None:
                        regist(stix_file_path, self._community, self._via)
                    count += 1
                except BaseException:
                    traceback.print_exc()

            self._taxii.last_requested = last_requested
            self._taxii.save()

            return count
        finally:
            if 'cert_file' in auth_credentials_dict:
                try:
                    os.remove(auth_credentials_dict['cert_file'])
                except Exception:
                    pass
            if 'key_file' in auth_credentials_dict:
                try:
                    os.remove(auth_credentials_dict['key_file'])
                except Exception:
                    pass
 def test_status_message_03(self):
     sm03 = tm11.StatusMessage(
             message_id = 'SM03', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_DESTINATION_COLLECTION_ERROR, #Required
             status_detail = {'ACCEPTABLE_DESTINATION': ['Collection1','Collection2']}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm03)
Example #26
0
    def handle_collection_information_request(s, msg):
        
        # Create poll response.
        msg_id=tm11.generate_message_id()
        resp = tm11.CollectionInformationResponse(message_id=msg_id,
                                      in_response_to=msg.message_id)

        # Send response
        s.respond(resp.to_xml())
 def test_status_message_04(self):
     sm04 = tm11.StatusMessage(
             message_id = 'SM04', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_INVALID_RESPONSE_PART, #Required
             status_detail = {'MAX_PART_NUMBER': 4}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm04)
 def test_status_message_06(self):
     sm06 = tm11.StatusMessage(
             message_id = 'SM06', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_PENDING, #Required
             status_detail = {'ESTIMATED_WAIT': 900, 'RESULT_ID': 'Result1', 'WILL_PUSH': False}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm06)
 def test_status_message_07(self):
     sm07 = tm11.StatusMessage(
             message_id = 'SM07', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_RETRY, #Required
             status_detail = {'ESTIMATED_WAIT': 900}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm07)
 def test_status_message_08(self):
     sm08 = tm11.StatusMessage(
             message_id = 'SM08', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_UNSUPPORTED_MESSAGE_BINDING, #Required
             status_detail = {'SUPPORTED_BINDING': [t.VID_TAXII_XML_10, t.VID_TAXII_XML_11]}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm08)
 def test_status_message_09(self):
     sm09 = tm11.StatusMessage(
             message_id = 'SM09', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_UNSUPPORTED_CONTENT_BINDING, #Required
             status_detail = {'SUPPORTED_CONTENT': ['%s>%s,%s' % (tm11.ContentBinding, 'subtype1','subtype2'), t.CB_STIX_XML_101]}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm09)
 def test_status_message_02(self):
     sm02 = tm11.StatusMessage(
             message_id = 'SM02', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_SUCCESS, #Required
             status_detail = None, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm02)
 def test_status_message_05(self):
     sm05 = tm11.StatusMessage(
             message_id = 'SM05', #Required
             in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
             status_type = tm11.ST_NOT_FOUND, #Required
             status_detail = {'ITEM': 'Collection1'}, #Required/optional depending on Status Type. See spec for details
             message = None# Optional
     )
     round_trip_message(sm05)
Example #34
0
def validate_taxii_headers(request, request_message_id):
    """
    Validates TAXII headers. It returns a response containing a TAXII
    status message if the headers were not valid. It returns None if 
    the headers are valid.
    """
    # Make sure the required headers are present
    missing_required_headers = set(DICT_REQUIRED_TAXII_HTTP_HEADERS).difference(set(request.META))
    if missing_required_headers:
        required_headers = ', '.join(DICT_REVERSE_DJANGO_NORMALIZATION[x] for x in missing_required_headers)
        msg = "Required headers not present: [%s]" % (required_headers) 
        m = tm11.StatusMessage(tm11.generate_message_id(), request_message_id, status_type=tm11.ST_FAILURE, message=msg)
        return create_taxii_response(m, use_https=request.is_secure())

    #For headers that exist, make sure the values are supported
    for header in DICT_TAXII_HTTP_HEADER_VALUES:
        if header not in request.META:
            continue

        header_value = request.META[header]
        supported_values = DICT_TAXII_HTTP_HEADER_VALUES[header]
        
        if header_value not in supported_values:
            msg = 'The value of %s is not supported. Supported values are %s' % (DICT_REVERSE_DJANGO_NORMALIZATION[header], supported_values)
            m = tm11.StatusMessage(tm11.generate_message_id(), request_message_id, status_type=tm11.ST_FAILURE, message=msg)
            return create_taxii_response(m, use_https=request.is_secure())
    
    # Check to make sure the specified protocol matches the protocol used
    if request.META[DJANGO_HTTP_HEADER_X_TAXII_PROTOCOL] == t.VID_TAXII_HTTPS_10:
        header_proto = 'HTTPS'
    elif request.META[DJANGO_HTTP_HEADER_X_TAXII_PROTOCOL] == t.VID_TAXII_HTTP_10:
        header_proto = 'HTTP'
    else:
        header_proto = 'unknown'
    
    request_proto = 'HTTPS' if request.is_secure() else 'HTTP' # Did the request come over HTTP or HTTPS?
    
    if header_proto != request_proto:
        msg = 'Protocol value incorrect. TAXII header specified %s but was sent over %s' % (header_proto, request_proto)
        m = tm11.StatusMessage(tm11.generate_message_id(), request_message_id, status_type=tm11.ST_FAILURE, message=msg)
        return create_taxii_response(m, use_https=request.is_secure())
    
    # At this point, the header values are known to be good.
    return None
Example #35
0
    def poll_11(self):
        #request xml作成
        poll_parameters = tm11.PollParameters()
        poll_request = tm11.PollRequest(
            message_id=tm11.generate_message_id(),
            collection_name=self._collection_name,
            exclusive_begin_timestamp_label=self._start,
            inclusive_end_timestamp_label=self._end,
            poll_parameters=poll_parameters,
        )
        last_requested = datetime.datetime.now(pytz.utc)
        
        #from xml.dom.minidom import parseString
        #print( parseString(poll_request.to_xml()).toprettyxml(encoding='utf-8'))

        #request
        http_resp = self._client.call_taxii_service2(
            self._address,
            self._path,
            const.VID_TAXII_XML_11,
            poll_request.to_xml(),
            port=self._port)
        
        #taxii_message抽出
        taxii_message = libtaxii.get_message_from_http_response(http_resp, poll_request.message_id)
        
        #content_blocks が None or 存在しない場合は登録ししない
        try:
            if taxii_message.content_blocks is None:
                return 0
        except AttributeError:
            return 0

        #content_blocksごとに登録処理
        count = 0
        for cb in taxii_message.content_blocks:
            #stixファイルを一時ファイルに出力
            _,stix_file_path = tempfile.mkstemp(suffix='.xml')
            with open(stix_file_path,'wb+') as fp:
                #cb.contentがstixの中身
                fp.write(cb.content)
            #登録
            try:
                from ctirs.core.stix.regist import regist
                if self._community is not None:
                    regist(stix_file_path,self._community,self._via)
                count += 1
            except:
                #taxiiの場合は途中で失敗しても処理を継続する
                traceback.print_exc()
            
        #last_requested更新
        self._taxii.last_requested = last_requested
        self._taxii.save()
        
        return count
 def test_status_message_01(self):
     sm01 = tm11.StatusMessage(
         message_id = 'SM01', #Required
         in_response_to = tm11.generate_message_id(), #Required, should be the ID of the message that this is in response to
         status_type = tm11.ST_SUCCESS, #Required
         status_detail = {'custom_status_detail_name': 'Custom status detail value', 
                         'Custom_detail_2': ['this one has', 'multiple values']}, #Required depending on Status Type. See spec for details
         message = 'This is a test message'#Optional
     )
     round_trip_message(sm01)
Example #37
0
    def process_exception(self, request, exception):
        logger = logging.getLogger('yeti.taxii_services.middleware.ProcessExceptionMiddleware.process_exception')
        logger.exception('Server error occured')
    
        if request.path.startswith('/services'):
            logger.debug('Returning ST_FAILURE message')
            m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_FAILURE, message='An internal server error occurred')
            return handlers.create_taxii_response(m, handlers.HTTP_STATUS_OK, use_https=request.is_secure())

        resp = HttpResponseServerError()
        resp.body = 'A server error occurred'
        return resp
    def test_nonexistent_service_url(self):
        """
        Sends an Inbox Message to an invalid URL.
        Should get back a 404.
        """
        # TODO: Why do we actually need a payload to return a 404? Shouldn't an
        # empty message to a non-existent URL also return a 404?
        inbox_msg = tm11.InboxMessage(tm11.generate_message_id())
        path = '/Services/PathThatShouldNotWork/'

        response = self.post(path, inbox_msg.to_xml())
        self.assertEqual(404, response.status_code)
Example #39
0
def main():
    parser = scripts.get_base_parser("Discovery Client", path="/services/discovery/")
    args = parser.parse_args()

    discovery_req = tm11.DiscoveryRequest(message_id=tm11.generate_message_id())
    discovery_req_xml = discovery_req.to_xml(pretty_print=True)

    print "Discovery Request: \r\n", discovery_req_xml
    client = scripts.create_client(args)
    resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_11, discovery_req_xml, args.port)
    response_message = t.get_message_from_http_response(resp, '0')
    print "Response Message: \r\n", response_message.to_xml(pretty_print=True)
Example #40
0
def taxii_inbox(config, dest, stix_package=None, src=None, crits_id=None):
    """inbox a stix package via taxii"""
    if src and crits_id:
        # check whether this has already been ingested
        sync_state = config["db"].get_object_id(src, dest, crits_id=crits_id)
        if sync_state and sync_state.get("crits_id", None):
            if config["daemon"]["debug"]:
                config["logger"].debug(
                    log.log_messages["object_already_ingested"].format(
                        src_type="crits",
                        src_id=crits_id,
                        src=src,
                        dest_type="edge",
                        dest=dest,
                        dest_id=sync_state["edge_id"],
                    )
                )
            return True
    if stix_package:
        stixroot = lxml.etree.fromstring(stix_package.to_xml())
        client = tc.HttpClient()
        client.setUseHttps(config["edge"]["sites"][dest]["taxii"]["ssl"])
        client.setAuthType(client.AUTH_BASIC)
        client.setAuthCredentials(
            {
                "username": config["edge"]["sites"][dest]["taxii"]["user"],
                "password": config["edge"]["sites"][dest]["taxii"]["pass"],
            }
        )
        message = tm11.InboxMessage(message_id=tm11.generate_message_id())
        content_block = tm11.ContentBlock(content_binding=t.CB_STIX_XML_11, content=stixroot)
        if config["edge"]["sites"][dest]["taxii"]["collection"] != "system.Default":
            message.destination_collection_names = [config["edge"]["sites"][dest]["taxii"]["collection"]]
        message.content_blocks.append(content_block)
        if config["daemon"]["debug"]:
            config["logger"].debug(log.log_messages["open_session"].format(type_="taxii", host=dest))
        taxii_response = client.callTaxiiService2(
            config["edge"]["sites"][dest]["host"],
            config["edge"]["sites"][dest]["taxii"]["path"],
            t.VID_TAXII_XML_11,
            message.to_xml(),
            port=config["edge"]["sites"][dest]["taxii"]["port"],
        )
        if taxii_response.code != 200 or taxii_response.msg != "OK":
            success = False
            config["logger"].error(
                log.log_messages["inbox_error"].format(type_="taxii", host=dest, msg=taxii_response.msg)
            )
        else:
            success = True
            if config["daemon"]["debug"]:
                config["logger"].debug(log.log_messages["inbox_success"].format(type_="taxii", host=dest))
        return success
Example #41
0
    def test_nonexistent_service_url(self):
        """
        Sends an Inbox Message to an invalid URL.
        Should get back a 404.
        """
        # TODO: Why do we actually need a payload to return a 404? Shouldn't an
        # empty message to a non-existent URL also return a 404?
        inbox_msg = tm11.InboxMessage(tm11.generate_message_id())
        path = '/Services/PathThatShouldNotWork/'

        response = self.post(path, inbox_msg.to_xml())
        self.assertEqual(404, response.status_code)
Example #42
0
def taxii_inbox(config, dest, stix_package=None, src=None, crits_id=None):
    '''inbox a stix package via taxii'''
    if src and crits_id:
        # check whether this has already been ingested
        sync_state = config['db'].get_object_id(src, dest, crits_id=crits_id)
        if sync_state and sync_state.get('crits_id', None):
            if config['daemon']['debug']:
                config['logger'].debug(
                    log.log_messages['object_already_ingested'].format(
                        src_type='crits', src_id=crits_id, src=src, 
                        dest_type='edge', dest=dest, dest_id=sync_state['edge_id']))
            return(True)
    if stix_package:
        stixroot = lxml.etree.fromstring(stix_package.to_xml())
        client = tc.HttpClient()
        client.setUseHttps(config['edge']['sites'][dest]['taxii']['ssl'])
        client.setAuthType(client.AUTH_BASIC)
        client.setAuthCredentials(
            {'username':
             config['edge']['sites'][dest]['taxii']['user'],
             'password':
             config['edge']['sites'][dest]['taxii']['pass']})
        message = tm11.InboxMessage(message_id=tm11.generate_message_id())
        content_block = tm11.ContentBlock(content_binding=t.CB_STIX_XML_11,
                                          content=stixroot)
        if config['edge']['sites'][dest]['taxii']['collection'] != \
           'system.Default':
            message.destination_collection_names = \
                [config['edge']['sites'][dest]['taxii']['collection']]
        message.content_blocks.append(content_block)
        if config['daemon']['debug']:
            config['logger'].debug(
                log.log_messages[
                    'open_session'].format(type_='taxii', host=dest))
        taxii_response = client.callTaxiiService2(
            config['edge']['sites'][dest]['host'],
            config['edge']['sites'][dest]['taxii']['path'],
            t.VID_TAXII_XML_11, message.to_xml(),
            port=config['edge']['sites'][dest]['taxii']['port'])
        if taxii_response.code != 200 or taxii_response.msg != 'OK':
            success = False
            config['logger'].error(
                log.log_messages[
                    'inbox_error'].format(type_='taxii', host=dest,
                                          msg=taxii_response.msg))
        else:
            success = True
            if config['daemon']['debug']:
                config['logger'].debug(
                    log.log_messages['inbox_success'].format(type_='taxii',
                                                              host=dest))
        return(success)
Example #43
0
def taxii_inbox(config, dest, stix_package=None, src=None, crits_id=None):
    '''inbox a stix package via taxii'''
    if src and crits_id:
        # check whether this has already been ingested
        sync_state = config['db'].get_object_id(src, dest, crits_id=crits_id)
        if sync_state and sync_state.get('crits_id', None):
            if config['daemon']['debug']:
                config['logger'].debug(
                    log_.log_messages['object_already_ingested'].format(
                        src_type='crits', src_id=crits_id, src=src, 
                        dest_type='edge', dest=dest, dest_id=sync_state['edge_id']))
            return(True)
    if stix_package:
        stixroot = lxml.etree.fromstring(stix_package.to_xml())
        client = tc.HttpClient()
        client.setUseHttps(config['edge']['sites'][dest]['taxii']['ssl'])
        client.setAuthType(client.AUTH_BASIC)
        client.setAuthCredentials(
            {'username':
             config['edge']['sites'][dest]['taxii']['user'],
             'password':
             config['edge']['sites'][dest]['taxii']['pass']})
        message = tm11.InboxMessage(message_id=tm11.generate_message_id())
        content_block = tm11.ContentBlock(content_binding=t.CB_STIX_XML_11,
                                          content=stixroot)
        if config['edge']['sites'][dest]['taxii']['collection'] != \
           'system.Default':
            message.destination_collection_names = \
                [config['edge']['sites'][dest]['taxii']['collection']]
        message.content_blocks.append(content_block)
        if config['daemon']['debug']:
            config['logger'].debug(
                log_.log_messages[
                    'open_session'].format(type_='taxii', host=dest))
        taxii_response = client.callTaxiiService2(
            config['edge']['sites'][dest]['host'],
            config['edge']['sites'][dest]['taxii']['path'],
            t.VID_TAXII_XML_11, message.to_xml(),
            port=config['edge']['sites'][dest]['taxii']['port'])
        if taxii_response.code != 200 or taxii_response.msg != 'OK':
            success = False
            config['logger'].error(
                log_.log_messages[
                    'inbox_error'].format(type_='taxii', host=dest,
                                          msg=taxii_response.msg))
        else:
            success = True
            if config['daemon']['debug']:
                config['logger'].debug(
                    log_.log_messages['inbox_success'].format(type_='taxii',
                                                              host=dest))
        return(success)
Example #44
0
def validate_taxii_request(request):
    """Validates the broader request parameters and request type for a TAXII exchange"""
    logger = logging.getLogger("taxii_services.utils.handlers.validate_taxii_request")
    logger.debug('Attempting to validate request')
    
    if request.method != 'POST':
        logger.info('Request was not POST - returning error')
        m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_FAILURE, message='Request must be POST')
        return create_taxii_response(m, use_https=request.is_secure())
    
    header_validation_resp = validate_taxii_headers(request, '0') # TODO: What to use for request message id?
    if header_validation_resp: # If response is not None an validation of the TAXII headers failed
        logger.info('TAXII header validation failed for reason [%s]', make_safe(header_validation_resp.message))
        return header_validation_resp
    
    if len(request.body) == 0:
        m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_FAILURE, message='No POST data')
        logger.info('Request had a body length of 0. Returning error.')
        return create_taxii_response(m, use_https=request.is_secure())
    
    logger.debug('Request was valid')
    return None
Example #45
0
    def push_11(self, stix_file_doc):
        self.debug_print('>>> push_11: enter')
        # stix_file_doc の versionが 2.0 ならスライド
        if stix_file_doc.version == '2.0':
            try:
                content = stix_file_doc.get_slide_1_x()
            except Exception as e:
                traceback.print_exc()
                raise e

        else:
            with open(stix_file_doc.origin_path, 'r', encoding='utf-8') as fp:
                content = fp.read()

        # Subscription Information xml作成
        subscription_information = tm11.SubscriptionInformation(
            collection_name=self._collection_name,
            subscription_id='subscripiton_id')
        cb = tm11.ContentBlock(const.CB_STIX_XML_11, content)
        im = tm11.InboxMessage(
            message_id=tm11.generate_message_id(),
            destination_collection_names=[self._collection_name],
            subscription_information=subscription_information,
            content_blocks=[cb])
        try:
            # push
            self._address = '10.0.3.100'
            # self.debug_print('>>> push_11: self._address:%s' %(self._address))
            # self.debug_print('>>> push_11: self._path:%s' %(self._path))
            # self.debug_print('>>> push_11: self._port:%d' %(self._port))
            # self.debug_print('>>> push_11: self._collection_name:%s' %(self._collection_name))
            # self.debug_print('>>> push_11: verify_server:%s' %(str(self._client.verify_server)))
            # self.debug_print('>>> push_11: use_https:%s' %(str(self._client.use_https)))
            http_resp = self._client.call_taxii_service2(
                self._address,
                self._path,
                const.VID_TAXII_XML_11,
                im.to_xml(),
                port=self._port)
            taxii_message = libtaxii.get_message_from_http_response(
                http_resp, im.message_id)
            if taxii_message.status_type != 'SUCCESS':
                self.debug_print('taxii_message.status_type is not SUCCESS')
                self.debug_print(taxii_message.to_xml(pretty_print=True))
                raise Exception('taxii_message.status_type is not SUCCESS')
        except Exception as e:
            traceback.print_exc()
            self.debug_print(e)
            raise e
Example #46
0
def discovery_service(request):
    """Handles TAXII Discovery Service requests"""
    logger = logging.getLogger('yeti.taxii_services.views.discovery_service')
    logger.debug('Entering discovery service')
    
    resp = handlers.validate_taxii_request(request)
    if resp: return resp # if validation fails, return the response
    
    try:
        taxii_message = tm11.get_message_from_xml(request.body)
    except Exception as ex:
        logger.debug('Unable to parse inbound message: %s', ex.message)
        m = tm11.StatusMessage(tm11.generate_message_id(), '0', status_type=tm11.ST_BAD_MESSAGE, message='Message received could not be parsed')
        return handlers.create_taxii_response(m, use_https=request.is_secure())
    
    logger.debug('Discovery service received TAXII message with id [%s] and type [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
    
    if taxii_message.message_type != tm11.MSG_DISCOVERY_REQUEST:
        logger.info('TAXII message with id [%s] was not Discovery request [%s]', make_safe(taxii_message.message_id), make_safe(taxii_message.message_type))
        m = tm11.StatusMessage(tm11.generate_message_id(), taxii_message.message_id, status_type=tm11.ST_FAILURE, message='Message sent to discovery service did not have a discovery request message type')
        return handlers.create_taxii_response(m, use_https=request.is_secure())

    resp = handlers.discovery_get_services(request, taxii_message)
    return resp
    def gen_post(self, msg_type, xml):
        content_block = tm11.ContentBlock(tm11.ContentBinding(Client.BINDING_STIX), xml)

        if msg_type.lower() == 'inbox':
            post = tm11.InboxMessage(tm11.generate_message_id())
            post.content_blocks.append(content_block)
            post.message = Client.CLIENT_MSG

            if self.subscription:
                post.subscription_id = self.subscription

            if self.collection:
                post.destination_collection_names.append(self.collection)

            return post
Example #48
0
def main():
    parser = argparse.ArgumentParser(description="Poll Client")
    parser.add_argument("--host", dest="host", default="localhost", help="Host where the Poll Service is hosted. Defaults to localhost.")
    parser.add_argument("--port", dest="port", default="8080", help="Port where the Poll Service is hosted. Defaults to 8080.")
    parser.add_argument("--path", dest="path", default="/services/poll/", help="Path where the Poll Service is hosted. Defaults to /services/poll/.")
    parser.add_argument("--feed", dest="feed", default="default", help="Data Feed to poll. Defaults to 'default'.")
    parser.add_argument("--begin_timestamp", dest="begin_ts", default=None, help="The begin timestamp (format: YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm) for the poll request. Defaults to None.")
    parser.add_argument("--end_timestamp", dest="end_ts", default=None, help="The end timestamp (format: YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm) for the poll request. Defaults to None.")
    parser.add_argument("--content-binding", dest="content_binding", default= t.CB_STIX_XML_10, help="Content binding of the Content Block to send. Defaults to %s" % t.CB_STIX_XML_10 )

    args = parser.parse_args()

    try:
        if args.begin_ts:
            begin_ts = dateutil.parser.parse(args.begin_ts)
            if not begin_ts.tzinfo:
                raise ValueError
        else:
            begin_ts = None

        if args.end_ts:
            end_ts = dateutil.parser.parse(args.end_ts)
            if not end_ts.tzinfo:
                raise ValueError
        else:
            end_ts = None
    except ValueError:
        print "Unable to parse timestamp value. Timestamp should include both date and time information along with a timezone or UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). Aborting poll."
        sys.exit()

    poll_req = tm11.PollRequest(message_id=tm11.generate_message_id(),
                                 collection_name = args.feed,
                                  exclusive_begin_timestamp_label=begin_ts,
                                  inclusive_end_timestamp_label=end_ts,
                                  subscription_id='1')
    
    poll_req_xml = poll_req.to_xml()
    print "Poll Request: \r\n", poll_req_xml
    client = tc.HttpClient()
    resp = client.callTaxiiService2(args.host, args.path, t.VID_TAXII_XML_10, poll_req_xml, args.port)
    response_message = t.get_message_from_http_response(resp, '0')
    print "Response Message: \r\n", response_message.to_xml()
    
    message = tm11.get_message_from_xml(response_message.to_xml())
    
    
    
    response_message.
Example #49
0
    def create_request_message(self, args):
        if args.content_file is self.stix_watchlist:
            data = self.stix_watchlist
        else:
            with open(args.content_file, 'r') as f:
                data = f.read()

        cb = tm11.ContentBlock(tm11.ContentBinding(args.content_binding), data)
        if args.subtype is not None:
            cb.content_binding.subtype_ids.append(args.subtype)

        inbox_message = tm11.InboxMessage(message_id=tm11.generate_message_id(), content_blocks=[cb])
        if args.dcn:
            inbox_message.destination_collection_names.append(args.dcn)

        return inbox_message
Example #50
0
    def handle_inbox_message(s, msg):

        # Process each content block
        for cb in msg.content_blocks:

            content = cb.content

            for collection in msg.destination_collection_names:
                
                s.received(content, collection)

        resp = tm11.StatusMessage(message_id=tm11.generate_message_id(),
                                  in_response_to=msg.message_id,
                                  status_type=tm11.ST_SUCCESS)

        # Respond
        s.respond(resp.to_xml())
Example #51
0
    def indicators(self,
                   collection_name,
                   starttime=(datetime.now(tzutc()) - timedelta(hours=1)),
                   endtime=datetime.now(tzutc()),
                   subscription_id=None):
        delivery_params = tm11.DeliveryParameters(VID_TAXII_HTTP_10,
                                                  self.remote,
                                                  VID_TAXII_XML_11)
        """
        poll_params = tm11.PollParameters(response_type=RT_COUNT_ONLY,
            #content_bindings=[tm11.ContentBinding(CB_STIX_XML_11)], 
            delivery_parameters=delivery_params
            )
        """
        poll_params = tm11.PollRequest.PollParameters()
        poll_req = tm11.PollRequest(message_id=tm11.generate_message_id(),
                                    collection_name=collection_name,
                                    exclusive_begin_timestamp_label=starttime,
                                    inclusive_end_timestamp_label=endtime,
                                    poll_parameters=poll_params,
                                    subscription_id=subscription_id)

        logger.debug('TAXII collection poll request: {}'.format(
            poll_req.to_xml(pretty_print=True)))

        poll_req_xml = poll_req.to_xml()
        http_resp = self.client.call_taxii_service2(self.up.hostname,
                                                    self.up.path,
                                                    VID_TAXII_XML_11,
                                                    poll_req_xml, self.up.port)
        taxii_message = t.get_message_from_http_response(
            http_resp, poll_req.message_id)

        logger.debug('TAXII collection poll response: {}'.format(
            taxii_message.to_xml(pretty_print=True)))

        if taxii_message.message_type == MSG_STATUS_MESSAGE:
            if taxii_message.status_type == ST_SUCCESS:
                logger.info(
                    'TAXII polled successfully but returned no results')
                return []
            raise RuntimeError('TAXII polling failed: {} - {}'.format(
                taxii_message.status_type, taxii_message.message))

        return self._parse_taxii_content(taxii_message.content_blocks)
Example #52
0
    def poll(s, path="/", collection="default", query=None, 
                     begin_ts=None, end_ts=None):
    
        if query != None:
            query=s.create_query(query)
            poll_params=tm11.PollRequest.PollParameters(query=query)
        else:
            poll_params=tm11.PollRequest.PollParameters()
            
        # Create poll request
        poll_req = tm11.PollRequest(message_id=tm11.generate_message_id(),
                                    collection_name=collection,
                                    exclusive_begin_timestamp_label=begin_ts,
                                    inclusive_end_timestamp_label=end_ts,
                                    poll_parameters=poll_params)
            
        # Convert to XML for request body
        poll_req_xml = poll_req.to_xml(True)

        # Create HTTP client
        client = tc.HttpClient()
        client.setProxy('noproxy') 

        # Call TAXII service, using the body
        resp = client.callTaxiiService2(s.host, path, 
                                        t.VID_TAXII_XML_11,
                                        poll_req_xml, s.port)
        
        # Get response
        resp = t.get_message_from_http_response(resp, '0')
            
        pkgs = []

        # Process each content block
        for cb in resp.content_blocks:
            
            content = cb.content

            # Parse the payload, should be a STIX document.
            package = STIXPackage.from_xml(StringIO.StringIO(content))

            pkgs.append(package)
            
        return resp.inclusive_end_timestamp_label, pkgs
Example #53
0
    def create_poll_request(collection,
                            subscription_id=None,
                            begin_timestamp=None,
                            end_timestamp=None):
        """Create a poll request message using supplied parameters."""

        request_kwargs = dict(
            message_id=generate_message_id(),
            collection_name=collection,
            exclusive_begin_timestamp_label=begin_timestamp,
            inclusive_end_timestamp_label=end_timestamp,
        )

        if subscription_id:
            request_kwargs['subscription_id'] = subscription_id
        else:
            request_kwargs['poll_parameters'] = PollRequest.PollParameters()

        return PollRequest(**request_kwargs)
Example #54
0
    def perform_discovery(path="/"):

        # Create discovery request
        req = tm11.DiscoveryRequest(message_id=tm11.generate_message_id())
        
        # Convert to XML for request body
        req_xml = req.to_xml()
        
        # Create HTTP client
        client = tc.HttpClient()
        client.setProxy('noproxy') 
        
        # Call TAXII service, using the body
        resp = client.callTaxiiService2(host, path, t.VID_TAXII_XML_11,
                                        req_xml, port)

        # Get response
        resp = t.get_message_from_http_response(resp, '0')
        
        print(resp.to_xml())
Example #55
0
    def subscribe(s, path="/", collection="default", query=None,
                  inbox="http://localhost:8888"):

        if query != None:
            query = s.create_query(query)
        else:
            query = None

        params = tm11.SubscriptionParameters(query=query)

        deliv = tm11.PushParameters(
            inbox_protocol=t.VID_TAXII_HTTP_10,
            inbox_address=inbox,
            delivery_message_binding=t.VID_TAXII_XML_11)

        # Create request
        msg_id=tm11.generate_message_id()
        req = tm11.ManageCollectionSubscriptionRequest(
            message_id=msg_id,
            collection_name=collection,
            action=tm11.ACT_SUBSCRIBE,
            subscription_parameters=params,
            push_parameters=deliv
        )

        # Convert to XML for request body
        req_xml = req.to_xml()
        
        # Create HTTP client
        client = tc.HttpClient()
        client.setProxy('noproxy') 

        # Call TAXII service, using the body
        resp = client.callTaxiiService2(s.host, path, t.VID_TAXII_XML_11,
                                        req_xml, s.port)

        # Get response
        resp = t.get_message_from_http_response(resp, '0')

        print(resp.to_xml())
Example #56
0
    def create_poll_request(self):
        """Create a poll request message using supplied parameters."""
        try:
            if self._begin_ts:
                begin_ts = dateutil.parser.parse(self._begin_ts)
                if not begin_ts.tzinfo:
                    raise ValueError
            else:
                begin_ts = None

            if self._end_ts:
                end_ts = dateutil.parser.parse(self._end_ts)
                if not end_ts.tzinfo:
                    raise ValueError
            else:
                end_ts = None

        except ValueError:
            self._logger.error(
                "Unable to parse timestamp value. Timestamp should include " +
                "both date and time information along with a timezone or " +
                "UTC offset (e.g., YYYY-MM-DDTHH:MM:SS.ssssss+/-hh:mm). " +
                "Aborting poll.")
            sys.exit()

        request_kwargs = {
            'message_id': generate_message_id(),
            'collection_name': self._collection,
            'exclusive_begin_timestamp_label': begin_ts,
            'inclusive_end_timestamp_label': end_ts,
        }

        if self._subscription_id:
            request_kwargs['subscription_id'] = self._subscription_id
        else:
            request_kwargs['poll_parameters'] = PollRequest.PollParameters()

        return PollRequest(**request_kwargs)
Example #57
0
    def perform_manage_collection_subscription(path="/", act="status",
                                               collection="default"):
        
        if act == "subscribe":
            action = tm11.ACT_SUBSCRIBE
        elif act == "unsubscribe":
            action = tm11.ACT_UNSUBSCRIBE
        elif act == "pause":
            action = tm11.ACT_PAUSE
        elif act == "resume":
            action = tm11.ACT_RESUME
        elif act == "status":
            action = tm11.ACT_STATUS
        else:
            print("Need a subscription action I recognise")
            sys.exit(1)

        # Create request
        msg_id=tm11.generate_message_id()
        req = tm11.ManageCollectionSubscriptionRequest(message_id=msg_id,
                                                       collection_name=collection,
                                                       action=action)

        # Convert to XML for request body
        req_xml = req.to_xml()

        # Create HTTP client
        client = tc.HttpClient()
        client.setProxy('noproxy') 

        # Call TAXII service, using the body
        resp = client.callTaxiiService2(host, path, t.VID_TAXII_XML_11,
                                        req_xml, port)

        # Get response
        resp = t.get_message_from_http_response(resp, '0')

        print(resp.to_xml())
Example #58
0
    def do_POST(s):

        # Get the HTTP bdoy
        varLen = int(s.headers['Content-Length'])
        data = s.rfile.read(varLen)

        # Parse body as TAXII message.
        msg = tm11.get_message_from_xml(data)

        # If it's a poll request, handle it.
        if type(msg) == tm11.PollRequest:
            s.handle_poll_request(msg)
            return

        if type(msg) == tm11.InboxMessage:
            s.handle_inbox_message(msg)
            return

        if type(msg) == tm11.DiscoveryRequest:
            s.handle_discovery_request(msg)
            return

        if type(msg) == tm11.CollectionInformationRequest:
            s.handle_collection_information_request(msg)
            return

        if type(msg) == tm11.ManageCollectionSubscriptionRequest:
            s.handle_manage_collection_subscription_request(msg)
            return

        # Sorry, I only handle inbox and poll requests.

        resp = tm11.StatusMessage(message_id=tm11.generate_message_id(),
                                  in_response_to=msg.message_id,
                                  status_type=tm11.ST_FAILURE,
                                  message="Your request type not supported.")
        s.respond(resp.to_xml())
Example #59
0
    def handle_poll_request(s, msg):

        collection = msg.collection_name
        query = msg.poll_parameters.query
        begin = msg.exclusive_begin_timestamp_label
        end = msg.inclusive_end_timestamp_label

        # Start constructing the content block list
        cbs = []

        def handle(content, file):

            print("Adding %s..." % file)
    
            # Create content block.
            cb = tm11.ContentBlock(tm11.ContentBinding(t.CB_STIX_XML_11), 
                                   content)

            # Append content block to list.
            cbs.append(cb)

        print("Building response...")

        latest = s.get_matching(collection, begin, end, query, handle)

        print("Done")

        # Create poll response.
        resp = tm11.PollResponse(message_id=tm11.generate_message_id(),
                                 in_response_to=msg.message_id,
                                 collection_name=msg.collection_name,
                                 inclusive_end_timestamp_label=latest,
                                 content_blocks=cbs,
                                 more=False)

        # Send response
        s.respond(resp.to_xml())
Example #60
0
    def _poll_taxii_11(self, args):
        '''Poll a TAXII 1.1 feed and return a generator over the content blocks found.
        
        Arguments:
            args - A dictionary of arguments.
        
        '''

        app = args.get('app')
        cert_file = args.get('cert_file')
        key_file = args.get('key_file')
        username = args.get('username')
        password = args.get('password')

        if app and cert_file and key_file:
            cert_file_path = make_splunkhome_path(
                ["etc", "apps", app, "auth", cert_file])
            key_file_path = make_splunkhome_path(
                ["etc", "apps", app, "auth", key_file])

            if not (os.path.exists(cert_file_path)
                    and os.path.exists(key_file_path)):
                logger.info(
                    "Certificate not found - falling back to AUTH_BASIC.")
                cert_file_path = key_file_path = None
        else:
            logger.info(
                "Certificate information incomplete - falling back to AUTH_BASIC."
            )
            cert_file_path = key_file_path = None

        client = tc.HttpClient()
        client.set_use_https(args.get('use_ssl'))

        # Add proxy parameters if present.
        if 'proxy' in args:
            client.set_proxy(args['proxy'])

        if cert_file_path and key_file_path and username:
            logger.info("Auth Type: AUTH_CERT_BASIC")
            client.set_auth_type(tc.HttpClient.AUTH_CERT_BASIC)
            client.set_auth_credentials({
                'username': username,
                'password': password,
                'cert_file': cert_file_path,
                'key_file': key_file_path
            })
        elif cert_file_path and key_file_path:
            logger.info("Auth Type: AUTH_CERT")
            client.set_auth_type(tc.HttpClient.AUTH_CERT)
            client.set_auth_credentials({
                'cert_file': cert_file_path,
                'key_file': key_file_path
            })
        else:
            logger.info("Auth Type: AUTH_BASIC")
            client.set_auth_type(tc.HttpClient.AUTH_BASIC)
            client.set_auth_credentials({
                'username': username,
                'password': password
            })

        poll_request = tm11.PollRequest(
            tm11.generate_message_id(),
            collection_name=args.get('collection'),
            exclusive_begin_timestamp_label=args.get('earliest'),
            #inclusive_end_timestamp_label=args.get('latest'),
            poll_parameters=tm11.PollParameters())

        poll_xml = poll_request.to_xml()

        http_resp = client.call_taxii_service2(args.get('url'),
                                               args.get('service'),
                                               tm11.VID_TAXII_XML_11,
                                               poll_xml,
                                               port=args.get('port'))

        taxii_message = libtaxii.get_message_from_http_response(
            http_resp, poll_request.message_id)
        if http_resp.getcode() == 200:
            if hasattr(taxii_message, 'content_blocks'):
                return taxii_message.to_xml()
            else:
                raise TaxiiHandlerException(
                    'Exception when polling TAXII feed (no content returned): %s'
                    % self._clean_taxii_message(taxii_message))
        else:
            raise TaxiiHandlerException(
                'Exception when polling TAXII feed: %s' %
                self._clean_taxii_message(taxii_message))