Package com.denimgroup.threadfix.service

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

////////////////////////////////////////////////////////////////////////
//
//     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.*;
import com.denimgroup.threadfix.data.entities.*;
import com.denimgroup.threadfix.data.enums.FrameworkType;
import com.denimgroup.threadfix.importer.util.IntegerUtils;
import com.denimgroup.threadfix.logging.SanitizedLogger;
import com.denimgroup.threadfix.service.beans.TableSortBean;
import com.denimgroup.threadfix.service.defects.AbstractDefectTracker;
import com.denimgroup.threadfix.service.defects.DefectTrackerFactory;
import com.denimgroup.threadfix.service.util.PermissionUtils;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.errors.EncryptionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import javax.annotation.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static com.denimgroup.threadfix.CollectionUtils.list;

@Service
@Transactional(readOnly = false)
public class ApplicationServiceImpl implements ApplicationService {
 
  protected final SanitizedLogger log = new SanitizedLogger(ApplicationServiceImpl.class);
 
  private String invalidProjectName = "The selected Project Name was invalid. " +
      "Either a non-existent project or a project with no components was selected.";
 
  private String invalidCredentials = "The User / password combination " +
      "(or possibly the Defect Tracker endpoint URL)";

  @Autowired private ApplicationDao applicationDao;
  @Autowired private DefectTrackerDao defectTrackerDao;
  @Autowired private RemoteProviderApplicationDao remoteProviderApplicationDao;
  @Autowired private WafRuleDao wafRuleDao;
  @Autowired private WafDao wafDao;
  @Autowired private VulnerabilityDao vulnerabilityDao;
  @Autowired private AccessControlMapService accessControlMapService;
  @Autowired private ApplicationCriticalityDao applicationCriticalityDao;
  @Autowired private DefectDao defectDao;
  @Autowired private ScanMergeService scanMergeService;
    @Autowired private GenericVulnerabilityDao genericVulnerabilityDao;

    @Nullable
  @Autowired(required = false)
    private PermissionService permissionService;

    @Nullable
  @Autowired(required = false)
    private ScanQueueService scanQueueService;

  @Override
  public List<Application> loadAllActive() {
    return applicationDao.retrieveAllActive();
  }
 
  @Override
  public List<Application> loadAllActiveFilter(Set<Integer> authenticatedTeamIds) {
   
    if (PermissionUtils.hasGlobalReadAccess()) {
      return loadAllActive();
    }
   
    if (authenticatedTeamIds == null || authenticatedTeamIds.size() == 0) {
      return list();
    }
   
    return applicationDao.retrieveAllActiveFilter(authenticatedTeamIds);
  }
 
  @Override
  public Application loadApplication(int applicationId) {
    return applicationDao.retrieveById(applicationId);
  }

  @Override
  public Application loadApplication(String applicationName, int teamId) {
    return applicationDao.retrieveByName(applicationName, teamId);
  }

  @Override
  @Transactional(readOnly = false)
  public void storeApplication(Application application) {
    if (application != null) {
            // Set default for Application Type is Detect
            if (application.getFrameworkType().equals(FrameworkType.NONE.toString()))
                application.setFrameworkType(FrameworkType.DETECT.toString());
      applicationDao.saveOrUpdate(application);
    }
  }

  @Override
  @Transactional(readOnly = false)
  public void deactivateApplication(Application application) {
    application.setActive(false);
    application.setModifiedDate(new Date());
        application.setTags(new ArrayList<Tag>());
    removeRemoteApplicationLinks(application);
    String possibleName = getNewName(application);
   
    if (application.getAccessControlApplicationMaps() != null) {
      for (AccessControlApplicationMap map : application.getAccessControlApplicationMaps()) {
        accessControlMapService.deactivate(map);
      }
    }

        if (scanQueueService != null && application.getScanQueueTasks() != null) {
      for (ScanQueueTask task : application.getScanQueueTasks())
        scanQueueService.deactivateTask(task);
       
    }

        application.setWaf(null);

        // Delete WafRules attached with application
        deleteWafRules(application);

    if (applicationDao.retrieveByName(possibleName, application.getOrganization().getId()) == null) {
      application.setName(possibleName);
    }
    applicationDao.saveOrUpdate(application);
  }

    private void deleteWafRules(Application application) {
        if (application.getWaf() != null &&
                application.getVulnerabilities() != null) {
            for (Vulnerability vulnerability : application.getVulnerabilities()) {
                if (vulnerability != null && vulnerability.getWafRules() != null) {
                    // Since WAF Rules can only have one vulnerability, just delete them.
                    for (WafRule wafRule : vulnerability.getWafRules()) {
                        log.debug("Deleting WAF Rule with ID " + wafRule.getId()
                                + " because it was attached to the Vulnerability with ID " + vulnerability.getId() +
                                " of application with ID " + application.getId());
                        wafRuleDao.delete(wafRule);
                    }
                }
                if (vulnerability != null) {
                    vulnerability.setWafRules(new ArrayList<WafRule>());
                }
            }
        }
    }

  private String getNewName(Application application) {
    if (application != null) {
     
      String testString = "deleted-" + application.getId() + "-" + application.getName();
      if (testString.length() > Application.NAME_LENGTH) {
        testString = testString.substring(0, Application.NAME_LENGTH - 2);
      }
      return testString;
    }
    return null;
  }
 
  private void removeRemoteApplicationLinks(Application application) {
    if (application.getRemoteProviderApplications() != null &&
        application.getRemoteProviderApplications().size() > 0) {
      log.info("Removing remote applications from the application " + application.getName() +
           " (id=" + application.getId() + ")");
      for (RemoteProviderApplication app : application.getRemoteProviderApplications()) {
        log.info("Removing remote application " + app.getNativeName() +
             " from application " + app.getApplication().getName());
        app.setApplication(null);
        app.setLastImportTime(null);
        app.setApplicationChannel(null);
        remoteProviderApplicationDao.saveOrUpdate(app);
      }
    }
  }
 
  @Override
  public boolean validateApplicationDefectTracker(Application application,
      BindingResult result) {
    if (application == null || result == null) {
      return false;
    }
   
    if (application.getDefectTracker() != null &&
        (application.getDefectTracker().getId() == null
        || application.getDefectTracker().getId() == 0)) {
      application.setDefectTracker(null);
      application.setUserName(null);
      application.setPassword(null);
    } else if (application.getDefectTracker() != null){
      DefectTracker defectTracker = defectTrackerDao.retrieveById(
          application.getDefectTracker().getId());
      if (defectTracker == null) {
        result.rejectValue("defectTracker.id", "errors.invalid",
            new String [] { "Defect Tracker choice" }, null);
        application.setUserName(null);
        application.setPassword(null);
        application.setProjectName(null);
      } else {
       
        application.setDefectTracker(defectTracker);
        AbstractDefectTracker dt = DefectTrackerFactory.getTracker(application);
        if (dt != null) {
          if (application.getUserName() == null
              || application.getUserName().isEmpty()) {
            result.rejectValue("userName", "errors.required",
                new String [] { "User Name" }, null);
          }
          if (application.getPassword() == null
              || application.getPassword().isEmpty()) {
            result.rejectValue("password", "errors.required",
                new String [] { "Password" }, null);
          }
         
          if (!result.hasErrors()) {
            if (!dt.hasValidCredentials()) {
              if (dt.getLastError() == null) {
                result.rejectValue("userName", "errors.invalid",
                    new String [] { invalidCredentials }, null);
              } else {
                result.rejectValue("userName", "errors.detail",
                    new String [] { dt.getLastError() }, null);
              }
              application.setUserName(null);
              application.setPassword(null);
              application.setProjectName(null);
            } else if (!dt.hasValidProjectName()) {
              result.rejectValue("projectName", "errors.detail",
                  new String [] { invalidProjectName }, null);
              application.setProjectName(null);
            } else {
              encryptCredentials(application);
              application.setProjectId(dt.getProjectIdByName());
              return checkNewDefectTracker(application);
            }
          }
        }
      }
    }
    return false;
  }
 
  /**
   *
   * @param application
   * @return true if the application has a different defect tracker
   *       than the database version, false otherwise
   */
  private boolean checkNewDefectTracker(Application application) {
    if (application == null || application.getId() == null ||
        application.getDefectTracker() == null ||
        application.getDefectTracker().getId() == null) {
      return false;
    }
   
    Application databaseApplication = applicationDao.retrieveById(application.getId());
   
    if (databaseApplication == null || databaseApplication.getId() == null ||
        databaseApplication.getDefectTracker() == null ||
        databaseApplication.getDefectTracker().getId() == null) {
      return false;
    }
   
    return !application.getDefectTracker().getId().equals(
        databaseApplication.getDefectTracker().getId());
  }
 
  @Override
  public boolean checkApplication(Application application) {
    if (application == null || application.getName() == null
        || application.getName().trim().isEmpty()
        || application.getName().length() > Application.NAME_LENGTH) {
      log.warn("The application's name was invalid.");
      return false;
    }
   
    if (application.getUrl() != null &&
        application.getUrl().length() > Application.URL_LENGTH) {
      log.warn("The application's url was too long.");
      return false;
    }
   
    Application databaseApplication = loadApplication(application.getName().trim(),
        application.getOrganization().getId());

    return databaseApplication == null;
  }
 
  @Override
  public void updateWafRules(Application application, Integer otherWafId) {
    if (application == null || application.getId() == null ||
        otherWafId == null) {
      return;
    }

    // if the new app doesn't have a WAF or the IDs don't match, need to remove the rules
    if (application.getWaf() == null ||
        application.getVulnerabilities() != null &&
         application.getWaf().getId() != null &&
         !otherWafId.equals(application.getWaf().getId())) {
     
      // Database vulns are still in session, also the vulns themselves
      // shouldn't have changed since we were only editing the information
      // about the Application object and not its vulnerabilities.
      for (Vulnerability vulnerability : application.getVulnerabilities()) {
        if (vulnerability != null && vulnerability.getWafRules() != null) {
          for (WafRule wafRule : vulnerability.getWafRules()) {
            wafRuleDao.delete(wafRule);
          }
          vulnerability.setWafRuleGeneratedTime(null);
          vulnerability.setWafRules(new ArrayList<WafRule>());
          vulnerabilityDao.saveOrUpdate(vulnerability);
        }
      }
    }
  }
 
  @Override
  public void validateAfterEdit(Application application, BindingResult result) {

    if (application.getName() == null || application.getName().trim().equals("")) {
      if (!result.hasFieldErrors("name")) {
        result.rejectValue("name", null, null, "This field cannot be blank");
      }
      return;
    }
   
    if (application.getRepositoryFolder() != null && !application.getRepositoryFolder().trim().equals("")) {
      File file = new File(application.getRepositoryFolder().trim());
      if (!file.exists() || !file.isDirectory()) {
        result.rejectValue("repositoryFolder", null, null, "Invalid directory");
        return;
      }
    }   

    Application databaseApplication = decryptCredentials(loadApplication(application.getName().trim(),
                application.getOrganization().getId()));

    if (application.getApplicationCriticality() == null ||
        application.getApplicationCriticality().getId() == null ||
        applicationCriticalityDao.retrieveById(
            application.getApplicationCriticality().getId()) == null) {
      result.rejectValue("applicationCriticality.id", "errors.invalid",
          new String [] { "Criticality" }, null);
    }
   
    boolean canManageWafs = false, canManageDefectTrackers = false;

        if (permissionService == null) { // not enterprise, which means everyone is admin
            canManageDefectTrackers = true;
            canManageWafs = true;
        } else if (application.getOrganization() != null) {
      canManageWafs = permissionService.isAuthorized(Permission.CAN_MANAGE_WAFS,
          application.getOrganization().getId(), application.getId());
     
      canManageDefectTrackers = permissionService.isAuthorized(Permission.CAN_MANAGE_DEFECT_TRACKERS,
          application.getOrganization().getId(), application.getId());
    }
   
    Application oldApp = loadApplication(application.getId());
   
    if (oldApp != null && !canManageWafs) {
      application.setWaf(oldApp.getWaf());
    }
   
    if (oldApp != null && !canManageDefectTrackers) {
      application.setDefectTracker(oldApp.getDefectTracker());
    }
   
    if (application.getWaf() != null && (application.getWaf().getId() == null ||
        application.getWaf().getId() == 0)) {
      application.setWaf(null);
    }
   
    if (application.getWaf() != null && application.getWaf().getId() != null) {
      Waf waf = wafDao.retrieveById(application.getWaf().getId());
     
      if (waf == null) {
        result.rejectValue("waf.id", "errors.invalid",
            new String [] { "WAF Choice" }, null);
      } else {
        application.setWaf(waf);
      }
    }
   
    // The password was set to the temp password so that it wouldn't show up on the page.
    // If the credentials haven't changed, re-decrypt the password to get the original.
    if (application.getPassword() != null && application.getPassword().equals(Application.TEMP_PASSWORD) &&
        databaseApplication != null && databaseApplication.getUserName() != null &&
        databaseApplication.getUserName().equals(application.getUserName()) &&
        databaseApplication.getDefectTracker() != null &&
        application.getDefectTracker() != null &&
        databaseApplication.getDefectTracker().getId().equals(
            application.getDefectTracker().getId())) {
      decryptCredentials(application);
    }
     
    if (databaseApplication != null && !databaseApplication.getId().equals(
        application.getId())) {
      result.rejectValue("name", "errors.nameTaken");
    }
   
    Integer databaseWafId = null;
    if (databaseApplication != null && databaseApplication.getWaf() != null) {
      databaseWafId = databaseApplication.getWaf().getId();
    }
   
    // remove any outdated vuln -> waf rule links
    updateWafRules(loadApplication(application.getId()), databaseWafId);

        encryptRepositoryCredentials(application);
  }
 
  @Override
  public void validateDefectTracker(Application application, BindingResult result) {
    boolean hasNewDefectTracker = validateApplicationDefectTracker(application, result);
   
    if (hasNewDefectTracker || application.getDefectTracker() == null
        && application.getDefectList() != null) {
      defectDao.deleteByApplicationId(application.getId());
     
      List<Vulnerability> vulns = applicationDao.getVulns(application);
     
      if (vulns != null) {
        for (Vulnerability vuln : vulns) {
          vuln.setDefect(null);
          vulnerabilityDao.saveOrUpdate(vuln);
        }
      }
    }
  }

    @Override
    public long getUnmappedFindingCount(Integer appId) {
        return applicationDao.getUnmappedFindingCount(appId);
    }

    @Override
  public void updateProjectRoot(Application application) {
    if (application != null && application.getProjectRoot() != null
        && !application.getProjectRoot().trim().equals("")) {
      Application app = loadApplication(application.getId());
     
      scanMergeService.updateSurfaceLocation(app);
      scanMergeService.updateVulnerabilities(app);
             
      storeApplication(app);
    }
  }
 
  @Override
  public void validateAfterCreate(Application application, BindingResult result) {
   
    if (application.getName() == null || application.getName().trim().equals("")) {
     
      if (!result.hasFieldErrors("name")) {
        result.rejectValue("name", null, null, "This field cannot be blank");
      }
      return;
    }
   
    if (application.getApplicationCriticality() == null ||
        application.getApplicationCriticality().getId() == null ||
        applicationCriticalityDao.retrieveById(
            application.getApplicationCriticality().getId()) == null) {
      result.rejectValue("applicationCriticality.id", "errors.invalid",
          new String [] { "Criticality" }, null);
    } else {
            application.getApplicationCriticality().setName(applicationCriticalityDao.retrieveById(
                    application.getApplicationCriticality().getId()).getName());
        }
   
    boolean canManageWafs = false, canManageDefectTrackers = false;

        if (permissionService == null) { // not enterprise, which means everyone is admin
            canManageDefectTrackers = true;
            canManageWafs = true;
        } else if (application.getOrganization() != null) {
      canManageWafs = permissionService.isAuthorized(Permission.CAN_MANAGE_WAFS,
          application.getOrganization().getId(), application.getId());
     
      canManageDefectTrackers = permissionService.isAuthorized(Permission.CAN_MANAGE_DEFECT_TRACKERS,
          application.getOrganization().getId(), application.getId());
    }
   
    Application databaseApplication = loadApplication(application.getName().trim(), application.getOrganization().getId());
    if (databaseApplication != null) {
      result.rejectValue("name", "errors.nameTaken");
      return;
    }
   
    if (application.getRepositoryFolder() != null && !application.getRepositoryFolder().trim().equals("")) {
      File file = new File(application.getRepositoryFolder().trim());
      if (!file.exists() || !file.isDirectory()) {
        result.rejectValue("repositoryFolder", null, null, "Invalid directory");
        return;
      }
    }
   
    if (!canManageWafs && application.getWaf() != null) {
      application.setWaf(null);
    }
   
    if (!canManageDefectTrackers && application.getDefectTracker() != null) {
      application.setDefectTracker(null);
    }

    if (application.getWaf() != null && application.getWaf().getId() == 0) {
      application.setWaf(null);
    }
   
    if (application.getWaf() != null && (application.getWaf().getId() == null
        || wafDao.retrieveById(application.getWaf().getId()) == null)) {
      result.rejectValue("waf.id", "errors.invalid",
          new String [] { "WAF Choice" }, null);
    }

    validateApplicationDefectTracker(application, result);
        encryptRepositoryCredentials(application);
  }

  @Override
  public List<Vulnerability> getVulnTable(int appId, TableSortBean bean) {
    if (bean != null) {
      int page = bean.getPage();
      int sort = bean.getSort();
      int field = bean.getField();
     
      String description = null, severity = null, path = null, param = null;
           
      if (bean.getDescriptionFilter() != null && !bean.getDescriptionFilter().trim().equals("")) {
        description = bean.getDescriptionFilter().trim();
      }
     
      if (bean.getSeverityFilter() != null && !bean.getSeverityFilter().trim().equals("")) {
        severity = bean.getSeverityFilter().trim();
      }
     
      if (bean.getLocationFilter() != null && !bean.getLocationFilter().trim().equals("")) {
        path = bean.getLocationFilter().trim();
      }
     
      if (bean.getParameterFilter() != null && !bean.getParameterFilter().trim().equals("")) {
        param = bean.getParameterFilter().trim();
      }
         
      Integer cweInteger = getCweId(bean);
     
      return vulnerabilityDao.retrieveActiveByAppIdAndPage(appId, page, sort, field, cweInteger,
                    description, severity, path, param, bean.isOpen(),
                    bean.isFalsePositive(), bean.isHidden());
    } else {
      return vulnerabilityDao.retrieveActiveByAppIdAndPage(appId, 1, 0, 0, null, null, null, null,
          null, true, false, false);
    }
  }
 
  private Integer getCweId(TableSortBean bean) {
    if (bean.getCweFilter() != null && !bean.getCweFilter().trim().equals("")) {
      String cwe = bean.getCweFilter().trim();

      Integer cweId = IntegerUtils.getIntegerOrNull(cwe);
            if (cweId != null) {
                GenericVulnerability genericVulnerability = genericVulnerabilityDao.retrieveByDisplayId(cweId);
                if (genericVulnerability != null)
                    return genericVulnerability.getId();
            }
    }
   
    return null;
  }
 
  @Override
  public long getCount(Integer appId, TableSortBean bean) {
    String description = null, severity = null, path = null, param = null;
   
    if (bean.getDescriptionFilter() != null && !bean.getDescriptionFilter().trim().equals("")) {
      description = bean.getDescriptionFilter().trim();
    }
   
    if (bean.getSeverityFilter() != null && !bean.getSeverityFilter().trim().equals("")) {
      severity = bean.getSeverityFilter().trim();
    }
   
    if (bean.getLocationFilter() != null && !bean.getLocationFilter().trim().equals("")) {
      path = bean.getLocationFilter().trim();
    }
   
    if (bean.getParameterFilter() != null && !bean.getParameterFilter().trim().equals("")) {
      param = bean.getParameterFilter().trim();
    }
   
    Integer cweInteger = getCweId(bean);
   
    return vulnerabilityDao.getVulnCountWithFilters(appId,description,severity,path,param, cweInteger,
                            bean.isOpen(), bean.isFalsePositive(), bean.isHidden());
  }
 
  @Override
  public long getVulnCount(Integer appId, boolean open) {
    return vulnerabilityDao.getVulnCount(appId, open);
  }
 
  public Application encryptCredentials(Application application) {
    try {
      if (application != null && application.getPassword() != null && application.getUserName() != null) {
        application.setEncryptedPassword(ESAPI.encryptor().encrypt(application.getPassword()));
        application.setEncryptedUserName(ESAPI.encryptor().encrypt(application.getUserName()));
      }
    } catch (EncryptionException e) {
      log.warn("Encountered an ESAPI encryption exception. Check your ESAPI configuration.", e);
    }
    return application;
  }
 
  @Override
  public Application decryptCredentials(Application application) {
    try {
      if (application != null && application.getEncryptedPassword() != null &&
          application.getEncryptedUserName() != null) {
        application.setPassword(ESAPI.encryptor().decrypt(application.getEncryptedPassword()));
        application.setUserName(ESAPI.encryptor().decrypt(application.getEncryptedUserName()));
      }
    } catch (EncryptionException e) {
      log.warn("Encountered an ESAPI encryption exception. Check your ESAPI configuration.", e);
    }
    return application;
  }

    @Override
    public Application encryptRepositoryCredentials(Application application) {
        try {
            if (application != null && application.getRepositoryPassword() != null && !application.getRepositoryPassword().isEmpty()
                    && application.getRepositoryUserName() != null && !application.getRepositoryUserName().isEmpty()) {
                application.setRepositoryEncryptedPassword(ESAPI.encryptor().encrypt(application.getRepositoryPassword()));
                application.setRepositoryEncryptedUserName(ESAPI.encryptor().encrypt(application.getRepositoryUserName()));
            }

        } catch (EncryptionException e) {
            log.warn("Encountered an ESAPI encryption exception. Check your ESAPI configuration.", e);
        }
        return application;
    }

    @Override
    public Application decryptRepositoryCredentials(Application application) {
        try {
            if (application != null && application.getRepositoryEncryptedPassword() != null &&
                    application.getRepositoryEncryptedUserName() != null) {
                application.setRepositoryPassword(ESAPI.encryptor().decrypt(application.getRepositoryEncryptedPassword()));
                application.setRepositoryUserName(ESAPI.encryptor().decrypt(application.getRepositoryEncryptedUserName()));
            }
        } catch (EncryptionException e) {
            log.warn("Encountered an ESAPI encryption exception. Check your ESAPI configuration.", e);
        }
        return application;
    }

  @Override
  public void generateVulnerabilityReports(List<Organization> organizations) {
    if (organizations == null) {
      return;
    }
    for (Organization org : organizations) {
      generateVulnerabilityReports(org);
    }
  }
 
  @Override
  public void generateVulnerabilityReports(Organization organization) {
    if (organization == null || organization.getActiveApplications() == null) {
      return;
    }
   
    for (Application app : organization.getActiveApplications()) {
      generateVulnerabilityReport(app);
    }
  }
 
  public void generateVulnerabilityReport(Application application) {
    application.setVulnerabilityReport(applicationDao.loadVulnerabilityReport(application));
        application.getOrganization().updateVulnerabilityReport();

    }
}
TOP

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

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.