/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright the ZAP Development Team * * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zaproxy.zap.extension.ascan; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.parosproxy.paros.Constant; import org.zaproxy.zap.utils.ZapXmlConfiguration; public class PolicyManager { public static final String POLICY_EXTENSION = ".policy"; private static final String DEFAULT_POLICY_NAME = Constant.messages.getString("ascan.policymgr.default.name"); public static final String ILLEGAL_POLICY_NAME_CHRS = "/`?*\\<>|\":\t\n\r"; private List<String> allPolicyNames = null; private ExtensionActiveScan extension; private static final Logger logger = Logger.getLogger(PolicyManager.class); public PolicyManager(ExtensionActiveScan extension) { this.extension = extension; } public void init() { // Force load getAllPolicyNames(); } public synchronized List<String> getAllPolicyNames() { if (allPolicyNames == null) { allPolicyNames = new ArrayList<String>(); String[] files = Constant.getPoliciesDir().list(); if (files != null) { for (String file : files) { if (file.endsWith(POLICY_EXTENSION)) { logger.debug("Found policy file " + file); allPolicyNames.add(file.substring(0, file.lastIndexOf(POLICY_EXTENSION))); } } } if (allPolicyNames.size() == 0) { // No policies :( Create a default one ScanPolicy defaultPolicy = new ScanPolicy(); defaultPolicy.setName(DEFAULT_POLICY_NAME); // Load from the 'old' configs defaultPolicy.getPluginFactory().loadAllPlugin(extension.getScannerParam().getConfig()); try { // Note this will add the name to allPolicyNames this.savePolicy(defaultPolicy); } catch (ConfigurationException e) { logger.debug("Failed to create default scan policy in " + Constant.getPoliciesDir().getAbsolutePath(), e); } } Collections.sort(allPolicyNames); } return allPolicyNames; } public void savePolicy (ScanPolicy policy) throws ConfigurationException { this.savePolicy(policy, null); } public void savePolicy (ScanPolicy policy, String previousName) throws ConfigurationException { logger.debug("Save policy " + policy.getName()); File file = new File(Constant.getPoliciesDir(), policy.getName() + POLICY_EXTENSION); ZapXmlConfiguration conf = new ZapXmlConfiguration(); conf.setProperty("policy", policy.getName()); conf.setProperty("scanner.level", policy.getDefaultThreshold().name()); conf.setProperty("scanner.strength", policy.getDefaultStrength().name()); policy.getPluginFactory().saveTo(conf); conf.save(file); if (previousName != null && previousName.length() > 0) { allPolicyNames.remove(previousName); } if (!allPolicyNames.contains(policy.getName())) { allPolicyNames.add(policy.getName()); Collections.sort(allPolicyNames); } } /** * Tells whether or not a scan policy with the given {@code name} exists. * * @param name the name of the scan policy * @return {@code true} if the scan policy exists, {@code false} otherwise * @since 2.4.3 */ public static boolean policyExists(String name) { return (new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION)).exists(); } public ScanPolicy getPolicy (String name) throws ConfigurationException { return this.loadPolicy(new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION)); } public ScanPolicy loadPolicy (String name) throws ConfigurationException { return this.loadPolicy(new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION)); } private ScanPolicy loadPolicy (File file) throws ConfigurationException { File policyFile; try { // Obtain the name of the file in correct case, for DEFAULT_POLICY_NAME it might not be exactly the same if the file // system is case insensitive, thus not matching with the name read directly from the file system (method // getAllPolicyNames()). policyFile = file.toPath().toRealPath().toFile(); } catch (IOException e) { throw new ConfigurationException("Failed to obtain the real path of the policy file:", e); } ScanPolicy policy = new ScanPolicy(new ZapXmlConfiguration(policyFile)); if (! policyFile.getName().equals(policy.getName() + POLICY_EXTENSION)) { // The file name takes precedence in case theres another policy with the same name policy.setName(policyFile.getName().substring(0, policyFile.getName().indexOf(POLICY_EXTENSION))); } return policy; } public void importPolicy (File file) throws ConfigurationException, IOException { logger.debug("Import policy from " + file.getAbsolutePath()); ScanPolicy policy = new ScanPolicy(new ZapXmlConfiguration(file)); String baseName = file.getName(); if (baseName.endsWith(POLICY_EXTENSION)) { // Stip off the extension for the 'friendly name' and if we need to prevent overwriting an existing one baseName = baseName.substring(0, baseName.indexOf(POLICY_EXTENSION)); } String finalName = baseName; File newFile = new File(Constant.getPoliciesDir(), finalName + POLICY_EXTENSION); int i=2; while (newFile.exists()) { finalName = baseName + i; newFile = new File(Constant.getPoliciesDir(), finalName + POLICY_EXTENSION); i++; } policy.setName(finalName); this.savePolicy(policy); } public void exportPolicy (ScanPolicy policy, File file) throws ConfigurationException { logger.debug("Export policy to " + file.getAbsolutePath()); ZapXmlConfiguration conf = new ZapXmlConfiguration(); conf.setProperty("policy", policy.getName()); conf.setProperty("scanner.level", policy.getDefaultThreshold().name()); conf.setProperty("scanner.strength", policy.getDefaultStrength().name()); policy.getPluginFactory().saveTo(conf); conf.save(file); } public ScanPolicy getTemplatePolicy() throws ConfigurationException { return new ScanPolicy(); } public void deletePolicy(String name) { logger.debug("Delete policy " + name); File file = new File(Constant.getPoliciesDir(), name + POLICY_EXTENSION); if (file.exists()) { file.delete(); } this.allPolicyNames.remove(name); } public ScanPolicy getDefaultScanPolicy() { try { String policyName = extension.getScannerParam().getDefaultPolicy(); if (policyExists(policyName)) { logger.debug("getDefaultScanPolicy: " + policyName); return this.loadPolicy(policyName); } // No good, try the default name policyName = DEFAULT_POLICY_NAME; if (policyExists(policyName)) { logger.debug("getDefaultScanPolicy (default name): " + policyName); return this.loadPolicy(policyName); } if (this.allPolicyNames.size() > 0) { // Still no joy, try the first logger.debug("getDefaultScanPolicy (first one): " + policyName); return this.loadPolicy(this.allPolicyNames.get(0)); } } catch (ConfigurationException e) { logger.error(e.getMessage(), e); } // Return a new 'blank' one logger.debug("getDefaultScanPolicy (new blank)"); return new ScanPolicy(); } public ScanPolicy getAttackScanPolicy() { try { String policyName = extension.getScannerParam().getAttackPolicy(); if (policyExists(policyName)) { return this.loadPolicy(policyName); } // No good, try the default name policyName = DEFAULT_POLICY_NAME; if (policyExists(policyName)) { return this.loadPolicy(policyName); } if (this.allPolicyNames.size() > 0) { // Still no joy, try the first return this.loadPolicy(this.allPolicyNames.get(0)); } } catch (ConfigurationException e) { logger.error(e.getMessage(), e); } // Return a new 'blank' one return new ScanPolicy(); } public boolean isLegalPolicyName(String str) { for (int i=0; i < str.length(); i++) { if (ILLEGAL_POLICY_NAME_CHRS.indexOf(str.charAt(i)) >= 0) { return false; } } return true; } }