예제 #1
0
    def run(self, argv):
        parser = OptionParser()
        parser.add_option("-f", "--file", dest="infile", action="store",
                          type="string", default='', help="File to import.")
        parser.add_option("-s", "--source", dest="source", action="store",
                          default=None, help="Source to use if not in file.")
        parser.add_option("-e", "--event", dest="event", action="store_true",
                          default=False, help="Make event.")
        parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                          default=False, help="Print saved objects.")

        (opts, args) = parser.parse_args(argv)

        if not opts.infile:
            print "Need a file to parse."
            return

        f = open(opts.infile, 'r')
        data = f.read()
        f.close()

        ret = import_standards_doc(data, "Command Line", "Standards Import Script", make_event=opts.event, source=opts.source)
        if ret['success']:
            for k in ["events", "samples", "emails", "indicators"]:
                print "%s (%i)" % (k, len(ret[k]))
                if opts.verbose:
                    for i in ret[k]:
                        print "\t" + i
        else:
            print "Failure: %s" % ret['reason']
예제 #2
0
    def run(self, argv):
        parser = OptionParser()
        parser.add_option("-f", "--file", dest="infile", action="store",
                          type="string", default='', help="File to import.")
        parser.add_option("-s", "--source", dest="source", action="store",
                          default=None, help="Source to use if not in file.")
        parser.add_option("-e", "--event", dest="event", action="store_true",
                          default=False, help="Make event.")
        parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                          default=False, help="Print saved objects.")

        (opts, args) = parser.parse_args(argv)

        if not opts.infile:
            print "Need a file to parse."
            return

        f = open(opts.infile, 'r')
        data = f.read()
        f.close()

        ret = import_standards_doc(data, "Command Line", "Standards Import Script", hdr_events=opts.event, source=opts.source)
        if ret['success']:
            for k in ["events", "samples", "emails", "indicators"]:
                print "%s (%i)" % (k, len(ret[k]))
                if opts.verbose:
                    for i in ret[k]:
                        print "\t" + i
        else:
            print "Failure: %s" % ret['reason']
예제 #3
0
파일: views.py 프로젝트: sidjames/crits
def upload_standards(request):
    """
    Upload a standards document.

    :param request: Django request.
    :type request: :class:`django.http.HttpRequest`
    :returns: :class:`django.http.HttpResponse`
    """

    std_form = UploadStandardsForm(request.user, request.POST, request.FILES)
    response = {'form': std_form.as_table(), 'success': False, 'message': ""}

    if request.method != "POST":
        response['message'] = "Must submit via POST."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    if not std_form.is_valid():
        response['message'] = "Form is invalid."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    data = ''
    for chunk in request.FILES['filedata']:
        data += chunk

    make_event = std_form.cleaned_data['make_event']
    source = std_form.cleaned_data['source']

    reference = std_form.cleaned_data['reference']

    # XXX: Add reference to form and handle here?
    status = import_standards_doc(data,
                                  request.user.username,
                                  "Upload",
                                  ref=reference,
                                  make_event=make_event,
                                  source=source)

    if not status['success']:
        response['message'] = status['reason']
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    response['success'] = True
    response['message'] = render_to_string("import_results.html", {
        'failed': status['failed'],
        'imported': status['imported']
    })
    return render_to_response('file_upload_response.html',
                              {'response': json.dumps(response)},
                              RequestContext(request))
예제 #4
0
파일: views.py 프로젝트: 0x3a/crits
def upload_standards(request):
    """
    Upload a standards document.

    :param request: Django request.
    :type request: :class:`django.http.HttpRequest`
    :returns: :class:`django.http.HttpResponse`
    """

    std_form = UploadStandardsForm(request.user, request.POST, request.FILES)
    response = {
                   'form': std_form.as_table(),
                   'success': False,
                   'message': ""
                 }

    if request.method != "POST":
        response['message'] = "Must submit via POST."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    if not std_form.is_valid():
        response['message'] = "Form is invalid."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    data = ''
    for chunk in request.FILES['filedata']:
        data += chunk

    make_event = std_form.cleaned_data['make_event']
    source = std_form.cleaned_data['source']

    reference = std_form.cleaned_data['reference']


    # XXX: Add reference to form and handle here?
    status = import_standards_doc(data, request.user.username, "Upload",
                                 ref=reference, make_event=make_event, source=source)

    if not status['success']:
        response['message'] = status['reason']
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    response['success'] = True
    response['message'] = render_to_string("import_results.html", {'failed' : status['failed'], 'imported' : status['imported']})
    return render_to_response('file_upload_response.html',
                              {'response': json.dumps(response)},
                              RequestContext(request))
예제 #5
0
    def obj_create(self, bundle, **kwargs):
        """
        Handles creating STIX documents through the API.

        :param bundle: Bundle to create the records associated with this STIX document.
        :type bundle: Tastypie Bundle object.
        :returns: Bundle object.
        :raises BadRequest: If a type_ is not provided or creation fails.
        """

        analyst = bundle.request.user.username
        type_ = bundle.data.get('upload_type', None)

        if not type_:
            raise BadRequest('You must specify the upload type.')
        elif type_ not in ('file', 'xml'):
            raise BadRequest('Unknown or unsupported upload type. ' + type_)

        # Remove this so it doesn't get included with the fields upload
        del bundle.data['upload_type']
        result = None

        # Extract common information
        source = bundle.data.get('source', None)
        method = bundle.data.get('method', None)
        reference = bundle.data.get('reference', None)
        me = bundle.data.get('make_event',
                             False)  # default to False for the event

        if not source:
            raise BadRequest('No Source was specified')

        if type_ == 'xml':
            filedata = bundle.data.get('xml', None)
        elif type_ == 'file':
            file_ = bundle.data.get('filedata', None)
            filedata = file_.read()
        if not filedata:
            raise BadRequest('No STIX content uploaded.')
        result = import_standards_doc(filedata,
                                      analyst,
                                      method,
                                      make_event=me,
                                      ref=reference,
                                      source=source)
        if not result:
            raise BadRequest('No upload type found.')
        if not result['success']:
            raise BadRequest(result['reason'])
        return bundle
예제 #6
0
파일: views.py 프로젝트: maurakilleen/crits
def upload_standards(request):
    """
    Upload a standards document.

    :param request: Django request.
    :type request: :class:`django.http.HttpRequest`
    :returns: :class:`django.http.HttpResponse`
    """

    std_form = UploadStandardsForm(request.user, request.POST, request.FILES)
    response = {
                   'form': std_form.as_table(),
                   'success': False,
                   'message': ""
                 }

    if request.method != "POST":
        response['message'] = "Must submit via POST."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    if not std_form.is_valid():
        response['message'] = "Form is invalid."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    data = ''
    for chunk in request.FILES['filedata']:
        data += chunk

    make_event = std_form.cleaned_data['make_event']
    source = std_form.cleaned_data['source']

    # XXX: Add reference to form and handle here?
    status = import_standards_doc(data, request.user.username, "Upload",
                                  make_event=make_event, source=source)

    if not status['success']:
        response['message'] = status['reason']
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    response['success'] = True

    msg = '<table class="vertical" width="353px">\n\t<thead></thead>\n\t<tbody>'
    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Events", len(status['events']))
    for id_ in status['events']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse('crits.events.views.view_event',
                                                        args=[id_]), id_)
    msg += '</td></tr>'

    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Samples", len(status['samples']))
    for id_ in status['samples']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse('crits.samples.views.detail',
                                                        args=[id_]), id_)
    msg += '</td></tr>'

    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Emails", len(status['emails']))
    for id_ in status['emails']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse('crits.emails.views.email_detail',
                                                        args=[id_]), id_)
    msg += '</td></tr>'

    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Indicators", len(status['indicators']))
    for id_ in status['indicators']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse('crits.indicators.views.indicator',
                                                        args=[id_]), id_)
    msg += '</td></tr>'

    response['message'] = msg
    return render_to_response('file_upload_response.html',
                              {'response': json.dumps(response)},
                              RequestContext(request))
예제 #7
0
def execute_taxii_agent(hostname=None, https=None, feed=None, keyfile=None,
                        certfile=None, start=None, end=None, analyst=None,
                        method=None):
    ret = {
            'Certificate': [],
            'Domain': [],
            'Email': [],
            'Event': [],
            'Indicator': [],
            'IP': [],
            'PCAP': [],
            'RawData': [],
            'Sample': [],
            'successes': 0,
            'failures': [],
            'status': False,
            'reason': ''
          }

    sc = manager.get_config('taxii_service')
    # XXX: Validate these!
    if not hostname:
        hostname = str(sc['hostname'])
    if not keyfile:
        keyfile = str(sc['keyfile'])
    if not certfile:
        certfile = str(sc['certfile'])
    if not feed:
        feed = str(sc['data_feed'])
    if https == None:
        https = sc['https']
    create_events = sc['create_events']


    # Last document's end time is our start time.
    if not start:
        last = taxii.Taxii.get_last()
        if last:
            start = pytz.utc.localize(last.end)

    # If start is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(start, str):
        start = pytz.utc.localize(parse(start, fuzzy=True))

    # store the current time as the time of this request
    runtime = datetime.now(tzutc())

    # End time is always now, unless specified.
    if not end:
        end = runtime

    # If end is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(end, str):
        end = pytz.utc.localize(parse(end, fuzzy=True))

    # compare start and end to make sure:
    # 1) start time is before end time
    # 2) end time is not in the future
    if (start != None and start >= end) and end > runtime:
        ret['reason'] = "Bad timestamp(s)"
        return ret

    client = tc.HttpClient()
    if https:
        client.setUseHttps(True)
        client.setAuthType(tc.HttpClient.AUTH_CERT)
        client.setAuthCredentials({'key_file': keyfile, 'cert_file': certfile})

    if settings.HTTP_PROXY:
        proxy = settings.HTTP_PROXY
        if not proxy.startswith('http://'):
            proxy = 'http://' + proxy
        client.setProxy(proxy, proxy_type=tc.HttpClient.PROXY_HTTPS)

    crits_taxii = taxii.Taxii()
    crits_taxii.runtime = runtime
    crits_taxii.end = end

    # Poll using 1.1 then 1.0 if that fails.
    poll_msg = tm11.PollRequest(message_id=tm11.generate_message_id(),
                                collection_name=feed,
                                poll_parameters=tm11.PollRequest.PollParameters(),
                                exclusive_begin_timestamp_label=start,
                                inclusive_end_timestamp_label=end)

    response = client.callTaxiiService2(hostname, '/poll/', t.VID_TAXII_XML_11,
                                        poll_msg.to_xml())
    taxii_msg = t.get_message_from_http_response(response, poll_msg.message_id)

    if response.getcode() != 200 or taxii_msg.message_type == tm11.MSG_STATUS_MESSAGE:
        # Check if this is a TAXII 1.0 server and try again
        if response.info().getheader('X-TAXII-Content-Type') == t.VID_TAXII_XML_10:
            poll_msg = tm.PollRequest(message_id=tm.generate_message_id(),
                                    feed_name=feed,
                                    exclusive_begin_timestamp_label=start,
                                    inclusive_end_timestamp_label=end)

            response = client.callTaxiiService2(hostname, '/poll/', t.VID_TAXII_XML_10,
                                            poll_msg.to_xml())
            taxii_msg = t.get_message_from_http_response(response, poll_msg.message_id)
            if response.getcode() != 200 or taxii_msg.message_type == tm.MSG_STATUS_MESSAGE:
                ret['reason'] = "%s: %s" % (taxii_msg.status_type,
                                            taxii_msg.message)
                return ret
        else:
            ret['reason'] = "%s: %s" % (taxii_msg.status_type,
                                        taxii_msg.message)
            return ret


    valid = tm.validate_xml(taxii_msg.to_xml())
    if valid != True:
        ret['reason'] = "Invalid XML: %s" % valid
        return ret

    if taxii_msg.message_type != tm.MSG_POLL_RESPONSE:
        ret['reason'] = "No poll response. Unexpected message type: %s" % taxii_msg.message_type
        return ret

    ret['status'] = True

    if not taxii_msg.content_blocks:
        crits_taxii.save()
        return ret

    mid = taxii_msg.message_id
    for content_block in taxii_msg.content_blocks:
        data = parse_content_block(content_block, keyfile, certfile)
        if not data:
            ret['failures'].append(('No data found in content block', 'Data'))
            continue

        objs = import_standards_doc(data, analyst, method, ref=mid,
                                    make_event=create_events)

        for k in objs['imported']:
            ret['successes'] += 1
            ret[k[0]].append(k[1])
        for k in objs['failed']:
            ret['failures'].append(k)


    crits_taxii.save()
    return ret
예제 #8
0
def execute_taxii_agent(hostname=None,
                        feed=None,
                        keyfile=None,
                        certfile=None,
                        start=None,
                        end=None,
                        analyst=None,
                        method=None):
    ret = {
        'events': [],
        'samples': [],
        'emails': [],
        'indicators': [],
        'successes': 0,
        'failures': 0,
        'status': False,
        'reason': ''
    }

    sc = manager.get_config('taxii_service')
    # XXX: Validate these!
    if not hostname:
        hostname = str(sc['hostname'])
    if not keyfile:
        keyfile = str(sc['keyfile'])
    if not certfile:
        certfile = str(sc['certfile'])
    if not feed:
        feed = str(sc['data_feed'])

    # Last document's end time is our start time.
    if not start:
        last = taxii.Taxii.get_last()
        if last:
            start = pytz.utc.localize(last.end)

    # If start is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(start, str):
        start = pytz.utc.localize(parse(start, fuzzy=True))

    # store the current time as the time of this request
    runtime = datetime.now(tzutc())

    # End time is always now, unless specified.
    if not end:
        end = runtime

    # If end is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(end, str):
        end = pytz.utc.localize(parse(end, fuzzy=True))

    # compare start and end to make sure:
    # 1) start time is before end time
    # 2) end time is not in the future
    if (start != None and start >= end) and end > runtime:
        ret['reason'] = "Bad timestamp(s)"
        return ret

    client = tc.HttpClient()
    client.setUseHttps(True)
    client.setAuthType(tc.HttpClient.AUTH_CERT)
    client.setAuthCredentials({'key_file': keyfile, 'cert_file': certfile})

    if settings.HTTP_PROXY:
        proxy = settings.HTTP_PROXY
        if not proxy.startswith('http://'):
            proxy = 'http://' + proxy
        client.setProxy(proxy, proxy_type=tc.HttpClient.PROXY_HTTPS)

    crits_taxii = taxii.Taxii()
    crits_taxii.runtime = runtime
    crits_taxii.end = end

    poll_msg = tm.PollRequest(message_id=tm.generate_message_id(),
                              feed_name=feed,
                              exclusive_begin_timestamp_label=start,
                              inclusive_end_timestamp_label=end)
    response = client.callTaxiiService2(hostname, '/poll/', t.VID_TAXII_XML_10,
                                        poll_msg.to_xml())

    if response.getcode() != 200:
        ret['reason'] = "Response is not 200 OK"
        return ret

    taxii_msg = t.get_message_from_http_response(response, poll_msg.message_id)

    valid = tm.validate_xml(taxii_msg.to_xml())
    if valid != True:
        ret['reason'] = valid
        return ret

    if taxii_msg.message_type != tm.MSG_POLL_RESPONSE:
        ret['reason'] = "No poll response"
        return ret

    ret['status'] = True

    if not taxii_msg.content_blocks:
        crits_taxii.save()
        return ret

    mid = taxii_msg.message_id
    for content_block in taxii_msg.content_blocks:
        data = parse_content_block(content_block, keyfile, certfile)
        if not data:
            ret['failures'] += 1
            continue

        objs = import_standards_doc(data,
                                    analyst,
                                    method,
                                    ref=mid,
                                    make_event=True)

        ret['successes'] += 1

        for k in ["events", "samples", "emails", "indicators"]:
            for i in objs[k]:
                ret[k].append(i)

    crits_taxii.save()
    return ret
예제 #9
0
    def obj_create(self, bundle, **kwargs):
        """
        Handles creating STIX documents through the API.

        :param bundle: Bundle to create the records associated with this STIX document.
        :type bundle: Tastypie Bundle object.
        :returns: HttpResponse.
        """

        analyst = bundle.request.user.username
        type_ = bundle.data.get('upload_type', None)

        content = {'return_code': 1, 'imported': [], 'failed': []}

        if not type_:
            content['message'] = 'You must specify the upload type.'
            self.crits_response(content)
        elif type_ not in ('file', 'xml'):
            content['message'] = 'Unknown or unsupported upload type. ' + type_
            self.crits_response(content)

        # Remove this so it doesn't get included with the fields upload
        del bundle.data['upload_type']

        # Extract common information
        source = bundle.data.get('source', None)
        method = bundle.data.get('method', None)
        reference = bundle.data.get('reference', None)
        me = bundle.data.get('make_event',
                             False)  # default to False for the event

        if not source:
            content['message'] = 'No Source was specified'
            self.crits_response(content)

        if type_ == 'xml':
            filedata = bundle.data.get('xml', None)
        elif type_ == 'file':
            file_ = bundle.data.get('filedata', None)
            filedata = file_.read()
        if not filedata:
            content['message'] = 'No STIX content uploaded.'
            self.crits_response(content)
        result = import_standards_doc(filedata,
                                      analyst,
                                      method,
                                      make_event=me,
                                      ref=reference,
                                      source=source)

        if len(result['imported']):
            for i in result['imported']:
                d = {}
                otype = i[0]
                obj = i[1]
                rname = self.resource_name_from_type(otype)
                url = reverse('api_dispatch_detail',
                              kwargs={
                                  'resource_name': rname,
                                  'api_name': 'v1',
                                  'pk': str(obj.id)
                              })
                d['url'] = url
                d['type'] = otype
                d['id'] = str(obj.id)
                content['imported'].append(d)
        if len(result['failed']):
            for f in result['failed']:
                d = {'type': f[1], 'message': f[0]}
                content['failed'].append(d)
        if result['success']:
            content['return_code'] = 0
        self.crits_response(content)
예제 #10
0
def execute_taxii_agent(hostname=None, https=None, feed=None, keyfile=None,
                        certfile=None, start=None, end=None, analyst=None,
                        method=None):
    ret = {
            'Certificate': [],
            'Domain': [],
            'Email': [],
            'Event': [],
            'Indicator': [],
            'IP': [],
            'PCAP': [],
            'RawData': [],
            'Sample': [],
            'successes': 0,
            'failures': [],
            'status': False,
            'reason': ''
          }

    sc = get_config('taxii_service')
    # XXX: Validate these!
    if not hostname:
        hostname = str(sc['hostname'])
    if not keyfile:
        keyfile = str(sc['keyfile'])
    if not certfile:
        certfile = str(sc['certfile'])
    if not feed:
        feed = str(sc['data_feed'])
    if https == None:
        https = sc['https']
    create_events = sc['create_events']


    # Last document's end time is our start time.
    if not start:
        last = taxii.Taxii.get_last()
        if last:
            start = pytz.utc.localize(last.end)

    # If start is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(start, str):
        start = pytz.utc.localize(parse(start, fuzzy=True))

    # store the current time as the time of this request
    runtime = datetime.now(tzutc())

    # End time is always now, unless specified.
    if not end:
        end = runtime

    # If end is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(end, str):
        end = pytz.utc.localize(parse(end, fuzzy=True))

    # compare start and end to make sure:
    # 1) start time is before end time
    # 2) end time is not in the future
    if (start != None and start >= end) and end > runtime:
        ret['reason'] = "Bad timestamp(s)"
        return ret

    client = tc.HttpClient()
    if https:
        client.setUseHttps(True)
        client.setAuthType(tc.HttpClient.AUTH_CERT)
        client.setAuthCredentials({'key_file': keyfile, 'cert_file': certfile})

    if settings.HTTP_PROXY:
        proxy = settings.HTTP_PROXY
        if not proxy.startswith('http://'):
            proxy = 'http://' + proxy
        client.setProxy(proxy, proxy_type=tc.HttpClient.PROXY_HTTPS)

    crits_taxii = taxii.Taxii()
    crits_taxii.runtime = runtime
    crits_taxii.end = end

    # Poll using 1.1 then 1.0 if that fails.
    poll_msg = tm11.PollRequest(message_id=tm11.generate_message_id(),
                                collection_name=feed,
                                poll_parameters=tm11.PollRequest.PollParameters(),
                                exclusive_begin_timestamp_label=start,
                                inclusive_end_timestamp_label=end)

    response = client.callTaxiiService2(hostname, '/poll/', t.VID_TAXII_XML_11,
                                        poll_msg.to_xml())
    taxii_msg = t.get_message_from_http_response(response, poll_msg.message_id)

    if response.getcode() != 200 or taxii_msg.message_type == tm11.MSG_STATUS_MESSAGE:
        # Check if this is a TAXII 1.0 server and try again
        if response.info().getheader('X-TAXII-Content-Type') == t.VID_TAXII_XML_10:
            poll_msg = tm.PollRequest(message_id=tm.generate_message_id(),
                                    feed_name=feed,
                                    exclusive_begin_timestamp_label=start,
                                    inclusive_end_timestamp_label=end)

            response = client.callTaxiiService2(hostname, '/poll/', t.VID_TAXII_XML_10,
                                            poll_msg.to_xml())
            taxii_msg = t.get_message_from_http_response(response, poll_msg.message_id)
            if response.getcode() != 200 or taxii_msg.message_type == tm.MSG_STATUS_MESSAGE:
                ret['reason'] = "%s: %s" % (taxii_msg.status_type,
                                            taxii_msg.message)
                return ret
        else:
            ret['reason'] = "%s: %s" % (taxii_msg.status_type,
                                        taxii_msg.message)
            return ret


    valid = tm.validate_xml(taxii_msg.to_xml())
    if valid != True:
        ret['reason'] = "Invalid XML: %s" % valid
        return ret

    if taxii_msg.message_type != tm.MSG_POLL_RESPONSE:
        ret['reason'] = "No poll response. Unexpected message type: %s" % taxii_msg.message_type
        return ret

    ret['status'] = True

    if not taxii_msg.content_blocks:
        crits_taxii.save()
        return ret

    mid = taxii_msg.message_id
    for content_block in taxii_msg.content_blocks:
        data = parse_content_block(content_block, keyfile, certfile)
        if not data:
            ret['failures'].append(('No data found in content block', 'Data'))
            continue

        objs = import_standards_doc(data, analyst, method, ref=mid,
                                    make_event=create_events)

        for k in objs['imported']:
            ret['successes'] += 1
            ret[k[0]].append(k[1])
        for k in objs['failed']:
            ret['failures'].append(k)


    crits_taxii.save()
    return ret
예제 #11
0
def execute_taxii_agent(hostname=None, feed=None, keyfile=None, certfile=None, start=None, end=None, analyst=None, method=None):
    ret = {
            'events': [],
            'samples': [],
            'emails': [],
            'indicators': [],
            'successes': 0,
            'failures': 0,
            'status': False,
            'reason': ''
          }

    sc = manager.get_config('taxii_service')
    # XXX: Validate these!
    if not hostname:
        hostname = str(sc['hostname'])
    if not keyfile:
        keyfile = str(sc['keyfile'])
    if not certfile:
        certfile = str(sc['certfile'])
    if not feed:
        feed = str(sc['data_feed'])

    # Last document's end time is our start time.
    if not start:
        last = taxii.Taxii.get_last()
        if last:
            start = pytz.utc.localize(last.end)

    # If start is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(start, str):
        start = pytz.utc.localize(parse(start, fuzzy=True))

    # store the current time as the time of this request
    runtime = datetime.now(tzutc())

    # End time is always now, unless specified.
    if not end:
        end = runtime

    # If end is a string, convert it to a datetime
    # YYYY-MM-DD HH:MM:SS
    if isinstance(end, str):
        end = pytz.utc.localize(parse(end, fuzzy=True))

    # compare start and end to make sure:
    # 1) start time is before end time
    # 2) end time is not in the future
    if (start != None and start >= end) and end > runtime:
        ret['reason'] = "Bad timestamp(s)"
        return ret 

    client = tc.HttpClient()
    client.setUseHttps(True)
    client.setAuthType(tc.HttpClient.AUTH_CERT)
    client.setAuthCredentials({'key_file': keyfile, 'cert_file': certfile})

    if settings.HTTP_PROXY:
        proxy = settings.HTTP_PROXY
        if not proxy.startswith('http://'):
            proxy = 'http://' + proxy
        client.setProxy(proxy, proxy_type=tc.HttpClient.PROXY_HTTPS)

    crits_taxii = taxii.Taxii()
    crits_taxii.runtime = runtime
    crits_taxii.end = end

    poll_msg = tm.PollRequest(message_id=tm.generate_message_id(),
                              feed_name=feed,
                              exclusive_begin_timestamp_label=start,
                              inclusive_end_timestamp_label=end)
    response = client.callTaxiiService2(hostname, '/poll/', t.VID_TAXII_XML_10,
                                        poll_msg.to_xml())

    if response.getcode() != 200:
        ret['reason'] = "Response is not 200 OK"
        return ret

    taxii_msg = t.get_message_from_http_response(response, poll_msg.message_id)

    valid = tm.validate_xml(taxii_msg.to_xml())
    if valid != True:
        ret['reason'] = valid
        return ret

    if taxii_msg.message_type != tm.MSG_POLL_RESPONSE:
        ret['reason'] = "No poll response"
        return ret

    ret['status'] = True

    if not taxii_msg.content_blocks:
        crits_taxii.save()
        return ret

    mid = taxii_msg.message_id
    for content_block in taxii_msg.content_blocks:
        data = parse_content_block(content_block, keyfile, certfile)
        if not data:
            ret['failures'] += 1
            continue

        objs = import_standards_doc(data, analyst, method, ref=mid, make_event=True)

        ret['successes'] += 1

        for k in ["events", "samples", "emails", "indicators"]:
            for i in objs[k]:
                ret[k].append(i)

    crits_taxii.save()
    return ret
예제 #12
0
def upload_standards(request):
    """
    Upload a standards document.

    :param request: Django request.
    :type request: :class:`django.http.HttpRequest`
    :returns: :class:`django.http.HttpResponse`
    """

    std_form = UploadStandardsForm(request.user, request.POST, request.FILES)
    response = {'form': std_form.as_table(), 'success': False, 'message': ""}

    if request.method != "POST":
        response['message'] = "Must submit via POST."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    if not std_form.is_valid():
        response['message'] = "Form is invalid."
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    data = ''
    for chunk in request.FILES['filedata']:
        data += chunk

    make_event = std_form.cleaned_data['make_event']
    source = std_form.cleaned_data['source']

    # XXX: Add reference to form and handle here?
    status = import_standards_doc(data,
                                  request.user.username,
                                  "Upload",
                                  make_event=make_event,
                                  source=source)

    if not status['success']:
        response['message'] = status['reason']
        return render_to_response('file_upload_response.html',
                                  {'response': json.dumps(response)},
                                  RequestContext(request))

    response['success'] = True

    msg = '<table class="vertical" width="353px">\n\t<thead></thead>\n\t<tbody>'
    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Events",
                                                     len(status['events']))
    for id_ in status['events']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse(
            'crits.events.views.view_event', args=[id_]), id_)
    msg += '</td></tr>'

    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Samples",
                                                     len(status['samples']))
    for id_ in status['samples']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse(
            'crits.samples.views.detail', args=[id_]), id_)
    msg += '</td></tr>'

    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Emails",
                                                     len(status['emails']))
    for id_ in status['emails']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse(
            'crits.emails.views.email_detail', args=[id_]), id_)
    msg += '</td></tr>'

    msg += '<tr><td class="key">%s (%i)</td><td>' % ("Indicators",
                                                     len(status['indicators']))
    for id_ in status['indicators']:
        msg += "<a href=\"%s\">%s</a><br />" % (reverse(
            'crits.indicators.views.indicator', args=[id_]), id_)
    msg += '</td></tr>'

    response['message'] = msg
    return render_to_response('file_upload_response.html',
                              {'response': json.dumps(response)},
                              RequestContext(request))
예제 #13
0
파일: api.py 프로젝트: 0x3a/crits
    def obj_create(self, bundle, **kwargs):
        """
        Handles creating STIX documents through the API.

        :param bundle: Bundle to create the records associated with this STIX document.
        :type bundle: Tastypie Bundle object.
        :returns: HttpResponse.
        """

        analyst = bundle.request.user.username
        type_ = bundle.data.get('upload_type', None)

        content = {'return_code': 1,
                   'imported': [],
                   'failed': []}

        if not type_:
            content['message'] = 'You must specify the upload type.'
            self.crits_response(content)
        elif type_ not in ('file', 'xml'):
            content['message'] = 'Unknown or unsupported upload type. ' + type_
            self.crits_response(content)

        # Remove this so it doesn't get included with the fields upload
        del bundle.data['upload_type']

        # Extract common information
        source = bundle.data.get('source', None)
        method = bundle.data.get('method', None)
        reference = bundle.data.get('reference', None)
        me = bundle.data.get('make_event', False)  # default to False for the event

        if not source:
            content['message'] = 'No Source was specified'
            self.crits_response(content)

        if type_ == 'xml':
            filedata = bundle.data.get('xml', None)
        elif type_ == 'file':
            file_ = bundle.data.get('filedata', None)
            filedata = file_.read()
        if not filedata:
            content['message'] = 'No STIX content uploaded.'
            self.crits_response(content)
        result = import_standards_doc(filedata,
                                      analyst,
                                      method,
                                      make_event = me,
                                      ref = reference,
                                      source = source)

        if len(result['imported']):
            for i in result['imported']:
                d = {}
                otype = i[0]
                obj = i[1]
                rname = self.resource_name_from_type(otype)
                url = reverse('api_dispatch_detail',
                            kwargs={'resource_name': rname,
                                    'api_name': 'v1',
                                    'pk': str(obj.id)})
                d['url'] = url
                d['type'] = otype
                d['id'] = str(obj.id)
                content['imported'].append(d)
        if len(result['failed']):
            for f in result['failed']:
                d = {'type': f[1],
                     'message': f[0]}
                content['failed'].append(d)
        if result['success']:
            content['return_code'] = 0
        self.crits_response(content)