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.dao.VulnerabilityDao; import com.denimgroup.threadfix.data.entities.*; import com.denimgroup.threadfix.data.enums.VulnerabilityDefectConsistencyState; import org.hibernate.Criteria; import org.hibernate.SessionFactory; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.util.Calendar; import java.util.List; import java.util.Map; import static com.denimgroup.threadfix.CollectionUtils.list; /** * Hibernate Vulnerability DAO implementation. Most basic methods are * implemented in the AbstractGenericDao * * @author mcollins, dwolf */ @Repository public class HibernateVulnerabilityDao implements VulnerabilityDao { private SessionFactory sessionFactory; @Autowired public HibernateVulnerabilityDao(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override @SuppressWarnings("unchecked") public List<Vulnerability> retrieveAllByApplication(int applicationId) { return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class) .createAlias("application", "app").add(Restrictions.eq("app.id", applicationId)).list(); } @Override @SuppressWarnings("unchecked") public List<Vulnerability> retrieveAllByGenericVulnerabilityAndApp(Vulnerability vulnerability) { return sessionFactory.getCurrentSession() .createQuery("from Vulnerability vuln where vuln.application = :appId " + "and vuln.genericVulnerability = :gvId and vuln.expired = :false") .setInteger("gvId", vulnerability.getGenericVulnerability().getId()) .setInteger("appId", vulnerability.getApplication().getId()).setBoolean("false", false).list(); } @SuppressWarnings("unchecked") @Override public List<Vulnerability> retrieveByApplicationIdList(List<Integer> applicationIdList) { if (applicationIdList == null || applicationIdList.isEmpty()) { return list(); } return sessionFactory.getCurrentSession() .createQuery("from Vulnerability vulnerability " + "where vulnerability.hidden = false and vulnerability.application.id in (:idList)") .setParameterList("idList", applicationIdList).list(); } @Override public List<Map<String, Object>> retrieveMapByApplicationIdList(List<Integer> applicationIdList) { return (List<Map<String, Object>>) sessionFactory.getCurrentSession() .createQuery("select new map( " + "vulnerability.genericSeverity.name as severity, " + "vulnerability.genericVulnerability.name as genericVulnName, " + "vulnerability.openTime as importTime, " + "vulnerability.closeTime as closeTime, " + "vulnerability.active as active, " + "vulnerability.hidden as hidden, " + "vulnerability.isFalsePositive as isFalsePositive, " + "vulnerability.application.name as appName, " + "vulnerability.application.id as appId, " + "vulnerability.application.organization.name as teamName, " + "vulnerability.application.organization.id as teamId " + ") " + "from Vulnerability vulnerability " + "where vulnerability.hidden = false and " + "vulnerability.isFalsePositive = false " + "and vulnerability.application.id in (:idList) " + // "and vulnerability.active = true " + "order by vulnerability.genericSeverity.name, vulnerability.application.name") .setParameterList("idList", applicationIdList).list(); } @Override public Vulnerability retrieveById(int id) { Vulnerability vuln = (Vulnerability) sessionFactory.getCurrentSession().get(Vulnerability.class, id); if (vuln != null && !vuln.isExpired()) { return vuln; } else { assert false : "Attempted to retrieve invalid vulnerability id."; return null; } } @Override @SuppressWarnings("unchecked") public List<Vulnerability> retrieveSimilarHashes(Vulnerability vulnerability) { return sessionFactory.getCurrentSession() .createQuery("from Vulnerability vuln where vuln.application = :appId " + "and vuln.expired = :false " + "and (vuln.locationVariableHash = :lvHash or " + "vuln.locationHash = :lHash or vuln.variableHash = :vHash)") .setString("lvHash", vulnerability.getLocationVariableHash()) .setString("lHash", vulnerability.getLocationHash()) .setString("vHash", vulnerability.getVariableHash()) .setInteger("appId", vulnerability.getApplication().getId()).setBoolean("false", false).list(); } @Override public void saveOrUpdate(Vulnerability vulnerability) { sessionFactory.getCurrentSession().saveOrUpdate(vulnerability); } @Override public void delete(Vulnerability vulnerability) { if (vulnerability.getDocuments() != null) { for (Document document : vulnerability.getDocuments()) { sessionFactory.getCurrentSession().delete(document); } } if (vulnerability.getEvents() != null) { for (Event event : vulnerability.getEvents()) { event.setVulnerability(null); sessionFactory.getCurrentSession().save(event); } } sessionFactory.getCurrentSession().save(new DeletedVulnerability(vulnerability)); sessionFactory.getCurrentSession().delete(vulnerability); } /** * I would feel bad about having so much logic here but the alternatives are * passing in a query string which is a terrible idea or * having a ton of methods which also isn't any good. */ @SuppressWarnings("unchecked") @Override public List<Vulnerability> retrieveActiveByAppIdAndPage(int appId, int page, int sort, int field, Integer cwe, String description, String severity, String path, String param, boolean open, boolean falsePositive, boolean hidden) { String[] headers = new String[] { "", "vuln.name", "severity.intValue", "surface.path", "surface.parameter" }; Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Vulnerability.class); if (hidden) { criteria.add(Restrictions.eq("hidden", true)); } else { criteria.add(Restrictions.eq("hidden", false)); if (!open && falsePositive) { criteria.add(Restrictions.eq("isFalsePositive", true)); } else { criteria.add(Restrictions.eq("active", open)).add(Restrictions.eq("hidden", false)) .add(Restrictions.eq("isFalsePositive", falsePositive)); } } criteria.add(Restrictions.eq("application.id", appId)).createAlias("genericSeverity", "severity") .createAlias("genericVulnerability", "vuln").createAlias("surfaceLocation", "surface") .setFirstResult((page - 1) * 100).setMaxResults(100); // Add Filtering restrictions if (description != null) { criteria.add(Restrictions.like("vuln.name", "%" + description + "%").ignoreCase()); } if (severity != null) { criteria.add(Restrictions.like("severity.name", "%" + severity + "%").ignoreCase()); } if (path != null) { criteria.add(Restrictions.like("surface.path", "%" + path + "%").ignoreCase()); } if (param != null) { criteria.add(Restrictions.like("surface.parameter", "%" + param + "%").ignoreCase()); } if (cwe != null) { criteria.add(Restrictions.eq("vuln.id", cwe)); } // Add Ordering if (sort != 1 && sort != 2 || field <= 0 || field > headers.length) { criteria.addOrder(Order.desc("severity.intValue")).addOrder(Order.asc("vuln.name")) .addOrder(Order.asc("surface.path")).addOrder(Order.asc("surface.parameter")); } else { String item = headers[field]; if (sort == 1) { criteria.addOrder(Order.asc(item)); } else if (sort == 2) { criteria.addOrder(Order.desc(item)); } } return criteria.list(); } @Override public long getVulnCountWithFilters(Integer appId, String description, String severity, String path, String param, Integer cweInteger, boolean open, boolean falsePositive, boolean hidden) { Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Vulnerability.class); if (hidden) { criteria.add(Restrictions.eq("hidden", true)); } else { criteria.add(Restrictions.eq("hidden", false)); if (!open && falsePositive) { criteria.add(Restrictions.eq("isFalsePositive", true)); } else { criteria.add(Restrictions.eq("active", open)).add(Restrictions.eq("hidden", false)) .add(Restrictions.eq("isFalsePositive", falsePositive)); } } criteria.createAlias("genericVulnerability", "vuln").add(Restrictions.eq("application.id", appId)); // Add Filtering restrictions if (description != null) { criteria.add(Restrictions.like("vuln.name", "%" + description + "%").ignoreCase()); } if (severity != null) { criteria.createAlias("genericSeverity", "severity") .add(Restrictions.like("severity.name", "%" + severity + "%").ignoreCase()); } if (path != null) { criteria.createAlias("surfaceLocation", "surface") .add(Restrictions.like("surface.path", "%" + path + "%").ignoreCase()); } if (cweInteger != null) { criteria.add(Restrictions.eq("vuln.id", cweInteger)); } if (param != null) { criteria.createAlias("surfaceLocation", "surface") .add(Restrictions.like("surface.parameter", "%" + param + "%").ignoreCase()); } return (Long) criteria.setProjection(Projections.rowCount()).uniqueResult(); } @Override public long getVulnCount(Integer appId, boolean open) { return (Long) sessionFactory.getCurrentSession().createCriteria(Vulnerability.class) .add(Restrictions.eq("active", open)).add(Restrictions.eq("hidden", false)) .add(Restrictions.eq("isFalsePositive", false)).add(Restrictions.eq("application.id", appId)) .setProjection(Projections.rowCount()).uniqueResult(); } @Override @SuppressWarnings("unchecked") public List<Vulnerability> getFalsePositiveVulnCount(Application application, boolean value) { return sessionFactory.getCurrentSession() .createQuery("from Vulnerability vuln where vuln.application = :appId " + "and vuln.isFalsePositive = :fp") .setBoolean("fp", value).setInteger("appId", application.getId()).list(); } @Override public void evict(Finding finding) { sessionFactory.getCurrentSession().evict(finding); } @SuppressWarnings("unchecked") @Override public List<Vulnerability> retrieveByIdList(List<Integer> vulnerabilityIds) { return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class) .add(Restrictions.in("id", vulnerabilityIds)).list(); } @SuppressWarnings("unchecked") @Override public void markAllClosed(List<Vulnerability> vulns) { for (Vulnerability vuln : vulns) { if (vuln != null && vuln.isActive()) { vuln.setActive(false); vuln.setCloseTime(Calendar.getInstance()); vuln.setFoundByScanner(false); determineVulnerabilityDefectConsistencyState(vuln); saveOrUpdate(vuln); } } } @SuppressWarnings("unchecked") @Override public void markAllOpen(List<Vulnerability> vulns) { for (Vulnerability vuln : vulns) { if (vuln != null && !vuln.isActive()) { vuln.setActive(true); vuln.setFoundByScanner(true); determineVulnerabilityDefectConsistencyState(vuln); saveOrUpdate(vuln); } } } @Override public boolean activeVulnerabilitiesExist() { return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class) .createAlias("application", "app").add(Restrictions.eq("app.active", true)).setMaxResults(1) .uniqueResult() != null; } @SuppressWarnings("unchecked") @Override public List<Integer> getTopTenVulnTypes(List<Integer> applicationIdList) { return sessionFactory.getCurrentSession() .createQuery("select vuln.genericVulnerability.id " + "from Vulnerability vuln " + "where vuln.active = true " + "and vuln.hidden = false " + "and vuln.application.id in (:ids) " + "group by vuln.genericVulnerability.id " + "order by count(vuln.genericVulnerability.id) desc") .setParameterList("ids", applicationIdList).setMaxResults(10).list(); } @Override public List<Object[]> getTopVulnsInfo(List<Integer> applicationIdList, List<Integer> vulnIds) { List<Object[]> results = sessionFactory.getCurrentSession().createQuery( "select vulnerability.genericVulnerability.id as genericVulnId, count(vulnerability) as vulnCount " + "from Vulnerability vulnerability " + "where vulnerability.active = true " + "and vulnerability.application.active = true " + "and vulnerability.isFalsePositive = false " + "and vulnerability.hidden = false " + "and vulnerability.application.id in (:appIds) " + "and vulnerability.genericVulnerability.id in (:vulnIds) " + "group by vulnerability.genericVulnerability.id " + "order by count(vulnerability) desc") .setParameterList("appIds", applicationIdList).setParameterList("vulnIds", vulnIds).list(); if (results == null) results = list(); return results; } public Criteria getActiveVulnCriteria() { return sessionFactory.getCurrentSession().createCriteria(Vulnerability.class) .add(Restrictions.eq("active", true)).add(Restrictions.eq("hidden", false)) .add(Restrictions.eq("isFalsePositive", false)); } @Override public VulnerabilityDefectConsistencyState determineVulnerabilityDefectConsistencyState( Vulnerability vulnerability) { VulnerabilityDefectConsistencyState vulnerabilityDefectConsistencyState = null; Defect defect = vulnerability.getDefect(); if (defect != null) { if (vulnerability.isActive() == defect.isOpen()) { vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.CONSISTENT; } else if (defect.isOpen()) { vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.VULN_CLOSED_DEFECT_OPEN_NEEDS_SCAN; } else { Calendar latestScanDate = null; for (Finding finding : vulnerability.getFindings()) { Calendar scanDate = finding.getScan().getImportTime(); if ((latestScanDate == null) || scanDate.after(latestScanDate)) { latestScanDate = scanDate; } if (finding.getScanRepeatFindingMaps() != null) { for (ScanRepeatFindingMap scanRepeatFindingMap : finding.getScanRepeatFindingMaps()) { Scan scan = scanRepeatFindingMap.getScan(); if (scan != null) { scanDate = scan.getImportTime(); if ((latestScanDate == null) || scanDate.after(latestScanDate)) { latestScanDate = scanDate; } } } } } Calendar defectStatusUpdatedDate = defect.getStatusUpdatedDate(); if (defectStatusUpdatedDate == null) { defectStatusUpdatedDate = Calendar.getInstance(); defectStatusUpdatedDate.setTime(defect.getModifiedDate()); } if ((latestScanDate != null) && latestScanDate.after(defectStatusUpdatedDate)) { vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.VULN_OPEN_DEFECT_CLOSED_STILL_IN_SCAN; } else { vulnerabilityDefectConsistencyState = VulnerabilityDefectConsistencyState.VULN_OPEN_DEFECT_CLOSED_NEEDS_SCAN; } } } vulnerability.setVulnerabilityDefectConsistencyState(vulnerabilityDefectConsistencyState); return vulnerabilityDefectConsistencyState; } }