package com.denimgroup.threadfix.webapp.controller; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.SessionAttributes; import com.denimgroup.threadfix.data.entities.Application; import com.denimgroup.threadfix.data.entities.Defect; import com.denimgroup.threadfix.data.entities.Permission; import com.denimgroup.threadfix.data.entities.Vulnerability; import com.denimgroup.threadfix.service.ApplicationService; import com.denimgroup.threadfix.service.PermissionService; import com.denimgroup.threadfix.service.SanitizedLogger; import com.denimgroup.threadfix.service.VulnerabilityService; import com.denimgroup.threadfix.webapp.viewmodels.VulnerabilityCollectionModel; @Controller @RequestMapping("/organizations/{orgId}/applications/{appId}") @SessionAttributes({"defectTracker", "application", "waf", "defectViewModel"}) public class VulnerabilityTabController { private final SanitizedLogger log = new SanitizedLogger(VulnerabilityTabController.class); private ApplicationService applicationService; private PermissionService permissionService; private VulnerabilityService vulnerabilityService; public VulnerabilityTabController(){} @Autowired public VulnerabilityTabController(ApplicationService applicationService, VulnerabilityService vulnerabilityService, PermissionService permissionService) { this.applicationService = applicationService; this.permissionService = permissionService; this.vulnerabilityService = vulnerabilityService; } //////////////////////////////////////////////////// // Tab Methods //////////////////////////////////////////////////// @RequestMapping(value="/vulnTab", method = RequestMethod.GET) public String vulnTab(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, Model model) { if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) { return "403"; } Application application = applicationService.loadApplication(appId); if (application == null || !application.isActive()) { log.warn(ResourceNotFoundException.getLogMessage("Application", appId)); throw new ResourceNotFoundException(); } long numVulns = applicationService.getVulnCount(appId, true); long numClosedVulns = applicationService.getVulnCount(appId, false); model.addAttribute("numVulns", numVulns); model.addAttribute("numClosedVulns", numClosedVulns); model.addAttribute(application); model.addAttribute("contentPage", "applications/tabs/vulnTab.jsp"); permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES); return "ajaxSuccessHarness"; } @RequestMapping(value="/scanTab", method = RequestMethod.GET) public String scanTab(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, Model model) { if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) { return "403"; } Application application = applicationService.loadApplication(appId); if (application == null || !application.isActive()) { log.warn(ResourceNotFoundException.getLogMessage("Application", appId)); throw new ResourceNotFoundException(); } model.addAttribute(application); permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES, Permission.CAN_UPLOAD_SCANS); model.addAttribute("contentPage", "applications/tabs/scanTab.jsp"); return "ajaxSuccessHarness"; } @RequestMapping(value="/closedTab", method = RequestMethod.GET) public String closedTab(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, Model model) { if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) { return "403"; } Application application = applicationService.loadApplication(appId); if (application == null || !application.isActive()) { log.warn(ResourceNotFoundException.getLogMessage("Application", appId)); throw new ResourceNotFoundException(); } TableSortBean basicBean = new TableSortBean(); basicBean.setOpen(false); long numVulns = applicationService.getCount(appId, basicBean); model.addAttribute("numVulns", numVulns); model.addAttribute(application); permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES); model.addAttribute("contentPage", "applications/tabs/closedTab.jsp"); return "ajaxSuccessHarness"; } @RequestMapping(value="/falsePositiveTab", method = RequestMethod.GET) public String falsePositiveTab(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, Model model) { if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) { return "403"; } permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES); model.addAttribute("contentPage", "applications/tabs/falsePositiveTab.jsp"); return "ajaxSuccessHarness"; } //////////////////////////////////////////////////// // Table Methods //////////////////////////////////////////////////// @RequestMapping(value="/table", method = RequestMethod.POST) public String getOpenTableVulns(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @RequestBody TableSortBean bean, Model model) { bean.setOpen(true); bean.setFalsePositive(false); return table(orgId, appId, bean, model); } @RequestMapping(value="/closedVulnerabilities/table", method = RequestMethod.POST) public String getClosedTableVulns(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @RequestBody TableSortBean bean, Model model) { bean.setOpen(false); bean.setFalsePositive(false); return table(orgId, appId, bean, model); } @RequestMapping(value="/falsePositives/table", method = RequestMethod.POST) public String markTableVulnsFalsePositive(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @RequestBody TableSortBean bean, Model model) { bean.setOpen(false); bean.setFalsePositive(true); return table(orgId, appId, bean, model); } public String table(int orgId, int appId, TableSortBean bean, Model model) { if (!permissionService.isAuthorized(Permission.READ_ACCESS, orgId, appId)) { return "403"; } Application application = applicationService.loadApplication(appId); if (application == null || !application.isActive()) { log.warn(ResourceNotFoundException.getLogMessage("Application", appId)); throw new ResourceNotFoundException(); } long numVulns = applicationService.getCount(appId, bean); long numPages = (numVulns / 100); if (numVulns % 100 == 0) { numPages -= 1; } model.addAttribute("numPages", numPages); model.addAttribute("numVulns", numVulns); if (bean.getPage() > numPages) { bean.setPage((int) (numPages + 1)); } if (bean.getPage() < 1) { bean.setPage(1); } List<Vulnerability> vulnList = applicationService.getVulnTable(appId, bean); model.addAttribute("vulnerabilityGroups", VulnerabilityGroup.generateGroups(vulnList, bean.isDefaultBean())); model.addAttribute("ages", vulnerabilityService.getAges(vulnList)); model.addAttribute("page", bean.getPage()); model.addAttribute("openCodes", Defect.OPEN_CODES); model.addAttribute("closedCodes", Defect.CLOSED_CODES); model.addAttribute(application); permissionService.addPermissions(model, orgId, appId, Permission.CAN_MODIFY_VULNERABILITIES, Permission.CAN_SUBMIT_DEFECTS); return "applications/vulnTable"; } @RequestMapping(value="/table/close", method = RequestMethod.POST) public String closeTableVulnList(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel, Model model, HttpServletRequest request) { if (!checkCollectionModel(vulnerabilityCollectionModel, model)) { return "ajaxFailureHarness"; } vulnerabilityService.closeAll( vulnerabilityCollectionModel.getVulnerabilityIds()); String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds()); ControllerUtils.addSuccessMessage(request, start + "been closed successfully."); return redirectToApp(model, orgId, appId); } @RequestMapping(value="/table/open", method = RequestMethod.POST) public String openTableVulnList(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel, Model model, HttpServletRequest request) { if (!checkCollectionModel(vulnerabilityCollectionModel, model)) { return "ajaxFailureHarness"; } vulnerabilityService.openAll( vulnerabilityCollectionModel.getVulnerabilityIds()); String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds()); ControllerUtils.addSuccessMessage(request, start + "been opened successfully."); return redirectToApp(model, orgId, appId); } @RequestMapping(value="/falsePositives/mark", method = RequestMethod.POST) public String setVulnsFalsePositive(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel, Model model, HttpServletRequest request) { if (!checkCollectionModel(vulnerabilityCollectionModel, model)) { return "ajaxFailureHarness"; } vulnerabilityService.markListAsFalsePositive(vulnerabilityCollectionModel .getVulnerabilityIds()); String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds()); ControllerUtils.addSuccessMessage(request, start + "been marked successfully as false positives."); return redirectToApp(model, orgId, appId); } @RequestMapping(value="/falsePositives/unmark", method = RequestMethod.POST) public String setVulnsNotFalsePositive(@PathVariable("orgId") Integer orgId, @PathVariable("appId") Integer appId, @ModelAttribute VulnerabilityCollectionModel vulnerabilityCollectionModel, Model model, HttpServletRequest request) { if (!checkCollectionModel(vulnerabilityCollectionModel, model)) { return "ajaxFailureHarness"; } vulnerabilityService.markListAsNotFalsePositive(vulnerabilityCollectionModel .getVulnerabilityIds()); String start = getMessageStart(vulnerabilityCollectionModel.getVulnerabilityIds()); ControllerUtils.addSuccessMessage(request, start + "been unmarked successfully."); return redirectToApp(model, orgId, appId); } private String redirectToApp(Model model, int orgId, int appId) { model.addAttribute("contentPage", "/organizations/" + orgId + "/applications/" + appId); return "ajaxRedirectHarness"; } private boolean checkCollectionModel(VulnerabilityCollectionModel vulnerabilityCollectionModel, Model model) { if (vulnerabilityCollectionModel == null || vulnerabilityCollectionModel.getVulnerabilityIds() == null || vulnerabilityCollectionModel.getVulnerabilityIds().size() == 0) { String error = "You must select at least one vulnerability."; model.addAttribute("errorMessage", error); model.addAttribute("contentPage", "errorMessage.jsp"); return false; } else { return true; } } private String getMessageStart(List<Integer> ids) { if (ids == null || ids.size() == 0) return ""; else if (ids.size() == 1) return "1 Vulnerability has "; else return ids.size() + " Vulnerabilities have "; } }