com.denimgroup.threadfix.data.dao.hibernate.VulnerabilitySearchCriteriaConstructor.java Source code

Java tutorial

Introduction

Here is the source code for com.denimgroup.threadfix.data.dao.hibernate.VulnerabilitySearchCriteriaConstructor.java

Source

////////////////////////////////////////////////////////////////////////
//
//     Copyright (c) 2009-2015 Denim Group, Ltd.
//
//     The contents of this file are subject to the Mozilla Public License
//     Version 2.0 (the "License"); you may not use this file except in
//     compliance with the License. You may obtain a copy of the License at
//     http://www.mozilla.org/MPL/
//
//     Software distributed under the License is distributed on an "AS IS"
//     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//     License for the specific language governing rights and limitations
//     under the License.
//
//     The Original Code is ThreadFix.
//
//     The Initial Developer of the Original Code is Denim Group, Ltd.
//     Portions created by Denim Group, Ltd. are Copyright (C)
//     Denim Group, Ltd. All Rights Reserved.
//
//     Contributor(s): Denim Group, Ltd.
//
////////////////////////////////////////////////////////////////////////
package com.denimgroup.threadfix.data.dao.hibernate;

import com.denimgroup.threadfix.data.entities.*;
import com.denimgroup.threadfix.data.enums.VulnerabilityDefectConsistencyState;
import com.denimgroup.threadfix.logging.SanitizedLogger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import java.util.Calendar;
import java.util.List;

import static com.denimgroup.threadfix.CollectionUtils.list;
import static com.denimgroup.threadfix.data.entities.AuthenticationRequired.*;

@SuppressWarnings("unchecked")
public class VulnerabilitySearchCriteriaConstructor {

    private static final SanitizedLogger LOG = new SanitizedLogger(VulnerabilitySearchCriteriaConstructor.class);

    final Session session;
    final Criteria criteria;
    final VulnerabilitySearchParameters parameters;

    private VulnerabilitySearchCriteriaConstructor(Session session, VulnerabilitySearchParameters parameters) {
        this.session = session;
        this.parameters = parameters;
        criteria = session.createCriteria(Vulnerability.class);
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        criteria.createAlias("genericSeverity", "severity");
        criteria.createAlias("genericVulnerability", "genericVulnAlias");
        criteria.createAlias("surfaceLocation", "surface");
        criteria.createAlias("application", "applicationAlias");
        criteria.createAlias("applicationAlias.organization", "team");

        LOG.debug("Creating criteria");

        addTeamsAndApplications();
        addAppTags();
        addVulnTags();
        addSeverities();
        addChannelTypeRestrictions();
        addTypeRestrictions();
        addDefectOptions();
        addRemediationOptions();
        addAgeRestrictions();
        addPathAndParameter();
        addMinimumMergedFindings();
        addStatusRestrictions();
        addDateRangeRestrictions();
        addPermissionRestrictions();
        addVulnCommentRestrictions();
    }

    private void addPermissionRestrictions() {
        if (parameters.getPermissionsList() != null && !parameters.getPermissionsList().isEmpty()) {
            criteria.createAlias("endpointPermissions", "permissionAlias");
            criteria.add(Restrictions.in("permissionAlias.name", parameters.getPermissionsList()));
        }

        if (parameters.getShowAuthenticated() || parameters.getShowUnknown()
                || parameters.getShowUnauthenticated()) {
            List<AuthenticationRequired> ordinalValues = list();

            boolean acceptNull = false;

            if (parameters.getShowAuthenticated()) {
                ordinalValues.add(AUTHENTICATED);
            }
            if (parameters.getShowUnauthenticated()) {
                ordinalValues.add(ANONYMOUS);
            }
            if (parameters.getShowUnknown()) {
                ordinalValues.add(UNKNOWN);
                acceptNull = true;
            }

            Criterion restrictions;
            if (acceptNull) {
                restrictions = Restrictions.or(Restrictions.in("authenticationRequired", ordinalValues),
                        Restrictions.isNull("authenticationRequired"));
            } else {
                restrictions = Restrictions.in("authenticationRequired", ordinalValues);
            }
            criteria.add(restrictions);
        }

    }

    public static Criteria getCriteriaWithRestrictions(Session session, VulnerabilitySearchParameters parameters) {
        assert session != null;
        assert parameters != null;

        return new VulnerabilitySearchCriteriaConstructor(session, parameters).criteria;
    }

    private void addDateRangeRestrictions() {
        if (parameters.getStartDate() != null || parameters.getEndDate() != null) {

            if (parameters.getStartDate() != null) {
                Calendar targetDate = Calendar.getInstance();
                targetDate.setTime(parameters.getStartDate());

                LOG.debug("Adding start date " + targetDate);
                criteria.add(Restrictions.gt("openTime", targetDate));
            }

            if (parameters.getEndDate() != null) {
                Calendar targetDate = Calendar.getInstance();
                targetDate.setTime(parameters.getEndDate());

                LOG.debug("Adding end date " + targetDate);
                criteria.add(Restrictions.lt("openTime", targetDate));
            }
        }

        if (parameters.getStartCloseDate() != null || parameters.getEndCloseDate() != null) {

            if (parameters.getStartCloseDate() != null) {
                Calendar targetDate = Calendar.getInstance();
                targetDate.setTime(parameters.getStartCloseDate());

                LOG.debug("Adding start close date " + targetDate);
                criteria.add(Restrictions.or(Restrictions.eq("closeTime", null),
                        Restrictions.gt("closeTime", targetDate)));
            }

            if (parameters.getEndCloseDate() != null) {
                Calendar targetDate = Calendar.getInstance();
                targetDate.setTime(parameters.getEndCloseDate());

                LOG.debug("Adding end close date " + targetDate);
                criteria.add(Restrictions.or(Restrictions.eq("closeTime", null),
                        Restrictions.lt("closeTime", targetDate)));
            }
        }
    }

    // Add team and application restrictions
    private void addTeamsAndApplications() {
        List<Integer> appIds = list(), teamIds = list();

        if (parameters.getTeams() != null && !parameters.getTeams().isEmpty()) {
            for (Organization organization : parameters.getTeams()) {
                if (organization.getId() != null) {
                    teamIds.add(organization.getId());
                }
            }
        }

        if (parameters.getApplications() != null && !parameters.getApplications().isEmpty()) {
            for (Application application : parameters.getApplications()) {
                if (application.getId() != null) {
                    appIds.add(application.getId());
                }
            }
        }

        if (appIds.isEmpty() || teamIds.isEmpty()) {
            if (appIds.isEmpty()) {
                criteria.add(Restrictions.eq("applicationAlias.active", true));
                LOG.debug("No application IDs added to the criteria.");
            } else {
                criteria.add(Restrictions.in("application.id", appIds));
                LOG.debug("Added applications with IDs " + appIds);
            }

            if (teamIds.isEmpty()) {
                criteria.add(Restrictions.eq("team.active", true));
                LOG.debug("No team IDs added to the criteria.");
            } else {
                criteria.add(Restrictions.in("team.id", teamIds));
                LOG.debug("Added teams with IDs " + teamIds);
            }
        } else {

            // Make sure to OR things together if both application and team IDs are present. This ensures that
            // if a user has permission to see one team and one application from a different team, all of the
            // vulnerabilities will show up.
            criteria.add(Restrictions.or(Restrictions.in("application.id", appIds),
                    Restrictions.in("team.id", teamIds)));

            LOG.debug("Added applications with IDs " + appIds);
            LOG.debug("Added teams with IDs " + teamIds);
        }
    }

    private void addStatusRestrictions() {
        boolean showOpen = parameters.getShowOpen() != null && parameters.getShowOpen();
        boolean showClosed = parameters.getShowClosed() != null && parameters.getShowClosed();
        if (showOpen != showClosed) {
            criteria.add(Restrictions.eq("active", showOpen));
            LOG.debug("Setting active = " + showOpen);
        }

        boolean hidden = parameters.getShowHidden() != null && parameters.getShowHidden();
        boolean falsePositive = parameters.getShowFalsePositive() != null && parameters.getShowFalsePositive();

        LOG.debug("Setting hidden = " + hidden);
        LOG.debug("Setting falsePositive = " + falsePositive);

        criteria.add(Restrictions.eq("hidden", hidden)).add(Restrictions.eq("isFalsePositive", falsePositive));
    }

    private void addMinimumMergedFindings() {
        if (parameters.getNumberMerged() != null && parameters.getNumberMerged() > 0) {
            LOG.debug("Adding number merged = " + parameters.getNumberMerged());
            criteria.add(Restrictions.sizeGe("findings", parameters.getNumberMerged()));
        }
    }

    private void addPathAndParameter() {
        String path = parameters.getPath();
        if (path != null && !path.trim().equals("")) {
            LOG.debug("Adding path  = " + path);
            criteria.add(Restrictions.like("surface.path", "%" + path + "%").ignoreCase());
        }

        String parameter = parameters.getParameter();
        if (parameter != null && !parameter.trim().equals("")) {
            LOG.debug("Adding parameter  = " + parameter);

            criteria.add(Restrictions.like("surface.parameter", "%" + parameter + "%").ignoreCase());
        }
    }

    private void addAgeRestrictions() {
        // Limit scanner if present
        if (parameters.getDaysOldModifier() != null
                && (parameters.getDaysOldModifier().equals("Less")
                        || parameters.getDaysOldModifier().equals("More"))
                && parameters.getDaysOld() != null && parameters.getDaysOld() > 0) {

            Criteria subCriteria = session.createCriteria(Finding.class);

            Calendar targetDate = Calendar.getInstance();
            targetDate.add(Calendar.DAY_OF_YEAR, -parameters.getDaysOld());

            subCriteria.createAlias("scan", "scanAlias");
            if (parameters.getDaysOldModifier().equals("More")) {
                //subCriteria.add(Restrictions.lt("scanAlias.openTime", targetDate));
                criteria.add(Restrictions.lt("openTime", targetDate));
                LOG.debug("Set age restriction to after " + parameters.getDaysOld() + " days ago.");
            } else if (parameters.getDaysOldModifier().equals("Less")) {
                //subCriteria.add(Restrictions.gt("scanAlias.openTime", targetDate));
                criteria.add(Restrictions.gt("openTime", targetDate));
                LOG.debug("Set age restriction to before " + parameters.getDaysOld() + " days ago.");
            }
        }
    }

    private void addAppTags() {
        List<Integer> appIds;
        List<Integer> tagIds = list();

        if (parameters.getTags() != null) {
            for (Tag tag : parameters.getTags()) {
                if (tag.getId() != null) {
                    tagIds.add(tag.getId());
                }
            }
        }

        if (tagIds.isEmpty()) {
            LOG.debug("No tag IDs found in parameters.");
        } else {
            Criteria subCriteria = session.createCriteria(Tag.class);
            subCriteria.createAlias("applications", "applicationsAlias");
            subCriteria.add(Restrictions.in("id", tagIds));
            subCriteria.setProjection(Projections.property("applicationsAlias.id"));
            appIds = (List<Integer>) subCriteria.list();

            if (appIds.isEmpty())
                appIds.add(0);
            criteria.add(Restrictions.in("application.id", appIds));
            LOG.debug("Added applications with IDs " + appIds);
        }
    }

    private void addVulnTags() {
        List<Integer> tagIds = list();

        if (parameters.getVulnTags() != null) {
            for (Tag tag : parameters.getVulnTags()) {
                if (tag.getId() != null) {
                    tagIds.add(tag.getId());
                }
            }
        }

        if (tagIds.isEmpty()) {
            LOG.debug("No vuln tag IDs found in parameters.");
        } else {
            criteria.createAlias("tags", "tagsAlias");
            criteria.add(Restrictions.in("tagsAlias.id", tagIds));
            LOG.debug("Added tags with IDs " + tagIds);
        }
    }

    private void addTypeRestrictions() {
        if (parameters.getGenericVulnerabilities() != null && !parameters.getGenericVulnerabilities().isEmpty()) {
            List<Integer> genericVulnerabilityIds = list();
            for (GenericVulnerability genericVulnerability : parameters.getGenericVulnerabilities()) {
                if (genericVulnerability.getId() != null) {
                    genericVulnerabilityIds.add(genericVulnerability.getId());
                }
            }
            if (!genericVulnerabilityIds.isEmpty()) {
                LOG.debug("Restricting CWE ID to " + genericVulnerabilityIds);
                criteria.add(Restrictions.in("genericVulnAlias.id", genericVulnerabilityIds));
            }
        }
    }

    private void addDefectOptions() {
        boolean showDefectPresent = parameters.getShowDefectPresent() != null && parameters.getShowDefectPresent();
        boolean showDefectNotPresent = parameters.getShowDefectNotPresent() != null
                && parameters.getShowDefectNotPresent();
        boolean showDefectOpen = parameters.getShowDefectOpen() != null && parameters.getShowDefectOpen();
        boolean showDefectClosed = parameters.getShowDefectClosed() != null && parameters.getShowDefectClosed();

        Criterion defectRestrictions = null;
        boolean defectAliasCreated = false;

        if (showDefectPresent) {
            defectRestrictions = disjoinRestrictions(defectRestrictions, Restrictions.isNotNull("defect"));
            LOG.debug("Adding defect not null restriction");
        }

        if (showDefectNotPresent) {
            defectRestrictions = disjoinRestrictions(defectRestrictions, Restrictions.isNull("defect"));
            LOG.debug("Adding defect is null restriction");
        }

        if (showDefectOpen) {
            if (!defectAliasCreated) {
                criteria.createAlias("defect", "d", Criteria.LEFT_JOIN);
                defectAliasCreated = true;
            }
            defectRestrictions = disjoinRestrictions(defectRestrictions,
                    Restrictions.in("d.status", Defect.OPEN_CODES));
            LOG.debug("Adding defect is open restriction");
        }

        if (showDefectClosed) {
            if (!defectAliasCreated) {
                criteria.createAlias("defect", "d", Criteria.LEFT_JOIN);
                defectAliasCreated = true;
            }
            defectRestrictions = disjoinRestrictions(defectRestrictions,
                    Restrictions.in("d.status", Defect.CLOSED_CODES));
            LOG.debug("Adding defect is closed restriction");
        }

        if (defectRestrictions != null) {
            criteria.add(defectRestrictions);
        }
    }

    private void addRemediationOptions() {
        boolean showInconsistentClosedDefectNeedsScan = parameters
                .getShowInconsistentClosedDefectNeedsScan() != null
                && parameters.getShowInconsistentClosedDefectNeedsScan();
        boolean showInconsistentClosedDefectOpenInScan = parameters
                .getShowInconsistentClosedDefectOpenInScan() != null
                && parameters.getShowInconsistentClosedDefectOpenInScan();
        boolean showInconsistentOpenDefect = parameters.getShowInconsistentOpenDefect() != null
                && parameters.getShowInconsistentOpenDefect();

        Criterion remediationRestrictions = null;

        if (showInconsistentClosedDefectNeedsScan) {
            remediationRestrictions = disjoinRestrictions(remediationRestrictions,
                    Restrictions.eq("vulnerabilityDefectConsistencyState",
                            VulnerabilityDefectConsistencyState.VULN_OPEN_DEFECT_CLOSED_NEEDS_SCAN.name()));
            LOG.debug("Adding defect is closed since last scan, but vulnerability is open restriction");
        }

        if (showInconsistentClosedDefectOpenInScan) {
            remediationRestrictions = disjoinRestrictions(remediationRestrictions,
                    Restrictions.eq("vulnerabilityDefectConsistencyState",
                            VulnerabilityDefectConsistencyState.VULN_OPEN_DEFECT_CLOSED_STILL_IN_SCAN.name()));
            LOG.debug("Adding defect is closed before last scan, but vulnerability is open restriction");
        }

        if (showInconsistentOpenDefect) {
            remediationRestrictions = disjoinRestrictions(remediationRestrictions,
                    Restrictions.eq("vulnerabilityDefectConsistencyState",
                            VulnerabilityDefectConsistencyState.VULN_CLOSED_DEFECT_OPEN_NEEDS_SCAN.name()));
            LOG.debug("Adding defect is open, but vulnerability is closed restriction");
        }

        if (remediationRestrictions != null) {
            criteria.add(remediationRestrictions);
        }
    }

    private Criterion disjoinRestrictions(Criterion restriction1, Criterion restriction2) {
        if (restriction1 == null) {
            return restriction2;
        } else {
            return Restrictions.or(restriction1, restriction2);
        }
    }

    // Limit Generic Severities if they were present
    private void addSeverities() {
        if (parameters.getGenericSeverities() != null && !parameters.getGenericSeverities().isEmpty()) {
            List<Integer> severityIntValues = list();
            for (GenericSeverity severity : parameters.getGenericSeverities()) {
                severityIntValues.add(severity.getIntValue());
            }
            if (!severityIntValues.isEmpty()) {
                LOG.debug("Restricting severity ID to one of " + severityIntValues);
                criteria.add(Restrictions.in("severity.intValue", severityIntValues));
            }
        }
    }

    private void addChannelTypeRestrictions() {

        // Limit scanner if present
        if (parameters.getChannelTypes() != null && !parameters.getChannelTypes().isEmpty()) {
            List<Integer> channelTypeIds = list();
            for (ChannelType channelType : parameters.getChannelTypes()) {
                if (channelType.getId() != null) {
                    channelTypeIds.add(channelType.getId());
                }
            }

            if (!channelTypeIds.isEmpty()) {
                Criteria subCriteria = session.createCriteria(Finding.class);

                subCriteria.createAlias("scan", "myScan");
                subCriteria.createAlias("myScan.applicationChannel", "myApplicationChannel");
                subCriteria.createAlias("myApplicationChannel.channelType", "myChannelType");

                subCriteria.add(Restrictions.in("myChannelType.id", channelTypeIds));

                subCriteria.setProjection(Projections.property("vulnerability.id"));

                List<Integer> ids = (List<Integer>) subCriteria.list();

                if (ids.isEmpty()) {
                    LOG.debug("Got no valid Scanner type IDs.");
                    ids.add(0); // should yield no results
                    // throw an exception here?
                } else {
                    LOG.debug("Adding scanner restriction: " + channelTypeIds);
                }

                criteria.add(Restrictions.in("id", ids));
            }
        }
    }

    private void addVulnCommentRestrictions() {
        if ((parameters.getShowCommentPresent() == null || !parameters.getShowCommentPresent())
                && (parameters.getCommentTags() == null || parameters.getCommentTags().isEmpty()))
            return;
        criteria.createAlias("vulnerabilityComments", "commentAlias");

        List<Integer> tagIds = list();

        if (parameters.getCommentTags() != null) {
            for (Tag tag : parameters.getCommentTags()) {
                if (tag.getId() != null) {
                    tagIds.add(tag.getId());
                }
            }
        }

        if (tagIds.isEmpty()) {
            LOG.debug("No vulnerability comment tag IDs found in parameters.");
        } else {
            criteria.createAlias("vulnerabilityComments.tags", "tagsAlias");
            criteria.add(Restrictions.in("tagsAlias.id", tagIds));
            LOG.debug("Added vulnerability comment tags with IDs " + tagIds);
        }

    }

}