def get_message_from_urllib_addinfourl(http_response, in_response_to): """ This function should not be called by libtaxii users directly. """ taxii_content_type = http_response.info().getheader('X-TAXII-Content-Type') response_message = http_response.read() if taxii_content_type is None: # Treat it as a Failure Status Message, per the spec message = [] header_dict = http_response.info().dict.iteritems() for k, v in header_dict: message.append(k + ': ' + v + '\r\n') message.append('\r\n') message.append(response_message) m = ''.join(message) return tm11.StatusMessage(message_id='0', in_response_to=in_response_to, status_type=ST_FAILURE, message=m) elif taxii_content_type == VID_TAXII_XML_10: # It's a TAXII XML 1.0 message return tm10.get_message_from_xml(response_message) elif taxii_content_type == VID_TAXII_XML_11: # It's a TAXII XML 1.1 message return tm11.get_message_from_xml(response_message) elif taxii_content_type == VID_CERT_EU_JSON_10: return tm10.get_message_from_json(response_message) else: raise ValueError('Unsupported X-TAXII-Content-Type: %s' % taxii_content_type) return None
def get_message_from_urllib2_httperror(http_response, in_response_to): """ This function should not be called by libtaxii users directly. """ info = http_response.info() if hasattr(info, 'getheader'): taxii_content_type = info.getheader('X-TAXII-Content-Type') _, params = cgi.parse_header(info.getheader('Content-Type')) else: taxii_content_type = info.get('X-TAXII-Content-Type') _, params = cgi.parse_header(info.get('Content-Type')) encoding = params.get('charset', 'utf-8') response_message = http_response.read() if taxii_content_type is None: m = str(http_response) + '\r\n' + str( http_response.info()) + '\r\n' + response_message return tm11.StatusMessage(message_id='0', in_response_to=in_response_to, status_type=ST_FAILURE, message=m) elif taxii_content_type == VID_TAXII_XML_10: # It's a TAXII XML 1.0 message return tm10.get_message_from_xml(response_message, encoding) elif taxii_content_type == VID_TAXII_XML_11: # It's a TAXII XML 1.1 message return tm11.get_message_from_xml(response_message, encoding) elif taxii_content_type == VID_CERT_EU_JSON_10: return tm10.get_message_from_json(response_message, encoding) else: raise ValueError('Unsupported X-TAXII-Content-Type: %s' % taxii_content_type)
def get_message_from_httplib_http_response(http_response, in_response_to): """ This function should not be called by libtaxii users directly. """ if hasattr(http_response, 'getheader'): taxii_content_type = http_response.getheader('X-TAXII-Content-Type') _, params = cgi.parse_header(http_response.getheader('Content-Type')) else: taxii_content_type = http_response.get('X-TAXII-Content-Type') _, params = cgi.parse_header(http_response.get('Content-Type')) encoding = params.get('charset', 'utf-8') response_message = http_response.read() if taxii_content_type is None: # Treat it as a Failure Status Message, per the spec message = [] header_tuples = http_response.getheaders() for k, v in header_tuples: message.append(k + ': ' + v + '\r\n') message.append('\r\n') message.append(response_message) m = ''.join(message) return tm11.StatusMessage(message_id='0', in_response_to=in_response_to, status_type=ST_FAILURE, message=m) elif taxii_content_type == VID_TAXII_XML_10: # It's a TAXII XML 1.0 message return tm10.get_message_from_xml(response_message, encoding) elif taxii_content_type == VID_TAXII_XML_11: # It's a TAXII XML 1.1 message return tm11.get_message_from_xml(response_message, encoding) else: raise ValueError('Unsupported X-TAXII-Content-Type: %s' % taxii_content_type)
def handle_message(cls, inbox_service, inbox_message, django_request): """ """ collections = inbox_service.validate_destination_collection_names( None, # Inbox 1.0 doesn't have a DCN inbox_message.message_id) # Store certain information about this Inbox Message in the database for bookkeeping inbox_message_db = models.InboxMessage.from_inbox_message_10( inbox_message, django_request, received_via=inbox_service) inbox_message_db.save() saved_blocks = 0 for content_block in inbox_message.content_blocks: inbox_support_info = inbox_service.is_content_supported( content_block.content_binding) if inbox_support_info.is_supported is False: continue cls.save_content_block(content_block) saved_blocks += 1 # Update the Inbox Message model with the number of ContentBlocks that were saved inbox_message_db.content_blocks_saved = saved_blocks inbox_message_db.save() # Create and return a Status Message indicating success status_message = tm11.StatusMessage( message_id=generate_message_id(), in_response_to=inbox_message.message_id, status_type=ST_SUCCESS) return status_message
def to_status_message_11(self): """ Creates a TAXII 1.1 Status Message based on the properties of this object """ sm = tm11.StatusMessage(message_id=generate_message_id(), in_response_to=self.in_response_to, extended_headers=self.extended_headers, status_type=self.status_type, status_detail=self.status_detail, message=self.message) return sm
def handle_message(cls, service, request): collections = service.validate_destination_collection_names( request.destination_collection_names, request.message_id) inbox_message = service.server.persistence.create_inbox_message( inbox_message_to_inbox_message_entity(request, service_id=service.id, version=11)) for content_block in request.content_blocks: is_supported = service.is_content_supported( content_block.content_binding, version=11) # FIXME: is it correct to skip unsupported content blocks? # 3.2 Inbox Exchange # version1.1/TAXII_Services_Specification.pdf if not is_supported: log.warning("Content binding is not supported: {}".format( content_block.content_binding)) continue supporting_collections = [] for collection in collections: if collection.is_content_supported( content_block.content_binding): supporting_collections.append(collection) if len(supporting_collections) == 0 and not is_supported: # There's nothing to add this content block to log.warning( "No collection that support binding {} were found".format( content_block.content_binding)) continue block = content_block_to_content_block_entity(content_block, version=11) service.server.persistence.create_content( block, collections=supporting_collections, service_id=service.id, inbox_message_id=inbox_message.id) # Create and return a Status Message indicating success status_message = tm11.StatusMessage(message_id=cls.generate_id(), in_response_to=request.message_id, status_type=ST_SUCCESS) return status_message
def exception_to_status(exception, format_version): data = dict(message_id=generate_message_id(), in_response_to=exception.in_response_to, extended_headers=exception.extended_headers, status_type=exception.status_type, status_detail=exception.status_details, message=exception.message) if format_version == VID_TAXII_XML_11: sm = tm11.StatusMessage(**data) elif format_version == VID_TAXII_XML_10: sm = tm10.StatusMessage(**data) else: raise ValueError("Unknown version: %s" % format_version) return sm
def create_pending_response(cls, poll_service, prp, content): """ Arguments: poll_service (models.PollService) - The TAXII Poll Service being invoked prp (util.PollRequestProperties) - The Poll Request Properties of the Poll Request content - A list of content (nominally, models.ContentBlock objects). This method returns a StatusMessage with a Status Type of Pending OR raises a StatusMessageException based on the following table:: asynch | Delivery_Params | can_push || Response Type ---------------------------------------------------- True | - | - || Pending - Asynch False | Yes | Yes || Pending - Push False | Yes | No || StatusMessageException False | No | - || StatusMessageException """ # Identify the Exception conditions first (e.g., rows #3 and #4) if (prp.allow_asynch is False and (prp.delivery_parameters is None or prp.can_push is False)): raise StatusMessageException( prp.message_id, ST_FAILURE, "The content was not available now and \ the request had allow_asynch=False and no \ Delivery Parameters were specified.") # Rows #1 and #2 are both Status Messages with a type of Pending result_set = cls.create_result_set(content, prp, poll_service) sm = tm11.StatusMessage(message_id=generate_message_id(), in_response_to=prp.message_id, status_type=ST_PENDING) if prp.allow_asynch: sm.status_details = { SD_ESTIMATED_WAIT: 300, SD_RESULT_ID: result_set.pk, SD_WILL_PUSH: False } else: # TODO: Check and see if the requested delivery parameters are supported sm.status_details = { SD_ESTIMATED_WAIT: 300, SD_RESULT_ID: result_set.pk, SD_WILL_PUSH: True } # TODO: Need to try pushing or something. return sm
def _wrapped_view(request, *args, **kwargs): if request.method != 'POST': raise StatusMessageException('0', ST_BAD_MESSAGE, 'Request method was not POST!') # If requested, attempt to validate # TODO: Validation has changed! if do_validate: try: validate(request) except Exception as e: raise StatusMessageException('0', ST_BAD_MESSAGE, e.message) # Attempt to deserialize try: message = deserialize(request) except Exception as e: raise StatusMessageException('0', ST_BAD_MESSAGE, e.message) try: if message_types is None: pass # No checking was requested elif isinstance(message_types, list): if message.__class__ not in message_types: raise ValueError( 'Message type not allowed. Must be one of: %s' % message_types) elif isinstance(message_types, object): if not isinstance(message, message_types): raise ValueError( 'Message type not allowed. Must be: %s' % message_types) elif message_types is not None: raise ValueError( 'Something strange happened with message_types! Was not a list or object!' ) except ValueError as e: msg = tm11.StatusMessage(generate_message_id(), message.message_id, status_type='FAILURE', message=e.message) return HttpResponseTaxii(msg.to_xml(), response_headers) kwargs['taxii_message'] = message return view_func(request, *args, **kwargs)
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())
def get_message_from_urllib2_httperror(http_response, in_response_to): """ This function should not be called by libtaxii users directly. """ taxii_content_type = http_response.info().getheader('X-TAXII-Content-Type') response_message = http_response.read() if taxii_content_type is None: m = str(http_response.info()) + '\r\n' + response_message return tm11.StatusMessage(message_id='0', in_response_to=in_response_to, status_type=ST_FAILURE, message=m) elif taxii_content_type == VID_TAXII_XML_10: # It's a TAXII XML 1.0 message return tm10.get_message_from_xml(response_message) elif taxii_content_type == VID_TAXII_XML_11: # It's a TAXII XML 1.1 message return tm11.get_message_from_xml(response_message) elif taxii_content_type == VID_CERT_EU_JSON_10: return tm10.get_message_from_json(response_message) else: raise ValueError('Unsupported X-TAXII-Content-Type: %s' % taxii_content_type) return None
def get_message_from_client_response(resp, in_response_to): """ helper func""" taxii_content_type = resp.get('X-TAXII-Content-Type', None) response_message = resp.content if taxii_content_type is None: m = str(resp) + '\r\n' + response_message return tm11.StatusMessage(message_id='0', in_response_to=in_response_to, status_type=ST_FAILURE, message=m) elif taxii_content_type == VID_TAXII_XML_10: # It's a TAXII XML 1.0 message return tm10.get_message_from_xml(response_message) elif taxii_content_type == VID_TAXII_XML_11: # It's a TAXII XML 1.1 message return tm11.get_message_from_xml(response_message) elif taxii_content_type == VID_CERT_EU_JSON_10: return tm10.get_message_from_json(response_message) else: raise ValueError('Unsupported X-TAXII-Content-Type: %s' % taxii_content_type) return None
def get_message_from_urllib_addinfourl(http_response, in_response_to): """ This function should not be called by libtaxii users directly. """ info = http_response.info() if hasattr(info, 'getheader'): taxii_content_type = info.getheader('X-TAXII-Content-Type') _, params = cgi.parse_header(info.getheader('Content-Type')) else: taxii_content_type = info.get('X-TAXII-Content-Type') _, params = cgi.parse_header(info.get('Content-Type')) encoding = params.get('charset', 'utf-8') response_message = six.ensure_text(http_response.read(), errors='replace') if taxii_content_type is None: # Treat it as a Failure Status Message, per the spec message = [] header_dict = six.iteritems(http_response.info().dict) for k, v in header_dict: message.append(k + ': ' + v + '\r\n') message.append('\r\n') message.append(response_message) m = ''.join(message) return tm11.StatusMessage(message_id='0', in_response_to=in_response_to, status_type=ST_FAILURE, message=m) elif taxii_content_type == VID_TAXII_XML_10: # It's a TAXII XML 1.0 message return tm10.get_message_from_xml(response_message, encoding) elif taxii_content_type == VID_TAXII_XML_11: # It's a TAXII XML 1.1 message return tm11.get_message_from_xml(response_message, encoding) elif taxii_content_type == VID_CERT_EU_JSON_10: return tm10.get_message_from_json(response_message, encoding) else: raise ValueError('Unsupported X-TAXII-Content-Type: %s' % taxii_content_type)
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())
def prepare_poll_response(cls, service, collection, in_response_to, timeframe=None, content_bindings=None, result_part=1, allow_async=False, return_content=True, result_id=None, subscription_id=None): timeframe = timeframe or (None, None) if not any(timeframe) and not content_bindings: total_count = collection.volume else: try: total_count = service.get_content_blocks_count( collection, timeframe=timeframe, content_bindings=content_bindings) except ResultsNotReady: if not allow_async: message = ("The content is not available now and " "the request has allow_asynch set to false") raise_failure(message=message, in_response_to=in_response_to) result_set = service.create_result_set( collection, timeframe=timeframe, content_bindings=content_bindings) return tm11.StatusMessage(message_id=generate_message_id(), in_response_to=in_response_to, status_type=ST_PENDING, status_details={ SD_ESTIMATED_WAIT: service.wait_time, SD_RESULT_ID: result_set.id, SD_WILL_PUSH: service.can_push }) # TODO: temporary fix, pending: # https://github.com/TAXIIProject/libtaxii/issues/191 result_part = int(result_part) # dividing instead of multiplying to be safe from overflow has_more = (float(total_count) / service.max_result_size) > result_part capped_count = min(service.max_result_count, total_count) is_partial = (capped_count < total_count) if has_more and not result_id: result_set = service.create_result_set( collection, timeframe=timeframe, content_bindings=content_bindings) result_id = result_set.id response = tm11.PollResponse( message_id=generate_message_id(), in_response_to=in_response_to, collection_name=collection.name, more=has_more, result_id=result_id, result_part_number=result_part, exclusive_begin_timestamp_label=timeframe[0], inclusive_end_timestamp_label=timeframe[1], # TODO: Temporararily make capped_count an int, pending: # https://github.com/TAXIIProject/libtaxii/issues/191 record_count=tm11.RecordCount(int(capped_count), is_partial), subscription_id=subscription_id) if return_content: content_blocks = service.get_content_blocks( collection, timeframe=timeframe, content_bindings=content_bindings, part_number=result_part) for block in content_blocks: response.content_blocks.append( content_block_entity_to_content_block(block, version=11)) return response
def handle_message(cls, service, request): collections = service.validate_destination_collection_names( request.destination_collection_names, request.message_id) inbox_message = service.server.persistence.create_inbox_message( inbox_message_to_inbox_message_entity( request, service_id=service.id, version=11 ) ) failure = False failure_message = "" for content_block in request.content_blocks: is_supported = service.is_content_supported( content_block.content_binding, version=11) # FIXME: is it correct to skip unsupported content blocks? # 3.2 Inbox Exchange # version1.1/TAXII_Services_Specification.pdf if not is_supported: failure = True failure_message = ( "Content binding is not supported by this" " Inbox service: {}".format(content_block.content_binding) ) log.warning(failure_message) continue supporting_collections = [] for collection in collections: if collection.is_content_supported( content_block.content_binding): supporting_collections.append(collection) if len(supporting_collections) == 0 and not is_supported: # There's nothing to add this content block to failure = True failure_message = ( "No collection that supports binding" " {} were found".format(content_block.content_binding) ) log.warning(failure_message) continue # Validate that the STIX content is actually STIX content with # the STIX Validator results = service.verify_content_is_valid( content_block.content, content_block.content_binding, request.message_id ) if results.is_valid: block = content_block_to_content_block_entity( content_block, version=11 ) service.server.persistence.create_content( block, collections=supporting_collections, service_id=service.id, inbox_message_id=inbox_message.id if inbox_message else None ) else: failure = True failure_message = results.message log.warning(failure_message) continue # If we had an error then indicate a failure if failure: status_message = tm11.StatusMessage( message=failure_message, message_id=cls.generate_id(), in_response_to=request.message_id, status_type=ST_FAILURE ) else: # Create and return a Status Message indicating success status_message = tm11.StatusMessage( message_id=cls.generate_id(), in_response_to=request.message_id, status_type=ST_SUCCESS ) return status_message
def handle_message(cls, inbox_service, inbox_message, django_request): """ Attempts to save all Content Blocks in the Inbox Message into the database. Workflow: #. Validate the request's Destination Collection Names against the InboxService model #. Create an InboxMessage model object for bookkeeping #. Iterate over each Content Block in the request: #. Identify which of the request's destination collections support the Content Block's Content Binding #. Call `save_content_block(tm11.ContentBlock, <list of Data Collections from 3a>)` #. Return Status Message with a Status Type of Success Raises: A StatusMessageException for errors """ collections = inbox_service.validate_destination_collection_names( inbox_message.destination_collection_names, inbox_message.message_id) # Store certain information about this Inbox Message in the database for bookkeeping inbox_message_db = models.InboxMessage.from_inbox_message_11( inbox_message, django_request, received_via=inbox_service) inbox_message_db.save() # Iterate over the ContentBlocks in the InboxMessage and try to add # them to the database saved_blocks = 0 for content_block in inbox_message.content_blocks: # 3a. Identify whether the InboxService supports the Content Block's Content Binding # TODO: Is this useful? inbox_support_info = inbox_service.is_content_supported( content_block.content_binding) supporting_collections = [] for collection in collections: collection_support_info = collection.is_content_supported( content_block.content_binding) if collection_support_info.is_supported: supporting_collections.append(collection) if len(supporting_collections ) == 0 and not inbox_support_info.is_supported: # There's nothing to add this content block to continue cls.save_content_block(content_block, supporting_collections) saved_blocks += 1 # Update the Inbox Message model with the number of ContentBlocks that were saved inbox_message_db.content_blocks_saved = saved_blocks inbox_message_db.save() # Create and return a Status Message indicating success status_message = tm11.StatusMessage( message_id=generate_message_id(), in_response_to=inbox_message.message_id, status_type=ST_SUCCESS) return status_message