Exemple #1
0
def update_object_value(type_, oid, object_type, value, new_value,
                        analyst):
    """
    Update an object value.

    :param type_: The top-level object type.
    :type type_: str
    :param oid: The ObjectId of the top-level object.
    :type oid: str
    :param object_type: The type of the object to update.
    :type object_type: str
    :param value: The value of the object to update.
    :type value: str
    :param new_value: The new value to use.
    :type new_value: str
    :param analyst: The user removing this object.
    :type analyst: str
    :returns: dict with keys "success" (boolean) and "message" (str)
    """

    obj = class_from_id(type_, oid)
    if not obj:
        return {'success': False,
                'message': "Could not find item to update object."}
    try:
        obj.update_object_value(object_type,
                                value,
                                new_value)
        obj.save(username=analyst)
        return {'success': True, 'message': 'Object value updated successfully.'}
    except ValidationError, e:
        return {'success': False, 'message': e}
Exemple #2
0
def delete_all_relationships(left_class=None, left_type=None,
                             left_id=None, analyst=None):
    """
    Delete all relationships for this top-level object.

    :param left_class: The top-level object to delete relationships for.
    :type left_class: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param left_type: The type of the top-level object.
    :type left_type: str
    :param left_id: The ObjectId of the top-level object.
    :type left_id: str
    :param analyst: The user deleting these relationships.
    :type analyst: str
    :returns: dict with keys "success" (boolean) and "message" (str)
    """

    if not left_class:
        if left_type and left_id:
            left_class = class_from_id(left_type, left_id)
            if not left_class:
                return {'success': False,
                        'message': "Unable to get object."}
        else:
            return {'success': False,
                    'message': "Need a valid left type and id"}

    return left_class.delete_all_relationships()
Exemple #3
0
def update_object_value(type_, oid, object_type, value, new_value, analyst):
    """
    Update an object value.

    :param type_: The top-level object type.
    :type type_: str
    :param oid: The ObjectId of the top-level object.
    :type oid: str
    :param object_type: The type of the object to update.
    :type object_type: str
    :param value: The value of the object to update.
    :type value: str
    :param new_value: The new value to use.
    :type new_value: str
    :param analyst: The user removing this object.
    :type analyst: str
    :returns: dict with keys "success" (boolean) and "message" (str)
    """

    obj = class_from_id(type_, oid)
    if not obj:
        return {
            'success': False,
            'message': "Could not find item to update object."
        }
    try:
        obj.update_object_value(object_type, value, new_value)
        obj.save(username=analyst)
        return {
            'success': True,
            'message': 'Object value updated successfully.'
        }
    except ValidationError, e:
        return {'success': False, 'message': e}
Exemple #4
0
def create_indicator_from_object(rel_type, rel_id, ind_type, value,
                                 source_name, method, reference, analyst,
                                 request):
    """
    Create an indicator out of this object.

    :param rel_type: The top-level object type this object is for.
    :type rel_type: str
    :param rel_id: The ObjectId of the top-level object.
    :param ind_type: The indicator type to use.
    :type ind_type: str
    :param value: The indicator value.
    :type value: str
    :param source_name: The source name for the indicator.
    :type source_name: str
    :param method: The source method for the indicator.
    :type method: str
    :param reference: The source reference for the indicator.
    :type reference: str
    :param analyst: The user creating this indicator.
    :type analyst: str
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :returns: dict with keys "success" (bool) and "message" (str)
    """

    result = None
    me = class_from_id(rel_type, rel_id)
    if not me:
        result = {'success': False, 'message': "Could not find %s" % rel_type}
    elif value == None or value.strip() == "":
        result = {
            'success': False,
            'message': "Can't create indicator with an empty value field"
        }
    elif ind_type == None or ind_type.strip() == "":
        result = {
            'success': False,
            'message': "Can't create indicator with an empty type field"
        }
    elif source_name == None or source_name.strip() == "":
        result = {
            'success': False,
            'message': "Can't create indicator with an empty source field"
        }
    else:
        value = value.lower().strip()
        ind_type = ind_type.strip()
        source_name = source_name.strip()

        create_indicator_result = {}

        result = {'success': False, 'message': "Could not create indicator"}

    return result
Exemple #5
0
def create_indicator_from_object(rel_type, rel_id, ind_type, value,
                                 source_name, method, reference, analyst, request):
    """
    Create an indicator out of this object.

    :param rel_type: The top-level object type this object is for.
    :type rel_type: str
    :param rel_id: The ObjectId of the top-level object.
    :param ind_type: The indicator type to use.
    :type ind_type: str
    :param value: The indicator value.
    :type value: str
    :param source_name: The source name for the indicator.
    :type source_name: str
    :param method: The source method for the indicator.
    :type method: str
    :param reference: The source reference for the indicator.
    :type reference: str
    :param analyst: The user creating this indicator.
    :type analyst: str
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :returns: dict with keys "success" (bool) and "message" (str)
    """

    result = None
    me = class_from_id(rel_type, rel_id)
    if not me:
        result = {'success': False,
                  'message': "Could not find %s" % rel_type}
    elif value == None or value.strip() == "":
        result = {'success':  False,
                  'message':  "Can't create indicator with an empty value field"}
    elif ind_type == None or ind_type.strip() == "":
        result = {'success':  False,
                  'message':  "Can't create indicator with an empty type field"}
    elif source_name == None or source_name.strip() == "":
        result = {'success':  False,
                  'message':  "Can't create indicator with an empty source field"}
    else:
        value = value.lower().strip()
        ind_type = ind_type.strip()
        source_name = source_name.strip()

        create_indicator_result = {}

        result = {'success': False,
                     'message': "Could not create indicator"}
       
    return result
Exemple #6
0
def delete_object(type_, oid, object_type, value, analyst, get_objects=True):
    """
    Delete an object.

    :param type_: The top-level object type.
    :type type_: str
    :param oid: The ObjectId of the top-level object.
    :type oid: str
    :param object_type: The type of the object to remove.
    :type object_type: str
    :param value: The value of the object to remove.
    :type value: str
    :param analyst: The user removing this object.
    :type analyst: str
    :param get_objects: Return the list of objects.
    :type get_objects: bool
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
              "objects" (list)
    """

    obj = class_from_id(type_, oid)
    if not obj:
        return {
            'success': False,
            'message': "Could not find item to remove object from."
        }
    try:
        cur_len = len(obj.obj)
        obj.remove_object(object_type, value)
        obj.save(username=analyst)

        new_len = len(obj.obj)
        result = {}
        if new_len < cur_len:
            result['success'] = True
            result['message'] = "Object removed successfully!"
        else:
            result['success'] = False
            result['message'] = "Could not find object to remove!"

        if (get_objects):
            result['objects'] = obj.sort_objects()
        return result
    except ValidationError, e:
        return {'success': False, 'message': e}
Exemple #7
0
def delete_object(type_, oid, object_type, value, analyst, get_objects=True):
    """
    Delete an object.

    :param type_: The top-level object type.
    :type type_: str
    :param oid: The ObjectId of the top-level object.
    :type oid: str
    :param object_type: The type of the object to remove.
    :type object_type: str
    :param value: The value of the object to remove.
    :type value: str
    :param analyst: The user removing this object.
    :type analyst: str
    :param get_objects: Return the list of objects.
    :type get_objects: bool
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
              "objects" (list)
    """

    obj = class_from_id(type_, oid)
    if not obj:
        return {'success': False,
                'message': "Could not find item to remove object from."}
    try:
        cur_len = len(obj.obj)
        obj.remove_object(object_type,
                          value)
        obj.save(username=analyst)

        new_len = len(obj.obj)
        result = {}
        if new_len < cur_len:
            result['success'] = True
            result['message'] = "Object removed successfully!"
        else:
            result['success'] = False
            result['message'] = "Could not find object to remove!"

        if (get_objects):
            result['objects'] = obj.sort_objects()
        return result
    except ValidationError, e:
        return {'success': False,
                'message': e}
Exemple #8
0
def get_relationships(obj=None, type_=None, id_=None, analyst=None):
    """
    Get relationships for a top-level object.

    :param obj: The top-level object to get relationships for.
    :type obj: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param type_: The top-level object type to get relationships for.
    :type type_: str
    :param id_: The ObjectId of the top-level object.
    :type id_: str
    :param analyst: The user requesting the relationships.
    :type analyst: str
    :returns: dict
    """

    if obj:
        return obj.sort_relationships("%s" % analyst, meta=True)
    elif type_ and id_:
        obj = class_from_id(type_, id_)
        if not obj:
            return {}
        return obj.sort_relationships("%s" % analyst, meta=True)
    else:
        return {}
Exemple #9
0
def run_service(name, type_, id_, user, obj=None,
                execute='local', custom_config={}, **kwargs):
    """
    Run a service.

    :param name: The name of the service to run.
    :type name: str
    :param type_: The type of the object.
    :type type_: str
    :param id_: The identifier of the object.
    :type id_: str
    :param user: The user running the service.
    :type user: str
    :param obj: The CRIPTs object, if given this overrides cripts_type and identifier.
    :type obj: CRIPTs object.
    :param analyst: The user updating the results.
    :type analyst: str
    :param execute: The execution type.
    :type execute: str
    :param custom_config: Use a custom configuration for this run.
    :type custom_config: dict
    """

    result = {'success': False}
    if type_ not in settings.CRIPTS_TYPES:
        result['html'] = "Unknown CRIPTs type."
        return result

    if name not in enabled_services():
        result['html'] = "Service %s is unknown or not enabled." % name
        return result

    service_class = cripts.services.manager.get_service_class(name)
    if not service_class:
        result['html'] = "Unable to get service class."
        return result

    if not obj:
        obj = class_from_id(type_, id_)
        if not obj:
            result['html'] = 'Could not find object.'
            return result

    service = CRIPTsService.objects(name=name).first()
    if not service:
        result['html'] = "Unable to find service in database."
        return result

    # See if the object is a supported type for the service.
    if not service_class.supported_for_type(type_):
        result['html'] = "Service not supported for type '%s'" % type_
        return result

    # When running in threaded mode, each thread needs to have its own copy of
    # the object. If we do not do this then one thread may read() from the
    # object (to get the binary) and then the second would would read() without
    # knowing and get undefined behavior as the file pointer would be who knows
    # where. By giving each thread a local copy they can operate independently.
    #
    # When not running in thread mode this has no effect except wasted memory.
    local_obj = local()
    local_obj.obj = copy.deepcopy(obj)

    # Give the service a chance to check for required fields.
    try:
        service_class.valid_for(local_obj.obj)
        if hasattr(local_obj.obj, 'filedata'):
            if local_obj.obj.filedata.grid_id:
                # Reset back to the start so the service gets the full file.
                local_obj.obj.filedata.seek(0)
    except ServiceConfigError as e:
        result['html'] = str(e)
        return result

    # Get the config from the database and validate the submitted options
    # exist.
    db_config = service.config.to_dict()
    try:
        service_class.validate_runtime(custom_config, db_config)
    except ServiceConfigError as e:
        result['html'] = str(e)
        return result

    final_config = db_config
    # Merge the submitted config with the one from the database.
    # This is because not all config options may be submitted.
    final_config.update(custom_config)

    form = service_class.bind_runtime_form(user, final_config)
    if form:
        if not form.is_valid():
            # TODO: return corrected form via AJAX
            result['html'] = str(form.errors)
            return result

        # If the form is valid, create the config using the cleaned data.
        final_config = db_config
        final_config.update(form.cleaned_data)

    logger.info("Running %s on %s, execute=%s" % (name, local_obj.obj.id, execute))
    service_instance = service_class(notify=update_analysis_results,
                                     complete=finish_task)

    # Give the service a chance to modify the config that gets saved to the DB.
    saved_config = dict(final_config)
    service_class.save_runtime_config(saved_config)

    task = AnalysisTask(local_obj.obj, service_instance, user)
    task.config = AnalysisConfig(**saved_config)
    task.start()
    add_task(task)

    service_instance.set_task(task)

    if execute == 'process':
        p = Process(target=service_instance.execute, args=(final_config,))
        p.start()
    elif execute == 'thread':
        t = Thread(target=service_instance.execute, args=(final_config,))
        t.start()
    elif execute == 'process_pool':
        if __service_process_pool__ is not None and service.compatability_mode != True:
            __service_process_pool__.apply_async(func=service_work_handler,
                                                 args=(service_instance, final_config,))
        else:
            logger.warning("Could not run %s on %s, execute=%s, running in process mode" % (name, local_obj.obj.id, execute))
            p = Process(target=service_instance.execute, args=(final_config,))
            p.start()
    elif execute == 'thread_pool':
        if __service_thread_pool__ is not None and service.compatability_mode != True:
            __service_thread_pool__.apply_async(func=service_work_handler,
                                                args=(service_instance, final_config,))
        else:
            logger.warning("Could not run %s on %s, execute=%s, running in thread mode" % (name, local_obj.obj.id, execute))
            t = Thread(target=service_instance.execute, args=(final_config,))
            t.start()
    elif execute == 'local':
        service_instance.execute(final_config)

    # Return after starting thread so web request can complete.
    result['success'] = True
    return result
Exemple #10
0
def bulk_add_object_inline(request):
    """
    Bulk add objects inline.

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

    formdict = form_to_dict(AddObjectForm(request.user))

    if request.method == "POST" and request.is_ajax():
        response = parse_bulk_upload(
            request,
            parse_row_to_bound_object_form,
            add_new_handler_object_via_bulk,
            formdict)

        secondary_data_array = response.get('secondary')
        if secondary_data_array:
            latest_secondary_data = secondary_data_array[-1]
            class_type = class_from_id(
                latest_secondary_data['type'],
                latest_secondary_data['id'])

            subscription = {'type': latest_secondary_data['type'],
                            'id': latest_secondary_data['id'],
                            'value': latest_secondary_data['id']}

            object_listing_html = render_to_string('objects_listing_widget.html',
                                                   {'objects': class_type.sort_objects(),
                                                    'subscription': subscription},
                                                   RequestContext(request))

            response['html'] = object_listing_html

            is_relationship_made = False
            for secondary_data in secondary_data_array:
                if secondary_data.get('relationships'):
                    is_relationship_made = True
                    break

            if is_relationship_made == True:
                rel_html = render_to_string('relationships_listing_widget.html',
                                            {'relationship': subscription,
                                             'relationships': class_type.sort_relationships(request.user, meta=True)},
                                            RequestContext(request))

                response['rel_msg'] = rel_html
                response['rel_made'] = True

        return HttpResponse(json.dumps(response,
                            default=json_handler),
                            content_type="application/json")
    else:
        is_prevent_initial_table = request.GET.get('isPreventInitialTable', False)
        is_use_item_source = request.GET.get('useItemSource', False)

        if is_use_item_source == True or is_use_item_source == "true":
            otype = request.GET.get('otype')
            oid = request.GET.get('oid')

            # Get the item with the type and ID from the database
            obj = class_from_id(otype, oid)

            if obj:
                source_field_name = get_source_field_for_class(otype)
                if source_field_name:

                    # If the item has a source, then use the source value
                    # to set as the default source
                    if hasattr(obj, "source"):
                        source_field = get_field_from_label("source", formdict)
                        earliest_source = None
                        earliest_date = None

                        # Get the earliest source, compared by date
                        for source in obj.source:
                            for source_instance in source.instances:
                                if earliest_source == None or source_instance.date < earliest_date:
                                    earliest_date = source_instance.date
                                    earliest_source = source

                        if earliest_source:
                            source_field['initial'] = earliest_source.name

        return render_to_response('bulk_add_object_inline.html',
                                  {'formdict': formdict,
                                   'title': "Bulk Add Objects",
                                   'is_prevent_initial_table': is_prevent_initial_table,
                                   'table_name': 'object_inline'},
                                  RequestContext(request))
Exemple #11
0
def get_notification_details(request, newer_than):
    """
    Generate the data to render the notification dialogs.

    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param newer_than: A filter that specifies that only notifications
                       newer than this time should be returned.
    :type newer_than: str in ISODate format.
    :returns: arguments (dict)
    """

    username = request.user.username
    notifications_list = []
    notifications = None
    latest_notification_time = None
    lock = NotificationLockManager.get_notification_lock(username)
    timeout = 0

    # Critical section, check if there are notifications to be consumed.
    lock.acquire()
    try:
        notifications = get_user_notifications(username, newer_than=newer_than)

        if len(notifications) > 0:
            latest_notification_time = str(notifications[0].created)
        else:
            # no new notifications -- block until time expiration or lock release
            lock.wait(60)

            # lock was released, check if there is any new information yet
            notifications = get_user_notifications(username, newer_than=newer_than)

            if len(notifications) > 0:
                latest_notification_time = str(notifications[0].created)
    finally:
        lock.release()

    if latest_notification_time is not None:
        acknowledgement_type = request.user.get_preference('toast_notifications', 'acknowledgement_type', 'sticky')

        if acknowledgement_type == 'timeout':
            timeout = request.user.get_preference('toast_notifications', 'timeout', 30) * 1000

    for notification in notifications:
        obj = class_from_id(notification.obj_type, notification.obj_id)

        if obj is not None:
            link_url = obj.get_details_url()
            header = generate_notification_header(obj)
        else:
            if notification.header is not None:
                header = notification.header
            else:
                header = "%s %s" % (notification.obj_type, notification.obj_id)

            if notification.link_url is not None:
                link_url = notification.link_url
            else:
                link_url = None

        notification_type = notification.notification_type

        if notification_type is None or notification_type not in NotificationType.ALL:
            notification_type = NotificationType.ALERT

        notification_data = {
            "header": header,
            "message": notification.notification,
            "date_modified": str(notification.created.strftime("%Y/%m/%d %H:%M:%S")),
            "link": link_url,
            "modified_by": notification.analyst,
            "id": str(notification.id),
            "type": notification_type,
        }

        notifications_list.append(notification_data)

    return {
        'notifications': notifications_list,
        'newest_notification': latest_notification_time,
        'server_time': str(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")),
        'timeout': timeout,
    }
Exemple #12
0
def process_changed_fields(initial_message, changed_fields, obj):
    """
    Processes the changed fields to determine what actually changed.

    :param message: An initial message to include.
    :type message: str
    :param changed_fields: A list of field names that were changed.
    :type changed_fields: list of str
    :param obj: The object.
    :type obj: class which inherits from
               :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :returns: str: Returns a message indicating what was changed.
    """

    obj_type = obj._meta['cripts_type']
    message = initial_message

    if message is None:
        message = ''

    source_filter = None

    for changed_field in changed_fields:

        # Fields may be fully qualified, e.g. source.1.instances.0.reference
        # So, split on the '.' character and get the root of the changed field
        base_changed_field = MappedMongoFields.get_mapped_mongo_field(obj_type, changed_field.split('.')[0])

        new_value = getattr(obj, base_changed_field, '')
        old_obj = class_from_id(obj_type, obj.id)
        old_value = getattr(old_obj, base_changed_field, '')

        change_handler = ChangeParser.get_changed_field_handler(obj_type, base_changed_field)

        if change_handler is not None:
            change_message = change_handler(old_value, new_value, base_changed_field)

            if isinstance(change_message, dict):
                if change_message.get('source_filter') is not None:
                    new_source_filter = change_message.get('source_filter')
                    source_filter = combine_source_filters(source_filter, new_source_filter)

                change_message = change_message.get('message')

            if change_message is not None:
                message += "\n" + change_message[:1].capitalize() + change_message[1:]
        else:
            change_field_handler = ChangeParser.generic_single_field_change_handler

            if isinstance(old_value, BaseList):

                list_value = None

                if len(old_value) > 0:
                    list_value = old_value[0]
                elif len(new_value) > 0:
                    list_value = new_value[0]

                if isinstance(list_value, basestring):
                    change_field_handler = ChangeParser.generic_list_change_handler
                elif isinstance(list_value, EmbeddedDocument):
                    change_field_handler = ChangeParser.generic_list_json_change_handler

            change_message = change_field_handler(old_value, new_value, base_changed_field)

            if isinstance(change_message, dict):
                if change_message.get('source_filter') is not None:
                    new_source_filter = change_message.get('source_filter')
                    combine_source_filters(source_filter, new_source_filter)

                change_message = change_message.get('message')

            if change_message is not None:
                message += "\n" + change_message[:1].capitalize() + change_message[1:]

    return {'message': message, 'source_filter': source_filter}
Exemple #13
0
def forge_relationship(type_=None, id_=None,
                       class_=None, right_type=None,
                       right_id=None, right_class=None,
                       rel_type=None, rel_date=None,
                       user=None, rel_reason="",
                       rel_confidence='unknown', get_rels=False, **kwargs):
    """
    Forge a relationship between two top-level objects.

    :param type_: The type of first top-level object to relate to.
    :type type_: str
    :param id_: The ObjectId of the first top-level object.
    :type id_: str
    :param class_: The first top-level object to relate to.
    :type class_: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param right_type: The type of second top-level object to relate to.
    :type right_type: str
    :param right_id: The ObjectId of the second top-level object.
    :type right_id: str
    :param right_class: The second top-level object to relate to.
    :type right_class: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param rel_type: The type of relationship.
    :type rel_type: str
    :param rel_date: The date this relationship applies.
    :type rel_date: datetime.datetime
    :param user: The user forging this relationship.
    :type user: str
    :param rel_reason: The reason for the relationship.
    :type rel_reason: str
    :param rel_confidence: The confidence of the relationship.
    :type rel_confidence: str
    :param get_rels: Return the relationships after forging.
    :type get_rels: boolean
    :returns: dict with keys:
              "success" (boolean)
              "message" (str if fail, EmbeddedObject if success)
              "relationships" (dict)
    """

    if rel_date == 'None':
        rel_date = None
    elif isinstance(rel_date, basestring) and rel_date != '':
        rel_date = parse(rel_date, fuzzy=True)
    elif not isinstance(rel_date, datetime.datetime):
        rel_date = None

    if not class_:
        if type_ and id_:
            class_ = class_from_id(type_, id_)
        if not class_:
            return {'success': False, 'message': "Failed to get left TLO"}
    if not right_class:
        if right_type and right_id:
            print ("right type:" + str(right_type))
            print ("right id:" + str(right_id))
            right_class = class_from_id(right_type, right_id)
        if not right_class:
            return {'success': False, 'message': "Failed to get right TLO"}

    try:
        # forge relationship
        results = class_.add_relationship(right_class, rel_type, rel_date,
                                          user, rel_confidence, rel_reason)
    except Exception as e:
        return {'success': False, 'message': e}

    if results['success']:
        class_.update(add_to_set__relationships=results['message'])
        if get_rels:
            results['relationships'] = class_.sort_relationships("%s" % user,
                                                                 meta=True)
    return results
Exemple #14
0
def get_notification_details(request, newer_than):
    """
    Generate the data to render the notification dialogs.

    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param newer_than: A filter that specifies that only notifications
                       newer than this time should be returned.
    :type newer_than: str in ISODate format.
    :returns: arguments (dict)
    """

    username = request.user.username
    notifications_list = []
    notifications = None
    latest_notification_time = None
    lock = NotificationLockManager.get_notification_lock(username)
    timeout = 0

    # Critical section, check if there are notifications to be consumed.
    lock.acquire()
    try:
        notifications = get_user_notifications(username, newer_than=newer_than)

        if len(notifications) > 0:
            latest_notification_time = str(notifications[0].created)
        else:
            # no new notifications -- block until time expiration or lock release
            lock.wait(60)

            # lock was released, check if there is any new information yet
            notifications = get_user_notifications(username,
                                                   newer_than=newer_than)

            if len(notifications) > 0:
                latest_notification_time = str(notifications[0].created)
    finally:
        lock.release()

    if latest_notification_time is not None:
        acknowledgement_type = request.user.get_preference(
            'toast_notifications', 'acknowledgement_type', 'sticky')

        if acknowledgement_type == 'timeout':
            timeout = request.user.get_preference('toast_notifications',
                                                  'timeout', 30) * 1000

    for notification in notifications:
        obj = class_from_id(notification.obj_type, notification.obj_id)

        if obj is not None:
            link_url = obj.get_details_url()
            header = generate_notification_header(obj)
        else:
            if notification.header is not None:
                header = notification.header
            else:
                header = "%s %s" % (notification.obj_type, notification.obj_id)

            if notification.link_url is not None:
                link_url = notification.link_url
            else:
                link_url = None

        notification_type = notification.notification_type

        if notification_type is None or notification_type not in NotificationType.ALL:
            notification_type = NotificationType.ALERT

        notification_data = {
            "header":
            header,
            "message":
            notification.notification,
            "date_modified":
            str(notification.created.strftime("%Y/%m/%d %H:%M:%S")),
            "link":
            link_url,
            "modified_by":
            notification.analyst,
            "id":
            str(notification.id),
            "type":
            notification_type,
        }

        notifications_list.append(notification_data)

    return {
        'notifications': notifications_list,
        'newest_notification': latest_notification_time,
        'server_time':
        str(datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")),
        'timeout': timeout,
    }
Exemple #15
0
def add_object(type_,
               id_,
               object_type,
               source,
               method,
               reference,
               user,
               value=None,
               file_=None,
               add_indicator=False,
               get_objects=True,
               tlo=None,
               is_sort_relationships=False,
               is_validate_only=False,
               is_validate_locally=False,
               cache={},
               **kwargs):
    """
    Add an object to the database.

    :param type_: The top-level object type.
    :type type_: str
    :param id_: The ObjectId of the top-level object.
    :type id_: str
    :param object_type: The type of the ObjectType being added.
    :type object_type: str
    :param source: The name of the source adding this object.
    :type source: str
    :param method: The method for this object.
    :type method: str
    :param reference: The reference for this object.
    :type reference: str
    :param user: The user adding this object.
    :type user: str
    :param value: The value of the object.
    :type value: str
    :param file_: The file if the object is a file upload.
    :type file_: file handle.
    :param add_indicator: Also add an indicator for this object.
    :type add_indicator: bool
    :param get_objects: Return the formatted list of objects when completed.
    :type get_objects: bool
    :param tlo: The CRIPTs top-level object we are adding objects to.
                This is an optional parameter used mainly for performance
                reasons (by not querying mongo if we already have the
                top level-object).
    :type tlo: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param is_sort_relationships: Return all relationships and meta, sorted
    :type is_sort_relationships: bool
    :param is_validate_only: Validate, but do not add to TLO.
    :type is_validate_only: bool
    :param is_validate_locally: Validate, but do not add b/c there is no TLO.
    :type is_validate_locally: bool
    :param cache: Cached data, typically for performance enhancements
                  during bulk operations.
    :type cache: dict
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
              "objects" (list),
              "relationships" (list)
    """

    if is_validate_locally:  # no TLO provided
        return {"success": True}

    if not tlo:
        if type_ and id_:
            tlo = class_from_id(type_, id_)
        if not tlo:
            return {'success': False, 'message': "Failed to find TLO"}

    try:
        if file_:
            data = file_.read()
            filename = file_.name
            md5sum = md5(data).hexdigest()
            value = md5sum
            reference = filename
        ret = tlo.add_object(object_type, value, source, method, reference,
                             user)

        if not ret['success']:
            msg = '%s! [Type: "%s"][Value: "%s"]'
            return {
                "success": False,
                "message": msg % (ret['message'], object_type, value)
            }
        else:
            results = {'success': True}

        if not is_validate_only:  # save the object
            tlo.update(add_to_set__obj=ret['object'])
            results['message'] = "Object added successfully"

        if file_:

            #XXX: MongoEngine provides no direct GridFS access so we
            #     need to use pymongo directly.
            col = settings.COL_OBJECTS
            grid = mongo_connector("%s.files" % col)
            if grid.find({'md5': md5sum}).count() == 0:
                put_file(filename, data, collection=col)

        if is_sort_relationships == True:
            results['relationships'] = tlo.sort_relationships(user, meta=True)

        if get_objects:
            results['objects'] = tlo.sort_objects()

        results['id'] = str(tlo.id)
        return results
    except ValidationError as e:
        return {'success': False, 'message': str(e)}
Exemple #16
0
def add_new_event(title, description, event_type, source, method, reference,
                  date, analyst, bucket_list=None, ticket=None,
                  related_id=None,
                  related_type=None, relationship_type=None):
    """
    Add a new Event to CRIPTs.

    :param title: Event title.
    :type title: str
    :param description: Event description.
    :type description: str
    :param event_type: Event type.
    :type event_type: str
    :param source: The source which provided this information.
    :type source: str
    :param method: THe method of acquiring this information.
    :type method: str
    :param reference: Reference to this data.
    :type reference: str
    :param date: Date of acquiring this data.
    :type date: datetime.datetime
    :param analyst: The user adding this Event.
    :type analyst: str
    :param bucket_list: The bucket(s) to associate with this Event.
    :type: str
    :param ticket: Ticket to associate with this event.
    :type ticket: str
    :param related_id: ID of object to create relationship with
    :type related_id: str
    :param related_type: Type of object to create relationship with
    :type related_type: str
    :param relationship_type: Type of relationship to create.
    :type relationship_type: str
    :returns: dict with keys "success" (boolean) and "message" (str)
    """
    result = dict()
    if not source:
        return {'success': False, 'message': "Missing source information."}

    event = Event()
    event.title = title
    event.description = description
    event.set_event_type(event_type)

    s = create_embedded_source(name=source,
                               reference=reference,
                               method=method,
                               analyst=analyst,
                               date=date)
    event.add_source(s)

    if bucket_list:
        event.add_bucket_list(bucket_list, analyst)

    if ticket:
        event.add_ticket(ticket, analyst)

    related_obj = None
    if related_id:
        related_obj = class_from_id(related_type, related_id)
        if not related_obj:
            retVal['success'] = False
            retVal['message'] = 'Related Object not found.'
            return retVal

    try:
        event.save(username=analyst)

        if related_obj and event and relationship_type:
            relationship_type=RelationshipTypes.inverse(relationship=relationship_type)
            event.add_relationship(related_obj,
                                  relationship_type,
                                  analyst=analyst,
                                  get_rels=False)
            event.save(username=analyst)

        # run event triage
        event.reload()
        run_triage(event, analyst)

        message = ('<div>Success! Click here to view the new event: <a href='
                   '"%s">%s</a></div>' % (reverse('cripts.events.views.view_event',
                                                  args=[event.id]),
                                          title))
        result = {'success': True,
                  'message': message,
                  'id': str(event.id),
                  'object': event}

    except ValidationError, e:
        result = {'success': False,
                  'message': e}
Exemple #17
0
def add_object(type_, id_, object_type, source, method, reference, user,
               value=None, file_=None, add_indicator=False, get_objects=True,
               tlo=None, is_sort_relationships=False, is_validate_only=False,
               is_validate_locally=False, cache={}, **kwargs):
    """
    Add an object to the database.

    :param type_: The top-level object type.
    :type type_: str
    :param id_: The ObjectId of the top-level object.
    :type id_: str
    :param object_type: The type of the ObjectType being added.
    :type object_type: str
    :param source: The name of the source adding this object.
    :type source: str
    :param method: The method for this object.
    :type method: str
    :param reference: The reference for this object.
    :type reference: str
    :param user: The user adding this object.
    :type user: str
    :param value: The value of the object.
    :type value: str
    :param file_: The file if the object is a file upload.
    :type file_: file handle.
    :param add_indicator: Also add an indicator for this object.
    :type add_indicator: bool
    :param get_objects: Return the formatted list of objects when completed.
    :type get_objects: bool
    :param tlo: The CRIPTs top-level object we are adding objects to.
                This is an optional parameter used mainly for performance
                reasons (by not querying mongo if we already have the
                top level-object).
    :type tlo: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param is_sort_relationships: Return all relationships and meta, sorted
    :type is_sort_relationships: bool
    :param is_validate_only: Validate, but do not add to TLO.
    :type is_validate_only: bool
    :param is_validate_locally: Validate, but do not add b/c there is no TLO.
    :type is_validate_locally: bool
    :param cache: Cached data, typically for performance enhancements
                  during bulk operations.
    :type cache: dict
    :returns: dict with keys:
              "success" (boolean),
              "message" (str),
              "objects" (list),
              "relationships" (list)
    """

    if is_validate_locally: # no TLO provided
        return {"success": True}

    if not tlo:
        if type_ and id_:
            tlo = class_from_id(type_, id_)
        if not tlo:
            return {'success': False, 'message': "Failed to find TLO"}

    try:
        if file_:
            data = file_.read()
            filename = file_.name
            md5sum = md5(data).hexdigest()
            value = md5sum
            reference = filename
        ret = tlo.add_object(object_type, value,
                             source, method, reference, user)

        if not ret['success']:
            msg = '%s! [Type: "%s"][Value: "%s"]'
            return {"success": False,
                    "message": msg % (ret['message'], object_type, value)}
        else:
            results = {'success': True}

        if not is_validate_only: # save the object
            tlo.update(add_to_set__obj=ret['object'])
            results['message'] = "Object added successfully"

        if file_:
            
            #XXX: MongoEngine provides no direct GridFS access so we
            #     need to use pymongo directly.
            col = settings.COL_OBJECTS
            grid = mongo_connector("%s.files" % col)
            if grid.find({'md5': md5sum}).count() == 0:
                put_file(filename, data, collection=col) 

        if is_sort_relationships == True:
            results['relationships'] = tlo.sort_relationships(user, meta=True)

        if get_objects:
            results['objects'] = tlo.sort_objects()

        results['id'] = str(tlo.id)
        return results
    except ValidationError as e:
        return {'success': False, 'message': str(e)}
Exemple #18
0
def add_new_handler_object(data, rowData, request, is_validate_only=False,
                           is_sort_relationships=False, cache={}, obj=None):
    """
    Add an object to the database.

    :param data: The data for the object.
    :type data: dict
    :param rowData: Data from the row if using mass object upload.
    :type rowData: dict
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param is_validate_only: Only validate.
    :type is_validate_only: bool
    :param cache: Cached data, typically for performance enhancements
                  during bulk operations.
    :type cache: dict
    :param obj: The CRIPTs top-level object we are adding objects to.
                This is an optional parameter used mainly for performance
                reasons (by not querying mongo if we already have the
                top level-object).
    :type obj: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :returns: tuple (<result>, <retVal>)
    """

    result = False
    retVal = {}
    username = request.user.username

    if data:
        object_type = data.get('object_type')
        value = data.get('value')
        source = data.get('source')
        method = data.get('method')
        reference = data.get('reference')
        otype = data.get('otype')
        oid = data.get('oid')
        add_indicator = data.get('add_indicator')
    elif rowData:
        object_type = rowData.get(form_consts.Object.OBJECT_TYPE)
        value = rowData.get(form_consts.Object.VALUE)
        source = rowData.get(form_consts.Object.SOURCE)
        method = rowData.get(form_consts.Object.METHOD)
        reference = rowData.get(form_consts.Object.REFERENCE)
        otype = rowData.get(form_consts.Object.PARENT_OBJECT_TYPE)
        oid = rowData.get(form_consts.Object.PARENT_OBJECT_ID)
        add_indicator = rowData.get(form_consts.Object.ADD_INDICATOR)

    is_validate_locally = False
    analyst = "%s" % username

    # Default the user source to the user's organization if not specified
    if not source:
        source = cache.get('object_user_source')

        if not source:
            source = get_user_organization(analyst)
            cache['object_user_source'] =  source

    if (otype == "" or otype == None) or (oid == "" or oid == None):
        is_validate_locally = True

    # TODO file_
    object_result = add_object(
        otype, oid, object_type, source, method, reference, analyst,
        value=value, file_=None, add_indicator=add_indicator, get_objects=False,
        tlo=obj, is_validate_only=is_validate_only,
        is_sort_relationships=is_sort_relationships,
        is_validate_locally=is_validate_locally, cache=cache
    )

    if object_result['success']:
        result = True
        if 'message' in object_result:
            retVal['message'] = object_result['message']
        if is_validate_only == False:
            if obj == None:
                obj = class_from_id(otype, oid)

            if obj:
                retVal['secondary'] = {'type': otype, 'id': oid}

                if object_result.get('relationships'):
                    retVal['secondary']['relationships'] = object_result.get('relationships')
    else:
        retVal['message'] = object_result['message']

    return result, retVal
Exemple #19
0
def update_relationship_dates(left_class=None, right_class=None,
                              left_type=None, left_id=None,
                              right_type=None, right_id=None,
                              rel_type=None, rel_date=None,
                              new_date=None,analyst=None):
    """
    Update the relationship date between two top-level objects.

    :param left_class: The first top-level object.
    :type left_class: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param right_class: The second top-level object.
    :type right_class: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param left_type: The type of first top-level object.
    :type left_type: str
    :param left_id: The ObjectId of the first top-level object.
    :type left_id: str
    :param right_type: The type of second top-level object.
    :type right_type: str
    :param right_id: The ObjectId of the second top-level object.
    :type right_id: str
    :param rel_type: The type of relationship.
    :type rel_type: str
    :param rel_date: The date this relationship applies.
    :type rel_date: datetime.datetime
    :param new_date: The new date of the relationship.
    :type new_date: str
    :param analyst: The user updating this relationship.
    :type analyst: str
    :returns: dict with keys "success" (boolean) and "message" (str)
    """

    if rel_date is None or rel_date == 'None':
        rel_date = None
    elif isinstance(rel_date, basestring) and rel_date != '':
        rel_date = parse(rel_date, fuzzy=True)
    elif not isinstance(rel_date, datetime.datetime):
        rel_date = None

    if new_date is None or new_date == 'None':
        new_date = None
    elif isinstance(new_date, basestring) and new_date != '':
        new_date = parse(new_date, fuzzy=True)
    elif not isinstance(new_date, datetime.datetime):
        new_date = None

    if not left_class:
        if left_type and left_id:
            left_class = class_from_id(left_type, left_id)
            if not left_class:
                return {'success': False,
                        'message': "Unable to get object."}
        else:
            return {'success': False,
                    'message': "Need a valid left type and id"}

    # update relationship
    if right_class:
        results = left_class.edit_relationship_date(rel_item=right_class,
                                                    rel_type=rel_type,
                                                    rel_date=rel_date,
                                                    new_date=new_date,
                                                    analyst=analyst)
        left_class.save(username=analyst)
        right_class.save(username=analyst)
    else:
        if right_type and right_id:
            results = left_class.edit_relationship_date(type_=right_type,
                                                        rel_id=right_id,
                                                        rel_type=rel_type,
                                                        rel_date=rel_date,
                                                        new_date=new_date,
                                                        analyst=analyst)
            left_class.save(username=analyst)
        else:
            return {'success': False,
                    'message': "Need a valid right type and id"}

    return results
Exemple #20
0
def bulk_add_object_inline(request):
    """
    Bulk add objects inline.

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

    formdict = form_to_dict(AddObjectForm(request.user))

    if request.method == "POST" and request.is_ajax():
        response = parse_bulk_upload(request, parse_row_to_bound_object_form,
                                     add_new_handler_object_via_bulk, formdict)

        secondary_data_array = response.get('secondary')
        if secondary_data_array:
            latest_secondary_data = secondary_data_array[-1]
            class_type = class_from_id(latest_secondary_data['type'],
                                       latest_secondary_data['id'])

            subscription = {
                'type': latest_secondary_data['type'],
                'id': latest_secondary_data['id'],
                'value': latest_secondary_data['id']
            }

            object_listing_html = render_to_string(
                'objects_listing_widget.html', {
                    'objects': class_type.sort_objects(),
                    'subscription': subscription
                }, RequestContext(request))

            response['html'] = object_listing_html

            is_relationship_made = False
            for secondary_data in secondary_data_array:
                if secondary_data.get('relationships'):
                    is_relationship_made = True
                    break

            if is_relationship_made == True:
                rel_html = render_to_string(
                    'relationships_listing_widget.html', {
                        'relationship':
                        subscription,
                        'relationships':
                        class_type.sort_relationships(request.user, meta=True)
                    }, RequestContext(request))

                response['rel_msg'] = rel_html
                response['rel_made'] = True

        return HttpResponse(json.dumps(response, default=json_handler),
                            content_type="application/json")
    else:
        is_prevent_initial_table = request.GET.get('isPreventInitialTable',
                                                   False)
        is_use_item_source = request.GET.get('useItemSource', False)

        if is_use_item_source == True or is_use_item_source == "true":
            otype = request.GET.get('otype')
            oid = request.GET.get('oid')

            # Get the item with the type and ID from the database
            obj = class_from_id(otype, oid)

            if obj:
                source_field_name = get_source_field_for_class(otype)
                if source_field_name:

                    # If the item has a source, then use the source value
                    # to set as the default source
                    if hasattr(obj, "source"):
                        source_field = get_field_from_label("source", formdict)
                        earliest_source = None
                        earliest_date = None

                        # Get the earliest source, compared by date
                        for source in obj.source:
                            for source_instance in source.instances:
                                if earliest_source == None or source_instance.date < earliest_date:
                                    earliest_date = source_instance.date
                                    earliest_source = source

                        if earliest_source:
                            source_field['initial'] = earliest_source.name

        return render_to_response(
            'bulk_add_object_inline.html', {
                'formdict': formdict,
                'title': "Bulk Add Objects",
                'is_prevent_initial_table': is_prevent_initial_table,
                'table_name': 'object_inline'
            }, RequestContext(request))
Exemple #21
0
def add_new_handler_object(data,
                           rowData,
                           request,
                           is_validate_only=False,
                           is_sort_relationships=False,
                           cache={},
                           obj=None):
    """
    Add an object to the database.

    :param data: The data for the object.
    :type data: dict
    :param rowData: Data from the row if using mass object upload.
    :type rowData: dict
    :param request: The Django request.
    :type request: :class:`django.http.HttpRequest`
    :param is_validate_only: Only validate.
    :type is_validate_only: bool
    :param cache: Cached data, typically for performance enhancements
                  during bulk operations.
    :type cache: dict
    :param obj: The CRIPTs top-level object we are adding objects to.
                This is an optional parameter used mainly for performance
                reasons (by not querying mongo if we already have the
                top level-object).
    :type obj: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :returns: tuple (<result>, <retVal>)
    """

    result = False
    retVal = {}
    username = request.user.username

    if data:
        object_type = data.get('object_type')
        value = data.get('value')
        source = data.get('source')
        method = data.get('method')
        reference = data.get('reference')
        otype = data.get('otype')
        oid = data.get('oid')
        add_indicator = data.get('add_indicator')
    elif rowData:
        object_type = rowData.get(form_consts.Object.OBJECT_TYPE)
        value = rowData.get(form_consts.Object.VALUE)
        source = rowData.get(form_consts.Object.SOURCE)
        method = rowData.get(form_consts.Object.METHOD)
        reference = rowData.get(form_consts.Object.REFERENCE)
        otype = rowData.get(form_consts.Object.PARENT_OBJECT_TYPE)
        oid = rowData.get(form_consts.Object.PARENT_OBJECT_ID)
        add_indicator = rowData.get(form_consts.Object.ADD_INDICATOR)

    is_validate_locally = False
    analyst = "%s" % username

    # Default the user source to the user's organization if not specified
    if not source:
        source = cache.get('object_user_source')

        if not source:
            source = get_user_organization(analyst)
            cache['object_user_source'] = source

    if (otype == "" or otype == None) or (oid == "" or oid == None):
        is_validate_locally = True

    # TODO file_
    object_result = add_object(otype,
                               oid,
                               object_type,
                               source,
                               method,
                               reference,
                               analyst,
                               value=value,
                               file_=None,
                               add_indicator=add_indicator,
                               get_objects=False,
                               tlo=obj,
                               is_validate_only=is_validate_only,
                               is_sort_relationships=is_sort_relationships,
                               is_validate_locally=is_validate_locally,
                               cache=cache)

    if object_result['success']:
        result = True
        if 'message' in object_result:
            retVal['message'] = object_result['message']
        if is_validate_only == False:
            if obj == None:
                obj = class_from_id(otype, oid)

            if obj:
                retVal['secondary'] = {'type': otype, 'id': oid}

                if object_result.get('relationships'):
                    retVal['secondary']['relationships'] = object_result.get(
                        'relationships')
    else:
        retVal['message'] = object_result['message']

    return result, retVal
Exemple #22
0
def process_changed_fields(initial_message, changed_fields, obj):
    """
    Processes the changed fields to determine what actually changed.

    :param message: An initial message to include.
    :type message: str
    :param changed_fields: A list of field names that were changed.
    :type changed_fields: list of str
    :param obj: The object.
    :type obj: class which inherits from
               :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :returns: str: Returns a message indicating what was changed.
    """

    obj_type = obj._meta['cripts_type']
    message = initial_message

    if message is None:
        message = ''

    source_filter = None

    for changed_field in changed_fields:

        # Fields may be fully qualified, e.g. source.1.instances.0.reference
        # So, split on the '.' character and get the root of the changed field
        base_changed_field = MappedMongoFields.get_mapped_mongo_field(
            obj_type,
            changed_field.split('.')[0])

        new_value = getattr(obj, base_changed_field, '')
        old_obj = class_from_id(obj_type, obj.id)
        old_value = getattr(old_obj, base_changed_field, '')

        change_handler = ChangeParser.get_changed_field_handler(
            obj_type, base_changed_field)

        if change_handler is not None:
            change_message = change_handler(old_value, new_value,
                                            base_changed_field)

            if isinstance(change_message, dict):
                if change_message.get('source_filter') is not None:
                    new_source_filter = change_message.get('source_filter')
                    source_filter = combine_source_filters(
                        source_filter, new_source_filter)

                change_message = change_message.get('message')

            if change_message is not None:
                message += "\n" + change_message[:1].capitalize(
                ) + change_message[1:]
        else:
            change_field_handler = ChangeParser.generic_single_field_change_handler

            if isinstance(old_value, BaseList):

                list_value = None

                if len(old_value) > 0:
                    list_value = old_value[0]
                elif len(new_value) > 0:
                    list_value = new_value[0]

                if isinstance(list_value, basestring):
                    change_field_handler = ChangeParser.generic_list_change_handler
                elif isinstance(list_value, EmbeddedDocument):
                    change_field_handler = ChangeParser.generic_list_json_change_handler

            change_message = change_field_handler(old_value, new_value,
                                                  base_changed_field)

            if isinstance(change_message, dict):
                if change_message.get('source_filter') is not None:
                    new_source_filter = change_message.get('source_filter')
                    combine_source_filters(source_filter, new_source_filter)

                change_message = change_message.get('message')

            if change_message is not None:
                message += "\n" + change_message[:1].capitalize(
                ) + change_message[1:]

    return {'message': message, 'source_filter': source_filter}
Exemple #23
0
def add_new_event(title,
                  description,
                  event_type,
                  source,
                  method,
                  reference,
                  date,
                  analyst,
                  bucket_list=None,
                  ticket=None,
                  related_id=None,
                  related_type=None,
                  relationship_type=None):
    """
    Add a new Event to CRIPTs.

    :param title: Event title.
    :type title: str
    :param description: Event description.
    :type description: str
    :param event_type: Event type.
    :type event_type: str
    :param source: The source which provided this information.
    :type source: str
    :param method: THe method of acquiring this information.
    :type method: str
    :param reference: Reference to this data.
    :type reference: str
    :param date: Date of acquiring this data.
    :type date: datetime.datetime
    :param analyst: The user adding this Event.
    :type analyst: str
    :param bucket_list: The bucket(s) to associate with this Event.
    :type: str
    :param ticket: Ticket to associate with this event.
    :type ticket: str
    :param related_id: ID of object to create relationship with
    :type related_id: str
    :param related_type: Type of object to create relationship with
    :type related_type: str
    :param relationship_type: Type of relationship to create.
    :type relationship_type: str
    :returns: dict with keys "success" (boolean) and "message" (str)
    """
    result = dict()
    if not source:
        return {'success': False, 'message': "Missing source information."}

    event = Event()
    event.title = title
    event.description = description
    event.set_event_type(event_type)

    s = create_embedded_source(name=source,
                               reference=reference,
                               method=method,
                               analyst=analyst,
                               date=date)
    event.add_source(s)

    if bucket_list:
        event.add_bucket_list(bucket_list, analyst)

    if ticket:
        event.add_ticket(ticket, analyst)

    related_obj = None
    if related_id:
        related_obj = class_from_id(related_type, related_id)
        if not related_obj:
            retVal['success'] = False
            retVal['message'] = 'Related Object not found.'
            return retVal

    try:
        event.save(username=analyst)

        if related_obj and event and relationship_type:
            relationship_type = RelationshipTypes.inverse(
                relationship=relationship_type)
            event.add_relationship(related_obj,
                                   relationship_type,
                                   analyst=analyst,
                                   get_rels=False)
            event.save(username=analyst)

        # run event triage
        event.reload()
        run_triage(event, analyst)

        message = ('<div>Success! Click here to view the new event: <a href='
                   '"%s">%s</a></div>' %
                   (reverse('cripts.events.views.view_event', args=[event.id
                                                                    ]), title))
        result = {
            'success': True,
            'message': message,
            'id': str(event.id),
            'object': event
        }

    except ValidationError, e:
        result = {'success': False, 'message': e}
Exemple #24
0
def create_notification(obj, username, message, source_filter=None,
                        notification_type=NotificationType.ALERT):
    """
    Generate a notification -- based on mongo obj.

    :param obj: The object.
    :type obj: class which inherits from
               :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param username: The user creating the notification.
    :type username: str
    :param message: The notification message.
    :type message: str
    :param source_filter: Filter on who can see this notification.
    :type source_filter: list(str)
    :param notification_type: The notification type (e.g. alert, error).
    :type notification_type: str
    """

    n = Notification()
    n.analyst = username
    obj_type = obj._meta['cripts_type']
    users = set()

    if notification_type not in NotificationType.ALL:
        notification_type = NotificationType.ALERT

    n.notification_type = notification_type

    if obj_type == 'Comment':
        n.obj_id = obj.obj_id
        n.obj_type = obj.obj_type
        n.notification = "%s added a comment: %s" % (username, obj.comment)
        users.update(obj.users) # notify mentioned users

        # for comments, use the sources from the object that it is linked to
        # instead of the comments's sources
        obj = class_from_id(n.obj_type, n.obj_id)
    else:
        n.notification = message
        n.obj_id = obj.id
        n.obj_type = obj_type

    if hasattr(obj, 'source'):
        sources = [s.name for s in obj.source]
        subscribed_users = get_subscribed_users(n.obj_type, n.obj_id, sources)

        # Filter on users that have access to the source of the object
        for subscribed_user in subscribed_users:
            allowed_sources = user_sources(subscribed_user)

            for allowed_source in allowed_sources:
                if allowed_source in sources:
                    if source_filter is None or allowed_source in source_filter:
                        users.add(subscribed_user)
                        break
    else:
        users.update(get_subscribed_users(n.obj_type, n.obj_id, []))

    users.discard(username) # don't notify the user creating this notification
    n.users = list(users)
    if not len(n.users):
        return
    try:
        n.save()
    except ValidationError:
        pass

    # Signal potentially waiting threads that notification information is available
    for user in n.users:
        notification_lock = NotificationLockManager.get_notification_lock(user)
        notification_lock.acquire()

        try:
            notification_lock.notifyAll()
        finally:
            notification_lock.release()
Exemple #25
0
def create_notification(obj,
                        username,
                        message,
                        source_filter=None,
                        notification_type=NotificationType.ALERT):
    """
    Generate a notification -- based on mongo obj.

    :param obj: The object.
    :type obj: class which inherits from
               :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param username: The user creating the notification.
    :type username: str
    :param message: The notification message.
    :type message: str
    :param source_filter: Filter on who can see this notification.
    :type source_filter: list(str)
    :param notification_type: The notification type (e.g. alert, error).
    :type notification_type: str
    """

    n = Notification()
    n.analyst = username
    obj_type = obj._meta['cripts_type']
    users = set()

    if notification_type not in NotificationType.ALL:
        notification_type = NotificationType.ALERT

    n.notification_type = notification_type

    if obj_type == 'Comment':
        n.obj_id = obj.obj_id
        n.obj_type = obj.obj_type
        n.notification = "%s added a comment: %s" % (username, obj.comment)
        users.update(obj.users)  # notify mentioned users

        # for comments, use the sources from the object that it is linked to
        # instead of the comments's sources
        obj = class_from_id(n.obj_type, n.obj_id)
    else:
        n.notification = message
        n.obj_id = obj.id
        n.obj_type = obj_type

    if hasattr(obj, 'source'):
        sources = [s.name for s in obj.source]
        subscribed_users = get_subscribed_users(n.obj_type, n.obj_id, sources)

        # Filter on users that have access to the source of the object
        for subscribed_user in subscribed_users:
            allowed_sources = user_sources(subscribed_user)

            for allowed_source in allowed_sources:
                if allowed_source in sources:
                    if source_filter is None or allowed_source in source_filter:
                        users.add(subscribed_user)
                        break
    else:
        users.update(get_subscribed_users(n.obj_type, n.obj_id, []))

    users.discard(username)  # don't notify the user creating this notification
    n.users = list(users)
    if not len(n.users):
        return
    try:
        n.save()
    except ValidationError:
        pass

    # Signal potentially waiting threads that notification information is available
    for user in n.users:
        notification_lock = NotificationLockManager.get_notification_lock(user)
        notification_lock.acquire()

        try:
            notification_lock.notifyAll()
        finally:
            notification_lock.release()
Exemple #26
0
def delete_relationship(left_class=None, right_class=None,
                       left_type=None, left_id=None,
                       right_type=None, right_id=None,
                       rel_type=None, rel_date=None,
                       analyst=None, get_rels=True):
    """
    Delete a relationship between two top-level objects.

    :param left_class: The first top-level object.
    :type left_class: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param right_class: The second top-level object.
    :type right_class: :class:`cripts.core.cripts_mongoengine.CriptsBaseAttributes`
    :param left_type: The type of first top-level object.
    :type left_type: str
    :param left_id: The ObjectId of the first top-level object.
    :type left_id: str
    :param right_type: The type of second top-level object.
    :type right_type: str
    :param right_id: The ObjectId of the second top-level object.
    :type right_id: str
    :param rel_type: The type of relationship.
    :type rel_type: str
    :param rel_date: The date this relationship applies.
    :type rel_date: datetime.datetime
    :param analyst: The user deleting this relationship.
    :type analyst: str
    :param get_rels: Return the relationships after forging.
    :type get_rels: boolean
    :returns: dict with keys "success" (boolean) and "message" (str if
                failed, dict if successful)
    """

    if rel_date is None or rel_date == 'None':
        rel_date = None
    elif isinstance(rel_date, basestring) and rel_date != '':
        rel_date = parse(rel_date, fuzzy=True)
    elif not isinstance(rel_date, datetime.datetime):
        rel_date = None

    if not left_class:
        if left_type and left_id:
            left_class = class_from_id(left_type, left_id)
            if not left_class:
                return {'success': False,
                        'message': "Unable to get object."}
        else:
            return {'success': False,
                    'message': "Need a valid left type and id"}

    # delete relationship
    if right_class:
        results = left_class.delete_relationship(rel_item=right_class,
                                    rel_type=rel_type,
                                    rel_date=rel_date,
                                    analyst=analyst)
    else:
        if right_type and right_id:
            results = left_class.delete_relationship(type_=right_type,
                                        rel_id=right_id,
                                        rel_type=rel_type,
                                        rel_date=rel_date,
                                        analyst=analyst)
        else:
            return {'success': False,
                    'message': "Need a valid right type and id"}
    if results['success']:
        left_class.save(username=analyst)
        if get_rels:
            results['relationships'] = left_class.sort_relationships("%s" % analyst, meta=True)
    return results