/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2012 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.parosproxy.paros.core.scanner;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.network.HttpMessage;
/**
* Module for parameter filtering according to URL,
* type and parameter name regexes
* @author yhawke (2014)
* @see NameValuePair
*/
public class ScannerParamFilter implements Cloneable {
private String wildcardedUrl;
private String paramNameRegex;
private int paramType;
private Pattern paramNamePattern;
private Pattern urlPattern;
private static final Map<Integer, String> typeMap = new HashMap<>();
static {
typeMap.put(NameValuePair.TYPE_UNDEFINED, Constant.messages.getString("variant.param.type.all"));
typeMap.put(NameValuePair.TYPE_QUERY_STRING, Constant.messages.getString("variant.param.type.query"));
typeMap.put(NameValuePair.TYPE_POST_DATA, Constant.messages.getString("variant.param.type.postdata"));
typeMap.put(NameValuePair.TYPE_URL_PATH, Constant.messages.getString("variant.param.type.path"));
typeMap.put(NameValuePair.TYPE_HEADER, Constant.messages.getString("variant.param.type.header"));
typeMap.put(NameValuePair.TYPE_COOKIE, Constant.messages.getString("variant.param.type.cookie"));
}
/**
* Default constructor to initialize default values
*/
public ScannerParamFilter() {
this.wildcardedUrl = "*";
this.paramType = NameValuePair.TYPE_UNDEFINED;
this.paramNamePattern = null;
this.urlPattern = null;
}
public ScannerParamFilter(String paramName, int paramType, String urlPattern) {
this.paramType = paramType;
this.setParamName(paramName);
this.setWildcardedUrl(urlPattern);
}
public int getType() {
return paramType;
}
public void setType(int paramType) {
this.paramType = paramType;
}
public String getParamName() {
return paramNameRegex;
}
public final void setParamName(String paramNameRegex) {
this.paramNameRegex = paramNameRegex;
this.paramNamePattern = Pattern.compile(paramNameRegex);
}
public static boolean isValidParamNameRegex(String paramNameRegex) {
try {
Pattern.compile(paramNameRegex);
return true;
} catch (PatternSyntaxException e) {
return false;
}
}
public String getWildcardedUrl() {
return wildcardedUrl;
}
public final void setWildcardedUrl(String wildcardedUrl) {
this.wildcardedUrl = wildcardedUrl;
if ((wildcardedUrl == null) || wildcardedUrl.equals("*")) {
this.urlPattern = null;
} else {
String wname = wildcardedUrl.toUpperCase(Locale.ROOT);
wname = Pattern.quote(wname);
wname = wname.replaceAll("\\?", "\\\\E.\\\\Q");
wname = wname.replaceAll("\\*", "\\\\E.*\\\\Q");
wname = wname.replaceAll("\\\\Q\\\\E", "");
this.urlPattern = Pattern.compile(wname);
}
}
/**
* Check if the parameter should be excluded by the scanner
* @param msg the message that is currently under scanning
* @param param the Value/Name param object thta is currently under scanning
* @return true if the parameter should be excluded
*/
public boolean isToExclude(HttpMessage msg, NameValuePair param) {
return ((paramType == NameValuePair.TYPE_UNDEFINED) || (param.getType() == paramType)) &&
((urlPattern == null) || urlPattern.matcher(msg.getRequestHeader().getURI().toString().toUpperCase(Locale.ROOT)).matches()) &&
(paramNamePattern.matcher(param.getName()).matches());
}
/**
* Clone this filter
* @return a new filter with replicated contents
*/
@Override
public ScannerParamFilter clone() {
return new ScannerParamFilter(paramNameRegex, paramType, wildcardedUrl);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((paramNameRegex == null) ? 0 : paramNameRegex.hashCode());
result = prime * result + paramType;
result = prime * result + ((wildcardedUrl == null) ? 0 : wildcardedUrl.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ScannerParamFilter) {
ScannerParamFilter p = (ScannerParamFilter)obj;
return ((p.getType() == getType()) &&
p.getWildcardedUrl().equals(getWildcardedUrl()) &&
p.getParamName().equals(getParamName()));
} else return false;
}
public String getTypeString() {
return typeMap.get(paramType);
}
public void setType(String value) {
int type = NameValuePair.TYPE_UNDEFINED;
for (Map.Entry<Integer, String> entry : typeMap.entrySet()) {
if (entry.getValue().equalsIgnoreCase(value)) {
type = entry.getKey();
break;
}
}
setType(type);
}
public static final Collection<String> getListTypes() {
return typeMap.values();
}
public static final String getStringType(int paramType) {
return typeMap.get(paramType);
}
/**
* Gets the parameter types (IDs and corresponding name).
*
* @return the parameter types.
* @since 2.6.0
*/
public static Map<Integer, String> getTypes() {
return Collections.unmodifiableMap(typeMap);
}
}