////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009-2013 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.webapp.controller;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;
import com.denimgroup.threadfix.data.entities.Application;
import com.denimgroup.threadfix.data.entities.Permission;
import com.denimgroup.threadfix.data.entities.Waf;
import com.denimgroup.threadfix.data.entities.WafRuleDirective;
import com.denimgroup.threadfix.service.PermissionService;
import com.denimgroup.threadfix.service.SanitizedLogger;
import com.denimgroup.threadfix.service.WafService;
@Controller
@RequestMapping("/wafs")
@SessionAttributes({"newWaf","waf"})
public class WafsController {
private WafService wafService = null;
private PermissionService permissionService = null;
private final SanitizedLogger log = new SanitizedLogger(WafsController.class);
@Autowired
public WafsController(PermissionService permissionService,
WafService wafService) {
this.wafService = wafService;
this.permissionService = permissionService;
}
public WafsController(){}
@RequestMapping(method = RequestMethod.GET)
public String index(Model model, HttpServletRequest request) {
List<Waf> wafs = wafService.loadAll();
model.addAttribute(wafs);
model.addAttribute("newWaf", new Waf());
model.addAttribute("successMessage", ControllerUtils.getSuccessMessage(request));
model.addAttribute("waf", new Waf());
model.addAttribute("wafPage", true);
model.addAttribute("createWafUrl", "wafs/new/ajax");
model.addAttribute("wafTypeList", wafService.loadAllWafTypes());
permissionService.addPermissions(model, null, null, Permission.CAN_MANAGE_WAFS);
return "wafs/index";
}
@RequestMapping("/{wafId}")
public ModelAndView detail(@PathVariable("wafId") int wafId,
HttpServletRequest request) {
ModelAndView mav = new ModelAndView("wafs/detail");
Waf waf = wafService.loadWaf(wafId);
if (waf == null) {
log.warn(ResourceNotFoundException.getLogMessage("WAF", wafId));
throw new ResourceNotFoundException();
}
boolean canSeeRules = false;
if (waf.getApplications() != null && !waf.getApplications().isEmpty()) {
canSeeRules = permissionService.canSeeRules(waf);
} else {
canSeeRules = true;
}
mav.addObject("canSeeRules", canSeeRules);
boolean hasApps = false;
if (waf.getApplications() != null) {
for (Application application : waf.getApplications()) {
if (application.isActive()) {
hasApps = true;
break;
}
}
}
mav.addObject("hasApps", hasApps);
mav.addObject("wafTypeList", wafService.loadAllWafTypes());
if (waf.getApplications() != null && waf.getApplications().size() != 0) {
boolean globalAccess = permissionService.isAuthorized(Permission.READ_ACCESS, null,null);
if (globalAccess) {
mav.addObject("apps", waf.getApplications());
} else {
List<Application> apps = new ArrayList<Application>();
Set<Integer> authenticatedAppIds = permissionService.getAuthenticatedAppIds();
Set<Integer> authenticatedTeamIds = permissionService.getAuthenticatedTeamIds();
for (Application app : waf.getApplications()) {
if ((authenticatedAppIds != null && app != null &&
app.getId() != null &&
authenticatedAppIds.contains(app.getId())) ||
(authenticatedTeamIds != null && app.getOrganization() != null &&
app.getOrganization().getId() != null &&
authenticatedTeamIds.contains(app.getOrganization().getId()))) {
apps.add(app);
}
}
mav.addObject("apps", apps);
}
}
if (canSeeRules) {
String rulesText = wafService.getAllRuleText(waf);
mav.addObject("rulesText", rulesText);
WafRuleDirective lastDirective = null;
List<WafRuleDirective> directives = null;
if ((waf.getLastWafRuleDirective() != null) && (waf.getWafType().getId().equals(
waf.getLastWafRuleDirective().getWafType().getId()))) {
lastDirective = waf.getLastWafRuleDirective();
directives = waf.getWafType().getWafRuleDirectives();
directives.remove(lastDirective);
} else if (waf.getWafType() != null && waf.getWafType().getWafRuleDirectives() != null
&& waf.getWafType().getWafRuleDirectives().size() >= 1) {
lastDirective = waf.getWafType().getWafRuleDirectives().get(0);
directives = waf.getWafType().getWafRuleDirectives();
directives.remove(0);
}
mav.addObject("lastDirective", lastDirective);
mav.addObject("directives", directives);
}
mav.addObject(waf);
permissionService.addPermissions(mav, null, null,
Permission.CAN_MANAGE_WAFS, Permission.CAN_GENERATE_WAF_RULES);
mav.addObject("successMessage", ControllerUtils.getSuccessMessage(request));
return mav;
}
@PreAuthorize("hasRole('ROLE_CAN_MANAGE_WAFS')")
@RequestMapping("/{wafId}/delete")
public String deleteWaf(@PathVariable("wafId") int wafId,
SessionStatus status, HttpServletRequest request) {
Waf waf = wafService.loadWaf(wafId);
boolean canDelete = waf != null && waf.getCanDelete();
if (waf != null && canDelete) {
wafService.deleteById(wafId);
status.setComplete();
ControllerUtils.addSuccessMessage(request,
"The WAF deletion was successful for WAF" + waf.getName() + ".");
return "redirect:/wafs";
} else {
// For now we can't do this.
log.warn("The user has attempted to delete a WAF with application mappings.");
return "redirect:/wafs/" + wafId;
}
}
@RequestMapping(value = "/{wafId}", method = RequestMethod.POST)
public ModelAndView download(@PathVariable("wafId") int wafId,
HttpServletResponse response, HttpServletRequest request) throws IOException {
Waf waf = wafService.loadWaf(wafId);
if (waf == null)
return null;
if (waf.getWafRules() == null)
wafService.generateWafRules(waf, new WafRuleDirective());
String pageString = wafService.getAllRuleText(waf);
if (pageString == null) {
return detail(wafId, request);
}
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"wafrules_" + wafId
+ ".txt\"");
ServletOutputStream out = response.getOutputStream();
InputStream in = new ByteArrayInputStream(pageString.getBytes("UTF-8"));
byte[] outputByte = new byte[65535];
// copy binary content to output stream
int numToTransfer = in.read(outputByte, 0, 65535);
while (numToTransfer != -1) {
out.write(outputByte, 0, numToTransfer);
numToTransfer = in.read(outputByte, 0, 65535);
}
in.close();
out.flush();
out.close();
return null;
}
}