Пример #1
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 = tm.get_message_from_xml(request.body)
    except Exception as ex:
        logger.debug('Unable to parse inbound message: %s', ex.message)
        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('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 != tm.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 = tm.StatusMessage(tm.generate_message_id(), taxii_message.message_id, status_type=tm.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
Пример #2
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
Пример #3
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())
Пример #4
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())
Пример #5
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
Пример #6
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 = tm.get_message_from_xml(request.body)
    except Exception as ex:
        logger.debug('Unable to parse inbound message: %s', ex.message)
        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('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 != tm.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 = tm.StatusMessage(tm.generate_message_id(), taxii_message.message_id, status_type=tm.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