Package com.denimgroup.threadfix.service

Source Code of com.denimgroup.threadfix.service.ScanMergeServiceImpl

////////////////////////////////////////////////////////////////////////
//
//     Copyright (c) 2009-2014 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.service;

import com.denimgroup.threadfix.data.dao.ApplicationChannelDao;
import com.denimgroup.threadfix.data.dao.ScanDao;
import com.denimgroup.threadfix.data.dao.UserDao;
import com.denimgroup.threadfix.data.entities.*;
import com.denimgroup.threadfix.importer.interop.ChannelImporter;
import com.denimgroup.threadfix.importer.interop.ChannelImporterFactory;
import com.denimgroup.threadfix.logging.SanitizedLogger;
import com.denimgroup.threadfix.service.merge.FindingMatcher;
import com.denimgroup.threadfix.service.merge.ScanMerger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.List;
import java.util.Map;

// TODO figure out this Transactional stuff
// TODO reorganize methods - not in a very good order right now.
@Service
@Transactional(readOnly = false)
public class ScanMergeServiceImpl implements ScanMergeService {

  private final SanitizedLogger log = new SanitizedLogger("ScanMergeService");

    @Autowired
  private ScanDao scanDao;
    @Autowired
  private ApplicationChannelDao applicationChannelDao;
    @Autowired
  private UserDao userDao;
    @Autowired
  private JobStatusService jobStatusService;
    @Autowired
  private ScanMerger scanMerger;
    @Autowired
  private VulnerabilityFilterService vulnerabilityFilterService;
    @Autowired
    private ChannelImporterFactory channelImporterFactory;
    @Autowired
    private VulnerabilityService vulnerabilityService;

  @Override
  public Scan saveRemoteScanAndRun(Integer channelId, String fileName) {
    if (channelId == null || fileName == null) {
      log.error("Unable to run RPC scan due to null input.");
      return null;
    }

    Scan scan = processScanFile(channelId, fileName, null);
    if (scan == null) {
      log.warn("The scan processing failed to produce a scan.");
      return null;
    }
   
    updateScanCounts(scan);
    vulnerabilityFilterService.updateVulnerabilities(scan);

    return scan;
  }

  @Override
  @Transactional(readOnly = false)
  public void updateSurfaceLocation(Application application) {
    if (application != null && application.getProjectRoot() != null
        && application.getVulnerabilities() != null) {
      for (Vulnerability vuln : application.getVulnerabilities()) {
        if (vuln == null || vuln.getFindings() == null) {
          continue;
        }
        for (Finding finding : vuln.getFindings()) {
          if (finding == null) {
            continue;
          }
          String newPath = "";
//          StaticFindingPathUtils.getFindingPathWithRoot(finding,
//              application.getProjectRoot());
//          if (newPath == null)
//            continue;
          if (finding.getSurfaceLocation() != null) {
            finding.getSurfaceLocation().setPath(newPath);
          }
        }
      }
    }
  }

  @Override
  @Transactional(readOnly = false)
  public void updateVulnerabilities(Application application) {
    List<Vulnerability> vulnerabilities = application.getVulnerabilities();
   
    FindingMatcher matcher = new FindingMatcher(null);

    if (vulnerabilities != null) {
      for (int i = 0; i < vulnerabilities.size(); i++) {
        if (vulnerabilities.get(i).getFindings() != null
            && vulnerabilities.get(i).getFindings().size() > 0) {
          Finding finding = vulnerabilities.get(i).getFindings()
              .get(0);
          for (int j = i + 1; j < vulnerabilities.size(); j++) {
            if (matcher.doesMatch(finding, vulnerabilities.get(j))) {

              for (Finding vulnFinding : vulnerabilities.get(j)
                  .getFindings()) {
                vulnerabilities.get(i).getFindings()
                    .add(vulnFinding);
                vulnFinding.setVulnerability(vulnerabilities
                    .get(i));
              }
              // set the matched vulnerability inactive, not a
              // good method, but deleting it will cause cascading
              // problems
              vulnerabilities.get(j).setActive(false);
            }
          }
        }
      }
    }
  }

  @Override
  public boolean processScan(Integer channelId, String fileName,
      Integer statusId, String userName) {
       
    if (channelId == null || fileName == null) {
      log.error("processScan() received null input and was unable to finish.");
      return false;
    }

    Scan scan = processScanFile(channelId, fileName, statusId);
    if (scan == null) {
      log.warn("processScanFile() failed to return a scan.");
      return false;
    }
   
    if (userName != null) {
      User user = userDao.retrieveByName(userName);
      scan.setUser(user);
    }
   
    scanDao.saveOrUpdate(scan);
   
    updateScanCounts(scan);
    vulnerabilityFilterService.updateVulnerabilities(scan);

    return true;
  }

  /**
   * This is now just a wrapper around mergeScan. Let's perhaps remove it.
   */
  @Override
  public Scan processRemoteScan(Scan scan) {
 
    if (scan == null) {
      log.warn("The remote import failed.");
      return null;
    }
 
    scanMerger.merge(scan, scan.getApplicationChannel());

        scanDao.saveOrUpdate(scan);

        // set numbers correctly
        updateScanCounts(scan);
 
    return scan;
  }
 
  private Scan processScanFile(Integer channelId, String fileName,
      Integer statusId) {
    if (channelId == null || fileName == null) {
      log.error("processScanFile() received null input and was unable to finish.");
      return null;
    }
 
    File file = new File(fileName);
    ApplicationChannel applicationChannel = applicationChannelDao
        .retrieveById(channelId);
 
    if (applicationChannel == null
        || applicationChannel.getChannelType() == null
        || !file.exists()) {
      log.warn("Invalid Application Channel, unable to find a ChannelImporter implementation.");
      return null;
    }
 
    // pick the appropriate parser
    ChannelImporter importer = channelImporterFactory.getChannelImporter(applicationChannel);
 
    if (importer == null) {
      log.warn("Unable to find suitable ChannelImporter implementation for "
          + applicationChannel.getChannelType().getName()
          + ". Returning null.");
      return null;
    }
 
    updateJobStatus(statusId, "Parsing findings from " +
        applicationChannel.getChannelType().getName() + " scan file.");
    log.info("Processing file " + fileName + " on channel "
        + applicationChannel.getChannelType().getName() + ".");
 
    importer.setFileName(fileName);
   
    Scan scan = importer.parseInput();
   
    if (scan == null) {
      log.warn("The " + applicationChannel.getChannelType().getName()
          + " import failed for file " + fileName + ".");
      return null;
    }
 
    updateJobStatus(statusId, "Findings successfully parsed, starting channel merge.");
   
    scanMerger.merge(scan, applicationChannel);

        scanDao.saveOrUpdate(scan);

        vulnerabilityFilterService.updateVulnerabilities(
        applicationChannel.getApplication().getOrganization().getId(),
        applicationChannel.getApplication().getId());
   
    importer.deleteScanFile();

        vulnerabilityService.updateVulnerabilityReport(applicationChannel.getApplication());

        return scan;
  }

  private void updateJobStatus(Integer statusId, String statusString) {
    if (statusId != null) {
      jobStatusService.updateJobStatus(statusId, statusString);
    }
  }

  public void updateScanCounts(Scan scan) {
    Map<String, Object> mapMap = scanDao.getMapSeverityMap(scan);
    Map<String, Object> findingMap = scanDao.getFindingSeverityMap(scan);
    if (mapMap.get("id").equals(scan.getId()) && mapMap.get("id").equals(scan.getId())) {
      scan.setNumberInfoVulnerabilities((Long)mapMap.get("info") + (Long)findingMap.get("info"));
      scan.setNumberLowVulnerabilities((Long)mapMap.get("low") + (Long)findingMap.get("low"));
      scan.setNumberMediumVulnerabilities((Long)mapMap.get("medium") + (Long)findingMap.get("medium"));
      scan.setNumberHighVulnerabilities((Long)mapMap.get("high") + (Long)findingMap.get("high"));
      scan.setNumberCriticalVulnerabilities((Long)mapMap.get("critical") + (Long)findingMap.get("critical"));
      scanDao.saveOrUpdate(scan);
    } else {
      log.warn("ID from the database didn't match the scan ID, counts will not be added to the scan.");
    }
  }
}
TOP

Related Classes of com.denimgroup.threadfix.service.ScanMergeServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.