Java tutorial
//////////////////////////////////////////////////////////////////////// // // 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); } } }